00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdlib.h>
00024
00025 #include <qclipboard.h>
00026 #include <qlistbox.h>
00027 #include <qpopupmenu.h>
00028 #include <qapplication.h>
00029
00030 #include <kcompletionbox.h>
00031 #include <kcursor.h>
00032 #include <kiconloader.h>
00033 #include <kicontheme.h>
00034 #include <klineedit.h>
00035 #include <klocale.h>
00036 #include <knotifyclient.h>
00037 #include <kpixmapprovider.h>
00038 #include <kstdaccel.h>
00039 #include <kurl.h>
00040 #include <kurldrag.h>
00041
00042 #include <kdebug.h>
00043
00044 #include "kcombobox.h"
00045
00046 class KComboBox::KComboBoxPrivate
00047 {
00048 public:
00049 KComboBoxPrivate()
00050 {
00051 klineEdit = 0L;
00052 }
00053 ~KComboBoxPrivate()
00054 {
00055 }
00056
00057 KLineEdit *klineEdit;
00058 };
00059
00060 KComboBox::KComboBox( QWidget *parent, const char *name )
00061 : QComboBox( parent, name )
00062 {
00063 init();
00064 }
00065
00066 KComboBox::KComboBox( bool rw, QWidget *parent, const char *name )
00067 : QComboBox( rw, parent, name )
00068 {
00069 init();
00070
00071 if ( rw )
00072 {
00073 KLineEdit *edit = new KLineEdit( this, "combo lineedit" );
00074 setLineEdit( edit );
00075 }
00076 }
00077
00078 KComboBox::~KComboBox()
00079 {
00080 delete d;
00081 }
00082
00083 void KComboBox::init()
00084 {
00085 d = new KComboBoxPrivate;
00086
00087
00088 QComboBox::setAutoCompletion( false );
00089
00090
00091
00092 setContextMenuEnabled( true );
00093
00094
00095 installEventFilter( this );
00096 if ( lineEdit() )
00097 {
00098 connect( lineEdit(), SIGNAL( returnPressed() ),
00099 this, SIGNAL( returnPressed() ));
00100 }
00101 }
00102
00103
00104 bool KComboBox::contains( const QString& _text ) const
00105 {
00106 if ( _text.isEmpty() )
00107 return false;
00108
00109 for (int i = 0; i < count(); i++ )
00110 {
00111 if ( text(i) == _text )
00112 return true;
00113 }
00114 return false;
00115 }
00116
00117 void KComboBox::setAutoCompletion( bool autocomplete )
00118 {
00119 if ( d->klineEdit )
00120 {
00121 if ( autocomplete )
00122 {
00123 d->klineEdit->setCompletionMode( KGlobalSettings::CompletionAuto );
00124 setCompletionMode( KGlobalSettings::CompletionAuto );
00125 }
00126 else
00127 {
00128 d->klineEdit->setCompletionMode( KGlobalSettings::completionMode() );
00129 setCompletionMode( KGlobalSettings::completionMode() );
00130 }
00131 }
00132 }
00133
00134 void KComboBox::setContextMenuEnabled( bool showMenu )
00135 {
00136 if( d->klineEdit )
00137 d->klineEdit->setContextMenuEnabled( showMenu );
00138 }
00139
00140
00141 void KComboBox::setURLDropsEnabled( bool enable )
00142 {
00143 if ( d->klineEdit )
00144 d->klineEdit->setURLDropsEnabled( enable );
00145 }
00146
00147 bool KComboBox::isURLDropsEnabled() const
00148 {
00149 return d->klineEdit && d->klineEdit->isURLDropsEnabled();
00150 }
00151
00152
00153 void KComboBox::setCompletedText( const QString& text, bool marked )
00154 {
00155 if ( d->klineEdit )
00156 d->klineEdit->setCompletedText( text, marked );
00157 }
00158
00159 void KComboBox::setCompletedText( const QString& text )
00160 {
00161 if ( d->klineEdit )
00162 d->klineEdit->setCompletedText( text );
00163 }
00164
00165 void KComboBox::makeCompletion( const QString& text )
00166 {
00167 if( d->klineEdit )
00168 d->klineEdit->makeCompletion( text );
00169
00170 else
00171 {
00172 if( text.isNull() || !listBox() )
00173 return;
00174
00175 int index = listBox()->index( listBox()->findItem( text ) );
00176 if( index >= 0 )
00177 setCurrentItem( index );
00178 }
00179 }
00180
00181 void KComboBox::rotateText( KCompletionBase::KeyBindingType type )
00182 {
00183 if ( d->klineEdit )
00184 d->klineEdit->rotateText( type );
00185 }
00186
00187
00188 bool KComboBox::eventFilter( QObject* o, QEvent* ev )
00189 {
00190 return QComboBox::eventFilter( o, ev );
00191 }
00192
00193 void KComboBox::setTrapReturnKey( bool grab )
00194 {
00195 if ( d->klineEdit )
00196 d->klineEdit->setTrapReturnKey( grab );
00197 else
00198 qWarning("KComboBox::setTrapReturnKey not supported with a non-KLineEdit.");
00199 }
00200
00201 bool KComboBox::trapReturnKey() const
00202 {
00203 return d->klineEdit && d->klineEdit->trapReturnKey();
00204 }
00205
00206
00207 void KComboBox::setEditURL( const KURL& url )
00208 {
00209 QComboBox::setEditText( url.prettyURL() );
00210 }
00211
00212 void KComboBox::insertURL( const KURL& url, int index )
00213 {
00214 QComboBox::insertItem( url.prettyURL(), index );
00215 }
00216
00217 void KComboBox::insertURL( const QPixmap& pixmap, const KURL& url, int index )
00218 {
00219 QComboBox::insertItem( pixmap, url.prettyURL(), index );
00220 }
00221
00222 void KComboBox::changeURL( const KURL& url, int index )
00223 {
00224 QComboBox::changeItem( url.prettyURL(), index );
00225 }
00226
00227 void KComboBox::changeURL( const QPixmap& pixmap, const KURL& url, int index )
00228 {
00229 QComboBox::changeItem( pixmap, url.prettyURL(), index );
00230 }
00231
00232 void KComboBox::setCompletedItems( const QStringList& items )
00233 {
00234 if ( d->klineEdit )
00235 d->klineEdit->setCompletedItems( items );
00236 }
00237
00238 KCompletionBox * KComboBox::completionBox( bool create )
00239 {
00240 if ( d->klineEdit )
00241 return d->klineEdit->completionBox( create );
00242 return 0;
00243 }
00244
00245
00246 void KComboBox::create( WId id, bool initializeWindow, bool destroyOldWindow )
00247 {
00248 QComboBox::create( id, initializeWindow, destroyOldWindow );
00249 KCursor::setAutoHideCursor( lineEdit(), true, true );
00250 }
00251
00252 void KComboBox::wheelEvent( QWheelEvent *ev )
00253 {
00254
00255 QComboBox::wheelEvent( ev );
00256 }
00257
00258 void KComboBox::setLineEdit( QLineEdit *edit )
00259 {
00260 if ( !editable() && edit &&
00261 qstrcmp( edit->className(), "QLineEdit" ) == 0 )
00262 {
00263
00264
00265
00266
00267
00268 delete edit;
00269 edit = new KLineEdit( this, "combo edit" );
00270 }
00271
00272 QComboBox::setLineEdit( edit );
00273 d->klineEdit = dynamic_cast<KLineEdit*>( edit );
00274 setDelegate( d->klineEdit );
00275
00276
00277 if ( edit )
00278 connect( edit, SIGNAL( returnPressed() ), SIGNAL( returnPressed() ));
00279
00280 if ( d->klineEdit )
00281 {
00282
00283
00284
00285
00286 connect( edit, SIGNAL( destroyed() ), SLOT( lineEditDeleted() ));
00287
00288 connect( d->klineEdit, SIGNAL( returnPressed( const QString& )),
00289 SIGNAL( returnPressed( const QString& ) ));
00290
00291 connect( d->klineEdit, SIGNAL( completion( const QString& )),
00292 SIGNAL( completion( const QString& )) );
00293
00294 connect( d->klineEdit, SIGNAL( substringCompletion( const QString& )),
00295 SIGNAL( substringCompletion( const QString& )) );
00296
00297 connect( d->klineEdit,
00298 SIGNAL( textRotation( KCompletionBase::KeyBindingType )),
00299 SIGNAL( textRotation( KCompletionBase::KeyBindingType )) );
00300
00301 connect( d->klineEdit,
00302 SIGNAL( completionModeChanged( KGlobalSettings::Completion )),
00303 SIGNAL( completionModeChanged( KGlobalSettings::Completion)));
00304
00305 connect( d->klineEdit,
00306 SIGNAL( aboutToShowContextMenu( QPopupMenu * )),
00307 SIGNAL( aboutToShowContextMenu( QPopupMenu * )) );
00308
00309 connect( d->klineEdit,
00310 SIGNAL( completionBoxActivated( const QString& )),
00311 SIGNAL( activated( const QString& )) );
00312 }
00313 }
00314
00315 void KComboBox::setCurrentItem( const QString& item, bool insert, int index )
00316 {
00317 int sel = -1;
00318
00319 for (int i = 0; i < count(); ++i)
00320 {
00321 if (text(i) == item)
00322 {
00323 sel = i;
00324 break;
00325 }
00326 }
00327
00328 if (sel == -1 && insert)
00329 {
00330 insertItem(item, index);
00331 if (index >= 0)
00332 sel = index;
00333 else
00334 sel = count() - 1;
00335 }
00336 setCurrentItem(sel);
00337 }
00338
00339 void KComboBox::lineEditDeleted()
00340 {
00341
00342
00343
00344 const KCompletionBase *base = static_cast<const KCompletionBase*>( static_cast<const KLineEdit*>( sender() ));
00345
00346
00347 if ( base == delegate() )
00348 setDelegate( 0L );
00349 }
00350
00351
00352
00353
00354
00355
00356 KHistoryCombo::KHistoryCombo( QWidget *parent, const char *name )
00357 : KComboBox( true, parent, name )
00358 {
00359 init( true );
00360 }
00361
00362
00363 KHistoryCombo::KHistoryCombo( bool useCompletion,
00364 QWidget *parent, const char *name )
00365 : KComboBox( true, parent, name )
00366 {
00367 init( useCompletion );
00368 }
00369
00370 void KHistoryCombo::init( bool useCompletion )
00371 {
00372 if ( useCompletion )
00373 completionObject()->setOrder( KCompletion::Weighted );
00374
00375 setInsertionPolicy( NoInsertion );
00376 myIterateIndex = -1;
00377 myRotated = false;
00378 myPixProvider = 0L;
00379
00380
00381 QCString histControl = getenv("HISTCONTROL");
00382 if ( histControl == "ignoredups" || histControl == "ignoreboth" )
00383 setDuplicatesEnabled( false );
00384
00385 connect( this, SIGNAL(aboutToShowContextMenu(QPopupMenu*)),
00386 SLOT(addContextMenuItems(QPopupMenu*)) );
00387 connect( this, SIGNAL( activated(int) ), SLOT( slotReset() ));
00388 connect( this, SIGNAL( returnPressed(const QString&) ), SLOT(slotReset()));
00389 }
00390
00391 KHistoryCombo::~KHistoryCombo()
00392 {
00393 delete myPixProvider;
00394 }
00395
00396 void KHistoryCombo::setHistoryItems( QStringList items,
00397 bool setCompletionList )
00398 {
00399 KComboBox::clear();
00400
00401
00402 while ( (int) items.count() > maxCount() && !items.isEmpty() )
00403 items.remove( items.begin() );
00404
00405 insertItems( items );
00406
00407 if ( setCompletionList && useCompletion() ) {
00408
00409 KCompletion *comp = completionObject();
00410 comp->setOrder( KCompletion::Insertion );
00411 comp->setItems( items );
00412 comp->setOrder( KCompletion::Weighted );
00413 }
00414
00415 clearEdit();
00416 }
00417
00418 QStringList KHistoryCombo::historyItems() const
00419 {
00420 QStringList list;
00421 for ( int i = 0; i < count(); i++ )
00422 list.append( text( i ) );
00423
00424 return list;
00425 }
00426
00427 void KHistoryCombo::clearHistory()
00428 {
00429 KComboBox::clear();
00430 if ( useCompletion() )
00431 completionObject()->clear();
00432 }
00433
00434 void KHistoryCombo::addContextMenuItems( QPopupMenu* menu )
00435 {
00436 if ( menu &&!lineEdit()->text().isEmpty())
00437 {
00438 menu->insertSeparator();
00439 menu->insertItem( i18n("Empty Contents"), this, SLOT( slotClear()));
00440 }
00441 }
00442
00443 void KHistoryCombo::addToHistory( const QString& item )
00444 {
00445 if ( item.isEmpty() || (count() > 0 && item == text(0) )) {
00446 return;
00447 }
00448
00449 bool wasCurrent = false;
00450
00451 if ( !duplicatesEnabled() ) {
00452 for ( int i = 0; i < count(); i++ ) {
00453 if ( text( i ) == item ) {
00454 if ( !wasCurrent )
00455 wasCurrent = ( i == currentItem() );
00456 removeItem( i );
00457 }
00458 }
00459 }
00460
00461
00462 if ( myPixProvider )
00463 insertItem( myPixProvider->pixmapFor(item, KIcon::SizeSmall), item, 0);
00464 else
00465 insertItem( item, 0 );
00466
00467 if ( wasCurrent )
00468 setCurrentItem( 0 );
00469
00470 int last;
00471 QString rmItem;
00472
00473 bool useComp = useCompletion();
00474 while ( count() > maxCount() && count() > 0 ) {
00475
00476
00477
00478 last = count() - 1;
00479 rmItem = text( last );
00480 removeItem( last );
00481 if ( useComp && !contains( rmItem ) )
00482 completionObject()->removeItem( rmItem );
00483 }
00484
00485 if ( useComp )
00486 completionObject()->addItem( item );
00487 }
00488
00489 bool KHistoryCombo::removeFromHistory( const QString& item )
00490 {
00491 if ( item.isEmpty() )
00492 return false;
00493
00494 bool removed = false;
00495 QString temp = currentText();
00496 for ( int i = 0; i < count(); i++ ) {
00497 while ( item == text( i ) ) {
00498 removed = true;
00499 removeItem( i );
00500 }
00501 }
00502
00503 if ( removed && useCompletion() )
00504 completionObject()->removeItem( item );
00505
00506 setEditText( temp );
00507 return removed;
00508 }
00509
00510 void KHistoryCombo::rotateUp()
00511 {
00512
00513 if ( myIterateIndex == -1 )
00514 myText = currentText();
00515
00516 myIterateIndex++;
00517
00518
00519 while ( myIterateIndex < count()-1 &&
00520 (currentText() == text( myIterateIndex ) ||
00521 text( myIterateIndex ).isEmpty()) )
00522 myIterateIndex++;
00523
00524 if ( myIterateIndex >= count() ) {
00525 myRotated = true;
00526 myIterateIndex = -1;
00527
00528
00529 if ( myText == text(0) )
00530 myIterateIndex = 0;
00531
00532 setEditText( myText );
00533 }
00534 else
00535 setEditText( text( myIterateIndex ));
00536 }
00537
00538 void KHistoryCombo::rotateDown()
00539 {
00540
00541 if ( myIterateIndex == -1 )
00542 myText = currentText();
00543
00544 myIterateIndex--;
00545
00546
00547 while ( myIterateIndex >= 0 &&
00548 (currentText() == text( myIterateIndex ) ||
00549 text( myIterateIndex ).isEmpty()) )
00550 myIterateIndex--;
00551
00552
00553 if ( myIterateIndex < 0 ) {
00554 if ( myRotated && myIterateIndex == -2 ) {
00555 myRotated = false;
00556 myIterateIndex = count() - 1;
00557 setEditText( text(myIterateIndex) );
00558 }
00559 else {
00560 if ( myIterateIndex == -2 ) {
00561 KNotifyClient::event( KNotifyClient::notification,
00562 i18n("No further item in the history."));
00563 }
00564
00565 myIterateIndex = -1;
00566 if ( currentText() != myText )
00567 setEditText( myText );
00568 }
00569 }
00570 else
00571 setEditText( text( myIterateIndex ));
00572
00573 }
00574
00575 void KHistoryCombo::keyPressEvent( QKeyEvent *e )
00576 {
00577
00578 if ( KStdAccel::isEqual( e, KStdAccel::rotateUp() ) ) {
00579 rotateUp();
00580 }
00581
00582
00583 else if ( KStdAccel::isEqual( e, KStdAccel::rotateDown() ) ) {
00584 rotateDown();
00585 }
00586 else
00587 KComboBox::keyPressEvent( e );
00588 }
00589
00590 void KHistoryCombo::wheelEvent( QWheelEvent *ev )
00591 {
00592
00593 QListBox *lb = listBox();
00594 if ( lb && lb->isVisible() )
00595 {
00596 QApplication::sendEvent( lb, ev );
00597 return;
00598 }
00599
00600 if ( ev->delta() > 0 ) {
00601 rotateUp();
00602 } else {
00603 rotateDown();
00604 }
00605 ev->accept();
00606 }
00607
00608 void KHistoryCombo::slotReset()
00609 {
00610 myIterateIndex = -1;
00611 myRotated = false;
00612 }
00613
00614
00615 void KHistoryCombo::setPixmapProvider( KPixmapProvider *prov )
00616 {
00617 if ( myPixProvider == prov )
00618 return;
00619
00620 delete myPixProvider;
00621 myPixProvider = prov;
00622
00623
00624
00625
00626 if ( count() > 0 ) {
00627 QStringList items( historyItems() );
00628 clear();
00629 insertItems( items );
00630 }
00631 }
00632
00633 void KHistoryCombo::insertItems( const QStringList& items )
00634 {
00635 QStringList::ConstIterator it = items.begin();
00636 QString item;
00637 while ( it != items.end() ) {
00638 item = *it;
00639 if ( !item.isEmpty() ) {
00640 if ( myPixProvider )
00641 insertItem( myPixProvider->pixmapFor(item, KIcon::SizeSmall),
00642 item );
00643 else
00644 insertItem( item );
00645 }
00646 ++it;
00647 }
00648 }
00649
00650 void KHistoryCombo::slotClear()
00651 {
00652 clearHistory();
00653 emit cleared();
00654 }
00655
00656 void KComboBox::virtual_hook( int id, void* data )
00657 { KCompletionBase::virtual_hook( id, data ); }
00658
00659 void KHistoryCombo::virtual_hook( int id, void* data )
00660 { KComboBox::virtual_hook( id, data ); }
00661
00662 #include "kcombobox.moc"