00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
#include "qcomboview.h"
00017
#include <kdeversion.h>
00018
#ifndef QT_NO_COMBOBOX
00019
#include "qpopupmenu.h"
00020
#include "qlistview.h"
00021
#include "qpainter.h"
00022
#include "qdrawutil.h"
00023
#include "qstrlist.h"
00024
#include "qpixmap.h"
00025
#include "qtimer.h"
00026
#include "qapplication.h"
00027
#include "qlineedit.h"
00028
#include "qbitmap.h"
00029
#include "private/qeffects_p.h"
00030
#include "qstringlist.h"
00031
#include "qcombobox.h"
00032
#include "qstyle.h"
00033
#include "qheader.h"
00034
#include <limits.h>
00035
00036 class QComboViewData
00037 {
00038
public:
00039 QComboViewData(
QComboView *cb ):
current(0),
lView( 0 ),
combo( cb )
00040 {
00041
duplicatesEnabled = TRUE;
00042 cb->setSizePolicy(
QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ) );
00043 }
00044
00045 inline QListView *
listView() {
return lView; }
00046
void updateLinedGeometry();
00047
00048 void setListView(
QListView *l ) {
lView = l ;
00049 l->setMouseTracking( TRUE );}
00050
00051 QListViewItem *
current;
00052 int maxCount;
00053 int sizeLimit;
00054 QComboView::Policy
p;
00055 bool autoresize;
00056 bool poppedUp;
00057 bool mouseWasInsidePopup;
00058 bool arrowPressed;
00059 bool arrowDown;
00060 bool discardNextMousePress;
00061 bool shortClick;
00062 bool useCompletion;
00063 bool completeNow;
00064 int completeAt;
00065 bool duplicatesEnabled;
00066 int fullHeight,
currHeight;
00067
00068 QLineEdit *
ed;
00069 QTimer *
completionTimer;
00070
00071 QSize sizeHint;
00072
00073
private:
00074 bool usinglView;
00075 QListView *
lView;
00076 QComboView *
combo;
00077
00078 };
00079
00080 void QComboViewData::updateLinedGeometry()
00081 {
00082
if ( !
ed || !
combo )
00083
return;
00084
QRect r = QStyle::visualRect(
combo->style().querySubControlMetrics(QStyle::CC_ComboBox,
combo,
00085 QStyle::SC_ComboBoxEditField),
combo );
00086
00087
00088
const QPixmap *pix =
combo->
currentItem() ?
combo->
currentItem()->pixmap(0) : 0;
00089
if ( pix && pix->width() < r.width() )
00090 r.setLeft( r.left() + pix->width() + 4 );
00091
if ( r !=
ed->geometry() )
00092
ed->setGeometry( r );
00093 }
00094
00095 static inline bool checkInsertIndex(
const char *method,
const char * name,
00096
int count,
int *index)
00097 {
00098
bool range_err = (*index > count);
00099
#if defined(QT_CHECK_RANGE)
00100
if ( range_err )
00101 qWarning(
"QComboView::%s: (%s) Index %d out of range",
00102 method, name ? name :
"<no name>", *index );
00103
#else
00104
Q_UNUSED( method )
00105 Q_UNUSED( name )
00106 #endif
00107
if ( *index < 0 )
00108 *index = count;
00109
return !range_err;
00110 }
00111
00112
00113 static inline bool checkIndex(
const char *method,
const char * name,
00114
int count,
int index )
00115 {
00116
bool range_err = (index >= count);
00117
#if defined(QT_CHECK_RANGE)
00118
if ( range_err )
00119 qWarning(
"QComboView::%s: (%s) Index %i out of range",
00120 method, name ? name :
"<no name>", index );
00121
#else
00122
Q_UNUSED( method )
00123 Q_UNUSED( name )
00124 #endif
00125
return !range_err;
00126 }
00127
00128
00141 QComboView::QComboView(
bool rw,
QWidget *parent,
const char *name )
00142 :
QWidget( parent, name, WResizeNoErase )
00143 {
00144
d =
new QComboViewData(
this );
00145
setUpListView();
00146
00147
d->
current = 0;
00148
d->
maxCount = INT_MAX;
00149
setSizeLimit(10);
00150
d->
p =
AtBottom;
00151
d->
autoresize = FALSE;
00152
d->
poppedUp = FALSE;
00153
d->
arrowDown = FALSE;
00154
d->
discardNextMousePress = FALSE;
00155
d->
shortClick = FALSE;
00156
d->
useCompletion = FALSE;
00157
d->
completeAt = 0;
00158
d->
completeNow = FALSE;
00159
d->
completionTimer =
new QTimer(
this );
00160
00161 setFocusPolicy( StrongFocus );
00162
00163
d->
ed = 0;
00164
if ( rw )
00165
setUpLineEdit();
00166 setBackgroundMode( PaletteButton, PaletteBase );
00167 }
00168
00169
00170
00175 QComboView::~QComboView()
00176 {
00177
delete d;
00178 }
00179
00180 void QComboView::setDuplicatesEnabled(
bool enable )
00181 {
00182
d->
duplicatesEnabled = enable;
00183 }
00184
00185
bool QComboView::duplicatesEnabled()
const
00186
{
00187
return d->
duplicatesEnabled;
00188 }
00189
00190 int QComboView::childCount()
const
00191
{
00192
return d->
listView()->childCount();
00193 }
00194
00195
00200 void QComboView::clear()
00201 {
00202
d->
listView()->resize( 0, 0 );
00203
d->
listView()->clear();
00204
00205
d->
current = 0;
00206
if (
d->
ed ) {
00207
d->
ed->setText( QString::fromLatin1(
"") );
00208
d->
updateLinedGeometry();
00209 }
00210
currentChanged();
00211 }
00212
00213 QListViewItem *
QComboView::currentItem()
const
00214
{
00215
return d->
current;
00216 }
00217
00218 void QComboView::setCurrentItem(
QListViewItem *item )
00219 {
00220
if ( item ==
d->
current && !
d->
ed ) {
00221
return;
00222 }
00223
00224
if (!item)
00225 {
00226
d->
current = 0;
00227
if (
d->
ed ) {
00228
00229
d->
updateLinedGeometry();
00230 }
00231
return;
00232 }
00233
00234
d->
current = item;
00235
d->
completeAt = 0;
00236
if (
d->
ed ) {
00237
d->
ed->setText( item->text(0) );
00238
00239
d->
updateLinedGeometry();
00240 }
00241
if (
d->
listView() ) {
00242
d->
listView()->setCurrentItem( item );
00243 }
else {
00244
internalHighlight( item );
00245
00246 }
00247
00248
currentChanged();
00249
00250
d->
listView()->ensureItemVisible(item);
00251 }
00252
00253
bool QComboView::autoResize()
const
00254
{
00255
return d->
autoresize;
00256 }
00257
00258 void QComboView::setAutoResize(
bool enable )
00259 {
00260
if ( (
bool)
d->
autoresize != enable ) {
00261
d->
autoresize = enable;
00262
if ( enable )
00263 adjustSize();
00264 }
00265 }
00266
00267
00275 QSize QComboView::sizeHint()
const
00276
{
00277
if ( isVisible() &&
d->
sizeHint.isValid() )
00278
return d->
sizeHint;
00279
00280 constPolish();
00281
00282
QFontMetrics fm = fontMetrics();
00283
00284
int maxW =
childCount() ? 18 : 7 * fm.width(
QChar(
'x')) + 18;
00285
int maxH = QMAX( fm.lineSpacing(), 14 ) + 2;
00286
00287
00288
00289
00290
00291
00292
00293
d->
sizeHint = (style().sizeFromContents(QStyle::CT_ComboBox,
this,
00294
QSize(maxW, maxH)).expandedTo(QApplication::globalStrut()));
00295
00296
return d->
sizeHint;
00297 }
00298
00299
00306 void QComboView::internalActivate(
QListViewItem * item )
00307 {
00308
if (!item)
00309 {
00310
d->
current = 0;
00311
if (
d->
ed ) {
00312
00313
d->
updateLinedGeometry();
00314 }
00315
return;
00316 }
00317
popDownListView();
00318
d->
poppedUp = FALSE;
00319
00320
d->
current = item;
00321
00322
QString t( item->text(0) );
00323
if (
d->
ed ) {
00324
d->
ed->setText( t );
00325
00326
d->
updateLinedGeometry();
00327 }
00328 emit
activated( item );
00329 emit activated( t );
00330
00331
00332 }
00333
00340 void QComboView::internalHighlight(
QListViewItem * item )
00341 {
00342
if (!item)
00343 {
00344
d->
current = 0;
00345
if (
d->
ed ) {
00346
00347
d->
updateLinedGeometry();
00348 }
00349
return;
00350 }
00351 emit
highlighted( item );
00352
QString t = item->text(0);
00353
if ( !t.isNull() )
00354 emit highlighted( t );
00355 }
00356
00362 void QComboView::internalClickTimeout()
00363 {
00364
d->
shortClick = FALSE;
00365 }
00366
00372 void QComboView::setPalette(
const QPalette &palette )
00373 {
00374 QWidget::setPalette( palette );
00375
if(
d ) {
00376
if(
d->
listView())
00377
d->
listView()->setPalette( palette );
00378 }
00379 }
00380
00386 void QComboView::setFont(
const QFont &font )
00387 {
00388
d->
sizeHint =
QSize();
00389 QWidget::setFont( font );
00390
d->
listView()->setFont( font );
00391
if (
d->
ed)
00392
d->
ed->setFont( font );
00393
if (
d->
autoresize )
00394 adjustSize();
00395 }
00396
00397
00401 void QComboView::resizeEvent(
QResizeEvent * e )
00402 {
00403
if (
d->
ed )
00404
d->
updateLinedGeometry();
00405
d->
listView()->resize( width(),
d->
listView()->height() );
00406 QWidget::resizeEvent( e );
00407 }
00408
00412 void QComboView::paintEvent(
QPaintEvent * )
00413 {
00414
QPainter p(
this );
00415
const QColorGroup & g = colorGroup();
00416 p.setPen(g.text());
00417
00418 QStyle::SFlags flags = QStyle::Style_Default;
00419
if (isEnabled())
00420 flags |= QStyle::Style_Enabled;
00421
if (hasFocus())
00422 flags |= QStyle::Style_HasFocus;
00423
00424
if ( width() < 5 || height() < 5 ) {
00425 qDrawShadePanel( &p, rect(), g, FALSE, 2,
00426 &g.brush( QColorGroup::Button ) );
00427
return;
00428 }
00429
00430
00431 style().drawComplexControl( QStyle::CC_ComboBox, &p,
this, rect(), g,
00432 flags, QStyle::SC_All,
00433 (
d->
arrowDown ?
00434 QStyle::SC_ComboBoxArrow :
00435 QStyle::SC_None ));
00436
00437
QRect re = style().querySubControlMetrics( QStyle::CC_ComboBox,
this,
00438 QStyle::SC_ComboBoxEditField );
00439 re = QStyle::visualRect(re,
this);
00440 p.setClipRect( re );
00441
00442
if ( !
d->
ed ) {
00443
QListViewItem * item =
d->
current;
00444
if ( item ) {
00445
00446
int itemh =
d->
listView()->fontMetrics().lineSpacing() + 2;
00447 p.
translate( re.x(), re.y() + (re.height() - itemh)/2 );
00448 item->paintCell( &p,
d->
listView()->colorGroup(), 0, width(), AlignLeft | AlignVCenter );
00449 }
00450 }
else if (
d->
listView() &&
d->
listView()->currentItem( ) &&
d->
current ) {
00451
QListViewItem * item =
d->
current ;
00452
const QPixmap *pix = item->pixmap(0);
00453
if ( pix ) {
00454 p.fillRect( re.x(), re.y(), pix->width() + 4, re.height(),
00455 colorGroup().brush( QColorGroup::Base ) );
00456 p.drawPixmap( re.x() + 2, re.y() +
00457 ( re.height() - pix->height() ) / 2, *pix );
00458 }
00459 }
00460 p.setClipping( FALSE );
00461 }
00462
00463
00467 void QComboView::mousePressEvent(
QMouseEvent *e )
00468 {
00469
if ( e->button() != LeftButton )
00470
return;
00471
if (
d->
discardNextMousePress ) {
00472
d->
discardNextMousePress = FALSE;
00473
return;
00474 }
00475
QRect arrowRect = style().querySubControlMetrics( QStyle::CC_ComboBox,
this,
00476 QStyle::SC_ComboBoxArrow);
00477 arrowRect = QStyle::visualRect(arrowRect,
this);
00478
00479
00480
00481 arrowRect.setHeight( QMAX( height() - (2 * arrowRect.y()), arrowRect.height() ) );
00482
00483
if (
childCount() && ( !
editable() || arrowRect.contains( e->pos() ) ) ) {
00484
d->
arrowPressed = FALSE;
00485
listView()->blockSignals( TRUE );
00486 qApp->sendEvent(
listView(), e );
00487
listView()->blockSignals( FALSE );
00488
popup();
00489
if ( arrowRect.contains( e->pos() ) ) {
00490
d->
arrowPressed = TRUE;
00491
d->
arrowDown = TRUE;
00492 repaint( FALSE );
00493 }
00494 QTimer::singleShot( 200,
this, SLOT(
internalClickTimeout()));
00495
d->
shortClick = TRUE;
00496 }
00497 }
00498
00502 void QComboView::mouseMoveEvent(
QMouseEvent * )
00503 {
00504 }
00505
00509 void QComboView::mouseReleaseEvent(
QMouseEvent * )
00510 {
00511 }
00512
00516 void QComboView::mouseDoubleClickEvent(
QMouseEvent *e )
00517 {
00518
mousePressEvent( e );
00519 }
00520
00521
00525 void QComboView::keyPressEvent(
QKeyEvent *e )
00526 {
00527
QListViewItem *c =
currentItem();
00528
if ( ( e->key() == Key_F4 && e->state() == 0 ) ||
00529 ( e->key() == Key_Down && (e->state() & AltButton) ) ||
00530 ( !
d->
ed && e->key() == Key_Space ) ) {
00531
if (
childCount() ) {
00532
popup();
00533 }
00534
return;
00535 }
else if ( e->key() == Key_Up ) {
00536
00537
00538
if (c && c->itemAbove() )
00539
setCurrentItem( c->itemAbove() );
00540
else
00541
return;
00542 }
else if ( e->key() == Key_Down ) {
00543
if ((!c) && (
listView()->firstChild()))
00544 {
00545
setCurrentItem(
listView()->firstChild());
00546
return;
00547 }
00548
if ( c && c->itemBelow() )
00549
setCurrentItem( c->itemBelow() );
00550
else
00551
return;
00552 }
else if ( e->key() == Key_Home && ( !
d->
ed || !
d->
ed->hasFocus() ) ) {
00553
if (
listView()->firstChild())
00554
setCurrentItem(
listView()->firstChild() );
00555
else
00556
return;
00557 }
else if ( e->key() == Key_End && ( !
d->
ed || !
d->
ed->hasFocus() ) ) {
00558
if (
listView()->lastItem())
00559
setCurrentItem(
listView()->lastItem() );
00560
else
00561
return;
00562 }
else if ( !
d->
ed && e->ascii() >= 32 && !e->text().isEmpty() ) {
00563
if ( !
d->
completionTimer->isActive() ) {
00564
d->
completeAt = 0;
00565 c =
completionIndex( e->text(), c->itemBelow() );
00566
if ( c ) {
00567
setCurrentItem( c );
00568
d->
completeAt = e->text().length();
00569 }
00570
else
00571
return;
00572 }
else {
00573
d->
completionTimer->stop();
00574
QString ct =
currentText().left(
d->
completeAt ) + e->text();
00575 c =
completionIndex( ct, c );
00576
if ( c == 0 &&
d->
completeAt > 0 ) {
00577 c = completionIndex( e->text(),
listView()->firstChild() );
00578 ct = e->text();
00579 }
00580
d->
completeAt = 0;
00581
if ( c ) {
00582
setCurrentItem( c );
00583
d->
completeAt = ct.length();
00584 }
00585
else
00586
return;
00587 }
00588
d->
completionTimer->start( 400, TRUE );
00589 }
else {
00590 e->ignore();
00591
return;
00592 }
00593
00594 c =
currentItem();
00595
if (
childCount() && c && !c->text(0).isNull() )
00596 emit
activated( c->text(0) );
00597 emit activated( c );
00598 }
00599
00600
QString QComboView::currentText()
const
00601
{
00602
if ( d->
ed )
00603
return d->
ed->text();
00604
else if ( d->
current )
00605
return currentItem()->text(0);
00606
else
00607
return QString::null;
00608 }
00609
00613 void QComboView::focusInEvent(
QFocusEvent * e )
00614 {
00615 QWidget::focusInEvent( e );
00616
d->
completeNow = FALSE;
00617
d->
completeAt = 0;
00618
00619 emit
focusGranted();
00620 }
00621
00625 void QComboView::focusOutEvent(
QFocusEvent * e )
00626 {
00627 QWidget::focusOutEvent( e );
00628
d->
completeNow = FALSE;
00629
d->
completeAt = 0;
00630
00631 emit
focusLost();
00632 }
00633
00637 void QComboView::wheelEvent(
QWheelEvent *e )
00638 {
00639
if (
d->
poppedUp ) {
00640 QApplication::sendEvent(
d->
listView(), e );
00641 }
else {
00642
if ( e->delta() > 0 ) {
00643
QListViewItem *c =
currentItem();
00644
if ( c && c->itemAbove() ) {
00645
setCurrentItem( c->itemAbove() );
00646 emit
activated(
currentItem() );
00647 emit activated(
currentText() );
00648 }
00649 }
else {
00650
QListViewItem *c =
currentItem();
00651
if ( c && c->itemBelow() ) {
00652
setCurrentItem( c->itemBelow() );
00653 emit
activated(
currentItem() );
00654 emit activated(
currentText() );
00655 }
00656 }
00657 e->accept();
00658 }
00659 }
00660
00661 int childCount(
QListViewItem *it)
00662 {
00663
int count = 1;
00664
QListViewItem * myChild = it->firstChild();
00665
while( myChild ) {
00666 count +=
childCount(myChild);
00667 myChild = myChild->nextSibling();
00668 }
00669
return count;
00670 }
00671
00672 int childCount(
QListView *lv)
00673 {
00674
int count = 0;
00675
QListViewItem * myChild = lv->firstChild();
00676
while( myChild ) {
00677 count +=
childCount(myChild);
00678
00679 myChild = myChild->nextSibling();
00680 }
00681
return count;
00682 }
00683
00689 static int listHeight(
QListView *l,
int )
00690 {
00691
00692
00693
00694
00695
int prefH = 0;
00696
int ch =
childCount(l);
00697 ch = QMIN(ch, 10);
00698
if (l->firstChild())
00699 {
00700 prefH = ch * l->firstChild()->height();
00701 }
00702
else
00703 prefH = l->sizeHint().height();
00704
00705
if (l->header()->isVisible())
00706 prefH += l->header()->sizeHint().height();
00707
00708
00709
00710
return prefH;
00711 }
00712
00719 void QComboView::popup()
00720 {
00721
if ( !
childCount() )
00722
return;
00723
00724
00725
QListView* lb =
d->
listView();
00726 lb->triggerUpdate( );
00727 lb->installEventFilter(
this );
00728 lb->viewport()->installEventFilter(
this );
00729
d->
mouseWasInsidePopup = FALSE;
00730
00731
int w = width();
00732
int h =
listHeight( lb,
d->
sizeLimit );
00733
#if KDE_VERSION > 305
00734
QRect screen = QApplication::desktop()->availableGeometry( const_cast<QComboView*>(
this) );
00735
#else
00736
QRect screen = geometry();
00737
#endif
00738
00739
int sx = screen.x();
00740
int sy = screen.y();
00741
int sw = screen.width();
00742
int sh = screen.height();
00743
QPoint pos = mapToGlobal(
QPoint(0,height()) );
00744
00745
int x = pos.x();
00746
int y = pos.y();
00747
00748
00749
if ( x + w > sx + sw )
00750 x = sx+sw - w;
00751
if ( x < sx )
00752 x = sx;
00753
if (y + h > sy+sh && y - h - height() >= 0 )
00754 y = y - h - height();
00755
#if KDE_VERSION >= 310
00756
QRect rect =
00757 style().querySubControlMetrics( QStyle::CC_ComboBox,
this,
00758 QStyle::SC_ComboBoxListBoxPopup,
00759
QStyleOption( x, y, w, h ) );
00760
if ( rect.isNull() )
00761 rect.setRect( x, y, w, h );
00762
#else
00763
QRect rect;
00764 rect.setRect( x, y, w, h );
00765
#endif
00766
lb->setGeometry( rect );
00767
00768 lb->raise();
00769
bool block = lb->signalsBlocked();
00770 lb->blockSignals( TRUE );
00771
QListViewItem *currentLBItem =
d->
current ;
00772 lb->setCurrentItem( currentLBItem );
00773
00774
if ( currentLBItem && currentLBItem->isSelectable() && !currentLBItem->isSelected() )
00775 lb->setSelected( currentLBItem, TRUE );
00776 lb->blockSignals( block );
00777 lb->setVScrollBarMode(QScrollView::Auto);
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 lb->show();
00788
d->
poppedUp = TRUE;
00789 }
00790
00791
00795 void QComboView::updateMask()
00796 {
00797
QBitmap bm(
size() );
00798 bm.fill( color0 );
00799
00800 {
00801
QPainter p( &bm,
this );
00802 style().drawComplexControlMask(QStyle::CC_ComboBox, &p,
this, rect());
00803 }
00804
00805 setMask( bm );
00806 }
00807
00812 void QComboView::popDownListView()
00813 {
00814
d->
listView()->removeEventFilter(
this );
00815
d->
listView()->viewport()->removeEventFilter(
this );
00816
d->
listView()->hide();
00817
d->
listView()->setCurrentItem(
d->
current );
00818
if (
d->
arrowDown ) {
00819
d->
arrowDown = FALSE;
00820 repaint( FALSE );
00821 }
00822
d->
poppedUp = FALSE;
00823 }
00824
00825
00831 void QComboView::reIndex()
00832 {
00833 }
00834
00840 void QComboView::currentChanged()
00841 {
00842
if (
d->
autoresize )
00843 adjustSize();
00844 update();
00845 }
00846
00858 bool QComboView::eventFilter(
QObject *object,
QEvent *event )
00859 {
00860
if ( !event )
00861
return TRUE;
00862
else if ( object ==
d->
ed ) {
00863
if ( event->type() == QEvent::KeyPress ) {
00864
bool isAccepted = ( (
QKeyEvent*)event )->isAccepted();
00865
keyPressEvent( (
QKeyEvent *)event );
00866
if ( ((
QKeyEvent *)event)->isAccepted() ) {
00867
d->
completeNow = FALSE;
00868
return TRUE;
00869 }
else if ( ((
QKeyEvent *)event)->key() != Key_End ) {
00870
d->
completeNow = TRUE;
00871
d->
completeAt =
d->
ed->cursorPosition();
00872 }
00873
if ( isAccepted )
00874 ( (
QKeyEvent*)event )->accept();
00875
else
00876 ( (
QKeyEvent*)event )->ignore();
00877 }
else if ( event->type() == QEvent::KeyRelease ) {
00878
d->
completeNow = FALSE;
00879 keyReleaseEvent( (
QKeyEvent *)event );
00880
return ((
QKeyEvent *)event)->isAccepted();
00881 }
else if ( event->type() == QEvent::FocusIn ) {
00882
focusInEvent( (
QFocusEvent *)event );
00883 }
else if ( event->type() == QEvent::FocusOut ) {
00884
focusOutEvent( (
QFocusEvent *)event );
00885 }
else if (
d->
useCompletion &&
d->
completeNow ) {
00886
if ( !
d->
ed->text().isNull() &&
00887
d->
ed->cursorPosition() >
d->
completeAt &&
00888
d->
ed->cursorPosition() == (
int)
d->
ed->text().length() ) {
00889
d->
completeNow = FALSE;
00890
QString ct(
d->
ed->text() );
00891
QListViewItem *i =
completionIndex( ct,
currentItem() );
00892
if ( i ) {
00893
QString it = i->text(0);
00894
d->
ed->validateAndSet( it, ct.length(),
00895 ct.length(), it.length() );
00896 }
00897 }
00898 }
00899 }
else if ( ( object ==
d->
listView() ||
00900 object ==
d->
listView()->viewport() )) {
00901
QMouseEvent *e = (
QMouseEvent*)event;
00902
switch( event->type() ) {
00903
case QEvent::MouseMove:
00904
if ( !
d->
mouseWasInsidePopup ) {
00905
00906
QPoint pos = e->pos();
00907
if (
d->
listView()->rect().contains( pos ) )
00908
d->
mouseWasInsidePopup = TRUE;
00909
00910
if (
d->
arrowPressed ) {
00911
QPoint comboPos;
00912 comboPos = mapFromGlobal(
d->
listView()->mapToGlobal(pos) );
00913
QRect arrowRect =
00914 style().querySubControlMetrics( QStyle::CC_ComboBox,
this,
00915 QStyle::SC_ComboBoxArrow);
00916 arrowRect = QStyle::visualRect(arrowRect,
this);
00917
if ( arrowRect.contains( comboPos ) ) {
00918
if ( !
d->
arrowDown ) {
00919
d->
arrowDown = TRUE;
00920 repaint( FALSE );
00921 }
00922 }
else {
00923
if (
d->
arrowDown ) {
00924
d->
arrowDown = FALSE;
00925 repaint( FALSE );
00926 }
00927 }
00928 }
00929 }
else if ((e->state() & ( RightButton | LeftButton | MidButton ) ) == 0 &&
00930 style().styleHint(QStyle::SH_ComboBox_ListMouseTracking,
this)) {
00931
00932
QWidget *mouseW = QApplication::widgetAt( e->globalPos(), TRUE );
00933
00934
if ( mouseW ==
d->
listView()->viewport() ) {
00935
QListViewItem *sel =
d->
listView()->itemAt(e->pos());
00936
if (sel)
00937 {
00938
d->
listView()->setCurrentItem(sel);
00939
d->
listView()->setSelected(sel,
true);
00940 }
00941
return TRUE;
00942 }
00943 }
00944
00945
break;
00946
case QEvent::MouseButtonRelease:
00947
if (
d->
listView()->rect().contains( e->pos() ) ) {
00948
QMouseEvent tmp( QEvent::MouseButtonDblClick,
00949 e->pos(), e->button(), e->state() ) ;
00950
00951 QApplication::sendEvent( object, &tmp );
00952
return TRUE;
00953 }
else {
00954
if (
d->
mouseWasInsidePopup ) {
00955
popDownListView();
00956 }
else {
00957
d->
arrowPressed = FALSE;
00958
if (
d->
arrowDown ) {
00959
d->
arrowDown = FALSE;
00960 repaint( FALSE );
00961 }
00962 }
00963 }
00964
break;
00965
case QEvent::MouseButtonDblClick:
00966
case QEvent::MouseButtonPress:
00967
if ( !
d->
listView()->rect().contains( e->pos() ) ) {
00968
QPoint globalPos =
d->
listView()->mapToGlobal(e->pos());
00969
if ( QApplication::widgetAt( globalPos, TRUE ) ==
this ) {
00970
d->
discardNextMousePress = TRUE;
00971
00972 }
00973
popDownListView();
00974
return TRUE;
00975 }
00976
break;
00977
case QEvent::KeyPress:
00978
switch( ((
QKeyEvent *)event)->key() ) {
00979
case Key_Up:
00980
case Key_Down:
00981
if ( !(((
QKeyEvent *)event)->state() & AltButton) )
00982
break;
00983
case Key_F4:
00984
case Key_Escape:
00985
if (
d->
poppedUp ) {
00986
popDownListView();
00987
return TRUE;
00988 }
00989
break;
00990
case Key_Enter:
00991
case Key_Return:
00992
00993
return FALSE;
00994
default:
00995
break;
00996 }
00997
break;
00998
case QEvent::Hide:
00999
popDownListView();
01000
break;
01001
default:
01002
break;
01003 }
01004 }
01005
return QWidget::eventFilter( object, event );
01006 }
01007
01008
01015 QListViewItem *
QComboView::completionIndex(
const QString & prefix,
01016
QListViewItem *startingAt )
const
01017
{
01018
QListViewItem *start = startingAt;
01019
01020
01021
01022
01023
if (!start)
01024 start =
listView()->firstChild();
01025
if (!start)
01026
return 0;
01027
01028
01029
QString match = prefix.lower();
01030
if ( match.length() < 1 )
01031
return start;
01032
01033
QString current;
01034
QListViewItem *i = start;
01035
do {
01036 current = i->text(0).lower();
01037
if ( current.startsWith( match ) )
01038
return i;
01039 i = i->itemBelow();
01040
if ( i )
01041 i =
listView()->firstChild();
01042 }
while ( i != start );
01043
return 0;
01044 }
01045
01046
01047
int QComboView::sizeLimit()
const
01048
{
01049
return d ? d->
sizeLimit : INT_MAX;
01050 }
01051
01052 void QComboView::setSizeLimit(
int lines )
01053 {
01054
d->
sizeLimit = lines;
01055 }
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071 QComboView::Policy
QComboView::insertionPolicy()
const
01072
{
01073
return d->
p;
01074 }
01075
01076 void QComboView::setInsertionPolicy( Policy policy )
01077 {
01078
d->
p = policy;
01079 }
01080
01081
01082
01087 void QComboView::returnPressed()
01088 {
01089
QString s(
d->
ed->text() );
01090
01091
if ( s.isEmpty() )
01092
return;
01093
01094
QListViewItem *c = 0;
01095
bool doInsert = TRUE;
01096
if ( !
d->
duplicatesEnabled ) {
01097 c =
listView()->findItem(s, 0);
01098
if ( c )
01099 doInsert = FALSE;
01100 }
01101
01102
if ( doInsert ) {
01103
if (
insertionPolicy() !=
NoInsertion ) {
01104
01105
01106
01107
01108 }
01109
01110
switch (
insertionPolicy() ) {
01111
case AtCurrent:
01112
if ( s !=
currentItem()->text(0) )
01113
currentItem()->setText(0, s);
01114 emit
activated(
currentItem() );
01115 emit activated( s );
01116
return;
01117
case NoInsertion:
01118 emit activated( s );
01119
return;
01120
case AtTop:
01121 c = 0;
01122
return;
01123
01124
case AtBottom:
01125 c =
new QListViewItem(
listView(),
listView()->lastItem(), s);
01126
break;
01127
case BeforeCurrent:
01128
if (
currentItem() &&
currentItem()->itemAbove())
01129 c =
new QListViewItem(
listView(),
currentItem()->itemAbove(), s);
01130
else
01131 {
01132 c = 0;
01133
return;
01134 }
01135
break;
01136
case AfterCurrent:
01137
if (
currentItem() &&
currentItem()->itemBelow())
01138 c =
new QListViewItem(
listView(),
currentItem()->itemBelow(), s);
01139
else
01140 {
01141 c = 0;
01142
return;
01143 }
01144
break;
01145 }
01146 }
01147
01148
if (c)
01149 {
01150
setCurrentItem( c );
01151 emit
activated( c );
01152 emit activated( s );
01153 }
01154 }
01155
01156
01160 void QComboView::setEnabled(
bool enable )
01161 {
01162 QWidget::setEnabled( enable );
01163 }
01164
01165
01166
01176 void QComboView::setValidator(
const QValidator * v )
01177 {
01178
if (
d &&
d->
ed )
01179
d->
ed->setValidator( v );
01180 }
01181
01182
01190 const QValidator *
QComboView::validator()
const
01191
{
01192
return d &&
d->
ed ?
d->
ed->validator() : 0;
01193 }
01194
01195
01200 void QComboView::clearValidator()
01201 {
01202
if (
d &&
d->
ed )
01203
d->
ed->setValidator( 0 );
01204 }
01205
01206
01217 void QComboView::setListView(
QListView * newListView )
01218 {
01219
clear();
01220
01221
delete d->
listView();
01222
01223 newListView->reparent(
this, WType_Popup,
QPoint(0,0), FALSE );
01224
d->
setListView( newListView );
01225
d->
listView()->setFont( font() );
01226
d->
listView()->setPalette( palette() );
01227
01228
01229
d->
listView()->setFrameStyle( QFrame::Box | QFrame::Plain );
01230
d->
listView()->setLineWidth( 1 );
01231
01232
01233
d->
listView()->resize( 100, 10 );
01234
01235
if (
d->
listView()->firstChild())
01236
d->
current =
d->
listView()->firstChild();
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253 connect(
d->
listView(), SIGNAL(
returnPressed(
QListViewItem*)),
01254 SLOT(
internalActivate(
QListViewItem*)));
01255 connect(
d->
listView(), SIGNAL(doubleClicked(
QListViewItem*)),
01256 SLOT(
internalActivate(
QListViewItem*)));
01257 connect(
d->
listView(), SIGNAL(doubleClicked(
QListViewItem*)),
01258 SLOT(
checkState(
QListViewItem*)));
01259 connect(
d->
listView(), SIGNAL(
currentChanged(
QListViewItem*)),
01260 SLOT(
internalHighlight(
QListViewItem*)));
01261 connect(
d->
listView(), SIGNAL(selectionChanged(
QListViewItem*)),
01262 SLOT(
internalHighlight(
QListViewItem*)));
01263 }
01264
01265
01274 QListView *
QComboView::listView()
const
01275
{
01276
return d ?
d->
listView() : 0;
01277 }
01278
01284 QLineEdit*
QComboView::lineEdit()
const
01285
{
01286
return d->
ed;
01287 }
01288
01289
01290
01303 void QComboView::clearEdit()
01304 {
01305
if (
d &&
d->
ed )
01306
d->
ed->clear();
01307 }
01308
01309
01321 void QComboView::setEditText(
const QString &newText )
01322 {
01323
if (
d &&
d->
ed ) {
01324
d->
updateLinedGeometry();
01325
d->
ed->setText( newText );
01326 }
01327 }
01328
01329 void QComboView::setAutoCompletion(
bool enable )
01330 {
01331
d->
useCompletion = enable;
01332
d->
completeNow = FALSE;
01333 }
01334
01335
01336
bool QComboView::autoCompletion()
const
01337
{
01338
return d->
useCompletion;
01339 }
01340
01343 void QComboView::styleChange(
QStyle& s )
01344 {
01345
d->
sizeHint =
QSize();
01346
if (
d->
ed )
01347
d->
updateLinedGeometry();
01348 QWidget::styleChange( s );
01349 }
01350
01351
bool QComboView::editable()
const
01352
{
01353
return d->
ed != 0;
01354 }
01355
01356 void QComboView::setEditable(
bool y )
01357 {
01358
if ( y ==
editable() )
01359
return;
01360
if ( y ) {
01361
setUpListView();
01362
setUpLineEdit();
01363
d->
ed->show();
01364
if (
currentItem() )
01365
setEditText(
currentText() );
01366 }
else {
01367
delete d->
ed;
01368
d->
ed = 0;
01369 }
01370
01371 setFocusPolicy( StrongFocus );
01372 updateGeometry();
01373 update();
01374 }
01375
01376
01377 void QComboView::setUpListView()
01378 {
01379
d->
setListView(
new QListView(
this,
"in-combo", WType_Popup ) );
01380
01381
d->
listView()->setFont( font() );
01382
d->
listView()->setPalette( palette() );
01383
01384
01385
d->
listView()->setFrameStyle( QFrame::Box | QFrame::Plain );
01386
d->
listView()->setLineWidth( 1 );
01387
d->
listView()->setRootIsDecorated(
false );
01388
d->
listView()->setAllColumnsShowFocus(
true);
01389
d->
listView()->addColumn(
"");
01390
d->
listView()->resize( 100, 10 );
01391
d->
listView()->setResizeMode(QListView::LastColumn);
01392
01393
if (
d->
listView()->firstChild())
01394
d->
current =
d->
listView()->firstChild();
01395
01396
d->
listView()->header()->hide();
01397
01398 connect(
d->
listView(), SIGNAL(
returnPressed(
QListViewItem*)),
01399 SLOT(
internalActivate(
QListViewItem*)));
01400 connect(
d->
listView(), SIGNAL(doubleClicked(
QListViewItem*)),
01401 SLOT(
internalActivate(
QListViewItem*)));
01402 connect(
d->
listView(), SIGNAL(doubleClicked(
QListViewItem*)),
01403 SLOT(
checkState(
QListViewItem*)));
01404 connect(
d->
listView(), SIGNAL(
currentChanged(
QListViewItem*)),
01405 SLOT(
internalHighlight(
QListViewItem*)));
01406 connect(
d->
listView(), SIGNAL(selectionChanged(
QListViewItem*)),
01407 SLOT(
internalHighlight(
QListViewItem*)));
01408 }
01409
01410
01411 void QComboView::setUpLineEdit()
01412 {
01413
if ( !
d->
ed )
01414
setLineEdit(
new QLineEdit(
this,
"combo edit" ) );
01415 }
01416
01421 void QComboView::setLineEdit(
QLineEdit *edit )
01422 {
01423
if ( !edit ) {
01424
#if defined(QT_CHECK_NULL)
01425
Q_ASSERT( edit != 0 );
01426
#endif
01427
return;
01428 }
01429
01430 edit->setText(
currentText() );
01431
if (
d->
ed ) {
01432
int start = 0, end = 0;
01433
d->
ed->getSelection( &start, &end );
01434 edit->setSelection( start, end );
01435 edit->setCursorPosition(
d->
ed->cursorPosition() );
01436 edit->setEdited(
d->
ed->edited() );
01437
delete d->
ed;
01438 }
01439
01440
d->
ed = edit;
01441
01442
if ( edit->parent() !=
this ) {
01443 edit->reparent(
this,
QPoint(0,0), FALSE );
01444 edit->setFont( font() );
01445 }
01446
01447 connect (edit, SIGNAL(
textChanged(
const QString& ) ),
01448
this, SIGNAL(
textChanged(
const QString& ) ) );
01449 connect( edit, SIGNAL(
returnPressed()), SLOT(
returnPressed()) );
01450
01451 edit->setFrame( FALSE );
01452
d->
updateLinedGeometry();
01453 edit->installEventFilter(
this );
01454 setFocusProxy( edit );
01455 setFocusPolicy( StrongFocus );
01456
01457
setUpListView();
01458
01459
if ( isVisible() )
01460 edit->show();
01461
01462 updateGeometry();
01463 update();
01464 }
01465
01466 void QComboView::setCurrentText(
const QString& txt )
01467 {
01468
QListViewItem *i;
01469 i =
listView()->findItem(txt, 0);
01470
if ( i )
01471
setCurrentItem( i );
01472
else if (
d->
ed )
01473
d->
ed->setText( txt );
01474
else if (
currentItem())
01475
currentItem()->setText(0, txt);
01476 }
01477
01478 void QComboView::checkState(
QListViewItem * item)
01479 {
01480 item->setOpen(!item->isOpen());
01481 }
01482
01483 void QComboView::setCurrentActiveItem(
QListViewItem * item )
01484 {
01485
if ( item ==
d->
current && !
d->
ed ) {
01486
return;
01487 }
01488
01489
d->
current = item;
01490
d->
completeAt = 0;
01491
if (
d->
ed ) {
01492
d->
ed->setText( item->text(0) );
01493
01494
d->
updateLinedGeometry();
01495 }
01496
if (
d->
listView() ) {
01497
d->
listView()->setCurrentItem( item );
01498 emit
activated( item );
01499 emit activated( item->text(0) );
01500 }
else {
01501
internalHighlight( item );
01502
internalActivate( item );
01503 }
01504
01505
currentChanged();
01506
01507
d->
listView()->ensureItemVisible(item);
01508 }
01509
01510
#include "qcomboview.moc"
01511
01512
#endif // QT_NO_COMBOBOX
01513