00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <kdebug.h>
00027 #include <klocale.h>
00028 #include <kfiledialog.h>
00029 #include <kcompletionbox.h>
00030 #include <kcursor.h>
00031
00032 #include <qstyle.h>
00033
00034 #include "misc/helper.h"
00035 #include "xml/dom2_eventsimpl.h"
00036 #include "html/html_formimpl.h"
00037 #include "misc/htmlhashes.h"
00038
00039 #include "rendering/render_form.h"
00040 #include <assert.h>
00041
00042 #include "khtmlview.h"
00043 #include "khtml_ext.h"
00044 #include "xml/dom_docimpl.h"
00045
00046 #include <qpopupmenu.h>
00047
00048 using namespace khtml;
00049
00050 RenderFormElement::RenderFormElement(HTMLGenericFormElementImpl *element)
00051 : RenderWidget(element)
00052 {
00053
00054 setInline(true);
00055
00056 m_state = 0;
00057 m_isDoubleClick = false;
00058 }
00059
00060 RenderFormElement::~RenderFormElement()
00061 {
00062 }
00063
00064 short RenderFormElement::baselinePosition( bool f ) const
00065 {
00066 return RenderWidget::baselinePosition( f ) - 2 - style()->fontMetrics().descent();
00067 }
00068
00069
00070 void RenderFormElement::updateFromElement()
00071 {
00072 m_widget->setEnabled(!element()->disabled());
00073 RenderWidget::updateFromElement();
00074 }
00075
00076 void RenderFormElement::layout()
00077 {
00078 KHTMLAssert( !layouted() );
00079 KHTMLAssert( minMaxKnown() );
00080
00081
00082 m_height = 0;
00083
00084 calcWidth();
00085 calcHeight();
00086
00087 if ( m_widget )
00088 resizeWidget(m_width-borderLeft()-borderRight()-paddingLeft()-paddingRight(),
00089 m_height-borderTop()-borderBottom()-paddingTop()-paddingBottom());
00090
00091 if ( !style()->width().isPercent() )
00092 setLayouted();
00093 }
00094
00095 void RenderFormElement::slotClicked()
00096 {
00097 ref();
00098 QMouseEvent e2( QEvent::MouseButtonRelease, m_mousePos, 1, m_state);
00099
00100 element()->dispatchMouseEvent(&e2, EventImpl::CLICK_EVENT, m_isDoubleClick + 1);
00101 m_isDoubleClick = false;
00102 deref();
00103 }
00104
00105 void RenderFormElement::slotPressed()
00106 {
00107 ref();
00108 QMouseEvent e2( QEvent::MouseButtonPress, m_mousePos, 1, m_state);
00109 element()->dispatchMouseEvent(&e2, EventImpl::MOUSEDOWN_EVENT, 1);
00110 deref();
00111 }
00112
00113 void RenderFormElement::slotReleased()
00114 {
00115 ref();
00116 QMouseEvent e2( QEvent::MouseButtonRelease, m_mousePos, 1, m_state);
00117 element()->dispatchMouseEvent(&e2, EventImpl::MOUSEUP_EVENT, 1);
00118 deref();
00119 }
00120
00121
00122
00123 RenderButton::RenderButton(HTMLGenericFormElementImpl *element)
00124 : RenderFormElement(element)
00125 {
00126 }
00127
00128 short RenderButton::baselinePosition( bool f ) const
00129 {
00130 return RenderWidget::baselinePosition( f ) - 2;
00131 }
00132
00133
00134
00135 RenderCheckBox::RenderCheckBox(HTMLInputElementImpl *element)
00136 : RenderButton(element)
00137 {
00138 QCheckBox* b = new QCheckBox(view()->viewport());
00139 b->setAutoMask(true);
00140 b->setMouseTracking(true);
00141 setQWidget(b);
00142 connect(b,SIGNAL(stateChanged(int)),this,SLOT(slotStateChanged(int)));
00143 connect(b, SIGNAL(clicked()), this, SLOT(slotClicked()));
00144 connect(b, SIGNAL(pressed()), this, SLOT(slotPressed()));
00145 connect(b, SIGNAL(released()), this, SLOT(slotReleased()));
00146 }
00147
00148
00149 void RenderCheckBox::calcMinMaxWidth()
00150 {
00151 KHTMLAssert( !minMaxKnown() );
00152
00153 QCheckBox *cb = static_cast<QCheckBox *>( m_widget );
00154 QSize s( cb->style().pixelMetric( QStyle::PM_IndicatorWidth ),
00155 cb->style().pixelMetric( QStyle::PM_IndicatorHeight ) );
00156 setIntrinsicWidth( s.width() );
00157 setIntrinsicHeight( s.height() );
00158
00159 RenderButton::calcMinMaxWidth();
00160 }
00161
00162 void RenderCheckBox::updateFromElement()
00163 {
00164 widget()->setChecked(element()->checked());
00165
00166 RenderButton::updateFromElement();
00167 }
00168
00169 void RenderCheckBox::slotStateChanged(int state)
00170 {
00171 element()->setChecked(state == 2);
00172 }
00173
00174
00175
00176 RenderRadioButton::RenderRadioButton(HTMLInputElementImpl *element)
00177 : RenderButton(element)
00178 {
00179 QRadioButton* b = new QRadioButton(view()->viewport());
00180 b->setAutoMask(true);
00181 b->setMouseTracking(true);
00182 setQWidget(b);
00183 connect(b, SIGNAL(clicked()), this, SLOT(slotClicked()));
00184 connect(b, SIGNAL(pressed()), this, SLOT(slotPressed()));
00185 connect(b, SIGNAL(released()), this, SLOT(slotReleased()));
00186 }
00187
00188 void RenderRadioButton::updateFromElement()
00189 {
00190 widget()->setChecked(element()->checked());
00191
00192 RenderButton::updateFromElement();
00193 }
00194
00195 void RenderRadioButton::slotClicked()
00196 {
00197 element()->setChecked(true);
00198
00199
00200 RenderButton::slotClicked();
00201 }
00202
00203 void RenderRadioButton::calcMinMaxWidth()
00204 {
00205 KHTMLAssert( !minMaxKnown() );
00206
00207 QRadioButton *rb = static_cast<QRadioButton *>( m_widget );
00208 QSize s( rb->style().pixelMetric( QStyle::PM_ExclusiveIndicatorWidth ),
00209 rb->style().pixelMetric( QStyle::PM_ExclusiveIndicatorHeight ) );
00210 setIntrinsicWidth( s.width() );
00211 setIntrinsicHeight( s.height() );
00212
00213 RenderButton::calcMinMaxWidth();
00214 }
00215
00216
00217
00218
00219 RenderSubmitButton::RenderSubmitButton(HTMLInputElementImpl *element)
00220 : RenderButton(element)
00221 {
00222 QPushButton* p = new QPushButton(view()->viewport());
00223 setQWidget(p);
00224 p->setAutoMask(true);
00225 p->setMouseTracking(true);
00226 connect(p, SIGNAL(clicked()), this, SLOT(slotClicked()));
00227 connect(p, SIGNAL(pressed()), this, SLOT(slotPressed()));
00228 connect(p, SIGNAL(released()), this, SLOT(slotReleased()));
00229 }
00230
00231 QString RenderSubmitButton::rawText()
00232 {
00233 QString value = element()->value().isEmpty() ? defaultLabel() : element()->value().string();
00234 value = value.stripWhiteSpace();
00235 QString raw;
00236 for(unsigned int i = 0; i < value.length(); i++) {
00237 raw += value[i];
00238 if(value[i] == '&')
00239 raw += '&';
00240 }
00241 return raw;
00242 }
00243
00244 void RenderSubmitButton::calcMinMaxWidth()
00245 {
00246 KHTMLAssert( !minMaxKnown() );
00247
00248 QString raw = rawText();
00249 QPushButton* pb = static_cast<QPushButton*>(m_widget);
00250 pb->setText(raw);
00251 pb->setFont(style()->font());
00252
00253 bool empty = raw.isEmpty();
00254 if ( empty )
00255 raw = QString::fromLatin1("X");
00256 QFontMetrics fm = pb->fontMetrics();
00257 QSize ts = fm.size( ShowPrefix, raw);
00258 QSize s(pb->style().sizeFromContents( QStyle::CT_PushButton, pb, ts )
00259 .expandedTo(QApplication::globalStrut()));
00260 int margin = pb->style().pixelMetric( QStyle::PM_ButtonMargin, pb) +
00261 pb->style().pixelMetric( QStyle::PM_DefaultFrameWidth, pb ) * 2;
00262 int w = ts.width() + margin;
00263 int h = s.height();
00264 if (pb->isDefault() || pb->autoDefault()) {
00265 int dbw = pb->style().pixelMetric( QStyle::PM_ButtonDefaultIndicator, pb ) * 2;
00266 w += dbw;
00267 }
00268
00269
00270 s = QSize( w*13/10, h ).expandedTo(QApplication::globalStrut());
00271
00272 setIntrinsicWidth( s.width() );
00273 setIntrinsicHeight( s.height() );
00274
00275 RenderButton::calcMinMaxWidth();
00276 }
00277
00278 void RenderSubmitButton::updateFromElement()
00279 {
00280 QString oldText = static_cast<QPushButton*>(m_widget)->text();
00281 QString newText = rawText();
00282 static_cast<QPushButton*>(m_widget)->setText(newText);
00283 if ( oldText != newText ) {
00284 setMinMaxKnown(false);
00285 setLayouted(false);
00286 }
00287 RenderFormElement::updateFromElement();
00288 }
00289
00290 QString RenderSubmitButton::defaultLabel() {
00291 return i18n("Submit");
00292 }
00293
00294 short RenderSubmitButton::baselinePosition( bool f ) const
00295 {
00296 return RenderFormElement::baselinePosition( f );
00297 }
00298
00299
00300
00301 RenderImageButton::RenderImageButton(HTMLInputElementImpl *element)
00302 : RenderImage(element)
00303 {
00304
00305 }
00306
00307
00308
00309
00310 RenderResetButton::RenderResetButton(HTMLInputElementImpl *element)
00311 : RenderSubmitButton(element)
00312 {
00313 }
00314
00315 QString RenderResetButton::defaultLabel() {
00316 return i18n("Reset");
00317 }
00318
00319
00320
00321
00322 RenderPushButton::RenderPushButton(HTMLInputElementImpl *element)
00323 : RenderSubmitButton(element)
00324 {
00325 }
00326
00327 QString RenderPushButton::defaultLabel()
00328 {
00329 return QString::null;
00330 }
00331
00332
00333
00334 LineEditWidget::LineEditWidget(QWidget *parent)
00335 : KLineEdit(parent)
00336 {
00337 setMouseTracking(true);
00338 }
00339
00340 QPopupMenu *LineEditWidget::createPopupMenu()
00341 {
00342 QPopupMenu *popup = KLineEdit::createPopupMenu();
00343 if ( !popup )
00344 return 0L;
00345 connect( popup, SIGNAL( activated( int ) ),
00346 this, SLOT( extendedMenuActivated( int ) ) );
00347 popup->insertSeparator();
00348 popup->insertItem( i18n("Clear History"), ClearHistory );
00349 return popup;
00350 }
00351
00352 void LineEditWidget::extendedMenuActivated( int id)
00353 {
00354 switch ( id )
00355 {
00356 case ClearHistory:
00357 clearMenuHistory();
00358 break;
00359 default:
00360 break;
00361 }
00362 }
00363
00364 void LineEditWidget::clearMenuHistory()
00365 {
00366 emit clearCompletionHistory();
00367 }
00368
00369
00370 bool LineEditWidget::event( QEvent *e )
00371 {
00372 if ( e->type() == QEvent::AccelAvailable && isReadOnly() ) {
00373 QKeyEvent* ke = (QKeyEvent*) e;
00374 if ( ke->state() & ControlButton ) {
00375 switch ( ke->key() ) {
00376 case Key_Left:
00377 case Key_Right:
00378 case Key_Up:
00379 case Key_Down:
00380 case Key_Home:
00381 case Key_End:
00382 ke->accept();
00383 default:
00384 break;
00385 }
00386 }
00387 }
00388 else if ( e->type() == QEvent::MouseButtonPress )
00389 emit pressed();
00390 else if ( e->type() == QEvent::MouseButtonRelease )
00391 emit released();
00392 return KLineEdit::event( e );
00393 }
00394
00395
00396
00397 RenderLineEdit::RenderLineEdit(HTMLInputElementImpl *element)
00398 : RenderFormElement(element)
00399 {
00400 LineEditWidget *edit = new LineEditWidget(view()->viewport());
00401 connect(edit,SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));
00402 connect(edit,SIGNAL(textChanged(const QString &)),this,SLOT(slotTextChanged(const QString &)));
00403 connect(edit,SIGNAL(pressed()), this, SLOT(slotPressed()));
00404 connect(edit,SIGNAL(released()), this, SLOT(slotReleased()));
00405 connect(edit, SIGNAL(clearCompletionHistory()), this, SLOT( slotClearCompletionHistory()));
00406 if(element->inputType() == HTMLInputElementImpl::PASSWORD)
00407 edit->setEchoMode( QLineEdit::Password );
00408
00409 if ( element->autoComplete() ) {
00410 QStringList completions = view()->formCompletionItems(element->name().string());
00411 if (completions.count()) {
00412 edit->completionObject()->setItems(completions);
00413 edit->setContextMenuEnabled(true);
00414 }
00415 }
00416
00417 setQWidget(edit);
00418 }
00419
00420 void RenderLineEdit::slotClearCompletionHistory()
00421 {
00422 if ( element()->autoComplete() ) {
00423 view()->clearCompletionHistory(element()->name().string());
00424 static_cast<LineEditWidget*>(m_widget)->completionObject()->clear();
00425 }
00426 }
00427
00428 void RenderLineEdit::slotReturnPressed()
00429 {
00430
00431 KCompletionBox *box = widget()->completionBox(false);
00432 if ( box && box->isVisible() && box->currentItem() != -1 )
00433 return;
00434
00435
00436
00437
00438 handleFocusOut();
00439
00440 HTMLFormElementImpl* fe = element()->form();
00441 if ( fe )
00442 fe->submitFromKeyboard();
00443 }
00444
00445 void RenderLineEdit::handleFocusOut()
00446 {
00447 if ( widget() && widget()->edited() ) {
00448 element()->onChange();
00449 widget()->setEdited( false );
00450 }
00451 }
00452
00453 void RenderLineEdit::calcMinMaxWidth()
00454 {
00455 KHTMLAssert( !minMaxKnown() );
00456
00457 const QFontMetrics &fm = style()->fontMetrics();
00458 QSize s;
00459
00460 int size = element()->size();
00461
00462 int h = fm.lineSpacing();
00463 int w = fm.width( 'x' ) * (size > 0 ? size+1 : 17);
00464 s = QSize(w + 2 + 2*widget()->frameWidth(),
00465 QMAX(h, 14) + 2 + 2*widget()->frameWidth())
00466 .expandedTo(QApplication::globalStrut());
00467
00468 setIntrinsicWidth( s.width() );
00469 setIntrinsicHeight( s.height() );
00470
00471 RenderFormElement::calcMinMaxWidth();
00472 }
00473
00474 void RenderLineEdit::updateFromElement()
00475 {
00476 int ml = element()->maxLength();
00477 if ( ml < 0 || ml > 1024 )
00478 ml = 1024;
00479 if ( widget()->maxLength() != ml ) {
00480 widget()->blockSignals( true );
00481 widget()->setMaxLength( ml );
00482 widget()->blockSignals( false );
00483 }
00484
00485 if (element()->value().string() != widget()->text()) {
00486 widget()->blockSignals(true);
00487 int pos = widget()->cursorPosition();
00488 widget()->setText(element()->value().string());
00489
00490 widget()->setEdited( false );
00491
00492 widget()->setCursorPosition(pos);
00493 widget()->blockSignals(false);
00494 }
00495 widget()->setReadOnly(element()->readOnly());
00496
00497 RenderFormElement::updateFromElement();
00498 }
00499
00500 void RenderLineEdit::slotTextChanged(const QString &string)
00501 {
00502
00503 element()->m_value = string;
00504 }
00505
00506 void RenderLineEdit::select()
00507 {
00508 static_cast<LineEditWidget*>(m_widget)->selectAll();
00509 }
00510
00511
00512
00513 RenderFieldset::RenderFieldset(HTMLGenericFormElementImpl *element)
00514 : RenderFlow(element)
00515 {
00516 }
00517
00518 bool RenderFieldset::findLegend( int &lx, int &ly, int &lw, int &lh)
00519 {
00520 RenderObject *r = this, *ref = 0;
00521 int minx = 0, curx = 0, maxw = 0;
00522 if( r->firstChild() && r->firstChild()->element() &&
00523 r->firstChild()->element()->id() == ID_LEGEND)
00524 r = r->firstChild();
00525 else
00526 return false;
00527 if(!r->firstChild() || r->isSpecial())
00528 return false;
00529 ly = r->yPos();
00530 minx = r->width();
00531 curx = r->xPos();
00532 lh = r->height();
00533 ref = r;
00534
00535 while(r) {
00536 if(r->firstChild())
00537 r = r->firstChild();
00538 else if(r->nextSibling())
00539 r = r->nextSibling();
00540 else {
00541 RenderObject *next = 0;
00542 while(!next) {
00543 r = r->parent();
00544 if(!r || r == (RenderObject *)ref ) goto end;
00545 next = r->nextSibling();
00546 }
00547 r = next;
00548 }
00549 if(r->isSpecial())
00550 continue;
00551 curx += r->xPos();
00552 if(r->width() && curx<minx)
00553 minx = curx;
00554 if(curx-minx+r->width() > maxw) {
00555 maxw = curx-minx+r->width();
00556 }
00557 if(!r->childrenInline())
00558 curx -= r->xPos();
00559 }
00560 end:
00561 lx = minx - ref->paddingLeft();
00562 lw = maxw + ref->paddingLeft() + ref->paddingRight();
00563 if(lx < 0 || lx+lw > width())
00564 return false;
00565 return !!maxw;
00566 }
00567
00568 void RenderFieldset::paintBoxDecorations(QPainter *p,int, int _y,
00569 int, int _h, int _tx, int _ty)
00570 {
00571
00572
00573 int w = width();
00574 int h = height() + borderTopExtra() + borderBottomExtra();
00575 int lx = 0, ly = 0, lw = 0, lh = 0;
00576 bool legend = findLegend(lx, ly, lw, lh);
00577
00578 if(legend) {
00579 int yOff = ly + lh/2 - borderTop()/2;
00580 h -= yOff;
00581 _ty += yOff;
00582 }
00583 _ty -= borderTopExtra();
00584
00585 int my = QMAX(_ty,_y);
00586 int end = QMIN( _y + _h, _ty + h );
00587 int mh = end - my;
00588
00589 paintBackground(p, style()->backgroundColor(), style()->backgroundImage(), my, mh, _tx, _ty, w, h);
00590
00591 if ( style()->hasBorder() ) {
00592 if ( legend )
00593 paintBorderMinusLegend(p, _tx, _ty, w, h, style(), lx, lw);
00594 else
00595 paintBorder(p, _tx, _ty, w, h, style());
00596 }
00597 }
00598
00599 void RenderFieldset::paintBorderMinusLegend(QPainter *p, int _tx, int _ty, int w, int h,
00600 const RenderStyle* style, int lx, int lw)
00601 {
00602
00603 const QColor& tc = style->borderTopColor();
00604 const QColor& bc = style->borderBottomColor();
00605
00606 EBorderStyle ts = style->borderTopStyle();
00607 EBorderStyle bs = style->borderBottomStyle();
00608 EBorderStyle ls = style->borderLeftStyle();
00609 EBorderStyle rs = style->borderRightStyle();
00610
00611 bool render_t = ts > BHIDDEN;
00612 bool render_l = ls > BHIDDEN;
00613 bool render_r = rs > BHIDDEN;
00614 bool render_b = bs > BHIDDEN;
00615
00616 if(render_t) {
00617 drawBorder(p, _tx, _ty, _tx + lx, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
00618 (render_l && ls<=DOUBLE?style->borderLeftWidth():0), 0);
00619 drawBorder(p, _tx+lx+lw, _ty, _tx + w, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
00620 0, (render_r && rs<=DOUBLE?style->borderRightWidth():0));
00621 }
00622
00623 if(render_b)
00624 drawBorder(p, _tx, _ty + h - style->borderBottomWidth(), _tx + w, _ty + h, BSBottom, bc, style->color(), bs,
00625 (render_l && ls<=DOUBLE?style->borderLeftWidth():0),
00626 (render_r && rs<=DOUBLE?style->borderRightWidth():0));
00627
00628 if(render_l)
00629 {
00630 const QColor& lc = style->borderLeftColor();
00631
00632 bool ignore_top =
00633 (tc == lc) &&
00634 (ls <= OUTSET) &&
00635 (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
00636
00637 bool ignore_bottom =
00638 (bc == lc) &&
00639 (ls <= OUTSET) &&
00640 (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
00641
00642 drawBorder(p, _tx, _ty, _tx + style->borderLeftWidth(), _ty + h, BSLeft, lc, style->color(), ls,
00643 ignore_top?0:style->borderTopWidth(),
00644 ignore_bottom?0:style->borderBottomWidth());
00645 }
00646
00647 if(render_r)
00648 {
00649 const QColor& rc = style->borderRightColor();
00650
00651 bool ignore_top =
00652 (tc == rc) &&
00653 (rs <= SOLID || rs == INSET) &&
00654 (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
00655
00656 bool ignore_bottom =
00657 (bc == rc) &&
00658 (rs <= SOLID || rs == INSET) &&
00659 (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
00660
00661 drawBorder(p, _tx + w - style->borderRightWidth(), _ty, _tx + w, _ty + h, BSRight, rc, style->color(), rs,
00662 ignore_top?0:style->borderTopWidth(),
00663 ignore_bottom?0:style->borderBottomWidth());
00664 }
00665 }
00666
00667
00668
00669 RenderFileButton::RenderFileButton(HTMLInputElementImpl *element)
00670 : RenderFormElement(element)
00671 {
00672
00673 QHBox *w = new QHBox(view()->viewport());
00674
00675 m_edit = new LineEditWidget(w);
00676
00677 connect(m_edit, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));
00678 connect(m_edit, SIGNAL(textChanged(const QString &)),this,SLOT(slotTextChanged(const QString &)));
00679
00680 m_button = new QPushButton(i18n("Browse..."), w);
00681 m_button->setFocusPolicy(QWidget::ClickFocus);
00682 connect(m_button,SIGNAL(clicked()), this, SLOT(slotClicked()));
00683 connect(m_button, SIGNAL(pressed()), this, SLOT(slotPressed()));
00684 connect(m_button, SIGNAL(released()), this, SLOT(slotReleased()));
00685
00686 w->setStretchFactor(m_edit, 2);
00687 w->setFocusProxy(m_edit);
00688
00689 setQWidget(w);
00690 m_haveFocus = false;
00691 }
00692
00693 void RenderFileButton::calcMinMaxWidth()
00694 {
00695 KHTMLAssert( !minMaxKnown() );
00696
00697 const QFontMetrics &fm = style()->fontMetrics();
00698 int size = element()->size();
00699
00700 int h = fm.lineSpacing();
00701 int w = fm.width( 'x' ) * (size > 0 ? size : 17);
00702 QSize s = m_edit->style().sizeFromContents(QStyle::CT_LineEdit, m_edit,
00703 QSize(w + 2 + 2*m_edit->frameWidth(), kMax(h, 14) + 2 + 2*m_edit->frameWidth()))
00704 .expandedTo(QApplication::globalStrut());
00705 QSize bs = m_button->sizeHint();
00706
00707 setIntrinsicWidth( s.width() + bs.width() );
00708 setIntrinsicHeight( kMax(s.height(), bs.height()) );
00709
00710 RenderFormElement::calcMinMaxWidth();
00711 }
00712
00713 void RenderFileButton::handleFocusOut()
00714 {
00715 if ( m_edit && m_edit->edited() ) {
00716 element()->onChange();
00717 m_edit->setEdited( false );
00718 }
00719 }
00720
00721 void RenderFileButton::slotClicked()
00722 {
00723 QString file_name = KFileDialog::getOpenFileName(QString::null, QString::null, 0, i18n("Browse"));
00724 if (!file_name.isNull()) {
00725 element()->m_value = DOMString(file_name);
00726 m_edit->setText(file_name);
00727 }
00728 }
00729
00730 void RenderFileButton::updateFromElement()
00731 {
00732 m_edit->blockSignals(true);
00733 m_edit->setText(element()->value().string());
00734 m_edit->blockSignals(false);
00735 int ml = element()->maxLength();
00736 if ( ml < 0 || ml > 1024 )
00737 ml = 1024;
00738 m_edit->setMaxLength( ml );
00739 m_edit->setEdited( false );
00740
00741 RenderFormElement::updateFromElement();
00742 }
00743
00744 void RenderFileButton::slotReturnPressed()
00745 {
00746 if (element()->form())
00747 element()->form()->submitFromKeyboard();
00748 }
00749
00750 void RenderFileButton::slotTextChanged(const QString &string)
00751 {
00752 element()->m_value = DOMString(string);
00753 }
00754
00755 void RenderFileButton::select()
00756 {
00757 m_edit->selectAll();
00758 }
00759
00760
00761
00762 RenderLabel::RenderLabel(HTMLGenericFormElementImpl *element)
00763 : RenderFormElement(element)
00764 {
00765
00766 }
00767
00768
00769
00770 RenderLegend::RenderLegend(HTMLGenericFormElementImpl *element)
00771 : RenderFlow(element)
00772 {
00773 setInline(false);
00774 }
00775
00776
00777
00778 ComboBoxWidget::ComboBoxWidget(QWidget *parent)
00779 : KComboBox(false, parent)
00780 {
00781 setAutoMask(true);
00782 if (listBox()) listBox()->installEventFilter(this);
00783 setMouseTracking(true);
00784 }
00785
00786 bool ComboBoxWidget::event(QEvent *e)
00787 {
00788 if (e->type()==QEvent::KeyPress)
00789 {
00790 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
00791 switch(ke->key())
00792 {
00793 case Key_Return:
00794 case Key_Enter:
00795 popup();
00796 ke->accept();
00797 return true;
00798 default:
00799 return KComboBox::event(e);
00800 }
00801 }
00802 return KComboBox::event(e);
00803 }
00804
00805 bool ComboBoxWidget::eventFilter(QObject *dest, QEvent *e)
00806 {
00807 if (dest==listBox() && e->type()==QEvent::KeyPress)
00808 {
00809 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
00810 bool forward = false;
00811 switch(ke->key())
00812 {
00813 case Key_Tab:
00814 forward=true;
00815 case Key_BackTab:
00816
00817
00818 ke = new QKeyEvent(QEvent::KeyPress, Key_Escape, 0, 0);
00819 QApplication::sendEvent(dest,ke);
00820 focusNextPrevChild(forward);
00821 delete ke;
00822 return true;
00823 default:
00824 return KComboBox::eventFilter(dest, e);
00825 }
00826 }
00827 return KComboBox::eventFilter(dest, e);
00828 }
00829
00830
00831
00832 RenderSelect::RenderSelect(HTMLSelectElementImpl *element)
00833 : RenderFormElement(element)
00834 {
00835 m_ignoreSelectEvents = false;
00836 m_multiple = element->multiple();
00837 m_size = element->size();
00838 m_useListBox = (m_multiple || m_size > 1);
00839 m_selectionChanged = true;
00840 m_optionsChanged = true;
00841
00842 if(m_useListBox)
00843 setQWidget(createListBox());
00844 else
00845 setQWidget(createComboBox());
00846 }
00847
00848 void RenderSelect::updateFromElement()
00849 {
00850 m_ignoreSelectEvents = true;
00851
00852
00853 bool oldMultiple = m_multiple;
00854 unsigned oldSize = m_size;
00855 bool oldListbox = m_useListBox;
00856
00857 m_multiple = element()->multiple();
00858 m_size = element()->size();
00859 m_useListBox = (m_multiple || m_size > 1);
00860
00861 if (oldMultiple != m_multiple || oldSize != m_size) {
00862 if (m_useListBox != oldListbox) {
00863
00864 if(m_useListBox)
00865 setQWidget(createListBox());
00866 else
00867 setQWidget(createComboBox());
00868 }
00869
00870 if (m_useListBox && oldMultiple != m_multiple) {
00871 static_cast<KListBox*>(m_widget)->setSelectionMode(m_multiple ? QListBox::Extended : QListBox::Single);
00872 }
00873 m_selectionChanged = true;
00874 m_optionsChanged = true;
00875 }
00876
00877
00878 if ( m_optionsChanged ) {
00879 if (element()->m_recalcListItems)
00880 element()->recalcListItems();
00881 QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
00882 int listIndex;
00883
00884 if(m_useListBox) {
00885 static_cast<KListBox*>(m_widget)->clear();
00886 }
00887
00888 else
00889 static_cast<KComboBox*>(m_widget)->clear();
00890
00891 for (listIndex = 0; listIndex < int(listItems.size()); listIndex++) {
00892 if (listItems[listIndex]->id() == ID_OPTGROUP) {
00893 DOMString text = listItems[listIndex]->getAttribute(ATTR_LABEL);
00894 if (text.isNull())
00895 text = "";
00896
00897 if(m_useListBox) {
00898 QListBoxText *item = new QListBoxText(QString(text.implementation()->s, text.implementation()->l));
00899 static_cast<KListBox*>(m_widget)
00900 ->insertItem(item, listIndex);
00901 item->setSelectable(false);
00902 }
00903 else
00904 static_cast<KComboBox*>(m_widget)
00905 ->insertItem(QString(text.implementation()->s, text.implementation()->l), listIndex);
00906 }
00907 else if (listItems[listIndex]->id() == ID_OPTION) {
00908 HTMLOptionElementImpl* optElem = static_cast<HTMLOptionElementImpl*>(listItems[listIndex]);
00909 QString text = optElem->text().string();
00910 if (optElem->parentNode()->id() == ID_OPTGROUP)
00911 {
00912
00913 DOMString label = optElem->getAttribute(ATTR_LABEL);
00914 if (!label.isEmpty())
00915 text = label.string();
00916 text = QString::fromLatin1(" ")+text;
00917 }
00918
00919 if(m_useListBox)
00920 static_cast<KListBox*>(m_widget)->insertItem(text, listIndex);
00921 else
00922 static_cast<KComboBox*>(m_widget)->insertItem(text, listIndex);
00923 }
00924 else
00925 KHTMLAssert(false);
00926 m_selectionChanged = true;
00927 }
00928 setMinMaxKnown(false);
00929 setLayouted(false);
00930 m_optionsChanged = false;
00931 }
00932
00933
00934 if (m_selectionChanged) {
00935 updateSelection();
00936 }
00937
00938
00939 m_ignoreSelectEvents = false;
00940
00941 RenderFormElement::updateFromElement();
00942 }
00943
00944 void RenderSelect::calcMinMaxWidth()
00945 {
00946 KHTMLAssert( !minMaxKnown() );
00947
00948 if (m_optionsChanged)
00949 updateFromElement();
00950
00951
00952 setMinMaxKnown();
00953 if ( !layouted() )
00954 layout();
00955 setLayouted( false );
00956 setMinMaxKnown( false );
00957
00958
00959 RenderFormElement::calcMinMaxWidth();
00960 }
00961
00962 void RenderSelect::layout( )
00963 {
00964 KHTMLAssert(!layouted());
00965 KHTMLAssert(minMaxKnown());
00966
00967
00968
00969
00970
00971
00972 if(m_useListBox) {
00973 KListBox* w = static_cast<KListBox*>(m_widget);
00974
00975 QListBoxItem* p = w->firstItem();
00976 int width = 0;
00977 int height = 0;
00978 while(p) {
00979 width = QMAX(width, p->width(p->listBox()));
00980 height = QMAX(height, p->height(p->listBox()));
00981 p = p->next();
00982 }
00983
00984 int size = m_size;
00985
00986
00987
00988
00989
00990 if(size < 1)
00991 size = QMIN(static_cast<KListBox*>(m_widget)->count(), 10);
00992
00993 width += 2*w->frameWidth() + w->verticalScrollBar()->sizeHint().width();
00994 height = size*height + 2*w->frameWidth();
00995
00996 setIntrinsicWidth( width );
00997 setIntrinsicHeight( height );
00998 }
00999 else {
01000 QSize s(m_widget->sizeHint());
01001 setIntrinsicWidth( s.width() );
01002 setIntrinsicHeight( s.height() );
01003 }
01004
01006 setLayouted( false );
01007 RenderFormElement::layout();
01008
01009
01010 QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
01011
01012 bool foundOption = false;
01013 for (uint i = 0; i < listItems.size() && !foundOption; i++)
01014 foundOption = (listItems[i]->id() == ID_OPTION);
01015
01016 m_widget->setEnabled(foundOption && ! element()->disabled());
01017 }
01018
01019 void RenderSelect::slotSelected(int index)
01020 {
01021 if ( m_ignoreSelectEvents ) return;
01022
01023 KHTMLAssert( !m_useListBox );
01024
01025 QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
01026 if(index >= 0 && index < int(listItems.size()))
01027 {
01028 bool found = ( listItems[index]->id() == ID_OPTION );
01029
01030 if ( !found ) {
01031
01032 while ( ( unsigned ) index < listItems.size() ) {
01033 if ( listItems[index]->id() == ID_OPTION ) {
01034 found = true;
01035 break;
01036 }
01037 ++index;
01038 }
01039
01040 if ( !found ) {
01041 while ( index >= 0 ) {
01042 if ( listItems[index]->id() == ID_OPTION ) {
01043 found = true;
01044 break;
01045 }
01046 --index;
01047 }
01048 }
01049 }
01050
01051 if ( found ) {
01052 bool changed = false;
01053
01054 for ( unsigned int i = 0; i < listItems.size(); ++i )
01055 if ( listItems[i]->id() == ID_OPTION && i != (unsigned int) index )
01056 {
01057 HTMLOptionElementImpl* opt = static_cast<HTMLOptionElementImpl*>( listItems[i] );
01058 changed |= (opt->m_selected == true);
01059 opt->m_selected = false;
01060 }
01061
01062 HTMLOptionElementImpl* opt = static_cast<HTMLOptionElementImpl*>(listItems[index]);
01063 changed |= (opt->m_selected == false);
01064 opt->m_selected = true;
01065
01066 if ( index != static_cast<ComboBoxWidget*>( m_widget )->currentItem() )
01067 static_cast<ComboBoxWidget*>( m_widget )->setCurrentItem( index );
01068
01069
01070
01071 if ( changed )
01072 {
01073 ref();
01074 element()->onChange();
01075 deref();
01076 }
01077 }
01078 }
01079 }
01080
01081
01082 void RenderSelect::slotSelectionChanged()
01083 {
01084 if ( m_ignoreSelectEvents ) return;
01085
01086
01087
01088 QMemArray<HTMLGenericFormElementImpl*> listItems = element()->m_listItems;
01089 for ( unsigned i = 0; i < listItems.count(); i++ )
01090
01091
01092 if ( listItems[i]->id() == ID_OPTION )
01093 static_cast<HTMLOptionElementImpl*>( listItems[i] )
01094 ->m_selected = static_cast<KListBox*>( m_widget )->isSelected( i );
01095
01096 ref();
01097 element()->onChange();
01098 deref();
01099 }
01100
01101 void RenderSelect::setOptionsChanged(bool _optionsChanged)
01102 {
01103 m_optionsChanged = _optionsChanged;
01104 }
01105
01106 KListBox* RenderSelect::createListBox()
01107 {
01108 KListBox *lb = new KListBox(view()->viewport());
01109 lb->setSelectionMode(m_multiple ? QListBox::Extended : QListBox::Single);
01110
01111
01112 connect( lb, SIGNAL( selectionChanged() ), this, SLOT( slotSelectionChanged() ) );
01113 connect( lb, SIGNAL( clicked( QListBoxItem * ) ), this, SLOT( slotClicked() ) );
01114 m_ignoreSelectEvents = false;
01115 lb->setMouseTracking(true);
01116
01117 return lb;
01118 }
01119
01120 ComboBoxWidget *RenderSelect::createComboBox()
01121 {
01122 ComboBoxWidget *cb = new ComboBoxWidget(view()->viewport());
01123 connect(cb, SIGNAL(activated(int)), this, SLOT(slotSelected(int)));
01124 return cb;
01125 }
01126
01127 void RenderSelect::updateSelection()
01128 {
01129 QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
01130 int i;
01131 if (m_useListBox) {
01132
01133 KListBox *listBox = static_cast<KListBox*>(m_widget);
01134 for (i = 0; i < int(listItems.size()); i++)
01135 listBox->setSelected(i,listItems[i]->id() == ID_OPTION &&
01136 static_cast<HTMLOptionElementImpl*>(listItems[i])->selected());
01137 }
01138 else {
01139 bool found = false;
01140 unsigned firstOption = listItems.size();
01141 i = listItems.size();
01142 while (i--)
01143 if (listItems[i]->id() == ID_OPTION) {
01144 if (found)
01145 static_cast<HTMLOptionElementImpl*>(listItems[i])->m_selected = false;
01146 else if (static_cast<HTMLOptionElementImpl*>(listItems[i])->selected()) {
01147 static_cast<KComboBox*>( m_widget )->setCurrentItem(i);
01148 found = true;
01149 }
01150 firstOption = i;
01151 }
01152
01153 Q_ASSERT(firstOption == listItems.size() || found);
01154 }
01155
01156 m_selectionChanged = false;
01157 }
01158
01159
01160
01161
01162 TextAreaWidget::TextAreaWidget(int wrap, QWidget* parent)
01163 : KTextEdit(parent)
01164 {
01165 if(wrap != DOM::HTMLTextAreaElementImpl::ta_NoWrap) {
01166 setWordWrap(QTextEdit::WidgetWidth);
01167 setHScrollBarMode( AlwaysOff );
01168 setVScrollBarMode( AlwaysOn );
01169 }
01170 else {
01171 setWordWrap(QTextEdit::NoWrap);
01172 setHScrollBarMode( Auto );
01173 setVScrollBarMode( Auto );
01174 }
01175 KCursor::setAutoHideCursor(viewport(), true);
01176 setTextFormat(QTextEdit::PlainText);
01177 setAutoMask(true);
01178 setMouseTracking(true);
01179 }
01180
01181 bool TextAreaWidget::event( QEvent *e )
01182 {
01183 if ( e->type() == QEvent::AccelAvailable && isReadOnly() ) {
01184 QKeyEvent* ke = (QKeyEvent*) e;
01185 if ( ke->state() & ControlButton ) {
01186 switch ( ke->key() ) {
01187 case Key_Left:
01188 case Key_Right:
01189 case Key_Up:
01190 case Key_Down:
01191 case Key_Home:
01192 case Key_End:
01193 ke->accept();
01194 default:
01195 break;
01196 }
01197 }
01198 }
01199 return KTextEdit::event( e );
01200 }
01201
01202
01203
01204 RenderTextArea::RenderTextArea(HTMLTextAreaElementImpl *element)
01205 : RenderFormElement(element)
01206 {
01207 TextAreaWidget *edit = new TextAreaWidget(element->wrap(), view());
01208 setQWidget(edit);
01209
01210 connect(edit,SIGNAL(textChanged()),this,SLOT(slotTextChanged()));
01211 }
01212
01213 RenderTextArea::~RenderTextArea()
01214 {
01215 if ( element()->m_dirtyvalue ) {
01216 element()->m_value = text();
01217 element()->m_dirtyvalue = false;
01218 }
01219 }
01220
01221 void RenderTextArea::handleFocusOut()
01222 {
01223 TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
01224 if ( w && element()->m_dirtyvalue ) {
01225 element()->m_value = text();
01226 element()->m_dirtyvalue = false;
01227 element()->onChange();
01228 }
01229 }
01230
01231 void RenderTextArea::calcMinMaxWidth()
01232 {
01233 KHTMLAssert( !minMaxKnown() );
01234
01235 TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
01236 const QFontMetrics &m = style()->fontMetrics();
01237 w->setTabStopWidth(8 * m.width(" "));
01238 QSize size( QMAX(element()->cols(), 1)*m.width('x') + w->frameWidth() +
01239 w->verticalScrollBar()->sizeHint().width(),
01240 QMAX(element()->rows(), 1)*m.lineSpacing() + w->frameWidth()*4 +
01241 (w->wordWrap() == QTextEdit::NoWrap ?
01242 w->horizontalScrollBar()->sizeHint().height() : 0)
01243 );
01244
01245 setIntrinsicWidth( size.width() );
01246 setIntrinsicHeight( size.height() );
01247
01248 RenderFormElement::calcMinMaxWidth();
01249 }
01250
01251 void RenderTextArea::updateFromElement()
01252 {
01253 TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
01254 w->setReadOnly(element()->readOnly());
01255 QString elementText = element()->value().string();
01256 if ( elementText != text() )
01257 {
01258 w->blockSignals(true);
01259 int line, col;
01260 w->getCursorPosition( &line, &col );
01261 w->setText( elementText );
01262 w->setCursorPosition( line, col );
01263 w->blockSignals(false);
01264 }
01265 element()->m_dirtyvalue = false;
01266
01267 RenderFormElement::updateFromElement();
01268 }
01269
01270 void RenderTextArea::close( )
01271 {
01272 element()->setValue( element()->defaultValue() );
01273
01274 RenderFormElement::close();
01275 }
01276
01277 QString RenderTextArea::text()
01278 {
01279 QString txt;
01280 TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
01281
01282 if(element()->wrap() == DOM::HTMLTextAreaElementImpl::ta_Physical) {
01283
01284 for (int p=0; p < w->paragraphs(); ++p) {
01285 int pl = w->paragraphLength(p);
01286 int ll = 0;
01287 int lindex = w->lineOfChar(p, 0);
01288 QString paragraphText = w->text(p);
01289 for (int l = 0; l < pl; ++l) {
01290 if (lindex != w->lineOfChar(p, l)) {
01291 paragraphText.insert(l+ll++, QString::fromLatin1("\n"));
01292 lindex = w->lineOfChar(p, l);
01293 }
01294 }
01295 txt += paragraphText;
01296 if (p < w->paragraphs() - 1)
01297 txt += QString::fromLatin1("\n");
01298 }
01299 }
01300 else
01301 txt = w->text();
01302
01303 return txt;
01304 }
01305
01306 void RenderTextArea::slotTextChanged()
01307 {
01308 element()->m_dirtyvalue = true;
01309 }
01310
01311 void RenderTextArea::select()
01312 {
01313 static_cast<TextAreaWidget *>(m_widget)->selectAll();
01314 }
01315
01316
01317
01318 #include "render_form.moc"