📄 q3combobox.cpp
字号:
{}/*!\reimp*/void Q3ComboBox::mouseReleaseEvent( QMouseEvent * ){}/*!\reimp*/void Q3ComboBox::mouseDoubleClickEvent( QMouseEvent *e ){ mousePressEvent( e );}/*!\reimp*/void Q3ComboBox::keyPressEvent( QKeyEvent *e ){ int c = currentItem(); if ( ( e->key() == Qt::Key_F4 && e->state() == 0 ) || ( e->key() == Qt::Key_Down && (e->state() & Qt::AltModifier) ) || ( !d->ed && e->key() == Qt::Key_Space ) ) { if ( count() ) { if ( !d->usingListBox() ) d->popup()->setActiveItem( this->d->current ); popup(); } return; } else if ( d->usingListBox() && e->key() == Qt::Key_Up ) { if ( c > 0 ) setCurrentItem( c-1 ); } else if ( d->usingListBox() && e->key() == Qt::Key_Down ) { if ( ++c < count() ) setCurrentItem( c ); } else if ( d->usingListBox() && e->key() == Qt::Key_Home && ( !d->ed || !d->ed->hasFocus() ) ) { setCurrentItem( 0 ); } else if ( d->usingListBox() && e->key() == Qt::Key_End && ( !d->ed || !d->ed->hasFocus() ) ) { setCurrentItem( count()-1 ); } else if ( !d->ed && e->ascii() >= 32 && !e->text().isEmpty() ) { if ( !d->completionTimer->isActive() ) { d->completeAt = 0; c = completionIndex( e->text(), ++c ); if ( c >= 0 ) { setCurrentItem( c ); d->completeAt = e->text().length(); } } else { d->completionTimer->stop(); QString ct = currentText().left( d->completeAt ) + e->text(); c = completionIndex( ct, c ); if ( c < 0 && d->completeAt > 0 ) { c = completionIndex( e->text(), 0 ); ct = e->text(); } d->completeAt = 0; if ( c >= 0 ) { setCurrentItem( c ); d->completeAt = ct.length(); } } d->completionTimer->start( 400, true ); } else { e->ignore(); return; } c = currentItem(); if ( count() && !text( c ).isNull() ) emit activated( text( c ) ); emit activated( c );}/*!\reimp*/void Q3ComboBox::focusInEvent( QFocusEvent * e ){ QWidget::focusInEvent( e ); d->completeNow = false; d->completeAt = 0;}/*!\reimp*/void Q3ComboBox::focusOutEvent( QFocusEvent * e ){ QWidget::focusOutEvent( e ); d->completeNow = false; d->completeAt = 0;}/*!\reimp*/#ifndef QT_NO_WHEELEVENTvoid Q3ComboBox::wheelEvent( QWheelEvent *e ){ if ( d->poppedUp ) { if ( d->usingListBox() ) { QApplication::sendEvent( d->listBox(), e ); } } else { if ( e->delta() > 0 ) { int c = currentItem(); if ( c > 0 ) { setCurrentItem( c-1 ); emit activated( currentItem() ); emit activated( currentText() ); } } else { int c = currentItem(); if ( ++c < count() ) { setCurrentItem( c ); emit activated( currentItem() ); emit activated( currentText() ); } } e->accept(); }}#endif/*! \internal Calculates the listbox height needed to contain all items, or as many as the list box is supposed to contain.*/static int listHeight( Q3ListBox *l, int sl ){ if ( l->count() > 0 ) return QMIN( l->count(), (uint)sl) * l->item( 0 )->height(l); else return l->sizeHint().height();}/*! Pops up the combobox popup list. If the list is empty, no items appear.*/void Q3ComboBox::popup(){ if ( !count() || d->poppedUp ) return; QStyleOptionComboBox opt = d->getStyleOption(); if( !d->usingListBox() || style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) ) { if(d->usingListBox()) { if(!d->popup()) { Q3ComboBoxPopup *p = new Q3ComboBoxPopup( this, "in-combo" ); d->setPopupMenu( p, false ); p->setFont( font() ); connect( p, SIGNAL(activated(int)), SLOT(internalActivate(int)) ); connect( p, SIGNAL(highlighted(int)), SLOT(internalHighlight(int)) ); } d->popup()->clear(); for(unsigned int i = 0; i < d->listBox()->count(); i++) { Q3ListBoxItem *item = d->listBox()->item(i); if(item->rtti() == Q3ListBoxText::RTTI) { d->popup()->insertItem(escapedComboString(item->text()), i, i); } else if(item->rtti() == Q3ListBoxPixmap::RTTI) { if(item->pixmap()) d->popup()->insertItem(QIcon(*item->pixmap()), escapedComboString(item->text()), i, i); else d->popup()->insertItem(escapedComboString(item->text()), i, i); } else { d->popup()->insertItem(new Q3ComboBoxPopupItem(item), i, i); } } } d->popup()->installEventFilter( this ); if(d->popup() && style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) d->popup()->setItemChecked(this->d->current, true); d->popup()->popup( mapToGlobal( QPoint(0,0) ), this->d->current ); update(); } else { // Send all listbox events to eventFilter(): Q3ListBox* lb = d->listBox(); lb->triggerUpdate( true ); lb->installEventFilter( this ); d->mouseWasInsidePopup = false; int w = lb->variableWidth() ? lb->sizeHint().width() : width(); int h = listHeight( lb, d->sizeLimit ) + 2; QRect screen = QApplication::desktop()->availableGeometry( this ); int sx = screen.x(); // screen pos int sy = screen.y(); int sw = screen.width(); // screen width int sh = screen.height(); // screen height QPoint pos = mapToGlobal( QPoint(0,height()) ); // ## Similar code is in QPopupMenu int x = pos.x(); int y = pos.y(); // the complete widget must be visible if ( x + w > sx + sw ) x = sx+sw - w; if ( x < sx ) x = sx; if (y + h > sy+sh && y - h - height() >= 0 ) y = y - h - height(); opt.rect = QRect(x, y, w, h); QRect rect = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxListBoxPopup, this); // work around older styles that don't implement the combobox // listbox popup subcontrol if ( rect.isNull() ) rect.setRect( x, y, w, h ); lb->setGeometry( rect ); lb->raise(); bool block = lb->signalsBlocked(); lb->blockSignals( true ); Q3ListBoxItem* currentLBItem = 0; if ( editable() && currentText() != text( currentItem() ) ) currentLBItem = lb->findItem( currentText() ); currentLBItem = currentLBItem ? currentLBItem : lb->item( d->current ); lb->setCurrentItem( currentLBItem ); lb->setContentsPos( lb->contentsX(), lb->viewportToContents( lb->itemRect( currentLBItem ).topLeft() ).y() ); // set the current item to also be the selected item if it isn't already if ( currentLBItem && currentLBItem->isSelectable() && !currentLBItem->isSelected() ) lb->setSelected( currentLBItem, true ); lb->blockSignals( block ); lb->setVScrollBarMode(Q3ScrollView::Auto);#ifndef QT_NO_EFFECTS if ( QApplication::isEffectEnabled( Qt::UI_AnimateCombo ) ) { if ( lb->y() < mapToGlobal(QPoint(0,0)).y() ) qScrollEffect( lb, QEffects::UpScroll ); else qScrollEffect( lb ); } else#endif lb->show(); } d->poppedUp = true;}/*! Updates the widget mask. \sa QWidget::setMask()*/void Q3ComboBox::updateMask(){ QBitmap bm( size() ); bm.fill( Qt::color0 ); QStyleOptionComboBox opt = d->getStyleOption(); { QPainter p(&bm); p.initFrom(this); p.fillRect(opt.rect, Qt::color1); // qcommonstyle old drawComplexControl implementation } setMask( bm );}/*! \internal Pops down (removes) the combobox popup list box.*/void Q3ComboBox::popDownListBox(){ Q_ASSERT( d->usingListBox() ); d->listBox()->removeEventFilter( this ); d->listBox()->viewport()->removeEventFilter( this ); d->listBox()->hide(); d->listBox()->setCurrentItem( d->current ); if ( d->arrowDown ) { d->arrowDown = false; repaint( false ); } d->poppedUp = false;}/*! \internal Re-indexes the identifiers in the popup list.*/void Q3ComboBox::reIndex(){ if ( !d->usingListBox() ) { int cnt = count(); while ( cnt-- ) d->popup()->setId( cnt, cnt ); }}/*! \internal Repaints the combobox.*/void Q3ComboBox::currentChanged(){ if ( d->autoresize ) adjustSize(); update();#if defined(QT_ACCESSIBILITY_SUPPORT) QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );#endif}/*! \reimp \internal The event filter steals events from the popup or listbox when they are popped up. It makes the popup stay up after a short click in motif style. In windows style it toggles the arrow button of the combobox field, and activates an item and takes down the listbox when the mouse button is released.*/bool Q3ComboBox::eventFilter( QObject *object, QEvent *event ){ QStyleOptionComboBox opt = d->getStyleOption(); if ( !event ) return true; else if ( object == d->ed ) { if ( event->type() == QEvent::KeyPress ) { bool isAccepted = ( (QKeyEvent*)event )->isAccepted(); keyPressEvent( (QKeyEvent *)event ); if ( ((QKeyEvent *)event)->isAccepted() ) { d->completeNow = false; return true; } else if ( ((QKeyEvent *)event)->key() != Qt::Key_End ) { d->completeNow = true; d->completeAt = d->ed->cursorPosition(); } if ( isAccepted ) ( (QKeyEvent*)event )->accept(); else ( (QKeyEvent*)event )->ignore(); } else if ( event->type() == QEvent::KeyRelease ) { keyReleaseEvent( (QKeyEvent *)event ); return ((QKeyEvent *)event)->isAccepted(); } else if ( event->type() == QEvent::FocusIn ) { focusInEvent( (QFocusEvent *)event ); } else if ( event->type() == QEvent::FocusOut ) { focusOutEvent( (QFocusEvent *)event ); } else if ( d->useCompletion && d->completeNow ) { d->completeNow = false; if ( !d->ed->text().isNull() && d->ed->cursorPosition() > d->completeAt && d->ed->cursorPosition() == (int)d->ed->text().length() ) { QString ct( d->ed->text() ); int i = completionIndex( ct, currentItem() ); if ( i > -1 ) { QString it = text( i ); d->ed->validateAndSet( it, ct.length(), ct.length(), it.length() ); d->current = i; // ### sets current item without emitting signals. This is to // make sure the right item is current if you change current with // wheel/up/down. While typing current is not valid anyway. Fix properly // in 4.0. } } } } else if ( d->usingListBox() && ( object == d->listBox() || object == d->listBox()->viewport() )) { QMouseEvent *e = (QMouseEvent*)event; switch( event->type() ) { case QEvent::MouseMove: if ( !d->mouseWasInsidePopup ) { QPoint pos = e->pos(); if ( d->listBox()->rect().contains( pos ) ) d->mouseWasInsidePopup = true; // Check if arrow button should toggle if ( d->arrowPressed ) { QPoint comboPos; comboPos = mapFromGlobal( d->listBox()->mapToGlobal(pos) ); QRect arrowRect = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxArrow, this); if ( arrowRect.contains( comboPos ) ) { if ( !d->arrowDown ) { d->arrowDown = true; repaint( false ); } } else { if ( d->arrowDown ) { d->arrowDown = false; repaint( false ); } } } } else if ((e->state() & ( Qt::RightButton | Qt::LeftButton | Qt::MidButton ) ) == 0 && style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, this)) { QWidget *mouseW = QApplication::widgetAt( e->globalPos(), true ); if ( mouseW == d->listBox()->viewport() ) { //### QMouseEvent m( QEvent::MouseMove, e->pos(), e->globalPos(), Qt::NoButton, Qt::LeftButton ); QApplication::sendEvent( object, &m ); //### Evil return true; } } break; case QEvent::MouseButtonRelease: if ( d->listBox()->rect().contains( e->pos() ) ) { QMouseEvent tmp( QEvent::MouseButtonDblClick, e->pos(), e->button(), e->state() ) ; // will hide popup QApplication::sendEvent( object, &tmp ); return true; } else { if ( d->mouseWasInsidePopup ) { popDownListBox(); } else { d->arrowPressed = false; if ( d->arrowDown ) { d->arrowDown = false; repaint( false ); } } } break; case QEvent::MouseButtonDblClick: case QEvent::MouseButtonPress: if ( !d->listBox()->rect().contains( e->pos() ) ) { QPoint globalPos = d->listBox()->mapToGlobal(e->pos()); if ( QApplication::widgetAt( globalPos, true ) == this ) { d->discardNextMousePress = true; // avoid popping up again } popDownListBox(); return true; } break; case QEvent::KeyPress: switch( ((QKeyEvent *)event)->key() ) { case Qt::Key_Up: case Qt::Key_Down: if ( !(((QKeyEvent *)event)->state() & Qt::AltModifier) ) break; case Qt::Key_F4: case Qt::Key_Escape: if ( d->poppedUp ) { popDownListBox(); return true; } break; case Qt::Key_Enter: case Qt::Key_Return: // work around QDialog's enter handling return false; default: break; } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -