00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <tqclipboard.h>
00024 #include <tqlistbox.h>
00025 #include <tqpopupmenu.h>
00026 #include <tqapplication.h>
00027
00028 #include <tdecompletionbox.h>
00029 #include <kcursor.h>
00030 #include <kiconloader.h>
00031 #include <kicontheme.h>
00032 #include <tdelistviewsearchline.h>
00033 #include <klineedit.h>
00034 #include <tdelocale.h>
00035 #include <knotifyclient.h>
00036 #include <kpixmapprovider.h>
00037 #include <tdestdaccel.h>
00038 #include <kurl.h>
00039 #include <kurldrag.h>
00040
00041 #include <kdebug.h>
00042
00043 #include "kcombobox.h"
00044
00045 #include <stdlib.h>
00046
00047 class KComboBox::KComboBoxPrivate
00048 {
00049 public:
00050 KComboBoxPrivate() : klineEdit(0L)
00051 {
00052 }
00053 ~KComboBoxPrivate()
00054 {
00055 }
00056
00057 KLineEdit *klineEdit;
00058 };
00059
00060 KComboBox::KComboBox( TQWidget *parent, const char *name )
00061 : TQComboBox( parent, name ), d(new KComboBoxPrivate)
00062 {
00063 init();
00064 }
00065
00066 KComboBox::KComboBox( bool rw, TQWidget *parent, const char *name )
00067 : TQComboBox( rw, parent, name ), d(new KComboBoxPrivate)
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
00086 TQComboBox::setAutoCompletion( false );
00087
00088
00089
00090 setContextMenuEnabled( true );
00091 }
00092
00093
00094 bool KComboBox::contains( const TQString& _text ) const
00095 {
00096 if ( _text.isEmpty() )
00097 return false;
00098
00099 const int itemCount = count();
00100 for (int i = 0; i < itemCount; ++i )
00101 {
00102 if ( text(i) == _text )
00103 return true;
00104 }
00105 return false;
00106 }
00107
00108 void KComboBox::setAutoCompletion( bool autocomplete )
00109 {
00110 if ( d->klineEdit )
00111 {
00112 if ( autocomplete )
00113 {
00114 d->klineEdit->setCompletionMode( TDEGlobalSettings::CompletionAuto );
00115 setCompletionMode( TDEGlobalSettings::CompletionAuto );
00116 }
00117 else
00118 {
00119 d->klineEdit->setCompletionMode( TDEGlobalSettings::completionMode() );
00120 setCompletionMode( TDEGlobalSettings::completionMode() );
00121 }
00122 }
00123 }
00124
00125 void KComboBox::setContextMenuEnabled( bool showMenu )
00126 {
00127 if( d->klineEdit )
00128 d->klineEdit->setContextMenuEnabled( showMenu );
00129 }
00130
00131
00132 void KComboBox::setURLDropsEnabled( bool enable )
00133 {
00134 if ( d->klineEdit )
00135 d->klineEdit->setURLDropsEnabled( enable );
00136 }
00137
00138 bool KComboBox::isURLDropsEnabled() const
00139 {
00140 return d->klineEdit && d->klineEdit->isURLDropsEnabled();
00141 }
00142
00143
00144 void KComboBox::setCompletedText( const TQString& text, bool marked )
00145 {
00146 if ( d->klineEdit )
00147 d->klineEdit->setCompletedText( text, marked );
00148 }
00149
00150 void KComboBox::setCompletedText( const TQString& text )
00151 {
00152 if ( d->klineEdit )
00153 d->klineEdit->setCompletedText( text );
00154 }
00155
00156 void KComboBox::makeCompletion( const TQString& text )
00157 {
00158 if( d->klineEdit )
00159 d->klineEdit->makeCompletion( text );
00160
00161 else
00162 {
00163 if( text.isNull() || !listBox() )
00164 return;
00165
00166 const int index = listBox()->index( listBox()->findItem( text ) );
00167 if( index >= 0 )
00168 setCurrentItem( index );
00169 }
00170 }
00171
00172 void KComboBox::rotateText( TDECompletionBase::KeyBindingType type )
00173 {
00174 if ( d->klineEdit )
00175 d->klineEdit->rotateText( type );
00176 }
00177
00178
00179 bool KComboBox::eventFilter( TQObject* o, TQEvent* ev )
00180 {
00181 return TQComboBox::eventFilter( o, ev );
00182 }
00183
00184 void KComboBox::setTrapReturnKey( bool grab )
00185 {
00186 if ( d->klineEdit )
00187 d->klineEdit->setTrapReturnKey( grab );
00188 else
00189 tqWarning("KComboBox::setTrapReturnKey not supported with a non-KLineEdit.");
00190 }
00191
00192 bool KComboBox::trapReturnKey() const
00193 {
00194 return d->klineEdit && d->klineEdit->trapReturnKey();
00195 }
00196
00197
00198 void KComboBox::setEditURL( const KURL& url )
00199 {
00200 TQComboBox::setEditText( url.prettyURL() );
00201 }
00202
00203 void KComboBox::insertURL( const KURL& url, int index )
00204 {
00205 TQComboBox::insertItem( url.prettyURL(), index );
00206 }
00207
00208 void KComboBox::insertURL( const TQPixmap& pixmap, const KURL& url, int index )
00209 {
00210 TQComboBox::insertItem( pixmap, url.prettyURL(), index );
00211 }
00212
00213 void KComboBox::changeURL( const KURL& url, int index )
00214 {
00215 TQComboBox::changeItem( url.prettyURL(), index );
00216 }
00217
00218 void KComboBox::changeURL( const TQPixmap& pixmap, const KURL& url, int index )
00219 {
00220 TQComboBox::changeItem( pixmap, url.prettyURL(), index );
00221 }
00222
00223 void KComboBox::setCompletedItems( const TQStringList& items )
00224 {
00225 if ( d->klineEdit )
00226 d->klineEdit->setCompletedItems( items );
00227 }
00228
00229 TDECompletionBox * KComboBox::completionBox( bool create )
00230 {
00231 if ( d->klineEdit )
00232 return d->klineEdit->completionBox( create );
00233 return 0;
00234 }
00235
00236
00237 void KComboBox::create( WId id, bool initializeWindow, bool destroyOldWindow )
00238 {
00239 TQComboBox::create( id, initializeWindow, destroyOldWindow );
00240 KCursor::setAutoHideCursor( lineEdit(), true, true );
00241 }
00242
00243 void KComboBox::wheelEvent( TQWheelEvent *ev )
00244 {
00245
00246 TQComboBox::wheelEvent( ev );
00247 }
00248
00249 void KComboBox::setLineEdit( TQLineEdit *edit )
00250 {
00251 if ( !editable() && edit &&
00252 !qstrcmp( edit->className(), TQLINEEDIT_OBJECT_NAME_STRING ) )
00253 {
00254
00255
00256
00257
00258
00259 delete edit;
00260 edit = new KLineEdit( this, "combo edit" );
00261 }
00262
00263 TQComboBox::setLineEdit( edit );
00264 d->klineEdit = tqt_dynamic_cast<KLineEdit*>( edit );
00265 setDelegate( d->klineEdit );
00266
00267
00268 if (edit)
00269 connect( edit, TQT_SIGNAL( returnPressed() ), TQT_SIGNAL( returnPressed() ));
00270
00271 if ( d->klineEdit )
00272 {
00273
00274
00275
00276
00277 connect( edit, TQT_SIGNAL( destroyed() ), TQT_SLOT( lineEditDeleted() ));
00278
00279 connect( d->klineEdit, TQT_SIGNAL( returnPressed( const TQString& )),
00280 TQT_SIGNAL( returnPressed( const TQString& ) ));
00281
00282 connect( d->klineEdit, TQT_SIGNAL( completion( const TQString& )),
00283 TQT_SIGNAL( completion( const TQString& )) );
00284
00285 connect( d->klineEdit, TQT_SIGNAL( substringCompletion( const TQString& )),
00286 TQT_SIGNAL( substringCompletion( const TQString& )) );
00287
00288 connect( d->klineEdit,
00289 TQT_SIGNAL( textRotation( TDECompletionBase::KeyBindingType )),
00290 TQT_SIGNAL( textRotation( TDECompletionBase::KeyBindingType )) );
00291
00292 connect( d->klineEdit,
00293 TQT_SIGNAL( completionModeChanged( TDEGlobalSettings::Completion )),
00294 TQT_SIGNAL( completionModeChanged( TDEGlobalSettings::Completion)));
00295
00296 connect( d->klineEdit,
00297 TQT_SIGNAL( aboutToShowContextMenu( TQPopupMenu * )),
00298 TQT_SIGNAL( aboutToShowContextMenu( TQPopupMenu * )) );
00299
00300 connect( d->klineEdit,
00301 TQT_SIGNAL( completionBoxActivated( const TQString& )),
00302 TQT_SIGNAL( activated( const TQString& )) );
00303 }
00304 }
00305
00306 void KComboBox::setCurrentItem( const TQString& item, bool insert, int index )
00307 {
00308 int sel = -1;
00309
00310 const int itemCount = count();
00311 for (int i = 0; i < itemCount; ++i)
00312 {
00313 if (text(i) == item)
00314 {
00315 sel = i;
00316 break;
00317 }
00318 }
00319
00320 if (sel == -1 && insert)
00321 {
00322 insertItem(item, index);
00323 if (index >= 0)
00324 sel = index;
00325 else
00326 sel = count() - 1;
00327 }
00328 setCurrentItem(sel);
00329 }
00330
00331 void KComboBox::lineEditDeleted()
00332 {
00333
00334
00335
00336 const TDECompletionBase *base = static_cast<const TDECompletionBase*>( static_cast<const KLineEdit*>( sender() ));
00337
00338
00339 if ( base == delegate() )
00340 setDelegate( 0L );
00341 }
00342
00343
00344
00345
00346
00347 class KHistoryCombo::KHistoryComboPrivate
00348 {
00349 public:
00350 KHistoryComboPrivate() : bHistoryEditorEnabled(false)
00351 {
00352 }
00353 ~KHistoryComboPrivate()
00354 {
00355 }
00356
00357 bool bHistoryEditorEnabled;
00358 };
00359
00360
00361 KHistoryCombo::KHistoryCombo( TQWidget *parent, const char *name )
00362 : KComboBox( true, parent, name ), d(new KHistoryComboPrivate)
00363 {
00364 init( true );
00365 }
00366
00367
00368 KHistoryCombo::KHistoryCombo( bool useCompletion,
00369 TQWidget *parent, const char *name )
00370 : KComboBox( true, parent, name ), d(new KHistoryComboPrivate)
00371 {
00372 init( useCompletion );
00373 }
00374
00375 void KHistoryCombo::init( bool useCompletion )
00376 {
00377
00378 setMaxCount( 50 );
00379
00380 if ( useCompletion )
00381 completionObject()->setOrder( TDECompletion::Weighted );
00382
00383 setInsertionPolicy( NoInsertion );
00384 myIterateIndex = -1;
00385 myRotated = false;
00386 myPixProvider = 0L;
00387
00388
00389 TQCString histControl = getenv("HISTCONTROL");
00390 if ( histControl == "ignoredups" || histControl == "ignoreboth" )
00391 setDuplicatesEnabled( false );
00392
00393 connect( this, TQT_SIGNAL(aboutToShowContextMenu(TQPopupMenu*)),
00394 TQT_SLOT(addContextMenuItems(TQPopupMenu*)) );
00395 connect( this, TQT_SIGNAL( activated(int) ), TQT_SLOT( slotReset() ));
00396 connect( this, TQT_SIGNAL( returnPressed(const TQString&) ), TQT_SLOT(slotReset()));
00397 }
00398
00399 KHistoryCombo::~KHistoryCombo()
00400 {
00401 delete myPixProvider;
00402 }
00403
00404 void KHistoryCombo::setHistoryItems( TQStringList items,
00405 bool setCompletionList )
00406 {
00407 KComboBox::clear();
00408
00409
00410 const int itemCount = items.count();
00411 const int toRemove = itemCount - maxCount();
00412
00413 if (toRemove >= itemCount) {
00414 items.clear();
00415 } else {
00416 for (int i = 0; i < toRemove; ++i)
00417 items.pop_front();
00418 }
00419
00420 insertItems( items );
00421
00422 if ( setCompletionList && useCompletion() ) {
00423
00424 TDECompletion *comp = completionObject();
00425 comp->setOrder( TDECompletion::Insertion );
00426 comp->setItems( items );
00427 comp->setOrder( TDECompletion::Weighted );
00428 }
00429
00430 clearEdit();
00431 }
00432
00433 TQStringList KHistoryCombo::historyItems() const
00434 {
00435 TQStringList list;
00436 const int itemCount = count();
00437 for ( int i = 0; i < itemCount; ++i )
00438 list.append( text( i ) );
00439
00440 return list;
00441 }
00442
00443 void KHistoryCombo::clearHistory()
00444 {
00445 const TQString temp = currentText();
00446 KComboBox::clear();
00447 if ( useCompletion() )
00448 completionObject()->clear();
00449 setEditText( temp );
00450 }
00451
00452 void KHistoryCombo::addContextMenuItems( TQPopupMenu* menu )
00453 {
00454 if ( menu )
00455 {
00456 menu->insertSeparator();
00457 if (d->bHistoryEditorEnabled) {
00458 int idedit = menu->insertItem( SmallIconSet("edit"), i18n("&Edit History..."), this, TQT_SLOT( slotEdit()) );
00459 menu->setItemEnabled(idedit, count());
00460 }
00461 int id = menu->insertItem( SmallIconSet("history_clear"), i18n("Clear &History"), this, TQT_SLOT( slotClear()));
00462 if (!count())
00463 menu->setItemEnabled(id, false);
00464 }
00465 }
00466
00467 void KHistoryCombo::addToHistory( const TQString& item )
00468 {
00469 if ( item.isEmpty() || (count() > 0 && item == text(0) )) {
00470 return;
00471 }
00472
00473 bool wasCurrent = false;
00474
00475 if ( !duplicatesEnabled() ) {
00476 int i = 0;
00477 int itemCount = count();
00478 while ( i < itemCount ) {
00479 if ( text( i ) == item ) {
00480 if ( !wasCurrent )
00481 wasCurrent = ( i == currentItem() );
00482 removeItem( i );
00483 --itemCount;
00484 } else {
00485 ++i;
00486 }
00487 }
00488 }
00489
00490
00491 if ( myPixProvider )
00492 insertItem( myPixProvider->pixmapFor(item, TDEIcon::SizeSmall), item, 0);
00493 else
00494 insertItem( item, 0 );
00495
00496 if ( wasCurrent )
00497 setCurrentItem( 0 );
00498
00499 const bool useComp = useCompletion();
00500
00501 const int last = count() - 1;
00502 const int mc = maxCount();
00503 const int stopAt = TQMAX(mc, 0);
00504
00505 for (int rmIndex = last; rmIndex >= stopAt; --rmIndex) {
00506
00507
00508
00509 const TQString rmItem = text( rmIndex );
00510 removeItem( rmIndex );
00511 if ( useComp && !contains( rmItem ) )
00512 completionObject()->removeItem( rmItem );
00513 }
00514
00515 if ( useComp )
00516 completionObject()->addItem( item );
00517 }
00518
00519 bool KHistoryCombo::removeFromHistory( const TQString& item )
00520 {
00521 if ( item.isEmpty() )
00522 return false;
00523
00524 bool removed = false;
00525 const TQString temp = currentText();
00526 int i = 0;
00527 int itemCount = count();
00528 while ( i < itemCount ) {
00529 if ( item == text( i ) ) {
00530 removed = true;
00531 removeItem( i );
00532 --itemCount;
00533 } else {
00534 ++i;
00535 }
00536 }
00537
00538 if ( removed && useCompletion() )
00539 completionObject()->removeItem( item );
00540
00541 setEditText( temp );
00542 return removed;
00543 }
00544
00545 void KHistoryCombo::rotateUp()
00546 {
00547
00548 if ( myIterateIndex == -1 )
00549 myText = currentText();
00550
00551 ++myIterateIndex;
00552
00553
00554 const int last = count() - 1;
00555 const TQString currText = currentText();
00556
00557 while ( myIterateIndex < last &&
00558 (currText == text( myIterateIndex ) ||
00559 text( myIterateIndex ).isEmpty()) )
00560 ++myIterateIndex;
00561
00562 if ( myIterateIndex >= count() ) {
00563 myRotated = true;
00564 myIterateIndex = -1;
00565
00566
00567 if ( count() > 0 && myText == text(0) )
00568 myIterateIndex = 0;
00569
00570 setEditText( myText );
00571 }
00572 else
00573 setEditText( text( myIterateIndex ));
00574 }
00575
00576 void KHistoryCombo::rotateDown()
00577 {
00578
00579 if ( myIterateIndex == -1 )
00580 myText = currentText();
00581
00582 --myIterateIndex;
00583
00584 const TQString currText = currentText();
00585
00586 while ( myIterateIndex >= 0 &&
00587 (currText == text( myIterateIndex ) ||
00588 text( myIterateIndex ).isEmpty()) )
00589 --myIterateIndex;
00590
00591
00592 if ( myIterateIndex < 0 ) {
00593 if ( myRotated && myIterateIndex == -2 ) {
00594 myRotated = false;
00595 myIterateIndex = count() - 1;
00596 setEditText( text(myIterateIndex) );
00597 }
00598 else {
00599 if ( myIterateIndex == -2 ) {
00600 KNotifyClient::event( (int)winId(), KNotifyClient::notification,
00601 i18n("No further item in the history."));
00602 }
00603
00604 myIterateIndex = -1;
00605 if ( currentText() != myText )
00606 setEditText( myText );
00607 }
00608 }
00609 else
00610 setEditText( text( myIterateIndex ));
00611
00612 }
00613
00614 void KHistoryCombo::keyPressEvent( TQKeyEvent *e )
00615 {
00616 KKey event_key( e );
00617
00618
00619 if ( TDEStdAccel::rotateUp().contains(event_key) )
00620 rotateUp();
00621
00622
00623
00624 else if ( TDEStdAccel::rotateDown().contains(event_key) )
00625 rotateDown();
00626 else
00627 KComboBox::keyPressEvent( e );
00628 }
00629
00630 void KHistoryCombo::wheelEvent( TQWheelEvent *ev )
00631 {
00632
00633 TQListBox* const lb = listBox();
00634 if ( lb && lb->isVisible() )
00635 {
00636 TQApplication::sendEvent( lb, ev );
00637 return;
00638 }
00639
00640 if ( ev->delta() > 0 ) {
00641 rotateUp();
00642 } else {
00643 rotateDown();
00644 }
00645 ev->accept();
00646 }
00647
00648 void KHistoryCombo::slotReset()
00649 {
00650 myIterateIndex = -1;
00651 myRotated = false;
00652 }
00653
00654
00655 void KHistoryCombo::setPixmapProvider( KPixmapProvider *prov )
00656 {
00657 if ( myPixProvider == prov )
00658 return;
00659
00660 delete myPixProvider;
00661 myPixProvider = prov;
00662
00663
00664
00665
00666 if ( count() > 0 ) {
00667 TQStringList items( historyItems() );
00668 clear();
00669 insertItems( items );
00670 }
00671 }
00672
00673 void KHistoryCombo::insertItems( const TQStringList& items )
00674 {
00675 TQStringList::ConstIterator it = items.constBegin();
00676 const TQStringList::ConstIterator itEnd = items.constEnd();
00677
00678 while ( it != itEnd ) {
00679 const TQString item = *it;
00680 if ( !item.isEmpty() ) {
00681 if ( myPixProvider )
00682 insertItem( myPixProvider->pixmapFor(item, TDEIcon::SizeSmall),
00683 item );
00684 else
00685 insertItem( item );
00686 }
00687 ++it;
00688 }
00689 }
00690
00691 void KHistoryCombo::slotClear()
00692 {
00693 clearHistory();
00694 emit cleared();
00695 }
00696
00697 void KHistoryCombo::slotEdit()
00698 {
00699 KHistoryComboEditor dlg( historyItems(), this );
00700 connect( &dlg, TQT_SIGNAL( removeFromHistory(const TQString&) ), TQT_SLOT( slotRemoveFromHistory(const TQString&)) );
00701 dlg.exec();
00702 }
00703
00704 void KHistoryCombo::slotRemoveFromHistory(const TQString &entry)
00705 {
00706 removeFromHistory(entry);
00707 emit removed(entry);
00708 }
00709
00710 void KHistoryCombo::setHistoryEditorEnabled( bool enable )
00711 {
00712 d->bHistoryEditorEnabled = enable;
00713 }
00714
00715 bool KHistoryCombo::isHistoryEditorEnabled() const
00716 {
00717 return d->bHistoryEditorEnabled;
00718 }
00719
00720 void KComboBox::virtual_hook( int id, void* data )
00721 { TDECompletionBase::virtual_hook( id, data ); }
00722
00723 void KHistoryCombo::virtual_hook( int id, void* data )
00724 { KComboBox::virtual_hook( id, data ); }
00725
00726 void KHistoryComboEditor::virtual_hook( int id, void* data )
00727 { KDialogBase::virtual_hook( id, data ); }
00728
00729 KHistoryComboEditor::KHistoryComboEditor( const TQStringList& entries, TQWidget *parent )
00730 : KDialogBase( parent, "khistorycomboeditor", true, i18n( "History Editor" ),
00731 KDialogBase::Close | KDialogBase::User1, KDialogBase::User1, true,
00732 KGuiItem( i18n( "&Delete Entry" ), "edit-delete") ), d(0)
00733 {
00734 TQVBox* box = new TQVBox( this );
00735 box->setSpacing( KDialog::spacingHint() );
00736 setMainWidget( box );
00737
00738 new TQLabel( i18n( "This dialog allows you to delete unwanted history items." ), box );
00739
00740
00741 TQHBox* searchbox = new TQHBox( box );
00742 searchbox->setSpacing( KDialog::spacingHint() );
00743
00744 TQToolButton *clearSearch = new TQToolButton(searchbox);
00745 clearSearch->setTextLabel(i18n("Clear Search"), true);
00746 clearSearch->setIconSet(SmallIconSet(TQApplication::reverseLayout() ? "clear_left" : "locationbar_erase"));
00747 TQLabel* slbl = new TQLabel(i18n("&Search:"), searchbox);
00748 TDEListViewSearchLine* listViewSearch = new TDEListViewSearchLine(searchbox);
00749 slbl->setBuddy(listViewSearch);
00750 connect(clearSearch, TQT_SIGNAL(pressed()), listViewSearch, TQT_SLOT(clear()));
00751
00752
00753 m_pListView = new TDEListView( box );
00754 listViewSearch->setListView(m_pListView);
00755 m_pListView->setAllColumnsShowFocus(true);
00756 m_pListView->header()->hide();
00757 m_pListView->addColumn("");
00758 m_pListView->setRenameable( 0 );
00759
00760 box->setStretchFactor( m_pListView, 1 );
00761
00762 TQStringList newlist = entries;
00763 for ( TQStringList::Iterator it = newlist.begin(); it != newlist.end(); ++it ) {
00764 new TQListViewItem( m_pListView, *it );
00765 }
00766
00767 m_pListView->setMinimumSize( m_pListView->sizeHint() );
00768
00769 connect( m_pListView, TQT_SIGNAL( selectionChanged( TQListViewItem * ) ),
00770 this, TQT_SLOT( slotSelectionChanged( TQListViewItem * ) ) );
00771
00772 enableButton( KDialogBase::User1, false );
00773
00774 resize( sizeHint() );
00775 }
00776
00777 KHistoryComboEditor::~KHistoryComboEditor()
00778 {
00779 }
00780
00781 void KHistoryComboEditor::slotUser1()
00782 {
00783 TQListViewItem *item = m_pListView->selectedItem();
00784
00785 if ( item ) {
00786 emit removeFromHistory( item->text(0) );
00787 m_pListView->takeItem( item );
00788 enableButton( KDialogBase::User1, false );
00789 }
00790 }
00791
00792 void KHistoryComboEditor::slotSelectionChanged( TQListViewItem * item )
00793 {
00794 enableButton( KDialogBase::User1, item );
00795 }
00796
00797 #include "kcombobox.moc"