📄 render_form.cpp
字号:
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<KListBox*>(m_widget)->setSelectionMode(m_multiple ? QListBox::Extended : QListBox::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(); QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems(); int listIndex; if(m_useListBox) { static_cast<KListBox*>(m_widget)->clear(); } else static_cast<KComboBox*>(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) { QListBoxText *item = new QListBoxText(QString(text.implementation()->s, text.implementation()->l)); static_cast<KListBox*>(m_widget) ->insertItem(item, listIndex); item->setSelectable(false); } else { static_cast<KComboBox*>(m_widget) ->insertItem(QString(text.implementation()->s, text.implementation()->l), listIndex); static_cast<KComboBox*>(m_widget)->listBox()->item(listIndex)->setSelectable(false); } } else if (listItems[listIndex]->id() == ID_OPTION) { HTMLOptionElementImpl* optElem = static_cast<HTMLOptionElementImpl*>(listItems[listIndex]); QString 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 = QString::fromLatin1(" ")+text; } if(m_useListBox) { KListBox *l = static_cast<KListBox*>(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<KComboBox*>(m_widget)->insertItem(text, listIndex); } else KHTMLAssert(false); m_selectionChanged = true; } // QComboBox caches the size hint unless you call setFont (ref: TT docu) if(!m_useListBox) { KComboBox *that = static_cast<KComboBox*>(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<KListBox*>(m_widget); QListBoxItem* 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<KListBox*>(m_widget)->count(), 10u); width += 2*w->frameWidth() + w->verticalScrollBar()->sizeHint().width(); height = size*height + 2*w->frameWidth(); setIntrinsicWidth( width ); setIntrinsicHeight( height ); } else { QSize 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 <option> given QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems(); bool foundOption = false; for (uint i = 0; i < listItems.size() && !foundOption; i++) foundOption = (listItems[i]->id() == ID_OPTION); m_widget->setEnabled(foundOption && ! element()->disabled());}void RenderSelect::slotSelected(int index) // emitted by the combobox only{ if ( m_ignoreSelectEvents ) return; KHTMLAssert( !m_useListBox ); QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems(); if(index >= 0 && index < int(listItems.size())) { bool found = ( listItems[index]->id() == ID_OPTION ); if ( !found ) { // this one is not selectable, we need to find an option element while ( ( unsigned ) index < listItems.size() ) { if ( listItems[index]->id() == ID_OPTION ) { found = true; break; } ++index; } if ( !found ) { while ( index >= 0 ) { if ( listItems[index]->id() == ID_OPTION ) { found = true; break; } --index; } } } if ( found ) { bool changed = false; for ( unsigned int i = 0; i < listItems.size(); ++i ) if ( listItems[i]->id() == ID_OPTION && i != (unsigned int) index ) { HTMLOptionElementImpl* opt = static_cast<HTMLOptionElementImpl*>( listItems[i] ); changed |= (opt->m_selected == true); opt->m_selected = false; } HTMLOptionElementImpl* opt = static_cast<HTMLOptionElementImpl*>(listItems[index]); changed |= (opt->m_selected == false); opt->m_selected = true; if ( index != static_cast<ComboBoxWidget*>( m_widget )->currentItem() ) static_cast<ComboBoxWidget*>( m_widget )->setCurrentItem( index ); // When selecting an optgroup item, and we move forward to we // shouldn't emit onChange. Hence this bool, the if above doesn't do it. if ( changed ) { ref(); element()->onChange(); deref(); } } }}void RenderSelect::slotSelectionChanged() // emitted by the listbox only{ if ( m_ignoreSelectEvents ) return; // don't use listItems() here as we have to avoid recalculations - changing the // option list will make use update options not in the way the user expects them QMemArray<HTMLGenericFormElementImpl*> listItems = element()->m_listItems; for ( unsigned i = 0; i < listItems.count(); i++ ) // don't use setSelected() here because it will cause us to be called // again with updateSelection. if ( listItems[i]->id() == ID_OPTION ) static_cast<HTMLOptionElementImpl*>( listItems[i] ) ->m_selected = static_cast<KListBox*>( m_widget )->isSelected( i ); ref(); element()->onChange(); deref();}void RenderSelect::setOptionsChanged(bool _optionsChanged){ m_optionsChanged = _optionsChanged;}KListBox* RenderSelect::createListBox(){ KListBox *lb = new KListBox(view()->viewport(), "__khtml"); lb->setSelectionMode(m_multiple ? QListBox::Extended : QListBox::Single); // ### looks broken //lb->setAutoMask(true); connect( lb, SIGNAL( selectionChanged() ), this, SLOT( slotSelectionChanged() ) );// connect( lb, SIGNAL( clicked( QListBoxItem * ) ), this, SLOT( slotClicked() ) ); m_ignoreSelectEvents = false; lb->setMouseTracking(true); return lb;}ComboBoxWidget *RenderSelect::createComboBox(){ ComboBoxWidget *cb = new ComboBoxWidget(view()->viewport()); connect(cb, SIGNAL(activated(int)), this, SLOT(slotSelected(int))); return cb;}void RenderSelect::updateSelection(){ QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems(); int i; if (m_useListBox) { // if multi-select, we select only the new selected index KListBox *listBox = static_cast<KListBox*>(m_widget); for (i = 0; i < int(listItems.size()); i++) listBox->setSelected(i,listItems[i]->id() == ID_OPTION && static_cast<HTMLOptionElementImpl*>(listItems[i])->selected()); } else { bool found = false; unsigned firstOption = listItems.size(); i = listItems.size(); while (i--) if (listItems[i]->id() == ID_OPTION) { if (found) static_cast<HTMLOptionElementImpl*>(listItems[i])->m_selected = false; else if (static_cast<HTMLOptionElementImpl*>(listItems[i])->selected()) { static_cast<KComboBox*>( m_widget )->setCurrentItem(i); found = true; } firstOption = i; } Q_ASSERT(firstOption == listItems.size() || found); } m_selectionChanged = false;}// -------------------------------------------------------------------------TextAreaWidget::TextAreaWidget(int wrap, QWidget* parent) : KTextEdit(parent, "__khtml"), m_findDlg(0), m_find(0), m_repDlg(0), m_replace(0){ if(wrap != DOM::HTMLTextAreaElementImpl::ta_NoWrap) { setWordWrap(QTextEdit::WidgetWidth); setHScrollBarMode( AlwaysOff ); setVScrollBarMode( AlwaysOn ); } else { setWordWrap(QTextEdit::NoWrap); setHScrollBarMode( Auto ); setVScrollBarMode( Auto ); } KCursor::setAutoHideCursor(viewport(), true); setTextFormat(QTextEdit::PlainText); setAutoMask(true); setMouseTracking(true);#ifndef KHTML_NO_SPELLING KActionCollection *ac = new KActionCollection(this); m_findAction = KStdAction::find( this, SLOT( slotFind() ), ac ); m_findNextAction = KStdAction::findNext( this, SLOT( slotFindNext() ), ac ); m_replaceAction = KStdAction::replace( this, SLOT( slotReplace() ), ac );#endif // KHTML_NO_SPELLING}TextAreaWidget::~TextAreaWidget(){ delete m_replace; m_replace = 0L; delete m_find; m_find = 0L; delete m_repDlg; m_repDlg = 0L; delete m_findDlg; m_findDlg = 0L;}QPopupMenu *TextAreaWidget::createPopupMenu(const QPoint& pos){ QPopupMenu *popup = KTextEdit::createPopupMenu(pos); if ( !popup ) { return 0L; }#ifndef KHTML_NO_SPELLING if (!isReadOnly()) { popup->insertSeparator(); m_findAction->plug(popup); m_findAction->setEnabled( !text().isEmpty() ); m_findNextAction->plug(popup); m_findNextAction->setEnabled( m_find != 0 ); m_replaceAction->plug(popup); m_replaceAction->setEnabled( !text().isEmpty() ); }#endif return popup;}void TextAreaWidget::slotFindHighlight(const QString& text, int matchingIndex, int matchingLength){ Q_UNUSED(text) //kdDebug() << "Highlight: [" << text << "] mi:" << matchingIndex << " ml:" << matchingLength << endl; if (sender() == m_replace) { setSelection(m_repPara, matchingIndex, m_repPara, matchingIndex + matchingLength); setCursorPosition(m_repPara, matchingIndex); } else { setSelection(m_findPara, matchingIndex, m_findPara, matchingIndex + matchingLength); setCursorPosition(m_findPara, matchingIndex); } ensureCursorVisible();}void TextAreaWidget::slotReplaceText(const QString &text, int replacementIndex, int /*replacedLength*/, int matchedLength) {#ifndef KHTML_NO_SPELLING Q_UNUSED(text) //kdDebug() << "Replace: [" << text << "] ri:" << replacementIndex << " rl:" << replacedLength << " ml:" << matchedLength << endl; setSelection(m_repPara, replacementIndex, m_repPara, replacementIndex + matchedLength); removeSelectedText(); insertAt(m_repDlg->replacement(), m_repPara, replacementIndex); if (m_replace->options() & KReplaceDialog::PromptOnReplace) { ensureCursorVisible(); }#endif // KHTML_NO_SPELLING}void TextAreaWidget::slotDoReplace(){#ifndef KHTML_NO_SPELLING if (!m_repDlg) { // Should really assert() return; } delete m_replace; m_replace = new KReplace(m_repDlg->pattern(), m_repDlg->replacement(), m_repDlg->options(), this); if (m_replace->options() & KFindDialog::FromCursor) { getCursorPosition(&m_repPara, &m_repIndex);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -