From dfe289850f068f19ba4a83ab4e7e22a7e09c13c9 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sat, 26 Jan 2013 13:17:21 -0600 Subject: Rename a number of libraries and executables to avoid conflicts with KDE4 --- tdehtml/rendering/render_form.cpp | 1914 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1914 insertions(+) create mode 100644 tdehtml/rendering/render_form.cpp (limited to 'tdehtml/rendering/render_form.cpp') diff --git a/tdehtml/rendering/render_form.cpp b/tdehtml/rendering/render_form.cpp new file mode 100644 index 000000000..7fe009a7f --- /dev/null +++ b/tdehtml/rendering/render_form.cpp @@ -0,0 +1,1914 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2000 Dirk Mueller (mueller@kde.org) + * (C) 2006 Maksim Orlovich (maksim@kde.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "misc/helper.h" +#include "xml/dom2_eventsimpl.h" +#include "html/html_formimpl.h" +#include "misc/htmlhashes.h" + +#include "rendering/render_form.h" +#include + +#include "tdehtmlview.h" +#include "tdehtml_ext.h" +#include "xml/dom_docimpl.h" + +#include +#include + +using namespace tdehtml; + +RenderFormElement::RenderFormElement(HTMLGenericFormElementImpl *element) + : RenderWidget(element) +{ + // init RenderObject attributes + setInline(true); // our object is Inline + + m_state = 0; +} + +RenderFormElement::~RenderFormElement() +{ +} + +short RenderFormElement::baselinePosition( bool f ) const +{ + return RenderWidget::baselinePosition( f ) - 2 - style()->fontMetrics().descent(); +} + +void RenderFormElement::updateFromElement() +{ + m_widget->setEnabled(!element()->disabled()); + RenderWidget::updateFromElement(); +} + +void RenderFormElement::layout() +{ + KHTMLAssert( needsLayout() ); + KHTMLAssert( minMaxKnown() ); + + // minimum height + m_height = 0; + + calcWidth(); + calcHeight(); + + if ( m_widget ) + resizeWidget(m_width-borderLeft()-borderRight()-paddingLeft()-paddingRight(), + m_height-borderTop()-borderBottom()-paddingTop()-paddingBottom()); + + setNeedsLayout(false); +} + +TQ_Alignment RenderFormElement::textAlignment() const +{ + switch (style()->textAlign()) { + case LEFT: + case KHTML_LEFT: + return Qt::AlignLeft; + case RIGHT: + case KHTML_RIGHT: + return Qt::AlignRight; + case CENTER: + case KHTML_CENTER: + return Qt::AlignHCenter; + case JUSTIFY: + // Just fall into the auto code for justify. + case TAAUTO: + return style()->direction() == RTL ? Qt::AlignRight : Qt::AlignLeft; + } + assert(false); // Should never be reached. + return Qt::AlignLeft; +} + +// ------------------------------------------------------------------------- + +RenderButton::RenderButton(HTMLGenericFormElementImpl *element) + : RenderFormElement(element) +{ +} + +short RenderButton::baselinePosition( bool f ) const +{ + return RenderWidget::baselinePosition( f ) - 2; +} + +// ------------------------------------------------------------------------------- + + +RenderCheckBox::RenderCheckBox(HTMLInputElementImpl *element) + : RenderButton(element) +{ + TQCheckBox* b = new TQCheckBox(view()->viewport(), "__tdehtml"); + b->setAutoMask(true); + b->setMouseTracking(true); + setQWidget(b); + + // prevent firing toggled() signals on initialization + b->setChecked(element->checked()); + + connect(b,TQT_SIGNAL(stateChanged(int)),this,TQT_SLOT(slotStateChanged(int))); +} + + +void RenderCheckBox::calcMinMaxWidth() +{ + KHTMLAssert( !minMaxKnown() ); + + TQCheckBox *cb = static_cast( m_widget ); + TQSize s( cb->style().pixelMetric( TQStyle::PM_IndicatorWidth ), + cb->style().pixelMetric( TQStyle::PM_IndicatorHeight ) ); + setIntrinsicWidth( s.width() ); + setIntrinsicHeight( s.height() ); + + RenderButton::calcMinMaxWidth(); +} + +void RenderCheckBox::updateFromElement() +{ + widget()->setChecked(element()->checked()); + + RenderButton::updateFromElement(); +} + +void RenderCheckBox::slotStateChanged(int state) +{ + element()->setChecked(state == TQButton::On); + element()->setIndeterminate(state == TQButton::NoChange); + + ref(); + element()->onChange(); + deref(); +} + +// ------------------------------------------------------------------------------- + +RenderRadioButton::RenderRadioButton(HTMLInputElementImpl *element) + : RenderButton(element) +{ + TQRadioButton* b = new TQRadioButton(view()->viewport(), "__tdehtml"); + b->setMouseTracking(true); + setQWidget(b); + + // prevent firing toggled() signals on initialization + b->setChecked(element->checked()); + + connect(b,TQT_SIGNAL(toggled(bool)),this,TQT_SLOT(slotToggled(bool))); +} + +void RenderRadioButton::updateFromElement() +{ + widget()->setChecked(element()->checked()); + + RenderButton::updateFromElement(); +} + +void RenderRadioButton::calcMinMaxWidth() +{ + KHTMLAssert( !minMaxKnown() ); + + TQRadioButton *rb = static_cast( m_widget ); + TQSize s( rb->style().pixelMetric( TQStyle::PM_ExclusiveIndicatorWidth ), + rb->style().pixelMetric( TQStyle::PM_ExclusiveIndicatorHeight ) ); + setIntrinsicWidth( s.width() ); + setIntrinsicHeight( s.height() ); + + RenderButton::calcMinMaxWidth(); +} + +void RenderRadioButton::slotToggled(bool activated) +{ + if(activated) { + ref(); + element()->onChange(); + deref(); + } +} + +// ------------------------------------------------------------------------------- + + +RenderSubmitButton::RenderSubmitButton(HTMLInputElementImpl *element) + : RenderButton(element) +{ + TQPushButton* p = new TQPushButton(view()->viewport(), "__tdehtml"); + setQWidget(p); + p->setAutoMask(true); + p->setMouseTracking(true); +} + +TQString RenderSubmitButton::rawText() +{ + TQString value = element()->valueWithDefault().string(); + value = value.stripWhiteSpace(); + TQString raw; + for(unsigned int i = 0; i < value.length(); i++) { + raw += value[i]; + if(value[i] == '&') + raw += '&'; + } + return raw; +} + +void RenderSubmitButton::calcMinMaxWidth() +{ + KHTMLAssert( !minMaxKnown() ); + + TQString raw = rawText(); + TQPushButton* pb = static_cast(m_widget); + pb->setText(raw); + pb->setFont(style()->font()); + + bool empty = raw.isEmpty(); + if ( empty ) + raw = TQString::fromLatin1("X"); + TQFontMetrics fm = pb->fontMetrics(); + TQSize ts = fm.size( ShowPrefix, raw); + TQSize s(pb->style().tqsizeFromContents( TQStyle::CT_PushButton, pb, ts ) + .expandedTo(TQApplication::globalStrut())); + int margin = pb->style().pixelMetric( TQStyle::PM_ButtonMargin, pb) + + pb->style().pixelMetric( TQStyle::PM_DefaultFrameWidth, pb ) * 2; + int w = ts.width() + margin; + int h = s.height(); + if (pb->isDefault() || pb->autoDefault()) { + int dbw = pb->style().pixelMetric( TQStyle::PM_ButtonDefaultIndicator, pb ) * 2; + w += dbw; + } + + // add 30% margins to the width (heuristics to make it look similar to IE) + s = TQSize( w*13/10, h ).expandedTo(TQApplication::globalStrut()); + + setIntrinsicWidth( s.width() ); + setIntrinsicHeight( s.height() ); + + RenderButton::calcMinMaxWidth(); +} + +void RenderSubmitButton::updateFromElement() +{ + TQString oldText = static_cast(m_widget)->text(); + TQString newText = rawText(); + static_cast(m_widget)->setText(newText); + if ( oldText != newText ) + setNeedsLayoutAndMinMaxRecalc(); + RenderFormElement::updateFromElement(); +} + +short RenderSubmitButton::baselinePosition( bool f ) const +{ + return RenderFormElement::baselinePosition( f ); +} + +// ------------------------------------------------------------------------------- + +RenderResetButton::RenderResetButton(HTMLInputElementImpl *element) + : RenderSubmitButton(element) +{ +} + +// ------------------------------------------------------------------------------- + +LineEditWidget::LineEditWidget(DOM::HTMLInputElementImpl* input, KHTMLView* view, TQWidget* parent) + : KLineEdit(parent, "__tdehtml"), m_input(input), m_view(view), m_spell(0) +{ + setMouseTracking(true); + KActionCollection *ac = new KActionCollection(this); + m_spellAction = KStdAction::spelling( TQT_TQOBJECT(this), TQT_SLOT( slotCheckSpelling() ), ac ); +} + +LineEditWidget::~LineEditWidget() +{ + delete m_spell; + m_spell = 0L; +} + +void LineEditWidget::slotCheckSpelling() +{ + if ( text().isEmpty() ) { + return; + } + + delete m_spell; + m_spell = new KSpell( this, i18n( "Spell Checking" ), TQT_TQOBJECT(this), TQT_SLOT( slotSpellCheckReady( KSpell *) ), 0, true, true); + + connect( m_spell, TQT_SIGNAL( death() ),this, TQT_SLOT( spellCheckerFinished() ) ); + connect( m_spell, TQT_SIGNAL( misspelling( const TQString &, const TQStringList &, unsigned int ) ),this, TQT_SLOT( spellCheckerMisspelling( const TQString &, const TQStringList &, unsigned int ) ) ); + connect( m_spell, TQT_SIGNAL( corrected( const TQString &, const TQString &, unsigned int ) ),this, TQT_SLOT( spellCheckerCorrected( const TQString &, const TQString &, unsigned int ) ) ); +} + +void LineEditWidget::spellCheckerMisspelling( const TQString &_text, const TQStringList &, unsigned int pos) +{ + highLightWord( _text.length(),pos ); +} + +void LineEditWidget::highLightWord( unsigned int length, unsigned int pos ) +{ + setSelection ( pos, length ); +} + +void LineEditWidget::spellCheckerCorrected( const TQString &old, const TQString &corr, unsigned int pos ) +{ + if( old!= corr ) + { + setSelection ( pos, old.length() ); + insert( corr ); + setSelection ( pos, corr.length() ); + } +} + +void LineEditWidget::spellCheckerFinished() +{ +} + +void LineEditWidget::slotSpellCheckReady( KSpell *s ) +{ + s->check( text() ); + connect( s, TQT_SIGNAL( done( const TQString & ) ), this, TQT_SLOT( slotSpellCheckDone( const TQString & ) ) ); +} + +void LineEditWidget::slotSpellCheckDone( const TQString &s ) +{ + if( s != text() ) + setText( s ); +} + + +TQPopupMenu *LineEditWidget::createPopupMenu() +{ + TQPopupMenu *popup = KLineEdit::createPopupMenu(); + + if ( !popup ) { + return 0L; + } + + connect( popup, TQT_SIGNAL( activated( int ) ), + this, TQT_SLOT( extendedMenuActivated( int ) ) ); + + if (m_input->autoComplete()) { + popup->insertSeparator(); + int id = popup->insertItem( SmallIconSet("edit"), i18n("&Edit History..."), EditHistory ); + popup->setItemEnabled( id, (compObj() && !compObj()->isEmpty()) ); + id = popup->insertItem( SmallIconSet("history_clear"), i18n("Clear &History"), ClearHistory ); + popup->setItemEnabled( id, (compObj() && !compObj()->isEmpty()) ); + } + + if (echoMode() == TQLineEdit::Normal && + !isReadOnly()) { + popup->insertSeparator(); + + m_spellAction->plug(popup); + m_spellAction->setEnabled( !text().isEmpty() ); + } + + return popup; +} + + +void LineEditWidget::extendedMenuActivated( int id) +{ + switch ( id ) + { + case ClearHistory: + m_view->clearCompletionHistory(m_input->name().string()); + if (compObj()) + compObj()->clear(); + case EditHistory: + { + KHistoryComboEditor dlg( compObj() ? compObj()->items() : TQStringList(), this ); + connect( &dlg, TQT_SIGNAL( removeFromHistory(const TQString&) ), TQT_SLOT( slotRemoveFromHistory(const TQString&)) ); + dlg.exec(); + } + default: + break; + } +} + +void LineEditWidget::slotRemoveFromHistory(const TQString &entry) +{ + m_view->removeFormCompletionItem(m_input->name().string(), entry); + if (compObj()) + compObj()->removeItem(entry); +} + + +bool LineEditWidget::event( TQEvent *e ) +{ + if (KLineEdit::event(e)) + return true; + + if ( e->type() == TQEvent::AccelAvailable && isReadOnly() ) { + TQKeyEvent* ke = (TQKeyEvent*) e; + if ( ke->state() & ControlButton ) { + switch ( ke->key() ) { + case Key_Left: + case Key_Right: + case Key_Up: + case Key_Down: + case Key_Home: + case Key_End: + ke->accept(); + default: + break; + } + } + } + return false; +} + +void LineEditWidget::mouseMoveEvent(TQMouseEvent *e) +{ + // hack to prevent Qt from calling setCursor on the widget + setDragEnabled(false); + KLineEdit::mouseMoveEvent(e); + setDragEnabled(true); +} + + +// ----------------------------------------------------------------------------- + +RenderLineEdit::RenderLineEdit(HTMLInputElementImpl *element) + : RenderFormElement(element) +{ + LineEditWidget *edit = new LineEditWidget(element, view(), view()->viewport()); + connect(edit,TQT_SIGNAL(returnPressed()), this, TQT_SLOT(slotReturnPressed())); + connect(edit,TQT_SIGNAL(textChanged(const TQString &)),this,TQT_SLOT(slotTextChanged(const TQString &))); + + if(element->inputType() == HTMLInputElementImpl::PASSWORD) + edit->setEchoMode( TQLineEdit::Password ); + + if ( element->autoComplete() ) { + TQStringList completions = view()->formCompletionItems(element->name().string()); + if (completions.count()) { + edit->completionObject()->setItems(completions); + edit->setContextMenuEnabled(true); + edit->completionBox()->setTabHandling( false ); + } + } + + setQWidget(edit); +} + +void RenderLineEdit::setStyle(RenderStyle* _style) +{ + RenderFormElement::setStyle( _style ); + + widget()->setAlignment(textAlignment()); +} + +void RenderLineEdit::highLightWord( unsigned int length, unsigned int pos ) +{ + LineEditWidget* w = static_cast(m_widget); + if ( w ) + w->highLightWord( length, pos ); +} + + +void RenderLineEdit::slotReturnPressed() +{ + // don't submit the form when return was pressed in a completion-popup + KCompletionBox *box = widget()->completionBox(false); + + if ( box && box->isVisible() && box->currentItem() != -1 ) { + box->hide(); + return; + } + + // Emit onChange if necessary + // Works but might not be enough, dirk said he had another solution at + // hand (can't remember which) - David + handleFocusOut(); + + HTMLFormElementImpl* fe = element()->form(); + if ( fe ) + fe->submitFromKeyboard(); +} + +void RenderLineEdit::handleFocusOut() +{ + if ( widget() && widget()->edited() ) { + element()->onChange(); + widget()->setEdited( false ); + } +} + +void RenderLineEdit::calcMinMaxWidth() +{ + KHTMLAssert( !minMaxKnown() ); + + const TQFontMetrics &fm = style()->fontMetrics(); + TQSize s; + + int size = element()->size(); + + int h = fm.lineSpacing(); + int w = fm.width( 'x' ) * (size > 0 ? size+1 : 17); // "some" + s = TQSize(w + 2 + 2*widget()->frameWidth(), + kMax(h, 14) + 2 + 2*widget()->frameWidth()) + .expandedTo(TQApplication::globalStrut()); + + setIntrinsicWidth( s.width() ); + setIntrinsicHeight( s.height() ); + + RenderFormElement::calcMinMaxWidth(); +} + +void RenderLineEdit::updateFromElement() +{ + int ml = element()->maxLength(); + if ( ml < 0 ) + ml = 32767; + + if ( widget()->maxLength() != ml ) { + widget()->setMaxLength( ml ); + } + + if (element()->value().string() != widget()->text()) { + widget()->blockSignals(true); + int pos = widget()->cursorPosition(); + widget()->setText(element()->value().string()); + + widget()->setEdited( false ); + + widget()->setCursorPosition(pos); + widget()->blockSignals(false); + } + widget()->setReadOnly(element()->readOnly()); + + RenderFormElement::updateFromElement(); +} + +void RenderLineEdit::slotTextChanged(const TQString &string) +{ + // don't use setValue here! + element()->m_value = string; + element()->m_unsubmittedFormChange = true; +} + +void RenderLineEdit::select() +{ + static_cast(m_widget)->selectAll(); +} + +long RenderLineEdit::selectionStart() +{ + LineEditWidget* w = static_cast(m_widget); + if (w->hasSelectedText()) + return w->selectionStart(); + else + return w->cursorPosition(); +} + + +long RenderLineEdit::selectionEnd() +{ + LineEditWidget* w = static_cast(m_widget); + if (w->hasSelectedText()) + return w->selectionStart() + w->selectedText().length(); + else + return w->cursorPosition(); +} + +void RenderLineEdit::setSelectionStart(long pos) +{ + LineEditWidget* w = static_cast(m_widget); + //See whether we have a non-empty selection now. + long end = selectionEnd(); + if (end > pos) + w->setSelection(pos, end - pos); + w->setCursorPosition(pos); +} + +void RenderLineEdit::setSelectionEnd(long pos) +{ + LineEditWidget* w = static_cast(m_widget); + //See whether we have a non-empty selection now. + long start = selectionStart(); + if (start < pos) + w->setSelection(start, pos - start); + + w->setCursorPosition(pos); +} + +void RenderLineEdit::setSelectionRange(long start, long end) +{ + LineEditWidget* w = static_cast(m_widget); + w->setCursorPosition(end); + w->setSelection(start, end - start); +} + +// --------------------------------------------------------------------------- + +RenderFieldset::RenderFieldset(HTMLGenericFormElementImpl *element) + : RenderBlock(element) +{ +} + +RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren) +{ + RenderObject* legend = findLegend(); + if (legend) { + if (relayoutChildren) + legend->setNeedsLayout(true); + legend->layoutIfNeeded(); + + int xPos = borderLeft() + paddingLeft() + legend->marginLeft(); + if (style()->direction() == RTL) + xPos = m_width - paddingRight() - borderRight() - legend->width() - legend->marginRight(); + int b = borderTop(); + int h = legend->height(); + legend->setPos(xPos, kMax((b-h)/2, 0)); + m_height = kMax(b,h) + paddingTop(); + } + return legend; +} + +RenderObject* RenderFieldset::findLegend() +{ + for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) { + if (!legend->isFloatingOrPositioned() && legend->element() && + legend->element()->id() == ID_LEGEND) + return legend; + } + return 0; +} + +void RenderFieldset::paintBoxDecorations(PaintInfo& pI, int _tx, int _ty) +{ + //kdDebug( 6040 ) << renderName() << "::paintDecorations()" << endl; + + RenderObject* legend = findLegend(); + if (!legend) + return RenderBlock::paintBoxDecorations(pI, _tx, _ty); + + int w = width(); + int h = height() + borderTopExtra() + borderBottomExtra(); + int yOff = (legend->yPos() > 0) ? 0 : (legend->height()-borderTop())/2; + h -= yOff; + _ty += yOff - borderTopExtra(); + + int my = kMax(_ty,pI.r.y()); + int end = kMin( pI.r.y() + pI.r.height(), _ty + h ); + int mh = end - my; + + paintBackground(pI.p, style()->backgroundColor(), style()->backgroundLayers(), my, mh, _tx, _ty, w, h); + + if ( style()->hasBorder() ) + paintBorderMinusLegend(pI.p, _tx, _ty, w, h, style(), legend->xPos(), legend->width()); +} + +void RenderFieldset::paintBorderMinusLegend(TQPainter *p, int _tx, int _ty, int w, int h, + const RenderStyle* style, int lx, int lw) +{ + + const TQColor& tc = style->borderTopColor(); + const TQColor& bc = style->borderBottomColor(); + + EBorderStyle ts = style->borderTopStyle(); + EBorderStyle bs = style->borderBottomStyle(); + EBorderStyle ls = style->borderLeftStyle(); + EBorderStyle rs = style->borderRightStyle(); + + bool render_t = ts > BHIDDEN; + bool render_l = ls > BHIDDEN; + bool render_r = rs > BHIDDEN; + bool render_b = bs > BHIDDEN; + + if(render_t) { + drawBorder(p, _tx, _ty, _tx + lx, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts, + (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE)?style->borderLeftWidth():0), 0); + drawBorder(p, _tx+lx+lw, _ty, _tx + w, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts, + 0, (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE)?style->borderRightWidth():0)); + } + + if(render_b) + drawBorder(p, _tx, _ty + h - style->borderBottomWidth(), _tx + w, _ty + h, BSBottom, bc, style->color(), bs, + (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE)?style->borderLeftWidth():0), + (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE)?style->borderRightWidth():0)); + + if(render_l) + { + const TQColor& lc = style->borderLeftColor(); + + bool ignore_top = + (tc == lc) && + (ls >= OUTSET) && + (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET); + + bool ignore_bottom = + (bc == lc) && + (ls >= OUTSET) && + (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET); + + drawBorder(p, _tx, _ty, _tx + style->borderLeftWidth(), _ty + h, BSLeft, lc, style->color(), ls, + ignore_top?0:style->borderTopWidth(), + ignore_bottom?0:style->borderBottomWidth()); + } + + if(render_r) + { + const TQColor& rc = style->borderRightColor(); + + bool ignore_top = + (tc == rc) && + (rs >= DOTTED || rs == INSET) && + (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET); + + bool ignore_bottom = + (bc == rc) && + (rs >= DOTTED || rs == INSET) && + (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET); + + drawBorder(p, _tx + w - style->borderRightWidth(), _ty, _tx + w, _ty + h, BSRight, rc, style->color(), rs, + ignore_top?0:style->borderTopWidth(), + ignore_bottom?0:style->borderBottomWidth()); + } +} + +void RenderFieldset::setStyle(RenderStyle* _style) +{ + RenderBlock::setStyle(_style); + + // WinIE renders fieldsets with display:inline like they're inline-blocks. For us, + // an inline-block is just a block element with replaced set to true and inline set + // to true. Ensure that if we ended up being inline that we set our replaced flag + // so that we're treated like an inline-block. + if (isInline()) + setReplaced(true); +} + +// ------------------------------------------------------------------------- + +RenderFileButton::RenderFileButton(HTMLInputElementImpl *element) + : RenderFormElement(element) +{ + KURLRequester* w = new KURLRequester( view()->viewport(), "__tdehtml" ); + + w->setMode(KFile::File | KFile::ExistingOnly); + w->completionObject()->setDir(TDEGlobalSettings::documentPath()); + + connect(w->lineEdit(), TQT_SIGNAL(returnPressed()), this, TQT_SLOT(slotReturnPressed())); + connect(w->lineEdit(), TQT_SIGNAL(textChanged(const TQString &)),this,TQT_SLOT(slotTextChanged(const TQString &))); + connect(w, TQT_SIGNAL(urlSelected(const TQString &)),this,TQT_SLOT(slotUrlSelected(const TQString &))); + + setQWidget(w); + m_haveFocus = false; +} + + + +void RenderFileButton::calcMinMaxWidth() +{ + KHTMLAssert( !minMaxKnown() ); + + const TQFontMetrics &fm = style()->fontMetrics(); + int size = element()->size(); + + int h = fm.lineSpacing(); + int w = fm.width( 'x' ) * (size > 0 ? size+1 : 17); // "some" + KLineEdit* edit = static_cast( m_widget )->lineEdit(); + TQSize s = edit->style().tqsizeFromContents(TQStyle::CT_LineEdit, + edit, + TQSize(w + 2 + 2*edit->frameWidth(), kMax(h, 14) + 2 + 2*edit->frameWidth())) + .expandedTo(TQApplication::globalStrut()); + TQSize bs = static_cast( m_widget )->minimumSizeHint() - edit->minimumSizeHint(); + + setIntrinsicWidth( s.width() + bs.width() ); + setIntrinsicHeight( kMax(s.height(), bs.height()) ); + + RenderFormElement::calcMinMaxWidth(); +} + +void RenderFileButton::handleFocusOut() +{ + if ( widget()->lineEdit() && widget()->lineEdit()->edited() ) { + element()->onChange(); + widget()->lineEdit()->setEdited( false ); + } +} + +void RenderFileButton::updateFromElement() +{ + KLineEdit* edit = widget()->lineEdit(); + edit->blockSignals(true); + edit->setText(element()->value().string()); + edit->blockSignals(false); + edit->setEdited( false ); + + RenderFormElement::updateFromElement(); +} + +void RenderFileButton::slotReturnPressed() +{ + handleFocusOut(); + + if (element()->form()) + element()->form()->submitFromKeyboard(); +} + +void RenderFileButton::slotTextChanged(const TQString &/*string*/) +{ + element()->m_value = KURL( widget()->url() ).prettyURL( 0, KURL::StripFileProtocol ); +} + +void RenderFileButton::slotUrlSelected(const TQString &) +{ + element()->onChange(); +} + +void RenderFileButton::select() +{ + widget()->lineEdit()->selectAll(); +} + +// ------------------------------------------------------------------------- + +RenderLabel::RenderLabel(HTMLGenericFormElementImpl *element) + : RenderFormElement(element) +{ + +} + +// ------------------------------------------------------------------------- + +RenderLegend::RenderLegend(HTMLGenericFormElementImpl *element) + : RenderBlock(element) +{ +} + +// ------------------------------------------------------------------------------- + +ComboBoxWidget::ComboBoxWidget(TQWidget *parent) + : KComboBox(false, parent, "__tdehtml") +{ + setAutoMask(true); + if (listBox()) listBox()->installEventFilter(this); + setMouseTracking(true); +} + +bool ComboBoxWidget::event(TQEvent *e) +{ + if (KComboBox::event(e)) + return true; + if (e->type()==TQEvent::KeyPress) + { + TQKeyEvent *ke = TQT_TQKEYEVENT(e); + switch(ke->key()) + { + case Key_Return: + case Key_Enter: + popup(); + ke->accept(); + return true; + default: + return false; + } + } + return false; +} + +bool ComboBoxWidget::eventFilter(TQObject *dest, TQEvent *e) +{ + if (TQT_BASE_OBJECT(dest)==TQT_BASE_OBJECT(listBox()) && e->type()==TQEvent::KeyPress) + { + TQKeyEvent *ke = TQT_TQKEYEVENT(e); + bool forward = false; + switch(ke->key()) + { + case Key_Tab: + forward=true; + case Key_BackTab: + // ugly hack. emulate popdownlistbox() (private in TQComboBox) + // we re-use ke here to store the reference to the generated event. + ke = new TQKeyEvent(TQEvent::KeyPress, Key_Escape, 0, 0); + TQApplication::sendEvent(dest,ke); + focusNextPrevChild(forward); + delete ke; + return true; + default: + return KComboBox::eventFilter(dest, e); + } + } + return KComboBox::eventFilter(dest, e); +} + +// ------------------------------------------------------------------------- + +RenderSelect::RenderSelect(HTMLSelectElementImpl *element) + : RenderFormElement(element) +{ + m_ignoreSelectEvents = false; + m_multiple = element->multiple(); + m_size = element->size(); + m_useListBox = (m_multiple || m_size > 1); + m_selectionChanged = true; + m_optionsChanged = true; + + if(m_useListBox) + setQWidget(createListBox()); + else + setQWidget(createComboBox()); +} + +void RenderSelect::updateFromElement() +{ + m_ignoreSelectEvents = true; + + // change widget type + bool oldMultiple = m_multiple; + unsigned oldSize = m_size; + bool oldListbox = m_useListBox; + + m_multiple = element()->multiple(); + m_size = element()->size(); + m_useListBox = (m_multiple || m_size > 1); + + if (oldMultiple != m_multiple || oldSize != m_size) { + if (m_useListBox != oldListbox) { + // type of select has changed + if(m_useListBox) + setQWidget(createListBox()); + else + setQWidget(createComboBox()); + } + + if (m_useListBox && oldMultiple != m_multiple) { + static_cast(m_widget)->setSelectionMode(m_multiple ? TQListBox::Extended : TQListBox::Single); + } + m_selectionChanged = true; + m_optionsChanged = true; + } + + // update contents listbox/combobox based on options in m_element + if ( m_optionsChanged ) { + if (element()->m_recalcListItems) + element()->recalcListItems(); + TQMemArray listItems = element()->listItems(); + int listIndex; + + if(m_useListBox) { + static_cast(m_widget)->clear(); + } + + else + static_cast(m_widget)->clear(); + + for (listIndex = 0; listIndex < int(listItems.size()); listIndex++) { + if (listItems[listIndex]->id() == ID_OPTGROUP) { + DOMString text = listItems[listIndex]->getAttribute(ATTR_LABEL); + if (text.isNull()) + text = ""; + + if(m_useListBox) { + TQListBoxText *item = new TQListBoxText(TQString(text.implementation()->s, text.implementation()->l)); + static_cast(m_widget) + ->insertItem(item, listIndex); + item->setSelectable(false); + } + else { + static_cast(m_widget) + ->insertItem(TQString(text.implementation()->s, text.implementation()->l), listIndex); + static_cast(m_widget)->listBox()->item(listIndex)->setSelectable(false); + } + } + else if (listItems[listIndex]->id() == ID_OPTION) { + HTMLOptionElementImpl* optElem = static_cast(listItems[listIndex]); + TQString text = optElem->text().string(); + if (optElem->parentNode()->id() == ID_OPTGROUP) + { + // Prefer label if set + DOMString label = optElem->getAttribute(ATTR_LABEL); + if (!label.isEmpty()) + text = label.string(); + text = TQString::fromLatin1(" ")+text; + } + + if(m_useListBox) { + KListBox *l = static_cast(m_widget); + l->insertItem(text, listIndex); + DOMString disabled = optElem->getAttribute(ATTR_DISABLED); + if (!disabled.isNull() && l->item( listIndex )) { + l->item( listIndex )->setSelectable( false ); + } + } else + static_cast(m_widget)->insertItem(text, listIndex); + } + else + KHTMLAssert(false); + m_selectionChanged = true; + } + + // TQComboBox caches the size hint unless you call setFont (ref: TT docu) + if(!m_useListBox) { + KComboBox *that = static_cast(m_widget); + that->setFont( that->font() ); + } + setNeedsLayoutAndMinMaxRecalc(); + m_optionsChanged = false; + } + + // update selection + if (m_selectionChanged) { + updateSelection(); + } + + + m_ignoreSelectEvents = false; + + RenderFormElement::updateFromElement(); +} + +void RenderSelect::calcMinMaxWidth() +{ + KHTMLAssert( !minMaxKnown() ); + + if (m_optionsChanged) + updateFromElement(); + + // ### ugly HACK FIXME!!! + setMinMaxKnown(); + layoutIfNeeded(); + setNeedsLayoutAndMinMaxRecalc(); + // ### end FIXME + + RenderFormElement::calcMinMaxWidth(); +} + +void RenderSelect::layout( ) +{ + KHTMLAssert(needsLayout()); + KHTMLAssert(minMaxKnown()); + + // ### maintain selection properly between type/size changes, and work + // out how to handle multiselect->singleselect (probably just select + // first selected one) + + // calculate size + if(m_useListBox) { + KListBox* w = static_cast(m_widget); + + TQListBoxItem* p = w->firstItem(); + int width = 0; + int height = 0; + while(p) { + width = kMax(width, p->width(p->listBox())); + height = kMax(height, p->height(p->listBox())); + p = p->next(); + } + if ( !height ) + height = w->fontMetrics().height(); + if ( !width ) + width = w->fontMetrics().width( 'x' ); + + int size = m_size; + // check if multiple and size was not given or invalid + // Internet Exploder sets size to kMin(number of elements, 4) + // Netscape seems to simply set it to "number of elements" + // the average of that is IMHO kMin(number of elements, 10) + // so I did that ;-) + if(size < 1) + size = kMin(static_cast(m_widget)->count(), 10u); + + width += 2*w->frameWidth() + w->verticalScrollBar()->sizeHint().width(); + height = size*height + 2*w->frameWidth(); + + setIntrinsicWidth( width ); + setIntrinsicHeight( height ); + } + else { + TQSize s(m_widget->sizeHint()); + setIntrinsicWidth( s.width() ); + setIntrinsicHeight( s.height() ); + } + + /// uuh, ignore the following line.. + setNeedsLayout(true); + RenderFormElement::layout(); + + // and now disable the widget in case there is no