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 return popup;
00348 }
00349
00350 void LineEditWidget::extendedMenuActivated( int id)
00351 {
00352 switch ( id )
00353 {
00354 case ClearHistory:
00355 clearMenuHistory();
00356 break;
00357 default:
00358 break;
00359 }
00360 }
00361
00362 void LineEditWidget::clearMenuHistory()
00363 {
00364 emit clearCompletionHistory();
00365 }
00366
00367
00368 bool LineEditWidget::event( QEvent *e )
00369 {
00370 if ( e->type() == QEvent::AccelAvailable && isReadOnly() ) {
00371 QKeyEvent* ke = (QKeyEvent*) e;
00372 if ( ke->state() & ControlButton ) {
00373 switch ( ke->key() ) {
00374 case Key_Left:
00375 case Key_Right:
00376 case Key_Up:
00377 case Key_Down:
00378 case Key_Home:
00379 case Key_End:
00380 ke->accept();
00381 default:
00382 break;
00383 }
00384 }
00385 }
00386 else if ( e->type() == QEvent::MouseButtonPress )
00387 emit pressed();
00388 else if ( e->type() == QEvent::MouseButtonRelease )
00389 emit released();
00390 return KLineEdit::event( e );
00391 }
00392
00393
00394
00395 RenderLineEdit::RenderLineEdit(HTMLInputElementImpl *element)
00396 : RenderFormElement(element)
00397 {
00398 LineEditWidget *edit = new LineEditWidget(view()->viewport());
00399 connect(edit,SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));
00400 connect(edit,SIGNAL(textChanged(const QString &)),this,SLOT(slotTextChanged(const QString &)));
00401 connect(edit,SIGNAL(pressed()), this, SLOT(slotPressed()));
00402 connect(edit,SIGNAL(released()), this, SLOT(slotReleased()));
00403 connect(edit, SIGNAL(clearCompletionHistory()), this, SLOT( slotClearCompletionHistory()));
00404 if(element->inputType() == HTMLInputElementImpl::PASSWORD)
00405 edit->setEchoMode( QLineEdit::Password );
00406
00407 if ( element->autoComplete() ) {
00408 QStringList completions = view()->formCompletionItems(element->name().string());
00409 if (completions.count()) {
00410 edit->completionObject()->setItems(completions);
00411 edit->setContextMenuEnabled(true);
00412 }
00413 }
00414
00415 setQWidget(edit);
00416 }
00417
00418 void RenderLineEdit::slotClearCompletionHistory()
00419 {
00420 if ( element()->autoComplete() ) {
00421 view()->clearCompletionHistory(element()->name().string());
00422 static_cast<LineEditWidget*>(m_widget)->completionObject()->clear();
00423 }
00424 }
00425
00426 void RenderLineEdit::slotReturnPressed()
00427 {
00428
00429 KCompletionBox *box = widget()->completionBox(false);
00430 if ( box && box->isVisible() && box->currentItem() != -1 )
00431 return;
00432
00433
00434
00435
00436 handleFocusOut();
00437
00438 HTMLFormElementImpl* fe = element()->form();
00439 if ( fe )
00440 fe->submitFromKeyboard();
00441 }
00442
00443 void RenderLineEdit::handleFocusOut()
00444 {
00445 if ( widget() && widget()->edited() ) {
00446 element()->onChange();
00447 widget()->setEdited( false );
00448 }
00449 }
00450
00451 void RenderLineEdit::calcMinMaxWidth()
00452 {
00453 KHTMLAssert( !minMaxKnown() );
00454
00455 const QFontMetrics &fm = style()->fontMetrics();
00456 QSize s;
00457
00458 int size = element()->size();
00459
00460 int h = fm.lineSpacing();
00461 int w = fm.width( 'x' ) * (size > 0 ? size+1 : 17);
00462 s = QSize(w + 2 + 2*widget()->frameWidth(),
00463 QMAX(h, 14) + 2 + 2*widget()->frameWidth())
00464 .expandedTo(QApplication::globalStrut());
00465
00466 setIntrinsicWidth( s.width() );
00467 setIntrinsicHeight( s.height() );
00468
00469 RenderFormElement::calcMinMaxWidth();
00470 }
00471
00472 void RenderLineEdit::updateFromElement()
00473 {
00474 int ml = element()->maxLength();
00475 if ( ml < 0 || ml > 1024 )
00476 ml = 1024;
00477 if ( widget()->maxLength() != ml )
00478 widget()->setMaxLength( ml );
00479
00480 if (element()->value().string() != widget()->text()) {
00481 widget()->blockSignals(true);
00482 int pos = widget()->cursorPosition();
00483 widget()->setText(element()->value().string());
00484
00485 widget()->setEdited( false );
00486
00487 widget()->setCursorPosition(pos);
00488 widget()->blockSignals(false);
00489 }
00490 widget()->setReadOnly(element()->readOnly());
00491
00492 RenderFormElement::updateFromElement();
00493 }
00494
00495 void RenderLineEdit::slotTextChanged(const QString &string)
00496 {
00497
00498 element()->m_value = string;
00499 }
00500
00501 void RenderLineEdit::select()
00502 {
00503 static_cast<LineEditWidget*>(m_widget)->selectAll();
00504 }
00505
00506
00507
00508 RenderFieldset::RenderFieldset(HTMLGenericFormElementImpl *element)
00509 : RenderFlow(element)
00510 {
00511 }
00512
00513 bool RenderFieldset::findLegend( int &lx, int &ly, int &lw, int &lh)
00514 {
00515 RenderObject *r = this, *ref = 0;
00516 int minx = 0, curx = 0, maxw = 0;
00517 if( r->firstChild() && r->firstChild()->element() &&
00518 r->firstChild()->element()->id() == ID_LEGEND)
00519 r = r->firstChild();
00520 else
00521 return false;
00522 if(!r->firstChild() || r->isSpecial())
00523 return false;
00524 ly = r->yPos();
00525 minx = r->width();
00526 curx = r->xPos();
00527 lh = r->height();
00528 ref = r;
00529
00530 while(r) {
00531 if(r->firstChild())
00532 r = r->firstChild();
00533 else if(r->nextSibling())
00534 r = r->nextSibling();
00535 else {
00536 RenderObject *next = 0;
00537 while(!next) {
00538 r = r->parent();
00539 if(!r || r == (RenderObject *)ref ) goto end;
00540 next = r->nextSibling();
00541 }
00542 r = next;
00543 }
00544 if(r->isSpecial())
00545 continue;
00546 curx += r->xPos();
00547 if(r->width() && curx<minx)
00548 minx = curx;
00549 if(curx-minx+r->width() > maxw) {
00550 maxw = curx-minx+r->width();
00551 }
00552 if(!r->childrenInline())
00553 curx -= r->xPos();
00554 }
00555 end:
00556 lx = minx - ref->paddingLeft();
00557 lw = maxw + ref->paddingLeft() + ref->paddingRight();
00558 if(lx < 0 || lx+lw > width())
00559 return false;
00560 return !!maxw;
00561 }
00562
00563 void RenderFieldset::paintBoxDecorations(QPainter *p,int, int _y,
00564 int, int _h, int _tx, int _ty)
00565 {
00566
00567
00568 int w = width();
00569 int h = height() + borderTopExtra() + borderBottomExtra();
00570 int lx = 0, ly = 0, lw = 0, lh = 0;
00571 bool legend = findLegend(lx, ly, lw, lh);
00572
00573 if(legend) {
00574 int yOff = ly + lh/2 - borderTop()/2;
00575 h -= yOff;
00576 _ty += yOff;
00577 }
00578 _ty -= borderTopExtra();
00579
00580 int my = QMAX(_ty,_y);
00581 int end = QMIN( _y + _h, _ty + h );
00582 int mh = end - my;
00583
00584 paintBackground(p, style()->backgroundColor(), style()->backgroundImage(), my, mh, _tx, _ty, w, h);
00585
00586 if ( style()->hasBorder() ) {
00587 if ( legend )
00588 paintBorderMinusLegend(p, _tx, _ty, w, h, style(), lx, lw);
00589 else
00590 paintBorder(p, _tx, _ty, w, h, style());
00591 }
00592 }
00593
00594 void RenderFieldset::paintBorderMinusLegend(QPainter *p, int _tx, int _ty, int w, int h,
00595 const RenderStyle* style, int lx, int lw)
00596 {
00597
00598 const QColor& tc = style->borderTopColor();
00599 const QColor& bc = style->borderBottomColor();
00600
00601 EBorderStyle ts = style->borderTopStyle();
00602 EBorderStyle bs = style->borderBottomStyle();
00603 EBorderStyle ls = style->borderLeftStyle();
00604 EBorderStyle rs = style->borderRightStyle();
00605
00606 bool render_t = ts > BHIDDEN;
00607 bool render_l = ls > BHIDDEN;
00608 bool render_r = rs > BHIDDEN;
00609 bool render_b = bs > BHIDDEN;
00610
00611 if(render_t) {
00612 drawBorder(p, _tx, _ty, _tx + lx, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
00613 (render_l && ls<=DOUBLE?style->borderLeftWidth():0), 0);
00614 drawBorder(p, _tx+lx+lw, _ty, _tx + w, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
00615 0, (render_r && rs<=DOUBLE?style->borderRightWidth():0));
00616 }
00617
00618 if(render_b)
00619 drawBorder(p, _tx, _ty + h - style->borderBottomWidth(), _tx + w, _ty + h, BSBottom, bc, style->color(), bs,
00620 (render_l && ls<=DOUBLE?style->borderLeftWidth():0),
00621 (render_r && rs<=DOUBLE?style->borderRightWidth():0));
00622
00623 if(render_l)
00624 {
00625 const QColor& lc = style->borderLeftColor();
00626
00627 bool ignore_top =
00628 (tc == lc) &&
00629 (ls <= OUTSET) &&
00630 (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
00631
00632 bool ignore_bottom =
00633 (bc == lc) &&
00634 (ls <= OUTSET) &&
00635 (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
00636
00637 drawBorder(p, _tx, _ty, _tx + style->borderLeftWidth(), _ty + h, BSLeft, lc, style->color(), ls,
00638 ignore_top?0:style->borderTopWidth(),
00639 ignore_bottom?0:style->borderBottomWidth());
00640 }
00641
00642 if(render_r)
00643 {
00644 const QColor& rc = style->borderRightColor();
00645
00646 bool ignore_top =
00647 (tc == rc) &&
00648 (rs <= SOLID || rs == INSET) &&
00649 (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
00650
00651 bool ignore_bottom =
00652 (bc == rc) &&
00653 (rs <= SOLID || rs == INSET) &&
00654 (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
00655
00656 drawBorder(p, _tx + w - style->borderRightWidth(), _ty, _tx + w, _ty + h, BSRight, rc, style->color(), rs,
00657 ignore_top?0:style->borderTopWidth(),
00658 ignore_bottom?0:style->borderBottomWidth());
00659 }
00660 }
00661
00662
00663
00664 RenderFileButton::RenderFileButton(HTMLInputElementImpl *element)
00665 : RenderFormElement(element)
00666 {
00667
00668 QHBox *w = new QHBox(view()->viewport());
00669
00670 m_edit = new LineEditWidget(w);
00671
00672 connect(m_edit, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));
00673 connect(m_edit, SIGNAL(textChanged(const QString &)),this,SLOT(slotTextChanged(const QString &)));
00674
00675 m_button = new QPushButton(i18n("Browse..."), w);
00676 m_button->setFocusPolicy(QWidget::ClickFocus);
00677 connect(m_button,SIGNAL(clicked()), this, SLOT(slotClicked()));
00678 connect(m_button, SIGNAL(pressed()), this, SLOT(slotPressed()));
00679 connect(m_button, SIGNAL(released()), this, SLOT(slotReleased()));
00680
00681 w->setStretchFactor(m_edit, 2);
00682 w->setFocusProxy(m_edit);
00683
00684 setQWidget(w);
00685 m_haveFocus = false;
00686 }
00687
00688 void RenderFileButton::calcMinMaxWidth()
00689 {
00690 KHTMLAssert( !minMaxKnown() );
00691
00692 const QFontMetrics &fm = style()->fontMetrics();
00693 int size = element()->size();
00694
00695 int h = fm.lineSpacing();
00696 int w = fm.width( 'x' ) * (size > 0 ? size : 17);
00697 QSize s = m_edit->style().sizeFromContents(QStyle::CT_LineEdit, m_edit,
00698 QSize(w + 2 + 2*m_edit->frameWidth(), kMax(h, 14) + 2 + 2*m_edit->frameWidth()))
00699 .expandedTo(QApplication::globalStrut());
00700 QSize bs = m_button->sizeHint();
00701
00702 setIntrinsicWidth( s.width() + bs.width() );
00703 setIntrinsicHeight( kMax(s.height(), bs.height()) );
00704
00705 RenderFormElement::calcMinMaxWidth();
00706 }
00707
00708 void RenderFileButton::handleFocusOut()
00709 {
00710 if ( m_edit && m_edit->edited() ) {
00711 element()->onChange();
00712 m_edit->setEdited( false );
00713 }
00714 }
00715
00716 void RenderFileButton::slotClicked()
00717 {
00718 QString file_name = KFileDialog::getOpenFileName(QString::null, QString::null, 0, i18n("Browse"));
00719 if (!file_name.isNull()) {
00720 element()->m_value = DOMString(file_name);
00721 m_edit->setText(file_name);
00722 }
00723 }
00724
00725 void RenderFileButton::updateFromElement()
00726 {
00727 m_edit->blockSignals(true);
00728 m_edit->setText(element()->value().string());
00729 m_edit->blockSignals(false);
00730 int ml = element()->maxLength();
00731 if ( ml < 0 || ml > 1024 )
00732 ml = 1024;
00733 m_edit->setMaxLength( ml );
00734 m_edit->setEdited( false );
00735
00736 RenderFormElement::updateFromElement();
00737 }
00738
00739 void RenderFileButton::slotReturnPressed()
00740 {
00741 if (element()->form())
00742 element()->form()->submitFromKeyboard();
00743 }
00744
00745 void RenderFileButton::slotTextChanged(const QString &string)
00746 {
00747 element()->m_value = DOMString(string);
00748 }
00749
00750 void RenderFileButton::select()
00751 {
00752 m_edit->selectAll();
00753 }
00754
00755
00756
00757 RenderLabel::RenderLabel(HTMLGenericFormElementImpl *element)
00758 : RenderFormElement(element)
00759 {
00760
00761 }
00762
00763
00764
00765 RenderLegend::RenderLegend(HTMLGenericFormElementImpl *element)
00766 : RenderFlow(element)
00767 {
00768 setInline(false);
00769 }
00770
00771
00772
00773 ComboBoxWidget::ComboBoxWidget(QWidget *parent)
00774 : KComboBox(false, parent)
00775 {
00776 setAutoMask(true);
00777 if (listBox()) listBox()->installEventFilter(this);
00778 setMouseTracking(true);
00779 }
00780
00781 bool ComboBoxWidget::event(QEvent *e)
00782 {
00783 if (e->type()==QEvent::KeyPress)
00784 {
00785 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
00786 switch(ke->key())
00787 {
00788 case Key_Return:
00789 case Key_Enter:
00790 popup();
00791 ke->accept();
00792 return true;
00793 default:
00794 return KComboBox::event(e);
00795 }
00796 }
00797 return KComboBox::event(e);
00798 }
00799
00800 bool ComboBoxWidget::eventFilter(QObject *dest, QEvent *e)
00801 {
00802 if (dest==listBox() && e->type()==QEvent::KeyPress)
00803 {
00804 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
00805 bool forward = false;
00806 switch(ke->key())
00807 {
00808 case Key_Tab:
00809 forward=true;
00810 case Key_BackTab:
00811
00812
00813 ke = new QKeyEvent(QEvent::KeyPress, Key_Escape, 0, 0);
00814 QApplication::sendEvent(dest,ke);
00815 focusNextPrevChild(forward);
00816 delete ke;
00817 return true;
00818 default:
00819 return KComboBox::eventFilter(dest, e);
00820 }
00821 }
00822 return KComboBox::eventFilter(dest, e);
00823 }
00824
00825
00826
00827 RenderSelect::RenderSelect(HTMLSelectElementImpl *element)
00828 : RenderFormElement(element)
00829 {
00830 m_ignoreSelectEvents = false;
00831 m_multiple = element->multiple();
00832 m_size = element->size();
00833 m_useListBox = (m_multiple || m_size > 1);
00834 m_selectionChanged = true;
00835 m_optionsChanged = true;
00836
00837 if(m_useListBox)
00838 setQWidget(createListBox());
00839 else
00840 setQWidget(createComboBox());
00841 }
00842
00843 void RenderSelect::updateFromElement()
00844 {
00845 m_ignoreSelectEvents = true;
00846
00847
00848 bool oldMultiple = m_multiple;
00849 unsigned oldSize = m_size;
00850 bool oldListbox = m_useListBox;
00851
00852 m_multiple = element()->multiple();
00853 m_size = element()->size();
00854 m_useListBox = (m_multiple || m_size > 1);
00855
00856 if (oldMultiple != m_multiple || oldSize != m_size) {
00857 if (m_useListBox != oldListbox) {
00858
00859 if(m_useListBox)
00860 setQWidget(createListBox());
00861 else
00862 setQWidget(createComboBox());
00863 }
00864
00865 if (m_useListBox && oldMultiple != m_multiple) {
00866 static_cast<KListBox*>(m_widget)->setSelectionMode(m_multiple ? QListBox::Extended : QListBox::Single);
00867 }
00868 m_selectionChanged = true;
00869 m_optionsChanged = true;
00870 }
00871
00872
00873 if ( m_optionsChanged ) {
00874 if (element()->m_recalcListItems)
00875 element()->recalcListItems();
00876 QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
00877 int listIndex;
00878
00879 if(m_useListBox) {
00880 static_cast<KListBox*>(m_widget)->clear();
00881 }
00882
00883 else
00884 static_cast<KComboBox*>(m_widget)->clear();
00885
00886 for (listIndex = 0; listIndex < int(listItems.size()); listIndex++) {
00887 if (listItems[listIndex]->id() == ID_OPTGROUP) {
00888 DOMString text = listItems[listIndex]->getAttribute(ATTR_LABEL);
00889 if (text.isNull())
00890 text = "";
00891
00892 if(m_useListBox) {
00893 QListBoxText *item = new QListBoxText(QString(text.implementation()->s, text.implementation()->l));
00894 static_cast<KListBox*>(m_widget)
00895 ->insertItem(item, listIndex);
00896 item->setSelectable(false);
00897 }
00898 else
00899 static_cast<KComboBox*>(m_widget)
00900 ->insertItem(QString(text.implementation()->s, text.implementation()->l), listIndex);
00901 }
00902 else if (listItems[listIndex]->id() == ID_OPTION) {
00903 HTMLOptionElementImpl* optElem = static_cast<HTMLOptionElementImpl*>(listItems[listIndex]);
00904 QString text = optElem->text().string();
00905 if (optElem->parentNode()->id() == ID_OPTGROUP)
00906 {
00907
00908 DOMString label = optElem->getAttribute(ATTR_LABEL);
00909 if (!label.isEmpty())
00910 text = label.string();
00911 text = QString::fromLatin1(" ")+text;
00912 }
00913
00914 if(m_useListBox)
00915 static_cast<KListBox*>(m_widget)->insertItem(text, listIndex);
00916 else
00917 static_cast<KComboBox*>(m_widget)->insertItem(text, listIndex);
00918 }
00919 else
00920 KHTMLAssert(false);
00921 m_selectionChanged = true;
00922 }
00923 setMinMaxKnown(false);
00924 setLayouted(false);
00925 m_optionsChanged = false;
00926 }
00927
00928
00929 if (m_selectionChanged) {
00930 updateSelection();
00931 }
00932
00933
00934 m_ignoreSelectEvents = false;
00935
00936 RenderFormElement::updateFromElement();
00937 }
00938
00939 void RenderSelect::calcMinMaxWidth()
00940 {
00941 KHTMLAssert( !minMaxKnown() );
00942
00943 if (m_optionsChanged)
00944 updateFromElement();
00945
00946
00947 setMinMaxKnown();
00948 if ( !layouted() )
00949 layout();
00950 setLayouted( false );
00951 setMinMaxKnown( false );
00952
00953
00954 RenderFormElement::calcMinMaxWidth();
00955 }
00956
00957 void RenderSelect::layout( )
00958 {
00959 KHTMLAssert(!layouted());
00960 KHTMLAssert(minMaxKnown());
00961
00962
00963
00964
00965
00966
00967 if(m_useListBox) {
00968 KListBox* w = static_cast<KListBox*>(m_widget);
00969
00970 QListBoxItem* p = w->firstItem();
00971 int width = 0;
00972 int height = 0;
00973 while(p) {
00974 width = QMAX(width, p->width(p->listBox()));
00975 height = QMAX(height, p->height(p->listBox()));
00976 p = p->next();
00977 }
00978
00979 int size = m_size;
00980
00981
00982
00983
00984
00985 if(size < 1)
00986 size = QMIN(static_cast<KListBox*>(m_widget)->count(), 10);
00987
00988 width += 2*w->frameWidth() + w->verticalScrollBar()->sizeHint().width();
00989 height = size*height + 2*w->frameWidth();
00990
00991 setIntrinsicWidth( width );
00992 setIntrinsicHeight( height );
00993 }
00994 else {
00995 QSize s(m_widget->sizeHint());
00996 setIntrinsicWidth( s.width() );
00997 setIntrinsicHeight( s.height() );
00998 }
00999
01001 setLayouted( false );
01002 RenderFormElement::layout();
01003
01004
01005 QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
01006
01007 bool foundOption = false;
01008 for (uint i = 0; i < listItems.size() && !foundOption; i++)
01009 foundOption = (listItems[i]->id() == ID_OPTION);
01010
01011 m_widget->setEnabled(foundOption && ! element()->disabled());
01012 }
01013
01014 void RenderSelect::slotSelected(int index)
01015 {
01016 if ( m_ignoreSelectEvents ) return;
01017
01018 KHTMLAssert( !m_useListBox );
01019
01020 QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
01021 if(index >= 0 && index < int(listItems.size()))
01022 {
01023 bool found = ( listItems[index]->id() == ID_OPTION );
01024
01025 if ( !found ) {
01026
01027 while ( ( unsigned ) index < listItems.size() ) {
01028 if ( listItems[index]->id() == ID_OPTION ) {
01029 found = true;
01030 break;
01031 }
01032 ++index;
01033 }
01034
01035 if ( !found ) {
01036 while ( index >= 0 ) {
01037 if ( listItems[index]->id() == ID_OPTION ) {
01038 found = true;
01039 break;
01040 }
01041 --index;
01042 }
01043 }
01044 }
01045
01046 if ( found ) {
01047 bool changed = false;
01048
01049 for ( unsigned int i = 0; i < listItems.size(); ++i )
01050 if ( listItems[i]->id() == ID_OPTION && i != (unsigned int) index )
01051 {
01052 HTMLOptionElementImpl* opt = static_cast<HTMLOptionElementImpl*>( listItems[i] );
01053 changed |= (opt->m_selected == true);
01054 opt->m_selected = false;
01055 }
01056
01057 HTMLOptionElementImpl* opt = static_cast<HTMLOptionElementImpl*>(listItems[index]);
01058 changed |= (opt->m_selected == false);
01059 opt->m_selected = true;
01060
01061 if ( index != static_cast<ComboBoxWidget*>( m_widget )->currentItem() )
01062 static_cast<ComboBoxWidget*>( m_widget )->setCurrentItem( index );
01063
01064
01065
01066 if ( changed )
01067 {
01068 ref();
01069 element()->onChange();
01070 deref();
01071 }
01072 }
01073 }
01074 }
01075
01076
01077 void RenderSelect::slotSelectionChanged()
01078 {
01079 if ( m_ignoreSelectEvents ) return;
01080
01081
01082
01083 QMemArray<HTMLGenericFormElementImpl*> listItems = element()->m_listItems;
01084 for ( unsigned i = 0; i < listItems.count(); i++ )
01085
01086
01087 if ( listItems[i]->id() == ID_OPTION )
01088 static_cast<HTMLOptionElementImpl*>( listItems[i] )
01089 ->m_selected = static_cast<KListBox*>( m_widget )->isSelected( i );
01090
01091 ref();
01092 element()->onChange();
01093 deref();
01094 }
01095
01096 void RenderSelect::setOptionsChanged(bool _optionsChanged)
01097 {
01098 m_optionsChanged = _optionsChanged;
01099 }
01100
01101 KListBox* RenderSelect::createListBox()
01102 {
01103 KListBox *lb = new KListBox(view()->viewport());
01104 lb->setSelectionMode(m_multiple ? QListBox::Extended : QListBox::Single);
01105
01106
01107 connect( lb, SIGNAL( selectionChanged() ), this, SLOT( slotSelectionChanged() ) );
01108 connect( lb, SIGNAL( clicked( QListBoxItem * ) ), this, SLOT( slotClicked() ) );
01109 m_ignoreSelectEvents = false;
01110 lb->setMouseTracking(true);
01111
01112 return lb;
01113 }
01114
01115 ComboBoxWidget *RenderSelect::createComboBox()
01116 {
01117 ComboBoxWidget *cb = new ComboBoxWidget(view()->viewport());
01118 connect(cb, SIGNAL(activated(int)), this, SLOT(slotSelected(int)));
01119 return cb;
01120 }
01121
01122 void RenderSelect::updateSelection()
01123 {
01124 QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
01125 int i;
01126 if (m_useListBox) {
01127
01128 KListBox *listBox = static_cast<KListBox*>(m_widget);
01129 for (i = 0; i < int(listItems.size()); i++)
01130 listBox->setSelected(i,listItems[i]->id() == ID_OPTION &&
01131 static_cast<HTMLOptionElementImpl*>(listItems[i])->selected());
01132 }
01133 else {
01134 bool found = false;
01135 unsigned firstOption = listItems.size();
01136 i = listItems.size();
01137 while (i--)
01138 if (listItems[i]->id() == ID_OPTION) {
01139 if (found)
01140 static_cast<HTMLOptionElementImpl*>(listItems[i])->m_selected = false;
01141 else if (static_cast<HTMLOptionElementImpl*>(listItems[i])->selected()) {
01142 static_cast<KComboBox*>( m_widget )->setCurrentItem(i);
01143 found = true;
01144 }
01145 firstOption = i;
01146 }
01147
01148 Q_ASSERT(firstOption == listItems.size() || found);
01149 }
01150
01151 m_selectionChanged = false;
01152 }
01153
01154
01155
01156
01157 TextAreaWidget::TextAreaWidget(int wrap, QWidget* parent)
01158 : KTextEdit(parent)
01159 {
01160 if(wrap != DOM::HTMLTextAreaElementImpl::ta_NoWrap) {
01161 setWordWrap(QTextEdit::WidgetWidth);
01162 setHScrollBarMode( AlwaysOff );
01163 setVScrollBarMode( AlwaysOn );
01164 }
01165 else {
01166 setWordWrap(QTextEdit::NoWrap);
01167 setHScrollBarMode( Auto );
01168 setVScrollBarMode( Auto );
01169 }
01170 KCursor::setAutoHideCursor(viewport(), true);
01171 setTextFormat(QTextEdit::PlainText);
01172 setAutoMask(true);
01173 setMouseTracking(true);
01174 }
01175
01176 bool TextAreaWidget::event( QEvent *e )
01177 {
01178 if ( e->type() == QEvent::AccelAvailable && isReadOnly() ) {
01179 QKeyEvent* ke = (QKeyEvent*) e;
01180 if ( ke->state() & ControlButton ) {
01181 switch ( ke->key() ) {
01182 case Key_Left:
01183 case Key_Right:
01184 case Key_Up:
01185 case Key_Down:
01186 case Key_Home:
01187 case Key_End:
01188 ke->accept();
01189 default:
01190 break;
01191 }
01192 }
01193 }
01194 return KTextEdit::event( e );
01195 }
01196
01197
01198
01199 RenderTextArea::RenderTextArea(HTMLTextAreaElementImpl *element)
01200 : RenderFormElement(element)
01201 {
01202 TextAreaWidget *edit = new TextAreaWidget(element->wrap(), view());
01203 setQWidget(edit);
01204
01205 connect(edit,SIGNAL(textChanged()),this,SLOT(slotTextChanged()));
01206 }
01207
01208 RenderTextArea::~RenderTextArea()
01209 {
01210 if ( element()->m_dirtyvalue ) {
01211 element()->m_value = text();
01212 element()->m_dirtyvalue = false;
01213 }
01214 }
01215
01216 void RenderTextArea::handleFocusOut()
01217 {
01218 TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
01219 if ( w && element()->m_dirtyvalue ) {
01220 element()->m_value = text();
01221 element()->m_dirtyvalue = false;
01222 element()->onChange();
01223 }
01224 }
01225
01226 void RenderTextArea::calcMinMaxWidth()
01227 {
01228 KHTMLAssert( !minMaxKnown() );
01229
01230 TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
01231 const QFontMetrics &m = style()->fontMetrics();
01232 w->setTabStopWidth(8 * m.width(" "));
01233 QSize size( QMAX(element()->cols(), 1)*m.width('x') + w->frameWidth() +
01234 w->verticalScrollBar()->sizeHint().width(),
01235 QMAX(element()->rows(), 1)*m.height() + w->frameWidth()*2 +
01236 (w->wordWrap() == QTextEdit::NoWrap ?
01237 w->horizontalScrollBar()->sizeHint().height() : 0)
01238 );
01239
01240 setIntrinsicWidth( size.width() );
01241 setIntrinsicHeight( size.height() );
01242
01243 RenderFormElement::calcMinMaxWidth();
01244 }
01245
01246 void RenderTextArea::updateFromElement()
01247 {
01248 TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
01249 w->setReadOnly(element()->readOnly());
01250 QString elementText = element()->value().string();
01251 if ( elementText != text() )
01252 {
01253 w->blockSignals(true);
01254 int line, col;
01255 w->getCursorPosition( &line, &col );
01256 w->setText( elementText );
01257 w->setCursorPosition( line, col );
01258 w->blockSignals(false);
01259 }
01260 element()->m_dirtyvalue = false;
01261
01262 RenderFormElement::updateFromElement();
01263 }
01264
01265 void RenderTextArea::close( )
01266 {
01267 element()->setValue( element()->defaultValue() );
01268
01269 RenderFormElement::close();
01270 }
01271
01272 QString RenderTextArea::text()
01273 {
01274 QString txt;
01275 TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
01276
01277 if(element()->wrap() == DOM::HTMLTextAreaElementImpl::ta_Physical) {
01278
01279 for (int p=0; p < w->paragraphs(); ++p) {
01280 int pl = w->paragraphLength(p);
01281 int ll = 0;
01282 int lindex = w->lineOfChar(p, 0);
01283 QString paragraphText = w->text(p);
01284 for (int l = 0; l < pl; ++l) {
01285 if (lindex != w->lineOfChar(p, l)) {
01286 paragraphText.insert(l+ll++, QString::fromLatin1("\n"));
01287 lindex = w->lineOfChar(p, l);
01288 }
01289 }
01290 txt += paragraphText;
01291 if (p < w->paragraphs() - 1)
01292 txt += QString::fromLatin1("\n");
01293 }
01294 }
01295 else
01296 txt = w->text();
01297
01298 return txt;
01299 }
01300
01301 void RenderTextArea::slotTextChanged()
01302 {
01303 element()->m_dirtyvalue = true;
01304 }
01305
01306 void RenderTextArea::select()
01307 {
01308 static_cast<TextAreaWidget *>(m_widget)->selectAll();
01309 }
01310
01311
01312
01313 #include "render_form.moc"