📄 render_form.cpp
字号:
/* * 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) * * 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 <kcompletionbox.h>#include <kcursor.h>#include <kdebug.h>#include <kfiledialog.h>#include <kfind.h>#include <kfinddialog.h>#include <kiconloader.h>#include <klocale.h>#include <kmessagebox.h>#include <kreplace.h>#include <kreplacedialog.h>#include <kspell.h>#include <kurlcompletion.h>#include <kwin.h>#include <qstyle.h>#include "misc/helper.h"#include "xml/dom2_eventsimpl.h"#include "html/html_formimpl.h"#include "misc/htmlhashes.h"#include "rendering/render_form.h"#include <assert.h>#include "khtmlview.h"#include "khtml_ext.h"#include "xml/dom_docimpl.h"#include <qpopupmenu.h>#include <qbitmap.h>using namespace khtml;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()); if ( !style()->width().isPercent() ) setNeedsLayout(false);}Qt::AlignmentFlags RenderFormElement::textAlignment() const{ switch (style()->textAlign()) { case LEFT: case KHTML_LEFT: return AlignLeft; case RIGHT: case KHTML_RIGHT: return AlignRight; case CENTER: case KHTML_CENTER: return AlignHCenter; case JUSTIFY: // Just fall into the auto code for justify. case TAAUTO: return style()->direction() == RTL ? AlignRight : AlignLeft; } assert(false); // Should never be reached. return AlignLeft;}// -------------------------------------------------------------------------RenderButton::RenderButton(HTMLGenericFormElementImpl *element) : RenderFormElement(element){}short RenderButton::baselinePosition( bool f ) const{ return RenderWidget::baselinePosition( f ) - 2;}// -------------------------------------------------------------------------------RenderCheckBox::RenderCheckBox(HTMLInputElementImpl *element) : RenderButton(element){ QCheckBox* b = new QCheckBox(view()->viewport(), "__khtml"); b->setAutoMask(true); b->setMouseTracking(true); setQWidget(b); // prevent firing toggled() signals on initialization b->setChecked(element->checked()); connect(b,SIGNAL(stateChanged(int)),this,SLOT(slotStateChanged(int)));}void RenderCheckBox::calcMinMaxWidth(){ KHTMLAssert( !minMaxKnown() ); QCheckBox *cb = static_cast<QCheckBox *>( m_widget ); QSize s( cb->style().pixelMetric( QStyle::PM_IndicatorWidth ), cb->style().pixelMetric( QStyle::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 == 2); ref(); element()->onChange(); deref();}// -------------------------------------------------------------------------------RenderRadioButton::RenderRadioButton(HTMLInputElementImpl *element) : RenderButton(element){ QRadioButton* b = new QRadioButton(view()->viewport(), "__khtml"); b->setMouseTracking(true); setQWidget(b); // prevent firing toggled() signals on initialization b->setChecked(element->checked()); connect(b,SIGNAL(toggled(bool)),this,SLOT(slotToggled(bool)));}void RenderRadioButton::updateFromElement(){ widget()->setChecked(element()->checked()); RenderButton::updateFromElement();}void RenderRadioButton::calcMinMaxWidth(){ KHTMLAssert( !minMaxKnown() ); QRadioButton *rb = static_cast<QRadioButton *>( m_widget ); QSize s( rb->style().pixelMetric( QStyle::PM_ExclusiveIndicatorWidth ), rb->style().pixelMetric( QStyle::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){ QPushButton* p = new QPushButton(view()->viewport(), "__khtml"); setQWidget(p); p->setAutoMask(true); p->setMouseTracking(true);}QString RenderSubmitButton::rawText(){ QString value = element()->valueWithDefault().string(); value = value.stripWhiteSpace(); QString raw; for(unsigned int i = 0; i < value.length(); i++) { raw += value[i]; if(value[i] == '&') raw += '&'; } return raw;}void RenderSubmitButton::calcMinMaxWidth(){ KHTMLAssert( !minMaxKnown() ); QString raw = rawText(); QPushButton* pb = static_cast<QPushButton*>(m_widget); pb->setText(raw); pb->setFont(style()->font()); bool empty = raw.isEmpty(); if ( empty ) raw = QString::fromLatin1("X"); QFontMetrics fm = pb->fontMetrics(); QSize ts = fm.size( ShowPrefix, raw); QSize s(pb->style().sizeFromContents( QStyle::CT_PushButton, pb, ts ) .expandedTo(QApplication::globalStrut())); int margin = pb->style().pixelMetric( QStyle::PM_ButtonMargin, pb) + pb->style().pixelMetric( QStyle::PM_DefaultFrameWidth, pb ) * 2; int w = ts.width() + margin; int h = s.height(); if (pb->isDefault() || pb->autoDefault()) { int dbw = pb->style().pixelMetric( QStyle::PM_ButtonDefaultIndicator, pb ) * 2; w += dbw; } // add 30% margins to the width (heuristics to make it look similar to IE) s = QSize( w*13/10, h ).expandedTo(QApplication::globalStrut()); setIntrinsicWidth( s.width() ); setIntrinsicHeight( s.height() ); RenderButton::calcMinMaxWidth();}void RenderSubmitButton::updateFromElement(){ QString oldText = static_cast<QPushButton*>(m_widget)->text(); QString newText = rawText(); static_cast<QPushButton*>(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, QWidget* parent) : KLineEdit(parent, "__khtml"), m_input(input), m_view(view), m_spell(0){ setMouseTracking(true);#ifndef KHTML_NO_SPELLING KActionCollection *ac = new KActionCollection(this); m_spellAction = KStdAction::spelling( this, SLOT( slotCheckSpelling() ), ac );#endif // KHTML_NO_SPELLING}LineEditWidget::~LineEditWidget(){#ifndef KHTML_NO_SPELLING delete m_spell; m_spell = 0L;#endif // KHTML_NO_SPELLING}void LineEditWidget::slotCheckSpelling(){#ifndef KHTML_NO_SPELLING if ( text().isEmpty() ) { return; } delete m_spell; m_spell = new KSpell( this, i18n( "Spell Checking" ), this, SLOT( slotSpellCheckReady( KSpell *) ), 0, true, true); connect( m_spell, SIGNAL( death() ),this, SLOT( spellCheckerFinished() ) ); connect( m_spell, SIGNAL( misspelling( const QString &, const QStringList &, unsigned int ) ),this, SLOT( spellCheckerMisspelling( const QString &, const QStringList &, unsigned int ) ) ); connect( m_spell, SIGNAL( corrected( const QString &, const QString &, unsigned int ) ),this, SLOT( spellCheckerCorrected( const QString &, const QString &, unsigned int ) ) );#endif // KHTML_NO_SPELLING}void LineEditWidget::spellCheckerMisspelling( const QString &_text, const QStringList &, unsigned int pos){ highLightWord( _text.length(),pos );}void LineEditWidget::highLightWord( unsigned int length, unsigned int pos ){ setSelection ( pos, length );}void LineEditWidget::spellCheckerCorrected( const QString &old, const QString &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 ){#ifndef KHTML_NO_SPELLING s->check( text() ); connect( s, SIGNAL( done( const QString & ) ), this, SLOT( slotSpellCheckDone( const QString & ) ) );#endif // KHTML_NO_SPELLING}void LineEditWidget::slotSpellCheckDone( const QString &s ){ if( s != text() ) setText( s );}QPopupMenu *LineEditWidget::createPopupMenu(){ QPopupMenu *popup = KLineEdit::createPopupMenu(); if ( !popup ) { return 0L; } connect( popup, SIGNAL( activated( int ) ), this, SLOT( extendedMenuActivated( int ) ) ); if (m_input->autoComplete()) { popup->insertSeparator(); int id = popup->insertItem( SmallIconSet("history_clear"), i18n("Clear &History"), ClearHistory ); popup->setItemEnabled( id, (compObj() && !compObj()->isEmpty()) ); }#ifndef KHTML_NO_SPELLING if (echoMode() == QLineEdit::Normal && !isReadOnly()) { popup->insertSeparator(); m_spellAction->plug(popup); m_spellAction->setEnabled( !text().isEmpty() ); }#endif // KHTML_NO_SPELLING return popup;}void LineEditWidget::extendedMenuActivated( int id){ switch ( id ) { case ClearHistory: m_view->clearCompletionHistory(m_input->name().string()); if (compObj()) compObj()->clear(); default: break; }}bool LineEditWidget::event( QEvent *e ){ if (KLineEdit::event(e)) return true; if ( e->type() == QEvent::AccelAvailable && isReadOnly() ) { QKeyEvent* ke = (QKeyEvent*) 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -