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