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