summaryrefslogtreecommitdiff
path: root/libopie2/qt3/opieui/ocombobox.cpp
Unidiff
Diffstat (limited to 'libopie2/qt3/opieui/ocombobox.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/qt3/opieui/ocombobox.cpp666
1 files changed, 666 insertions, 0 deletions
diff --git a/libopie2/qt3/opieui/ocombobox.cpp b/libopie2/qt3/opieui/ocombobox.cpp
new file mode 100644
index 0000000..a1dd5f5
--- a/dev/null
+++ b/libopie2/qt3/opieui/ocombobox.cpp
@@ -0,0 +1,666 @@
1/*
2 This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
3 is part of the Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
4 Opie Project Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
5
6 =. Originally part of the KDE Project
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33/* QT */
34
35#include <qclipboard.h>
36#include <qlistbox.h>
37#include <qpopupmenu.h>
38
39/* OPIE */
40
41#include <opie2/ocompletionbox.h>
42#include <opie2/olineedit.h>
43#include <opie2/opixmapprovider.h>
44#include <opie2/ocombobox.h>
45
46/*======================================================================================
47 * OComboBoxPrivate
48 *======================================================================================*/
49
50class OComboBox::OComboBoxPrivate
51{
52public:
53 OComboBoxPrivate()
54 {
55 olineEdit = 0L;
56 }
57 ~OComboBoxPrivate()
58 {
59 }
60
61 OLineEdit *olineEdit;
62};
63
64/*======================================================================================
65 * OComboBox
66 *======================================================================================*/
67
68OComboBox::OComboBox( QWidget *parent, const char *name )
69 : QComboBox( parent, name )
70{
71 init();
72}
73
74OComboBox::OComboBox( bool rw, QWidget *parent, const char *name )
75 : QComboBox( rw, parent, name )
76{
77 init();
78
79 if ( rw )
80 {
81 OLineEdit *edit = new OLineEdit( this, "combo lineedit" );
82 setLineEdit( edit );
83 }
84}
85
86OComboBox::~OComboBox()
87{
88 delete d;
89}
90
91void OComboBox::init()
92{
93 d = new OComboBoxPrivate;
94
95 // Permanently set some parameters in the parent object.
96 QComboBox::setAutoCompletion( false );
97
98 // Initialize enable popup menu to false.
99 // Below it will be enabled if the widget
100 // is editable.
101 m_bEnableMenu = false;
102
103 m_trapReturnKey = false;
104
105 // Enable context menu by default if widget
106 // is editable.
107 setContextMenuEnabled( true );
108
109 // for wheelscrolling
110 installEventFilter( this );
111 if ( lineEdit() )
112 lineEdit()->installEventFilter( this );
113}
114
115
116bool OComboBox::contains( const QString& _text ) const
117{
118 if ( _text.isEmpty() )
119 return false;
120
121 for (int i = 0; i < count(); i++ ) {
122 if ( text(i) == _text )
123 return true;
124 }
125 return false;
126}
127
128void OComboBox::setAutoCompletion( bool autocomplete )
129{
130 if ( d->olineEdit )
131 {
132 if ( autocomplete )
133 {
134 d->olineEdit->setCompletionMode( OGlobalSettings::CompletionAuto );
135 setCompletionMode( OGlobalSettings::CompletionAuto );
136 }
137 else
138 {
139 d->olineEdit->setCompletionMode( OGlobalSettings::completionMode() );
140 setCompletionMode( OGlobalSettings::completionMode() );
141 }
142 }
143}
144
145void OComboBox::setContextMenuEnabled( bool showMenu )
146{
147 if( d->olineEdit )
148 {
149 d->olineEdit->setContextMenuEnabled( showMenu );
150 m_bEnableMenu = showMenu;
151 }
152}
153
154/*
155void OComboBox::setURLDropsEnabled( bool enable )
156{
157 if ( d->olineEdit )
158 d->olineEdit->setURLDropsEnabled( enable );
159}
160
161bool OComboBox::isURLDropsEnabled() const
162{
163 return d->olineEdit && d->olineEdit->isURLDropsEnabled();
164}
165*/
166
167void OComboBox::setCompletedText( const QString& text, bool marked )
168{
169 if ( d->olineEdit )
170 d->olineEdit->setCompletedText( text, marked );
171}
172
173void OComboBox::setCompletedText( const QString& text )
174{
175 if ( d->olineEdit )
176 d->olineEdit->setCompletedText( text );
177}
178
179void OComboBox::makeCompletion( const QString& text )
180{
181 if( d->olineEdit )
182 d->olineEdit->makeCompletion( text );
183
184 else // read-only combo completion
185 {
186 if( text.isNull() || !listBox() )
187 return;
188
189 int index = listBox()->index( listBox()->findItem( text ) );
190 if( index >= 0 ) {
191 setCurrentItem( index );
192 }
193 }
194}
195
196void OComboBox::rotateText( OCompletionBase::KeyBindingType type )
197{
198 if ( d->olineEdit )
199 d->olineEdit->rotateText( type );
200}
201
202bool OComboBox::eventFilter( QObject* o, QEvent* ev )
203{
204 QLineEdit *edit = lineEdit();
205
206 int type = ev->type();
207
208 if ( o == edit )
209 {
210 //OCursor::autoHideEventFilter( edit, ev );
211
212 if ( type == QEvent::KeyPress )
213 {
214 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
215
216 if ( e->key() == Key_Return || e->key() == Key_Enter)
217 {
218 // On Return pressed event, emit both
219 // returnPressed(const QString&) and returnPressed() signals
220 emit returnPressed();
221 emit returnPressed( currentText() );
222 if ( d->olineEdit && d->olineEdit->completionBox(false) &&
223 d->olineEdit->completionBox()->isVisible() )
224 d->olineEdit->completionBox()->hide();
225
226 return m_trapReturnKey;
227 }
228 }
229 }
230
231
232 // wheel-scrolling changes the current item
233 if ( type == QEvent::Wheel ) {
234 if ( !listBox() || listBox()->isHidden() ) {
235 QWheelEvent *e = static_cast<QWheelEvent*>( ev );
236 static const int WHEEL_DELTA = 120;
237 int skipItems = e->delta() / WHEEL_DELTA;
238 if ( e->state() & ControlButton ) // fast skipping
239 skipItems *= 10;
240
241 int newItem = currentItem() - skipItems;
242
243 if ( newItem < 0 )
244 newItem = 0;
245 else if ( newItem >= count() )
246 newItem = count() -1;
247
248 setCurrentItem( newItem );
249 if ( !text( newItem ).isNull() )
250 emit activated( text( newItem ) );
251 emit activated( newItem );
252 e->accept();
253 return true;
254 }
255 }
256
257 return QComboBox::eventFilter( o, ev );
258}
259
260void OComboBox::setTrapReturnKey( bool grab )
261{
262 m_trapReturnKey = grab;
263}
264
265bool OComboBox::trapReturnKey() const
266{
267 return m_trapReturnKey;
268}
269
270/*
271void OComboBox::setEditURL( const OURL& url )
272{
273 QComboBox::setEditText( url.prettyURL() );
274}
275
276void OComboBox::insertURL( const OURL& url, int index )
277{
278 QComboBox::insertItem( url.prettyURL(), index );
279}
280
281void OComboBox::insertURL( const QPixmap& pixmap, const OURL& url, int index )
282{
283 QComboBox::insertItem( pixmap, url.prettyURL(), index );
284}
285
286void OComboBox::changeURL( const OURL& url, int index )
287{
288 QComboBox::changeItem( url.prettyURL(), index );
289}
290
291void OComboBox::changeURL( const QPixmap& pixmap, const OURL& url, int index )
292{
293 QComboBox::changeItem( pixmap, url.prettyURL(), index );
294}
295*/
296
297
298void OComboBox::setCompletedItems( const QStringList& items )
299{
300 if ( d->olineEdit )
301 d->olineEdit->setCompletedItems( items );
302}
303
304
305OCompletionBox * OComboBox::completionBox( bool create )
306{
307 if ( d->olineEdit )
308 return d->olineEdit->completionBox( create );
309 return 0;
310}
311
312// QWidget::create() turns off mouse-Tracking which would break auto-hiding
313void OComboBox::create( WId id, bool initializeWindow, bool destroyOldWindow )
314{
315 QComboBox::create( id, initializeWindow, destroyOldWindow );
316 //OCursor::setAutoHideCursor( lineEdit(), true, true );
317}
318
319void OComboBox::setLineEdit( OLineEdit *edit )
320{
321 #if QT_VERSION > 290
322 QComboBox::setLineEdit( edit );
323 d->olineEdit = dynamic_cast<OLineEdit*>( edit );
324 setDelegate( d->olineEdit );
325
326 // forward some signals. We only emit returnPressed() ourselves.
327 if ( d->olineEdit ) {
328 connect( d->olineEdit, SIGNAL( completion( const QString& )),
329 SIGNAL( completion( const QString& )) );
330 connect( d->olineEdit, SIGNAL( substringCompletion( const QString& )),
331 SIGNAL( substringCompletion( const QString& )) );
332 connect( d->olineEdit,
333 SIGNAL( textRotation( OCompletionBase::KeyBindingType )),
334 SIGNAL( textRotation( OCompletionBase::KeyBindingType )) );
335 connect( d->olineEdit,
336 SIGNAL( completionModeChanged( OGlobalSettings::Completion )),
337 SIGNAL( completionModeChanged( OGlobalSettings::Completion)));
338
339 connect( d->olineEdit,
340 SIGNAL( aboutToShowContextMenu( QPopupMenu * )),
341 SIGNAL( aboutToShowContextMenu( QPopupMenu * )) );
342 }
343 #else
344 #warning OComboBox is not fully functional with Qt2
345 #endif
346}
347
348// Temporary functions until QT3 appears. - Seth Chaiklin 20 may 2001
349void OComboBox::deleteWordForward()
350{
351 lineEdit()->cursorWordForward(TRUE);
352 #if QT_VERSION > 290
353 if ( lineEdit()->hasSelectedText() )
354 #else
355 if ( lineEdit()->hasMarkedText() )
356 #endif
357 {
358 lineEdit()->del();
359 }
360}
361
362void OComboBox::deleteWordBack()
363{
364 lineEdit()->cursorWordBackward(TRUE);
365 #if QT_VERSION > 290
366 if ( lineEdit()->hasSelectedText() )
367 #else
368 if ( lineEdit()->hasMarkedText() )
369 #endif
370 {
371 lineEdit()->del();
372 }
373}
374
375void OComboBox::setCurrentItem( const QString& item, bool insert, int index )
376{
377 int sel = -1;
378 for (int i = 0; i < count(); ++i)
379 if (text(i) == item)
380 {
381 sel = i;
382 break;
383 }
384 if (sel == -1 && insert)
385 {
386 insertItem(item, index);
387 if (index >= 0)
388 sel = index;
389 else
390 sel = count() - 1;
391 }
392 setCurrentItem(sel);
393}
394
395void OComboBox::setCurrentItem(int index)
396{
397 QComboBox::setCurrentItem(index);
398}
399
400
401/*======================================================================================
402 * OHistoryCombo
403 *======================================================================================*/
404
405// we are always read-write
406OHistoryCombo::OHistoryCombo( QWidget *parent, const char *name )
407 : OComboBox( true, parent, name )
408{
409 init( true ); // using completion
410}
411
412// we are always read-write
413OHistoryCombo::OHistoryCombo( bool useCompletion,
414 QWidget *parent, const char *name )
415 : OComboBox( true, parent, name )
416{
417 init( useCompletion );
418}
419
420void OHistoryCombo::init( bool useCompletion )
421{
422 if ( useCompletion )
423 completionObject()->setOrder( OCompletion::Weighted );
424
425 setInsertionPolicy( NoInsertion );
426 myIterateIndex = -1;
427 myRotated = false;
428 myPixProvider = 0L;
429
430 connect( this, SIGNAL(aboutToShowContextMenu(QPopupMenu*)),
431 SLOT(addContextMenuItems(QPopupMenu*)) );
432 connect( this, SIGNAL( activated(int) ), SLOT( slotReset() ));
433 connect( this, SIGNAL( returnPressed(const QString&) ), SLOT(slotReset()));
434}
435
436OHistoryCombo::~OHistoryCombo()
437{
438 delete myPixProvider;
439}
440
441void OHistoryCombo::setHistoryItems( QStringList items,
442 bool setCompletionList )
443{
444 OComboBox::clear();
445
446 // limit to maxCount()
447 while ( (int) items.count() > maxCount() && !items.isEmpty() )
448 items.remove( items.begin() );
449
450 insertItems( items );
451
452 if ( setCompletionList && useCompletion() ) {
453 // we don't have any weighting information here ;(
454 OCompletion *comp = completionObject();
455 comp->setOrder( OCompletion::Insertion );
456 comp->setItems( items );
457 comp->setOrder( OCompletion::Weighted );
458 }
459
460 clearEdit();
461}
462
463QStringList OHistoryCombo::historyItems() const
464{
465 QStringList list;
466 for ( int i = 0; i < count(); i++ )
467 list.append( text( i ) );
468
469 return list;
470}
471
472void OHistoryCombo::clearHistory()
473{
474 OComboBox::clear();
475 if ( useCompletion() )
476 completionObject()->clear();
477}
478
479void OHistoryCombo::addContextMenuItems( QPopupMenu* menu )
480{
481 if ( menu &&!lineEdit()->text().isEmpty())
482 {
483 menu->insertSeparator();
484 menu->insertItem( tr("Empty Contents"), this, SLOT( slotClear()));
485 }
486}
487
488void OHistoryCombo::addToHistory( const QString& item )
489{
490 if ( item.isEmpty() || (count() > 0 && item == text(0) ))
491 return;
492
493 // remove all existing items before adding
494 if ( !duplicatesEnabled() ) {
495 for ( int i = 0; i < count(); i++ ) {
496 if ( text( i ) == item )
497 removeItem( i );
498 }
499 }
500
501 // now add the item
502 if ( myPixProvider )
503 //insertItem( myPixProvider->pixmapFor(item, KIcon::SizeSmall), item, 0);
504 insertItem( myPixProvider->pixmapFor(item, 16), item, 0);
505 else
506 insertItem( item, 0 );
507
508 int last;
509 QString rmItem;
510
511 bool useComp = useCompletion();
512 while ( count() > maxCount() && count() > 0 ) {
513 // remove the last item, as long as we are longer than maxCount()
514 // remove the removed item from the completionObject if it isn't
515 // anymore available at all in the combobox.
516 last = count() - 1;
517 rmItem = text( last );
518 removeItem( last );
519 if ( useComp && !contains( rmItem ) )
520 completionObject()->removeItem( rmItem );
521 }
522
523 if ( useComp )
524 completionObject()->addItem( item );
525}
526
527bool OHistoryCombo::removeFromHistory( const QString& item )
528{
529 if ( item.isEmpty() )
530 return false;
531
532 bool removed = false;
533 QString temp = currentText();
534 for ( int i = 0; i < count(); i++ ) {
535 while ( item == text( i ) ) {
536 removed = true;
537 removeItem( i );
538 }
539 }
540
541 if ( removed && useCompletion() )
542 completionObject()->removeItem( item );
543
544 setEditText( temp );
545 return removed;
546}
547
548void OHistoryCombo::keyPressEvent( QKeyEvent *e )
549{
550 // save the current text in the lineedit
551 if ( myIterateIndex == -1 )
552 myText = currentText();
553
554 // going up in the history, rotating when reaching QListBox::count()
555 //if ( OStdAccel::isEqual( e, OStdAccel::rotateUp() ) ) {
556 if ( e->key() == Qt::Key_Up ) {
557 myIterateIndex++;
558
559 // skip duplicates/empty items
560 while ( myIterateIndex < count()-1 &&
561 (currentText() == text( myIterateIndex ) ||
562 text( myIterateIndex ).isEmpty()) )
563 myIterateIndex++;
564
565 if ( myIterateIndex >= count() ) {
566 myRotated = true;
567 myIterateIndex = -1;
568
569 // if the typed text is the same as the first item, skip the first
570 if ( myText == text(0) )
571 myIterateIndex = 0;
572
573 setEditText( myText );
574 }
575 else
576 setEditText( text( myIterateIndex ));
577 }
578
579
580 // going down in the history, no rotation possible. Last item will be
581 // the text that was in the lineedit before Up was called.
582 //else if ( OStdAccel::isEqual( e, OStdAccel::rotateDown() ) ) {
583 else if ( e->key() == Qt::Key_Down ) {
584 myIterateIndex--;
585
586 // skip duplicates/empty items
587 while ( myIterateIndex >= 0 &&
588 (currentText() == text( myIterateIndex ) ||
589 text( myIterateIndex ).isEmpty()) )
590 myIterateIndex--;
591
592
593 if ( myIterateIndex < 0 ) {
594 if ( myRotated && myIterateIndex == -2 ) {
595 myRotated = false;
596 myIterateIndex = count() - 1;
597 setEditText( text(myIterateIndex) );
598 }
599 else { // bottom of history
600 if ( myIterateIndex == -2 ) {
601 qDebug( "ONotifyClient is not implemented yet." );
602 //ONotifyClient::event( ONotifyClient::notification,
603 // i18n("No further item in the history."));
604 }
605
606 myIterateIndex = -1;
607 if ( currentText() != myText )
608 setEditText( myText );
609 }
610 }
611 else
612 setEditText( text( myIterateIndex ));
613 }
614
615 else
616 OComboBox::keyPressEvent( e );
617}
618
619void OHistoryCombo::slotReset()
620{
621 myIterateIndex = -1;
622 myRotated = false;
623}
624
625
626void OHistoryCombo::setPixmapProvider( OPixmapProvider *prov )
627{
628 if ( myPixProvider == prov )
629 return;
630
631 delete myPixProvider;
632 myPixProvider = prov;
633
634 // re-insert all the items with/without pixmap
635 // I would prefer to use changeItem(), but that doesn't honour the pixmap
636 // when using an editable combobox (what we do)
637 if ( count() > 0 ) {
638 QStringList items( historyItems() );
639 clear();
640 insertItems( items );
641 }
642}
643
644void OHistoryCombo::insertItems( const QStringList& items )
645{
646 QStringList::ConstIterator it = items.begin();
647 QString item;
648 while ( it != items.end() ) {
649 item = *it;
650 if ( !item.isEmpty() ) { // only insert non-empty items
651 if ( myPixProvider )
652 // insertItem( myPixProvider->pixmapFor(item, OIcon::SizeSmall), item );
653 insertItem( myPixProvider->pixmapFor(item, 16), item );
654 else
655 insertItem( item );
656 }
657 ++it;
658 }
659}
660
661void OHistoryCombo::slotClear()
662{
663 clearHistory();
664 emit cleared();
665}
666