📄 q3combobox.cpp
字号:
/*! \internal Receives highlighted signals from an internal popup list and emits the highlighted() signal.*/void Q3ComboBox::internalHighlight( int index ){ emit highlighted( index ); QString t = text( index ); if ( !t.isNull() ) emit highlighted( t );}/*! \internal Receives timeouts after a click. Used to decide if a Motif style popup should stay up or not after a click.*/void Q3ComboBox::internalClickTimeout(){ d->shortClick = false;}/*! Sets the palette for both the combobox button and the combobox popup list to \a palette.*/void Q3ComboBox::setPalette( const QPalette &palette ){ QWidget::setPalette( palette ); if ( d->listBox() ) d->listBox()->setPalette( palette ); if ( d->popup() ) d->popup()->setPalette( palette );}/*! Sets the font for both the combobox button and the combobox popup list to \a font.*/void Q3ComboBox::setFont( const QFont &font ){ d->sizeHint = QSize(); // invalidate size hint QWidget::setFont( font ); if ( d->usingListBox() ) d->listBox()->setFont( font ); else d->popup()->setFont( font ); if (d->ed) d->ed->setFont( font ); if ( d->autoresize ) adjustSize();}/*!\reimp*/void Q3ComboBox::resizeEvent( QResizeEvent * e ){ if ( d->ed ) d->updateLinedGeometry(); if ( d->listBox() ) d->listBox()->resize( width(), d->listBox()->height() ); QWidget::resizeEvent( e );}/*!\reimp*/void Q3ComboBox::paintEvent( QPaintEvent * ){ QPainter p( this ); const QColorGroup & g = colorGroup(); p.setPen(g.text()); if ( width() < 5 || height() < 5 ) { qDrawShadePanel( &p, rect(), g, false, 2, &g.brush( QColorGroup::Button ) ); return; } QStyleOptionComboBox opt = d->getStyleOption(); bool reverse = QApplication::reverseLayout(); if ( !d->usingListBox() && style()->styleHint(QStyle::SH_GUIStyle) == Qt::MotifStyle) { // motif 1.x style int dist, buttonH, buttonW; dist = 8; buttonH = 7; buttonW = 11; int xPos; int x0; int w = width() - dist - buttonW - 1; if ( reverse ) { xPos = dist + 1; x0 = xPos + 4; } else { xPos = w; x0 = 4; } qDrawShadePanel( &p, rect(), g, false, style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, this), &g.brush( QColorGroup::Button ) ); qDrawShadePanel( &p, xPos, (height() - buttonH)/2, buttonW, buttonH, g, false, style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, this) ); QRect clip( x0, 2, w - 2 - 4 - 5, height() - 4 ); QString str = d->popup()->text( this->d->current ); if ( !str.isNull() ) { p.drawText( clip, Qt::AlignCenter | Qt::TextSingleLine, str ); } QPixmap pix = d->popup()->pixmap( this->d->current ); QIcon iconSet = d->popup()->iconSet( this->d->current ); if (!pix.isNull() || !iconSet.isNull()) { QPixmap pm = ( !pix.isNull() ? pix : iconSet.pixmap() ); p.setClipRect( clip ); p.drawPixmap( 4, (height()-pm.height())/2, pm ); p.setClipping( false ); } if ( hasFocus() ) p.drawRect( xPos - 5, 4, width() - xPos + 1 , height() - 8 ); } else if(!d->usingListBox()) { style()->drawComplexControl(QStyle::CC_ComboBox, &opt, &p, this); QRect re = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this); p.setClipRect( re ); QString str = d->popup()->text( this->d->current ); QPixmap pix = d->popup()->pixmap( this->d->current ); if ( !str.isNull() ) { p.save(); p.setFont(font()); QFontMetrics fm(font()); int x = re.x(), y = re.y() + fm.ascent(); x += pix.width() + 5; p.drawText( x, y, str ); p.restore(); } if (!pix.isNull()) { p.fillRect(re.x(), re.y(), pix.width() + 4, re.height(), colorGroup().brush(QColorGroup::Base)); p.drawPixmap(re.x() + 2, re.y() + (re.height() - pix.height()) / 2, pix); } } else { style()->drawComplexControl(QStyle::CC_ComboBox, &opt, &p, this); QRect re = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this); p.setClipRect(re); if ( !d->ed ) { Q3ListBoxItem * item = d->listBox()->item( d->current ); if ( item ) { int itemh = item->height( d->listBox() ); p.translate( re.x(), re.y() + (re.height() - itemh)/2 ); item->paint( &p ); } } else if ( d->listBox() && d->listBox()->item( d->current ) ) { Q3ListBoxItem * item = d->listBox()->item( d->current ); const QPixmap *pix = item->pixmap(); if ( pix ) { p.fillRect( re.x(), re.y(), pix->width() + 4, re.height(), colorGroup().brush( QColorGroup::Base ) ); p.drawPixmap( re.x() + 2, re.y() + ( re.height() - pix->height() ) / 2, *pix ); } } p.setClipping( false ); }}/*!\reimp*/void Q3ComboBox::mousePressEvent( QMouseEvent *e ){ if ( e->button() != Qt::LeftButton ) return; if ( d->discardNextMousePress ) { d->discardNextMousePress = false; return; } QStyleOptionComboBox opt = d->getStyleOption(); QRect arrowRect = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxArrow , this); // Correction for motif style, where arrow is smaller // and thus has a rect that doesn't fit the button. arrowRect.setHeight( QMAX( height() - (2 * arrowRect.y()), arrowRect.height() ) ); if ( count() && ( !editable() || arrowRect.contains( e->pos() ) ) ) { d->arrowPressed = false; if ( d->usingListBox() ) { listBox()->blockSignals( true ); qApp->sendEvent( listBox(), e ); // trigger the listbox's autoscroll listBox()->setCurrentItem(d->current); listBox()->blockSignals( false ); popup(); if ( arrowRect.contains( e->pos() ) ) { d->arrowPressed = true; d->arrowDown = true; repaint( false ); } } else { popup(); } QTimer::singleShot( 200, this, SLOT(internalClickTimeout())); d->shortClick = true; }}/*!\reimp*/void Q3ComboBox::mouseMoveEvent( QMouseEvent * ){}/*!\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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -