summaryrefslogtreecommitdiff
path: root/libopie2/qt3/opieui
Unidiff
Diffstat (limited to 'libopie2/qt3/opieui') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/qt3/opieui/ocombobox.cpp666
-rw-r--r--libopie2/qt3/opieui/ocombobox.h790
-rw-r--r--libopie2/qt3/opieui/ocompletionbox.cpp408
-rw-r--r--libopie2/qt3/opieui/ocompletionbox.h232
-rw-r--r--libopie2/qt3/opieui/oeditlistbox.cpp416
-rw-r--r--libopie2/qt3/opieui/oeditlistbox.h250
-rw-r--r--libopie2/qt3/opieui/ojanuswidget.cpp1116
-rw-r--r--libopie2/qt3/opieui/ojanuswidget.h551
-rw-r--r--libopie2/qt3/opieui/olineedit.cpp729
-rw-r--r--libopie2/qt3/opieui/olineedit.h498
10 files changed, 5656 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
diff --git a/libopie2/qt3/opieui/ocombobox.h b/libopie2/qt3/opieui/ocombobox.h
new file mode 100644
index 0000000..4e35b61
--- a/dev/null
+++ b/libopie2/qt3/opieui/ocombobox.h
@@ -0,0 +1,790 @@
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 projects
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#ifndef OCOMBOBOX_H
34#define OCOMBOBOX_H
35
36/* QT */
37
38#include <qcombobox.h>
39
40/* OPIE */
41
42#include <opie2/olineedit.h>
43#include <opie2/ocompletion.h>
44#include <opie2/ocompletionbase.h>
45
46/* FORWARDS */
47
48class QListBoxItem;
49class QPopupMenu;
50class OCompletionBox;
51typedef QString OURL;
52
53/**
54 * A combined button, line-edit and a popup list widget.
55 *
56 * @sect Detail
57 *
58 * This widget inherits from @ref QComboBox and implements
59 * the following additional functionalities: a completion
60 * object that provides both automatic and manual text
61 * completion as well as text rotation features, configurable
62 * key-bindings to activate these features, and a popup-menu
63 * item that can be used to allow the user to set text completion
64 * modes on the fly based on their preference.
65 *
66 * To support these new features OComboBox also emits a few
67 * more additional signals as well. The main ones are the
68 * @ref completion( const QString& ) and @ref textRotation( KeyBindingType )
69 * signals. The completion signal is intended to be connected to a slot
70 * that will assist the user in filling out the remaining text while
71 * the rotation signals is intended to be used to traverse through all
72 * possible matches whenever text completion results in multiple matches.
73 * The @ref returnPressed() and @ref returnPressed( const QString& )
74 * signal is emitted when the user presses the Enter/Return key.
75 *
76 * This widget by default creates a completion object when you invoke
77 * the @ref completionObject( bool ) member function for the first time
78 * or use @ref setCompletionObject( OCompletion*, bool ) to assign your
79 * own completion object. Additionally, to make this widget more functional,
80 * OComboBox will by default handle the text rotation and completion
81 * events internally whenever a completion object is created through either
82 * one of the methods mentioned above. If you do not need this functionality,
83 * simply use @ref OCompletionBase::setHandleSignals( bool ) or alternatively
84 * set the boolean parameter in the above methods to FALSE.
85 *
86 * The default key-bindings for completion and rotation is determined
87 * from the global settings in @ref OStdAccel. These values, however,
88 * can be overriden locally by invoking @ref OCompletionBase::setKeyBinding().
89 * The values can easily be reverted back to the default setting, by simply
90 * calling @ref useGlobalSettings(). An alternate method would be to default
91 * individual key-bindings by usning @ref setKeyBinding() with the default
92 * second argument.
93 *
94 * Note that if this widget is not editable ( i.e. select-only ), then only
95 * one completion mode, @p CompletionAuto, will work. All the other modes are
96 * simply ignored. The @p CompletionAuto mode in this case allows you to
97 * automatically select an item from the list by trying to match the pressed
98 * keycode with the first letter of the enteries in the combo box.
99 *
100 * @sect Useage
101 *
102 * To enable the basic completion feature:
103 *
104 * <pre>
105 * OComboBox *combo = new OComboBox( true, this, "mywidget" );
106 * OCompletion *comp = combo->completionObject();
107 * // Connect to the return pressed signal - optional
108 * connect(combo,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
109 * </pre>
110 *
111 * To use your own completion object:
112 *
113 * <pre>
114 * OComboBox *combo = new OComboBox( this,"mywidget" );
115 * OURLCompletion *comp = new OURLCompletion();
116 * combo->setCompletionObject( comp );
117 * // Connect to the return pressed signal - optional
118 * connect(combo,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
119 * </pre>
120 *
121 * Note that you have to either delete the allocated completion object
122 * when you don't need it anymore, or call
123 * setAutoDeleteCompletionObject( true );
124 *
125 * Miscellaneous function calls:
126 *
127 * <pre>
128 * // Tell the widget not to handle completion and rotation
129 * combo->setHandleSignals( false );
130 * // Set your own completion key for manual completions.
131 * combo->setKeyBinding( OCompletionBase::TextCompletion, Qt::End );
132 * // Hide the context (popup) menu
133 * combo->setContextMenuEnabled( false );
134 * // Temporarly disable signal emition
135 * combo->disableSignals();
136 * // Default the all key-bindings to their system-wide settings.
137 * combo->useGlobalKeyBindings();
138 * </pre>
139 *
140 * @short An enhanced combo box.
141 * @author Dawit Alemayehu <adawit@kde.org>
142 */
143class OComboBox : public QComboBox, public OCompletionBase
144{
145 Q_OBJECT
146
147 //Q_PROPERTY( bool autoCompletion READ autoCompletion WRITE setAutoCompletion )
148 //Q_PROPERTY( bool contextMenuEnabled READ isContextMenuEnabled WRITE setContextMenuEnabled )
149 //Q_PROPERTY( bool urlDropsEnabled READ isURLDropsEnabled WRITE setURLDropsEnabled )
150
151public:
152
153 /**
154 * Constructs a read-only or rather select-only combo box with a
155 * parent object and a name.
156 *
157 * @param parent The parent object of this widget
158 * @param name The name of this widget
159 */
160 OComboBox( QWidget *parent=0, const char *name=0 );
161
162 /**
163 * Constructs a "read-write" or "read-only" combo box depending on
164 * the value of the first argument( @p rw ) with a parent, a
165 * name.
166 *
167 * @param rw When @p true, widget will be editable.
168 * @param parent The parent object of this widget.
169 * @param name The name of this widget.
170 */
171 OComboBox( bool rw, QWidget *parent=0, const char *name=0 );
172
173 /**
174 * Destructor.
175 */
176 virtual ~OComboBox();
177
178 /**
179 * Sets @p url into the edit field of the combobox. It uses
180 * @ref OURL::prettyURL() so that the url is properly decoded for
181 * displaying.
182 */
183 //void setEditURL( const OURL& url );
184
185 /**
186 * Inserts @p url at position @p index into the combobox. The item will
187 * be appended if @p index is negative. @ref OURL::prettyURL() is used
188 * so that the url is properly decoded for displaying.
189 */
190 //void insertURL( const OURL& url, int index = -1 );
191
192 /**
193 * Inserts @p url with the pixmap &p pixmap at position @p index into
194 * the combobox. The item will be appended if @p index is negative.
195 * @ref OURL::prettyURL() is used so that the url is properly decoded
196 * for displaying.
197 */
198 //void insertURL( const QPixmap& pixmap, const OURL& url, int index = -1 );
199
200 /**
201 * Replaces the item at position @p index with @p url.
202 * @ref OURL::prettyURL() is used so that the url is properly decoded
203 * for displaying.
204 */
205 //void changeURL( const OURL& url, int index );
206
207 /**
208 * Replaces the item at position @p index with @p url and pixmap @p pixmap.
209 * @ref OURL::prettyURL() is used so that the url is properly decoded
210 * for displaying.
211 */
212 //void changeURL( const QPixmap& pixmap, const OURL& url, int index );
213
214 /**
215 * Returns the current cursor position.
216 *
217 * This method always returns a -1 if the combo-box is @em not
218 * editable (read-write).
219 *
220 * @return Current cursor position.
221 */
222 int cursorPosition() const { return ( lineEdit() ) ? lineEdit()->cursorPosition() : -1; }
223
224 /**
225 * Re-implemented from @ref QComboBox.
226 *
227 * If @p true, the completion mode will be set to automatic.
228 * Otherwise, it is defaulted to the global setting. This
229 * method has been replaced by the more comprehensive
230 * @ref setCompletionMode().
231 *
232 * @param autocomplete Flag to enable/disable automatic completion mode.
233 */
234 virtual void setAutoCompletion( bool autocomplete );
235
236 /**
237 * Re-implemented from QComboBox.
238 *
239 * Returns @p true if the current completion mode is set
240 * to automatic. See its more comprehensive replacement
241 * @ref completionMode().
242 *
243 * @return @p true when completion mode is automatic.
244 */
245 bool autoCompletion() const {
246 return completionMode() == OGlobalSettings::CompletionAuto;
247 }
248
249 /**
250 * Enables or disable the popup (context) menu.
251 *
252 * This method only works if this widget is editable, i.e.
253 * read-write and allows you to enable/disable the context
254 * menu. It does nothing if invoked for a none-editable
255 * combo-box. Note that by default the mode changer item
256 * is made visiable whenever the context menu is enabled.
257 * Use @ref hideModechanger() if you want to hide this
258 * item. Also by default, the context menu is created if
259 * this widget is editable. Call this function with the
260 * argument set to false to disable the popup menu.
261 *
262 * @param showMenu If @p true, show the context menu.
263 * @param showMode If @p true, show the mode changer.
264 */
265 virtual void setContextMenuEnabled( bool showMenu );
266
267 /**
268 * Returns @p true when the context menu is enabled.
269 */
270 bool isContextMenuEnabled() const { return m_bEnableMenu; }
271
272 /**
273 * Enables/Disables handling of URL drops. If enabled and the user
274 * drops an URL, the decoded URL will be inserted. Otherwise the default
275 * behaviour of QComboBox is used, which inserts the encoded URL.
276 *
277 * @param enable If @p true, insert decoded URLs
278 */
279 //void setURLDropsEnabled( bool enable );
280
281 /**
282 * Returns @p true when decoded URL drops are enabled
283 */
284 //bool isURLDropsEnabled() const;
285
286 /**
287 * Convenience method which iterates over all items and checks if
288 * any of them is equal to @p text.
289 *
290 * If @p text is an empty string, @p false
291 * is returned.
292 *
293 * @return @p true if an item with the string @p text is in the combobox.
294 */
295 bool contains( const QString& text ) const;
296
297 /**
298 * By default, OComboBox recognizes Key_Return and Key_Enter
299 * and emits
300 * the @ref returnPressed() signals, but it also lets the event pass,
301 * for example causing a dialog's default-button to be called.
302 *
303 * Call this method with @p trap equal to true to make OComboBox
304 * stop these
305 * events. The signals will still be emitted of course.
306 *
307 * Only affects read-writable comboboxes.
308 *
309 * @see setTrapReturnKey()
310 */
311 void setTrapReturnKey( bool trap );
312
313 /**
314 * @return @p true if keyevents of Key_Return or Key_Enter will
315 * be stopped or if they will be propagated.
316 *
317 * @see setTrapReturnKey ()
318 */
319 bool trapReturnKey() const;
320
321 /**
322 * Re-implemented for internal reasons. API not affected.
323 *
324 * @reimplemented
325 */
326 virtual bool eventFilter( QObject *, QEvent * );
327
328 /**
329 * @returns the completion-box, that is used in completion mode
330 * @ref OGlobalSettings::CompletionPopup and @ref OGlobalSettings::CompletionPopupAuto.
331 * This method will create a completion-box by calling
332 * @ref OLineEdit::completionBox, if none is there, yet.
333 *
334 * @param create Set this to false if you don't want the box to be created
335 * i.e. to test if it is available.
336 */
337 OCompletionBox * completionBox( bool create = true );
338
339 virtual void setLineEdit( OLineEdit * );
340
341signals:
342 /**
343 * Emitted when the user presses the Enter key.
344 *
345 * Note that this signal is only
346 * emitted if this widget is editable.
347 */
348 void returnPressed();
349
350 /**
351 * Emitted when the user presses
352 * the Enter key.
353 *
354 * The argument is the current
355 * text being edited. This signal is just like
356 * @ref returnPressed() except it contains the
357 * current text as its argument.
358 *
359 * Note that this signal is only emitted if this
360 * widget is editable.
361 */
362 void returnPressed( const QString& );
363
364 /**
365 * This signal is emitted when the completion key
366 * is pressed.
367 *
368 * The argument is the current text
369 * being edited.
370 *
371 * Note that this signal is @em not available if this
372 * widget is non-editable or the completion mode is
373 * set to @p OGlobalSettings::CompletionNone.
374 */
375 void completion( const QString& );
376
377 /**
378 * Emitted when the shortcut for substring completion is pressed.
379 */
380 void substringCompletion( const QString& );
381
382 /**
383 * Emitted when the text rotation key-bindings are pressed.
384 *
385 * The argument indicates which key-binding was pressed.
386 * In this case this can be either one of four values:
387 * @p PrevCompletionMatch, @p NextCompletionMatch, @p RotateUp or
388 * @p RotateDown. See @ref OCompletionBase::setKeyBinding() for
389 * details.
390 *
391 * Note that this signal is @em NOT emitted if the completion
392 * mode is set to CompletionNone.
393 */
394 void textRotation( OCompletionBase::KeyBindingType );
395
396 /**
397 * Emitted when the user changed the completion mode by using the
398 * popupmenu.
399 */
400 void completionModeChanged( OGlobalSettings::Completion );
401
402 /**
403 * Emitted before the context menu is displayed.
404 *
405 * The signal allows you to add your own entries into the
406 * the context menu that is created on demand.
407 *
408 * NOTE: Do not store the pointer to the QPopupMenu
409 * provided through since it is created and deleted
410 * on demand.
411 *
412 * @param the context menu about to be displayed
413 */
414 void aboutToShowContextMenu( QPopupMenu * );
415
416public slots:
417
418 /**
419 * Iterates through all possible matches of the completed text
420 * or the history list.
421 *
422 * Depending on the value of the argument, this function either
423 * iterates through the history list of this widget or the all
424 * possible matches in whenever multiple matches result from a
425 * text completion request. Note that the all-possible-match
426 * iteration will not work if there are no previous matches, i.e.
427 * no text has been completed and the *nix shell history list
428 * rotation is only available if the insertion policy for this
429 * widget is set either @p QComobBox::AtTop or @p QComboBox::AtBottom.
430 * For other insertion modes whatever has been typed by the user
431 * when the rotation event was initiated will be lost.
432 *
433 * @param type The key-binding invoked.
434 */
435 void rotateText( OCompletionBase::KeyBindingType /* type */ );
436
437 /**
438 * Sets the completed text in the line-edit appropriately.
439 *
440 * This function is an implementation for
441 * @ref OCompletionBase::setCompletedText.
442 */
443 virtual void setCompletedText( const QString& );
444
445 /**
446 * Sets @p items into the completion-box if @ref completionMode() is
447 * CompletionPopup. The popup will be shown immediately.
448 */
449 void setCompletedItems( const QStringList& items );
450
451 public:
452 /**
453 * Selects the first item that matches @p item. If there is no such item,
454 * it is inserted at position @p index if @p insert is true. Otherwise,
455 * no item is selected.
456 */
457 void setCurrentItem( const QString& item, bool insert = false, int index = -1 );
458 void setCurrentItem(int index);
459
460protected slots:
461
462 /**
463 * @deprecated.
464 */
465 virtual void itemSelected( QListBoxItem* ) {};
466
467 /**
468 * Completes text according to the completion mode.
469 *
470 * Note: this method is @p not invoked if the completion mode is
471 * set to CompletionNone. Also if the mode is set to @p CompletionShell
472 * and multiple matches are found, this method will complete the
473 * text to the first match with a beep to inidicate that there are
474 * more matches. Then any successive completion key event iterates
475 * through the remaining matches. This way the rotation functionality
476 * is left to iterate through the list as usual.
477 */
478 virtual void makeCompletion( const QString& );
479
480protected:
481 /*
482 * This function simply sets the lineedit text and
483 * highlights the text appropriately if the boolean
484 * value is set to true.
485 *
486 * @param
487 * @param
488 */
489 virtual void setCompletedText( const QString& /* */, bool /*marked*/ );
490
491 /**
492 * Reimplemented for internal reasons, the API is not affected.
493 */
494 virtual void create( WId = 0, bool initializeWindow = true,
495 bool destroyOldWindow = true );
496
497private:
498 // Constants that represent the ID's of the popup menu.
499 // TODO: See if we can replace this mess with OActionMenu
500 // in the future though this is working lovely.
501 enum MenuID {
502 Default=0,
503 Cut,
504 Copy,
505 Paste,
506 Clear,
507 Unselect,
508 SelectAll,
509 NoCompletion,
510 AutoCompletion,
511 ShellCompletion,
512 PopupCompletion,
513 SemiAutoCompletion
514 };
515
516 /**
517 * Initializes the variables upon construction.
518 */
519 void init();
520 /**
521 * Temporary functions to delete words back and foward until
522 * alternatives are available in QT3 (Seth Chaiklin, 21 may 2001)
523 */
524 void deleteWordBack();
525 void deleteWordForward();
526
527 bool m_bEnableMenu;
528
529 // indicating if we should stop return-key events from propagating
530 bool m_trapReturnKey;
531
532//protected:
533// virtual void virtual_hook( int id, void* data );
534private:
535 class OComboBoxPrivate;
536 OComboBoxPrivate *d;
537};
538
539
540class OPixmapProvider;
541
542/**
543 * A combobox which implements a history like a unix shell. You can navigate
544 * through all the items by using the Up or Down arrows (configurable of
545 * course). Additionally, weighted completion is available. So you should
546 * load and save the completion list to preserve the weighting between
547 * sessions.
548 *
549 * @author Carsten Pfeiffer <pfeiffer@kde.org>
550 * @short A combobox for offering a history and completion
551 */
552class OHistoryCombo : public OComboBox
553{
554 Q_OBJECT
555 Q_PROPERTY( QStringList historyItems READ historyItems WRITE setHistoryItems )
556
557public:
558 /**
559 * Constructs a "read-write" combobox. A read-only history combobox
560 * doesn't make much sense, so it is only available as read-write.
561 * Completion will be used automatically for the items in the combo.
562 *
563 * The insertion-policy is set to NoInsertion, you have to add the items
564 * yourself via the slot @ref addToHistory. If you want every item added,
565 * use
566 *
567 * <pre>
568 * connect( combo, SIGNAL( activated( const QString& )),
569 * combo, SLOT( addToHistory( const QString& )));
570 * </pre>
571 *
572 * Use @ref QComboBox::setMaxCount() to limit the history.
573 *
574 * @p parent the parent object of this widget.
575 * @p name the name of this widget.
576 */
577 OHistoryCombo( QWidget *parent = 0L, const char *name = 0L );
578
579 // ### merge these two constructors
580 /**
581 * Same as the previous constructor, but additionally has the option
582 * to specify whether you want to let OHistoryCombo handle completion
583 * or not. If set to @p true, OHistoryCombo will sync the completion to the
584 * contents of the combobox.
585 */
586 OHistoryCombo( bool useCompletion,
587 QWidget *parent = 0L, const char *name = 0L );
588
589 /**
590 * Destructs the combo, the completion-object and the pixmap-provider
591 */
592 ~OHistoryCombo();
593
594 /**
595 * Inserts @p items into the combobox. @p items might get
596 * truncated if it is longer than @ref maxCount()
597 *
598 * @see #historyItems
599 */
600 inline void setHistoryItems( QStringList items ) {
601 setHistoryItems(items, false);
602 }
603
604 /**
605 * Inserts @p items into the combobox. @p items might get
606 * truncated if it is longer than @ref maxCount()
607 *
608 * Set @p setCompletionList to true, if you don't have a list of
609 * completions. This tells OHistoryCombo to use all the items for the
610 * completion object as well.
611 * You won't have the benefit of weighted completion though, so normally
612 * you should do something like
613 * <pre>
614 * OConfig *config = kapp->config();
615 * QStringList list;
616 *
617 * // load the history and completion list after creating the history combo
618 * list = config->readListEntry( "Completion list" );
619 * combo->completionObject()->setItems( list );
620 * list = config->readListEntry( "History list" );
621 * combo->setHistoryItems( list );
622 *
623 * [...]
624 *
625 * // save the history and completion list when the history combo is
626 * // destroyed
627 * list = combo->completionObject()->items()
628 * config->writeEntry( "Completion list", list );
629 * list = combo->historyItems();
630 * config->writeEntry( "History list", list );
631 * </pre>
632 *
633 * Be sure to use different names for saving with OConfig if you have more
634 * than one OHistoryCombo.
635 *
636 * Note: When @p setCompletionList is true, the items are inserted into the
637 * OCompletion object with mode OCompletion::Insertion and the mode is set
638 * to OCompletion::Weighted afterwards.
639 *
640 * @see #historyItems
641 * @see OComboBox::completionObject
642 * @see OCompletion::setItems
643 * @see OCompletion::items
644 */
645 void setHistoryItems( QStringList items, bool setCompletionList );
646
647 /**
648 * Returns the list of history items. Empty, when this is not a read-write
649 * combobox.
650 *
651 * @see #setHistoryItems
652 */
653 QStringList historyItems() const;
654
655 /**
656 * Removes all items named @p item.
657 *
658 * @return @p true if at least one item was removed.
659 *
660 * @see #addToHistory
661 */
662 bool removeFromHistory( const QString& item );
663
664 /**
665 * Sets a pixmap provider, so that items in the combobox can have a pixmap.
666 * @ref OPixmapProvider is just an abstract class with the one pure virtual
667 * method @ref OPixmapProvider::pixmapFor(). This method is called whenever
668 * an item is added to the OHistoryComboBox. Implement it to return your
669 * own custom pixmaps, or use the @ref OURLPixmapProvider from libkio,
670 * which uses @ref OMimeType::pixmapForURL to resolve icons.
671 *
672 * Set @p prov to 0L if you want to disable pixmaps. Default no pixmaps.
673 *
674 * @see #pixmapProvider
675 */
676 void setPixmapProvider( OPixmapProvider *prov );
677
678 /**
679 * @returns the current pixmap provider.
680 * @see #setPixmapProvider
681 * @see OPixmapProvider
682 */
683 OPixmapProvider * pixmapProvider() const { return myPixProvider; }
684
685 /**
686 * Resets the current position of the up/down history. Call this
687 * when you manually call @ref setCurrentItem() or @ref clearEdit().
688 */
689 void reset() { slotReset(); }
690
691public slots:
692 /**
693 * Adds an item to the end of the history list and to the completion list.
694 * If @ref maxCount() is reached, the first item of the list will be
695 * removed.
696 *
697 * If the last inserted item is the same as @p item, it will not be
698 * inserted again.
699 *
700 * If @ref duplicatesEnabled() is false, any equal existing item will be
701 * removed before @p item is added.
702 *
703 * Note: By using this method and not the Q and OComboBox insertItem()
704 * methods, you make sure that the combobox stays in sync with the
705 * completion. It would be annoying if completion would give an item
706 * not in the combobox, and vice versa.
707 *
708 * @see #removeFromHistory
709 * @see QComboBox::setDuplicatesEnabled
710 */
711 void addToHistory( const QString& item );
712
713 /**
714 * Clears the history and the completion list.
715 */
716 void clearHistory();
717
718signals:
719 /**
720 * Emitted when the history was cleared by the entry in the popup menu.
721 */
722 void cleared();
723
724protected:
725 /**
726 * Handling key-events, the shortcuts to rotate the items.
727 */
728 virtual void keyPressEvent( QKeyEvent * );
729
730
731 /**
732 * Inserts @p items into the combo, honouring @ref pixmapProvider()
733 * Does not update the completionObject.
734 *
735 * Note: @ref duplicatesEnabled() is not honored here.
736 *
737 * Called from @ref setHistoryItems() and @ref setPixmapProvider()
738 */
739 void insertItems( const QStringList& items );
740
741 /**
742 * @returns if we can modify the completion object or not.
743 */
744 bool useCompletion() const { return compObj() != 0L; }
745
746private slots:
747 /**
748 * Resets the iterate index to -1
749 */
750 void slotReset();
751
752 /**
753 * Called from the popupmenu,
754 * calls clearHistory() and emits cleared()
755 */
756 void slotClear();
757
758 /**
759 * Appends our own context menu entry.
760 */
761 void addContextMenuItems( QPopupMenu* );
762
763private:
764 void init( bool useCompletion );
765
766 /**
767 * The current position (index) in the combobox, used for Up and Down
768 */
769 int myIterateIndex;
770
771 /**
772 * The text typed before Up or Down was pressed.
773 */
774 QString myText;
775
776 /**
777 * Indicates that the user at least once rotated Up through the entire list
778 * Needed to allow going back after rotation.
779 */
780 bool myRotated;
781 OPixmapProvider *myPixProvider;
782
783private:
784 class OHistoryComboPrivate;
785 OHistoryComboPrivate *d;
786};
787
788
789#endif
790
diff --git a/libopie2/qt3/opieui/ocompletionbox.cpp b/libopie2/qt3/opieui/ocompletionbox.cpp
new file mode 100644
index 0000000..b594b8e
--- a/dev/null
+++ b/libopie2/qt3/opieui/ocompletionbox.cpp
@@ -0,0 +1,408 @@
1/*
2 This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
3 is part of the Copyright (C) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
4 Opie Project Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de>
5 Copyright (C) 2000,2001 Dawit Alemayehu <adawit@kde.org>
6 =.
7 .=l. Originally part of the KDE Project
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#include <qapplication.h>
34#include <qevent.h>
35#include <qstyle.h>
36
37#include <opie2/ocompletionbox.h>
38
39#define OListBox QListBox
40
41class OCompletionBox::OCompletionBoxPrivate
42{
43public:
44 QWidget *m_parent; // necessary to set the focus back
45 QString cancelText;
46 bool tabHandling;
47 bool down_workaround;
48};
49
50OCompletionBox::OCompletionBox( QWidget *parent, const char *name )
51 :OListBox( parent, name, WType_Popup )
52{
53 d = new OCompletionBoxPrivate;
54 d->m_parent = parent;
55 d->tabHandling = true;
56 d->down_workaround = false;
57
58 setColumnMode( 1 );
59 setLineWidth( 1 );
60 setFrameStyle( QFrame::Box | QFrame::Plain );
61
62 if ( parent )
63 setFocusProxy( parent );
64 else
65 setFocusPolicy( NoFocus );
66
67 setVScrollBarMode( Auto );
68 setHScrollBarMode( AlwaysOff );
69
70 connect( this, SIGNAL( doubleClicked( QListBoxItem * )),
71 SLOT( slotActivated( QListBoxItem * )) );
72
73 // grmbl, just QListBox workarounds :[ Thanks Volker.
74 connect( this, SIGNAL( currentChanged( QListBoxItem * )),
75 SLOT( slotCurrentChanged() ));
76 connect( this, SIGNAL( clicked( QListBoxItem * )),
77 SLOT( slotItemClicked( QListBoxItem * )) );
78}
79
80OCompletionBox::~OCompletionBox()
81{
82 d->m_parent = 0L;
83 delete d;
84}
85
86QStringList OCompletionBox::items() const
87{
88 QStringList list;
89 for ( uint i = 0; i < count(); i++ ) {
90 list.append( text( i ) );
91 }
92 return list;
93}
94
95void OCompletionBox::slotActivated( QListBoxItem *item )
96{
97 if ( !item )
98 return;
99
100 hide();
101 emit activated( item->text() );
102}
103
104bool OCompletionBox::eventFilter( QObject *o, QEvent *e )
105{
106 int type = e->type();
107
108 if ( o == d->m_parent ) {
109 if ( isVisible() ) {
110 if ( type == QEvent::KeyPress ) {
111 QKeyEvent *ev = static_cast<QKeyEvent *>( e );
112 switch ( ev->key() ) {
113 case Key_BackTab:
114 if ( d->tabHandling ) {
115 up();
116 ev->accept();
117 return true;
118 }
119 break;
120 case Key_Tab:
121 if ( d->tabHandling ) {
122 down(); // Only on TAB!!
123 ev->accept();
124 return true;
125 }
126 break;
127 case Key_Down:
128 down();
129 ev->accept();
130 return true;
131 case Key_Up:
132 up();
133 ev->accept();
134 return true;
135 case Key_Prior:
136 pageUp();
137 ev->accept();
138 return true;
139 case Key_Next:
140 pageDown();
141 ev->accept();
142 return true;
143 case Key_Escape:
144 cancelled();
145 ev->accept();
146 return true;
147 case Key_Enter:
148 case Key_Return:
149 if ( ev->state() & ShiftButton ) {
150 hide();
151 ev->accept(); // Consume the Enter event
152 return true;
153 }
154 break;
155 default:
156 break;
157 }
158 }
159 else if ( type == QEvent::AccelOverride ) {
160 // Override any acceleartors that match
161 // the key sequences we use here...
162 QKeyEvent *ev = static_cast<QKeyEvent *>( e );
163 switch ( ev->key() ) {
164 case Key_Tab:
165 case Key_BackTab:
166 case Key_Down:
167 case Key_Up:
168 case Key_Prior:
169 case Key_Next:
170 case Key_Escape:
171 case Key_Enter:
172 case Key_Return:
173 ev->accept();
174 return true;
175 break;
176 default:
177 break;
178 }
179 }
180
181 // parent loses focus or gets a click -> we hide
182 else if ( type == QEvent::FocusOut || type == QEvent::Resize ||
183 type == QEvent::Close || type == QEvent::Hide ||
184 type == QEvent::Move ) {
185 hide();
186 }
187 else if ( type == QEvent::Move )
188 move( d->m_parent->mapToGlobal(QPoint(0, d->m_parent->height())));
189 else if ( type == QEvent::Resize )
190 resize( sizeHint() );
191 }
192 }
193
194 // any mouse-click on something else than "this" makes us hide
195 else if ( type == QEvent::MouseButtonPress ) {
196 QMouseEvent *ev = static_cast<QMouseEvent *>( e );
197 if ( !rect().contains( ev->pos() )) // this widget
198 hide();
199 }
200
201 return OListBox::eventFilter( o, e );
202}
203
204
205void OCompletionBox::popup()
206{
207 if ( count() == 0 )
208 hide();
209 else {
210 ensureCurrentVisible();
211 bool block = signalsBlocked();
212 blockSignals( true );
213 setCurrentItem( 0 );
214 blockSignals( block );
215 clearSelection();
216 if ( !isVisible() )
217 show();
218 else if ( size().height() < sizeHint().height() )
219 resize( sizeHint() );
220 }
221}
222
223void OCompletionBox::show()
224{
225 resize( sizeHint() );
226
227 if ( d->m_parent )
228 {
229 //QDesktopWidget *screen = QApplication::desktop();
230 QWidget *screen = QApplication::desktop();
231
232 QPoint orig = d->m_parent->mapToGlobal( QPoint(0, d->m_parent->height()) );
233 int x = orig.x();
234 int y = orig.y();
235
236 if ( x + width() > screen->width() )
237 x = screen->width() - width();
238 if (y + height() > screen->height() )
239 y = y - height() - d->m_parent->height();
240
241 move( x, y);
242 qApp->installEventFilter( this );
243 }
244
245 // ### we shouldn't need to call this, but without this, the scrollbars
246 // are pretty b0rked.
247 //triggerUpdate( true );
248
249 OListBox::show();
250}
251
252void OCompletionBox::hide()
253{
254 if ( d->m_parent )
255 qApp->removeEventFilter( this );
256 d->cancelText = QString::null;
257 OListBox::hide();
258}
259
260QSize OCompletionBox::sizeHint() const
261{
262 int ih = itemHeight();
263 int h = QMIN( 15 * ih, (int) count() * ih ) +1;
264 h = QMAX( h, OListBox::minimumSizeHint().height() );
265
266 int w = (d->m_parent) ? d->m_parent->width() : OListBox::minimumSizeHint().width();
267 w = QMAX( OListBox::minimumSizeHint().width(), w );
268 return QSize( w, h );
269}
270
271void OCompletionBox::down()
272{
273 int i = currentItem();
274
275 if ( i == 0 && d->down_workaround ) {
276 d->down_workaround = false;
277 setCurrentItem( 0 );
278 setSelected( 0, true );
279 emit highlighted( currentText() );
280 }
281
282 else if ( i < (int) count() - 1 )
283 setCurrentItem( i + 1 );
284}
285
286void OCompletionBox::up()
287{
288 if ( currentItem() > 0 )
289 setCurrentItem( currentItem() - 1 );
290}
291
292void OCompletionBox::pageDown()
293{
294 int i = currentItem() + numItemsVisible();
295 i = i > (int)count() - 1 ? (int)count() - 1 : i;
296 setCurrentItem( i );
297}
298
299void OCompletionBox::pageUp()
300{
301 int i = currentItem() - numItemsVisible();
302 i = i < 0 ? 0 : i;
303 setCurrentItem( i );
304}
305
306void OCompletionBox::home()
307{
308 setCurrentItem( 0 );
309}
310
311void OCompletionBox::end()
312{
313 setCurrentItem( count() -1 );
314}
315
316void OCompletionBox::setTabHandling( bool enable )
317{
318 d->tabHandling = enable;
319}
320
321bool OCompletionBox::isTabHandling() const
322{
323 return d->tabHandling;
324}
325
326void OCompletionBox::setCancelledText( const QString& text )
327{
328 d->cancelText = text;
329}
330
331QString OCompletionBox::cancelledText() const
332{
333 return d->cancelText;
334}
335
336void OCompletionBox::cancelled()
337{
338 if ( !d->cancelText.isNull() )
339 emit userCancelled( d->cancelText );
340 if ( isVisible() )
341 hide();
342}
343
344class OCompletionBoxItem : public QListBoxItem
345{
346public:
347 void reuse( const QString &text ) { setText( text ); }
348};
349
350
351void OCompletionBox::insertItems( const QStringList& items, int index )
352{
353 bool block = signalsBlocked();
354 blockSignals( true );
355 insertStringList( items, index );
356 blockSignals( block );
357 d->down_workaround = true;
358}
359
360void OCompletionBox::setItems( const QStringList& items )
361{
362 bool block = signalsBlocked();
363 blockSignals( true );
364
365 QListBoxItem* item = firstItem();
366 if ( !item ) {
367 insertStringList( items );
368 }
369 else {
370 for ( QStringList::ConstIterator it = items.begin(); it != items.end(); it++) {
371 if ( item ) {
372 ((OCompletionBoxItem*)item)->reuse( *it );
373 item = item->next();
374 }
375 else {
376 insertItem( new QListBoxText( *it ) );
377 }
378 }
379 QListBoxItem* tmp = item;
380 while ( (item = tmp ) ) {
381 tmp = item->next();
382 delete item;
383 }
384 triggerUpdate( false );
385 }
386
387 blockSignals( block );
388 d->down_workaround = true;
389}
390
391void OCompletionBox::slotCurrentChanged()
392{
393 d->down_workaround = false;
394}
395
396void OCompletionBox::slotItemClicked( QListBoxItem *item )
397{
398 if ( item )
399 {
400 if ( d->down_workaround ) {
401 d->down_workaround = false;
402 emit highlighted( item->text() );
403 }
404
405 hide();
406 emit activated( item->text() );
407 }
408}
diff --git a/libopie2/qt3/opieui/ocompletionbox.h b/libopie2/qt3/opieui/ocompletionbox.h
new file mode 100644
index 0000000..54d9ef5
--- a/dev/null
+++ b/libopie2/qt3/opieui/ocompletionbox.h
@@ -0,0 +1,232 @@
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 Stefan Schimanski <1Stein@gmx.de>
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#ifndef OCOMPLETIONBOX_H
34#define OCOMPLETIONBOX_H
35
36class QEvent;
37#include <qstringlist.h>
38#include <qlistbox.h>
39
40// ML: Until we don't have an own OListBox, we use the QListBox
41#define OListBox QListBox
42
43/**
44 * A little utility class for "completion-widgets", like @ref OLineEdit or
45 * @ref OComboBox. OCompletionBox is a listbox, displayed as a rectangle without
46 * any window decoration, usually directly under the lineedit or combobox.
47 * It is filled with all possible matches for a completion, so the user
48 * can select the one he wants.
49 *
50 * It is used when OGlobalSettings::Completion == CompletionPopup or CompletionPopupAuto.
51 *
52 * @short A helper widget for "completion-widgets" (OLineEdit, OComboBox))
53 * @short Adapted for the Opie project by Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
54 * @author Carsten Pfeiffer <pfeiffer@kde.org>
55 *
56 */
57class OCompletionBox : public OListBox
58{
59 Q_OBJECT
60 Q_PROPERTY( bool isTabHandling READ isTabHandling WRITE setTabHandling )
61 Q_PROPERTY(QString cancelledText READ cancelledText WRITE setCancelledText)
62
63public:
64 /**
65 * Constructs a OCompletionBox.
66 *
67 * Notice: the parent needs to be always 0L,
68 * so you can't specify it in the constructor. Because of that, Qt's
69 * auto-deletion does not take place, so you have to explicitly delete
70 * this widget when you don't need it anymore.
71 *
72 * The parent widget is used to give the focus back when pressing the
73 * up-button on the very first item.
74 */
75 OCompletionBox( QWidget *parent, const char *name = 0 );
76
77 /**
78 * Destroys the box
79 */
80 ~OCompletionBox();
81
82 virtual QSize sizeHint() const;
83
84public slots:
85 /**
86 * Returns a list of all items currently in the box.
87 */
88 QStringList items() const;
89
90 /**
91 * Inserts @p items into the box. Does not clear the items before.
92 * @p index determines at which position @p items will be inserted.
93 * (defaults to appending them at the end)
94 */
95 void insertItems( const QStringList& items, int index = -1 );
96
97 /**
98 * Clears the box and inserts @p items.
99 */
100 void setItems( const QStringList& items );
101
102 /**
103 * Adjusts the size of the box to fit the width of the parent given in the
104 * constructor and pops it up at the most appropriate place, relative to
105 * the parent.
106 *
107 * Depending on the screensize and the position of the parent, this may
108 * be a different place, however the default is to pop it up and the
109 * lower left corner of the parent.
110 *
111 * Make sure to hide() the box when appropriate.
112 */
113 virtual void popup();
114
115 /**
116 * Makes this widget (when visible) capture Tab-key events to traverse the
117 * items in the dropdown list.
118 *
119 * Default off, as it conflicts with the usual behavior of Tab to traverse
120 * widgets. It is useful for cases like Konqueror's Location Bar, though.
121 *
122 * @see #isTabHandling
123 */
124 void setTabHandling( bool enable );
125
126 /**
127 * @returns true if this widget is handling Tab-key events to traverse the
128 * items in the dropdown list, otherwise false.
129 *
130 * Default is false.
131 *
132 * @see #setTabHandling
133 */
134 bool isTabHandling() const;
135
136 /**
137 * Sets the text to be emitted if the user chooses not to
138 * pick from the available matches.
139 *
140 * If the cancelled text is not set through this function, the
141 * @ref userCancelled signal will not be emitted.
142 *
143 * @see userCancelled( const QString& )
144 * @param txt the text to be emitted if the user cancels this box
145 */
146 void setCancelledText( const QString& );
147
148 /**
149 * @returns the text set via @ref setCancelledText() or QString::null.
150 */
151 QString cancelledText() const;
152
153 /**
154 * Moves the selection one line down or select the first item if nothing is selected yet.
155 */
156 void down();
157
158 /**
159 * Moves the selection one line up or select the first item if nothing is selected yet.
160 */
161 void up();
162
163 /**
164 * Moves the selection one page down.
165 */
166 void pageDown();
167
168 /**
169 * Moves the selection one page up.
170 */
171 void pageUp();
172
173 /**
174 * Moves the selection up to the first item.
175 */
176 void home();
177
178 /**
179 * Moves the selection down to the last item.
180 */
181 void end();
182
183 /**
184 * Re-implemented for internal reasons. API is unaffected.
185 */
186 virtual void show();
187
188 /**
189 * Re-implemented for internal reasons. API is unaffected.
190 */
191 virtual void hide();
192
193signals:
194 /**
195 * Emitted when an item was selected, contains the text of
196 * the selected item.
197 */
198 void activated( const QString& );
199
200 /**
201 * Emitted whenever the user chooses to ignore the available
202 * selections and close the this box.
203 */
204 void userCancelled( const QString& );
205
206protected:
207 /**
208 * Reimplemented from OListBox to get events from the viewport (to hide
209 * this widget on mouse-click, Escape-presses, etc.
210 */
211 virtual bool eventFilter( QObject *, QEvent * );
212
213protected slots:
214 /**
215 * Called when an item was activated. Emits
216 * @ref activated() with the item.
217 */
218 virtual void slotActivated( QListBoxItem * );
219
220private slots:
221 void slotSetCurrentItem( QListBoxItem *i ) { setCurrentItem( i ); } // grrr
222 void slotCurrentChanged();
223 void cancelled();
224 void slotItemClicked( QListBoxItem * );
225
226private:
227 class OCompletionBoxPrivate;
228 OCompletionBoxPrivate* d;
229};
230
231
232#endif // OCOMPLETIONBOX_H
diff --git a/libopie2/qt3/opieui/oeditlistbox.cpp b/libopie2/qt3/opieui/oeditlistbox.cpp
new file mode 100644
index 0000000..3c53552
--- a/dev/null
+++ b/libopie2/qt3/opieui/oeditlistbox.cpp
@@ -0,0 +1,416 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org>
3 2000, 2002 Carsten Pfeiffer <pfeiffer@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/* QT */
22
23#include <qstringlist.h>
24#include <qpushbutton.h>
25#include <qlayout.h>
26#include <qgroupbox.h>
27#include <qlistbox.h>
28#include <qwhatsthis.h>
29#include <qlabel.h>
30
31/* OPIE */
32
33#include <opie2/ocombobox.h>
34#include <opie2/odialog.h>
35#include <opie2/olineedit.h>
36#include <opie2/oeditlistbox.h>
37
38/* UNIX */
39
40#include <assert.h>
41
42/*======================================================================================
43 * OEditListBoxPrivate
44 *======================================================================================*/
45
46class OEditListBoxPrivate
47{
48public:
49 bool m_checkAtEntering;
50 int buttons;
51};
52
53/*======================================================================================
54 * OEditListBox
55 *======================================================================================*/
56
57OEditListBox::OEditListBox(QWidget *parent, const char *name,
58 bool checkAtEntering, int buttons )
59 :QGroupBox(parent, name )
60{
61 init( checkAtEntering, buttons );
62}
63
64OEditListBox::OEditListBox(const QString& title, QWidget *parent,
65 const char *name, bool checkAtEntering, int buttons)
66 :QGroupBox(title, parent, name )
67{
68 init( checkAtEntering, buttons );
69}
70
71OEditListBox::OEditListBox(const QString& title, const CustomEditor& custom,
72 QWidget *parent, const char *name,
73 bool checkAtEntering, int buttons)
74 :QGroupBox(title, parent, name )
75{
76 m_lineEdit = custom.lineEdit();
77 init( checkAtEntering, buttons, custom.representationWidget() );
78}
79
80OEditListBox::~OEditListBox()
81{
82 delete d;
83 d=0;
84}
85
86void OEditListBox::init( bool checkAtEntering, int buttons,
87 QWidget *representationWidget )
88{
89 d=new OEditListBoxPrivate;
90 d->m_checkAtEntering=checkAtEntering;
91 d->buttons = buttons;
92
93 int lostButtons = 0;
94 if ( (buttons & Add) == 0 )
95 lostButtons++;
96 if ( (buttons & Remove) == 0 )
97 lostButtons++;
98 if ( (buttons & UpDown) == 0 )
99 lostButtons += 2;
100
101
102 servNewButton = servRemoveButton = servUpButton = servDownButton = 0L;
103 setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,
104 QSizePolicy::MinimumExpanding));
105
106 QWidget * gb = this;
107 QGridLayout * grid = new QGridLayout(gb, 7 - lostButtons, 2,
108 ODialog::marginHint(),
109 ODialog::spacingHint());
110 grid->addRowSpacing(0, fontMetrics().lineSpacing());
111 for ( int i = 1; i < 7 - lostButtons; i++ )
112 grid->setRowStretch(i, 1);
113
114 grid->setMargin(15);
115
116 if ( representationWidget )
117 representationWidget->reparent( gb, QPoint(0,0) );
118 else
119 m_lineEdit=new OLineEdit(gb);
120
121 m_listBox = new QListBox(gb);
122
123 QWidget *editingWidget = representationWidget ?
124 representationWidget : m_lineEdit;
125 grid->addMultiCellWidget(editingWidget,1,1,0,1);
126 grid->addMultiCellWidget(m_listBox, 2, 6 - lostButtons, 0, 0);
127 int row = 2;
128 if ( buttons & Add ) {
129 servNewButton = new QPushButton(tr("&Add"), gb);
130 servNewButton->setEnabled(false);
131 connect(servNewButton, SIGNAL(clicked()), SLOT(addItem()));
132
133 grid->addWidget(servNewButton, row++, 1);
134 }
135
136 if ( buttons & Remove ) {
137 servRemoveButton = new QPushButton(tr("&Remove"), gb);
138 servRemoveButton->setEnabled(false);
139 connect(servRemoveButton, SIGNAL(clicked()), SLOT(removeItem()));
140
141 grid->addWidget(servRemoveButton, row++, 1);
142 }
143
144 if ( buttons & UpDown ) {
145 servUpButton = new QPushButton(tr("Move &Up"), gb);
146 servUpButton->setEnabled(false);
147 connect(servUpButton, SIGNAL(clicked()), SLOT(moveItemUp()));
148
149 servDownButton = new QPushButton(tr("Move &Down"), gb);
150 servDownButton->setEnabled(false);
151 connect(servDownButton, SIGNAL(clicked()), SLOT(moveItemDown()));
152
153 grid->addWidget(servUpButton, row++, 1);
154 grid->addWidget(servDownButton, row++, 1);
155 }
156
157 connect(m_lineEdit,SIGNAL(textChanged(const QString&)),this,SLOT(typedSomething(const QString&)));
158 m_lineEdit->setTrapReturnKey(true);
159 connect(m_lineEdit,SIGNAL(returnPressed()),this,SLOT(addItem()));
160 connect(m_listBox, SIGNAL(highlighted(int)), SLOT(enableMoveButtons(int)));
161
162 // maybe supplied lineedit has some text already
163 typedSomething( m_lineEdit->text() );
164}
165
166void OEditListBox::typedSomething(const QString& text)
167{
168 if(currentItem() >= 0) {
169 if(currentText() != m_lineEdit->text())
170 {
171 // IMHO changeItem() shouldn't do anything with the value
172 // of currentItem() ... like changing it or emitting signals ...
173 // but TT disagree with me on this one (it's been that way since ages ... grrr)
174 bool block = m_listBox->signalsBlocked();
175 m_listBox->blockSignals( true );
176 m_listBox->changeItem(text, currentItem());
177 m_listBox->blockSignals( block );
178 emit changed();
179 }
180 }
181
182 if ( !servNewButton )
183 return;
184
185 if (!d->m_checkAtEntering)
186 servNewButton->setEnabled(!text.isEmpty());
187 else
188 {
189 if (text.isEmpty())
190 {
191 servNewButton->setEnabled(false);
192 }
193 else
194 {
195 #if QT_VERSION > 290
196 StringComparisonMode mode = (StringComparisonMode) (ExactMatch | CaseSensitive );
197 bool enable = (m_listBox->findItem( text, mode ) == 0L);
198 #else
199 bool enable = (m_listBox->findItem( text ) == 0L);
200 #endif
201 servNewButton->setEnabled( enable );
202 }
203 }
204}
205
206void OEditListBox::moveItemUp()
207{
208 if (!m_listBox->isEnabled())
209 {
210 //ONotifyClient::beep();
211 return;
212 }
213
214 unsigned int selIndex = m_listBox->currentItem();
215 if (selIndex == 0)
216 {
217 //ONotifyClient::beep();
218 return;
219 }
220
221 QListBoxItem *selItem = m_listBox->item(selIndex);
222 m_listBox->takeItem(selItem);
223 m_listBox->insertItem(selItem, selIndex-1);
224 m_listBox->setCurrentItem(selIndex - 1);
225
226 emit changed();
227}
228
229void OEditListBox::moveItemDown()
230{
231 if (!m_listBox->isEnabled())
232 {
233 //ONotifyClient::beep();
234 return;
235 }
236
237 unsigned int selIndex = m_listBox->currentItem();
238 if (selIndex == m_listBox->count() - 1)
239 {
240 //ONotifyClient::beep();
241 return;
242 }
243
244 QListBoxItem *selItem = m_listBox->item(selIndex);
245 m_listBox->takeItem(selItem);
246 m_listBox->insertItem(selItem, selIndex+1);
247 m_listBox->setCurrentItem(selIndex + 1);
248
249 emit changed();
250}
251
252void OEditListBox::addItem()
253{
254 // when m_checkAtEntering is true, the add-button is disabled, but this
255 // slot can still be called through Key_Return/Key_Enter. So we guard
256 // against this.
257 if ( !servNewButton || !servNewButton->isEnabled() )
258 return;
259
260 const QString& currentTextLE=m_lineEdit->text();
261 bool alreadyInList(false);
262 //if we didn't check for dupes at the inserting we have to do it now
263 if (!d->m_checkAtEntering)
264 {
265 // first check current item instead of dumb iterating the entire list
266 if ( m_listBox->currentText() == currentTextLE )
267 alreadyInList = true;
268 else
269 {
270 #if QT_VERSION > 290
271 StringComparisonMode mode = (StringComparisonMode) (ExactMatch | CaseSensitive );
272 alreadyInList =(m_listBox->findItem(currentTextLE, mode) != 0);
273 #else
274 alreadyInList =(m_listBox->findItem(currentTextLE) != 0);
275 #endif
276 }
277 }
278
279 if ( servNewButton )
280 servNewButton->setEnabled(false);
281
282 bool block = m_lineEdit->signalsBlocked();
283 m_lineEdit->blockSignals(true);
284 m_lineEdit->clear();
285 m_lineEdit->blockSignals(block);
286
287 m_listBox->setSelected(currentItem(), false);
288
289 if (!alreadyInList)
290 {
291 block = m_listBox->signalsBlocked();
292 m_listBox->blockSignals( true );
293 m_listBox->insertItem(currentTextLE);
294 m_listBox->blockSignals( block );
295 emit changed();
296 emit added( currentTextLE );
297 }
298}
299
300int OEditListBox::currentItem() const
301{
302 int nr = m_listBox->currentItem();
303 #if QT_VERSION > 290
304 if(nr >= 0 && !m_listBox->item(nr)->isSelected()) return -1;
305 #else
306 if(nr >= 0 && !m_listBox->isSelected(m_listBox->item(nr))) return -1;
307 #endif
308 return nr;
309}
310
311void OEditListBox::removeItem()
312{
313 int selected = m_listBox->currentItem();
314
315 if ( selected >= 0 )
316 {
317 QString removedText = m_listBox->currentText();
318
319 m_listBox->removeItem( selected );
320 if ( count() > 0 )
321 m_listBox->setSelected( QMIN( selected, count() - 1 ), true );
322
323 emit changed();
324 emit removed( removedText );
325 }
326
327 if ( servRemoveButton && m_listBox->currentItem() == -1 )
328 servRemoveButton->setEnabled(false);
329}
330
331void OEditListBox::enableMoveButtons(int index)
332{
333 // Update the lineEdit when we select a different line.
334 if(currentText() != m_lineEdit->text())
335 m_lineEdit->setText(currentText());
336
337 bool moveEnabled = servUpButton && servDownButton;
338
339 if (moveEnabled )
340 {
341 if (m_listBox->count() <= 1)
342 {
343 servUpButton->setEnabled(false);
344 servDownButton->setEnabled(false);
345 }
346 else if ((uint) index == (m_listBox->count() - 1))
347 {
348 servUpButton->setEnabled(true);
349 servDownButton->setEnabled(false);
350 }
351 else if (index == 0)
352 {
353 servUpButton->setEnabled(false);
354 servDownButton->setEnabled(true);
355 }
356 else
357 {
358 servUpButton->setEnabled(true);
359 servDownButton->setEnabled(true);
360 }
361 }
362
363 if ( servRemoveButton )
364 servRemoveButton->setEnabled(true);
365}
366
367void OEditListBox::clear()
368{
369 m_lineEdit->clear();
370 m_listBox->clear();
371 emit changed();
372}
373
374void OEditListBox::insertStringList(const QStringList& list, int index)
375{
376 m_listBox->insertStringList(list,index);
377}
378
379void OEditListBox::insertStrList(const QStrList* list, int index)
380{
381 m_listBox->insertStrList(list,index);
382}
383
384void OEditListBox::insertStrList(const QStrList& list, int index)
385{
386 m_listBox->insertStrList(list,index);
387}
388
389void OEditListBox::insertStrList(const char ** list, int numStrings, int index)
390{
391 m_listBox->insertStrList(list,numStrings,index);
392}
393
394QStringList OEditListBox::items() const
395{
396 QStringList list;
397 for ( uint i = 0; i < m_listBox->count(); i++ )
398 list.append( m_listBox->text( i ));
399
400 return list;
401}
402
403void OEditListBox::virtual_hook( int, void* )
404{ /*BASE::virtual_hook( id, data );*/ }
405
406
407/*======================================================================================
408 * CustomEditor
409 *======================================================================================*/
410
411OEditListBox::CustomEditor::CustomEditor( OComboBox *combo )
412{
413 m_representationWidget = combo;
414 m_lineEdit = dynamic_cast<OLineEdit*>( combo->lineEdit() );
415 assert( m_lineEdit );
416}
diff --git a/libopie2/qt3/opieui/oeditlistbox.h b/libopie2/qt3/opieui/oeditlistbox.h
new file mode 100644
index 0000000..63fab11
--- a/dev/null
+++ b/libopie2/qt3/opieui/oeditlistbox.h
@@ -0,0 +1,250 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20#ifndef OEDITLISTBOX_H
21#define OEDITLISTBOX_H
22
23#include <qgroupbox.h>
24#include <qlistbox.h>
25
26class OLineEdit;
27class OComboBox;
28class QPushButton;
29
30#if QT_VERSION < 300
31 enum StringComparisonMode {
32 CaseSensitive = 0x00001, // 0 0001
33 BeginsWith = 0x00002, // 0 0010
34 EndsWith = 0x00004, // 0 0100
35 Contains = 0x00008, // 0 1000
36 ExactMatch = 0x00010 // 1 0000
37 };
38#endif
39
40class OEditListBoxPrivate;
41/**
42 * An editable listbox
43 *
44 * This class provides a editable listbox ;-), this means
45 * a listbox which is accompanied by a line edit to enter new
46 * items into the listbox and pushbuttons to add and remove
47 * items from the listbox and two buttons to move items up and down.
48 */
49class OEditListBox : public QGroupBox
50{
51 Q_OBJECT
52
53public:
54 /// @since 3.1
55 class CustomEditor
56 {
57 public:
58 CustomEditor()
59 : m_representationWidget( 0L ),
60 m_lineEdit( 0L ) {}
61 CustomEditor( QWidget *repWidget, OLineEdit *edit )
62 : m_representationWidget( repWidget ),
63 m_lineEdit( edit ) {}
64 CustomEditor( OComboBox *combo );
65
66 void setRepresentationWidget( QWidget *repWidget ) {
67 m_representationWidget = repWidget;
68 }
69 void setLineEdit( OLineEdit *edit ) {
70 m_lineEdit = edit;
71 }
72
73 virtual QWidget *representationWidget() const {
74 return m_representationWidget;
75 }
76 virtual OLineEdit *lineEdit() const {
77 return m_lineEdit;
78 }
79
80 protected:
81 QWidget *m_representationWidget;
82 OLineEdit *m_lineEdit;
83 };
84
85 public:
86
87 /**
88 * Enumeration of the buttons, the listbox offers. Specify them in the
89 * constructor in the buttons parameter.
90 */
91 enum Button { Add = 1, Remove = 2, UpDown = 4, All = Add|Remove|UpDown };
92
93 /**
94 * Create an editable listbox.
95 *
96 * If @p checkAtEntering is true, after every character you type
97 * in the line edit OEditListBox will enable or disable
98 * the Add-button, depending whether the current content of the
99 * line edit is already in the listbox. Maybe this can become a
100 * performance hit with large lists on slow machines.
101 * If @p checkAtEntering is false,
102 * it will be checked if you press the Add-button. It is not
103 * possible to enter items twice into the listbox.
104 */
105 OEditListBox(QWidget *parent = 0, const char *name = 0,
106 bool checkAtEntering=false, int buttons = All );
107 /**
108 * Create an editable listbox.
109 *
110 * The same as the other constructor, additionally it takes
111 * @title, which will be the title of the frame around the listbox.
112 */
113 OEditListBox(const QString& title, QWidget *parent = 0,
114 const char *name = 0, bool checkAtEntering=false,
115 int buttons = All );
116
117 /**
118 * Another constructor, which allows to use a custom editing widget
119 * instead of the standard OLineEdit widget. E.g. you can use a
120 * @ref OURLRequester or a @ref OComboBox as input widget. The custom
121 * editor must consist of a lineedit and optionally another widget that
122 * is used as representation. A OComboBox or a OURLRequester have a
123 * OLineEdit as child-widget for example, so the OComboBox is used as
124 * the representation widget.
125 *
126 * @see OURLRequester::customEditor()
127 * @since 3.1
128 */
129 OEditListBox( const QString& title,
130 const CustomEditor &customEditor,
131 QWidget *parent = 0, const char *name = 0,
132 bool checkAtEntering = false, int buttons = All );
133
134 virtual ~OEditListBox();
135
136 /**
137 * Return a pointer to the embedded QListBox.
138 */
139 QListBox* listBox() const { return m_listBox; }
140 /**
141 * Return a pointer to the embedded QLineEdit.
142 */
143 OLineEdit* lineEdit() const { return m_lineEdit; }
144 /**
145 * Return a pointer to the Add button
146 */
147 QPushButton* addButton() const { return servNewButton; }
148 /**
149 * Return a pointer to the Remove button
150 */
151 QPushButton* removeButton() const { return servRemoveButton; }
152 /**
153 * Return a pointer to the Up button
154 */
155 QPushButton* upButton() const { return servUpButton; }
156 /**
157 * Return a pointer to the Down button
158 */
159 QPushButton* downButton() const { return servDownButton; }
160
161 /**
162 * See @ref QListBox::count()
163 */
164 int count() const { return int(m_listBox->count()); }
165 /**
166 * See @ref QListBox::insertStringList()
167 */
168 void insertStringList(const QStringList& list, int index=-1);
169 /**
170 * See @ref QListBox::insertStringList()
171 */
172 void insertStrList(const QStrList* list, int index=-1);
173 /**
174 * See @ref QListBox::insertStrList()
175 */
176 void insertStrList(const QStrList& list, int index=-1);
177 /**
178 * See @ref QListBox::insertStrList()
179 */
180 void insertStrList(const char ** list, int numStrings=-1, int index=-1);
181 /**
182 * See @ref QListBox::insertItem()
183 */
184 void insertItem(const QString& text, int index=-1) {m_listBox->insertItem(text,index);}
185 /**
186 * Clears both the listbox and the line edit.
187 */
188 void clear();
189 /**
190 * See @ref QListBox::text()
191 */
192 QString text(int index) const { return m_listBox->text(index); }
193 /**
194 * See @ref QListBox::currentItem()
195 */
196 int currentItem() const;
197 /**
198 * See @ref QListBox::currentText()
199 */
200 QString currentText() const { return m_listBox->currentText(); }
201
202 /**
203 * @returns a stringlist of all items in the listbox
204 */
205 QStringList items() const;
206
207 signals:
208 void changed();
209
210 /**
211 * This signal is emitted when the user adds a new string to the list,
212 * the parameter is the added string.
213 * @since 3.2
214 */
215 void added( const QString & text );
216
217 /**
218 * This signal is emitted when the user removes a string from the list,
219 * the parameter is the removed string.
220 * @since 3.2
221 */
222 void removed( const QString & text );
223
224 protected slots:
225 //the names should be self-explaining
226 void moveItemUp();
227 void moveItemDown();
228 void addItem();
229 void removeItem();
230 void enableMoveButtons(int index);
231 void typedSomething(const QString& text);
232
233 private:
234 QListBox *m_listBox;
235 QPushButton *servUpButton, *servDownButton;
236 QPushButton *servNewButton, *servRemoveButton;
237 OLineEdit *m_lineEdit;
238
239 //this is called in both ctors, to avoid code duplication
240 void init( bool checkAtEntering, int buttons,
241 QWidget *representationWidget = 0L );
242
243 protected:
244 virtual void virtual_hook( int id, void* data );
245 private:
246 //our lovely private d-pointer
247 OEditListBoxPrivate *d;
248};
249
250#endif // OEDITLISTBOX
diff --git a/libopie2/qt3/opieui/ojanuswidget.cpp b/libopie2/qt3/opieui/ojanuswidget.cpp
new file mode 100644
index 0000000..0a037ff
--- a/dev/null
+++ b/libopie2/qt3/opieui/ojanuswidget.cpp
@@ -0,0 +1,1116 @@
1/*
2                 This file is part of the Opie Project
3
4 Originally part of the KDE project
5 (C) 1999-2000 Espen Sand (espensa@online.no)
6 =.
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 <qbitmap.h>
36#include <qgrid.h>
37#include <qhbox.h>
38#include <qheader.h>
39#include <qlabel.h>
40#include <qlayout.h>
41#include <qobjectlist.h>
42#include <qpixmap.h>
43#include <qlistview.h>
44#include <qsplitter.h>
45#include <qtabwidget.h>
46#include <qvbox.h>
47#include <qwidgetstack.h>
48#include <qpainter.h>
49#include <qtimer.h>
50#include <qstyle.h>
51
52/* OPIE */
53
54#include <opie2/odialog.h>
55#include <opie2/oseparator.h>
56#include <opie2/ojanuswidget.h>
57
58/*======================================================================================
59 * IconListItem
60 *======================================================================================*/
61
62class OJanusWidget::IconListItem : public QListBoxItem
63{
64 public:
65 IconListItem( QListBox *listbox, const QPixmap &pixmap,
66 const QString &text );
67 virtual int height( const QListBox *lb ) const;
68 virtual int width( const QListBox *lb ) const;
69 int expandMinimumWidth( int width );
70
71 protected:
72 const QPixmap &defaultPixmap();
73 void paint( QPainter *painter );
74
75 private:
76 QPixmap mPixmap;
77 int mMinimumWidth;
78};
79
80template class QPtrList<QListViewItem>;
81
82/*======================================================================================
83 * OJanusWidget
84 *======================================================================================*/
85
86OJanusWidget::OJanusWidget( QWidget *parent, const char *name, int face )
87 : QWidget( parent, name, 0 ),
88 mValid(false), mPageList(0),
89 mTitleList(0), mFace(face), mTitleLabel(0), mActivePageWidget(0),
90 mShowIconsInTreeList(false), d(0)
91{
92 QVBoxLayout *topLayout = new QVBoxLayout( this );
93
94 if( mFace == TreeList || mFace == IconList )
95 {
96 mPageList = new QPtrList<QWidget>;
97 mTitleList = new QStringList();
98
99 QFrame *page;
100 if( mFace == TreeList )
101 {
102 QSplitter *splitter = new QSplitter( this );
103 topLayout->addWidget( splitter, 10 );
104 mTreeListResizeMode = QSplitter::KeepSize;
105
106 mTreeList = new QListView( splitter );
107 mTreeList->addColumn( QString::fromLatin1("") );
108 mTreeList->header()->hide();
109 mTreeList->setRootIsDecorated(true);
110 mTreeList->setSorting( -1 );
111 connect( mTreeList, SIGNAL(selectionChanged()), SLOT(slotShowPage()) );
112 connect( mTreeList, SIGNAL(clicked(QListViewItem *)), SLOT(slotItemClicked(QListViewItem *)));
113
114 //
115 // Page area. Title at top with a separator below and a pagestack using
116 // all available space at bottom.
117 //
118 QFrame *p = new QFrame( splitter );
119
120 QHBoxLayout *hbox = new QHBoxLayout( p, 0, 0 );
121 hbox->addSpacing( ODialog::spacingHint() );
122
123 page = new QFrame( p );
124 hbox->addWidget( page, 10 );
125 }
126 else
127 {
128 QHBoxLayout *hbox = new QHBoxLayout( topLayout );
129 mIconList = new IconListBox( this );
130
131 QFont listFont( mIconList->font() );
132 listFont.setBold( true );
133 mIconList->setFont( listFont );
134
135 mIconList->verticalScrollBar()->installEventFilter( this );
136 hbox->addWidget( mIconList );
137 connect( mIconList, SIGNAL(selectionChanged()), SLOT(slotShowPage()));
138 hbox->addSpacing( ODialog::spacingHint() );
139 page = new QFrame( this );
140 hbox->addWidget( page, 10 );
141 }
142
143 //
144 // Rest of page area. Title at top with a separator below and a
145 // pagestack using all available space at bottom.
146 //
147
148 QVBoxLayout *vbox = new QVBoxLayout( page, 0, ODialog::spacingHint() );
149
150 mTitleLabel = new QLabel( QString::fromLatin1("Empty page"), page, "OJanusWidgetTitleLabel" );
151 vbox->addWidget( mTitleLabel );
152
153 QFont titleFont( mTitleLabel->font() );
154 titleFont.setBold( true );
155 mTitleLabel->setFont( titleFont );
156
157 mTitleSep = new OSeparator( page );
158 mTitleSep->setFrameStyle( QFrame::HLine|QFrame::Plain );
159 vbox->addWidget( mTitleSep );
160
161 mPageStack = new QWidgetStack( page );
162 connect(mPageStack, SIGNAL(aboutToShow(QWidget *)),
163 this, SIGNAL(aboutToShowPage(QWidget *)));
164 vbox->addWidget( mPageStack, 10 );
165 }
166 else if( mFace == Tabbed )
167 {
168 mPageList = new QPtrList<QWidget>;
169
170 mTabControl = new QTabWidget( this );
171 mTabControl->setMargin (ODialog::marginHint());
172 topLayout->addWidget( mTabControl, 10 );
173 }
174 else if( mFace == Swallow )
175 {
176 mSwallowPage = new QWidget( this );
177 topLayout->addWidget( mSwallowPage, 10 );
178 }
179 else
180 {
181 mFace = Plain;
182 mPlainPage = new QFrame( this );
183 topLayout->addWidget( mPlainPage, 10 );
184 }
185
186 /* FIXME: Revise for Opie
187 if ( kapp )
188 connect(kapp,SIGNAL(kdisplayFontChanged()),SLOT(slotFontChanged()));
189 */
190
191 mValid = true;
192
193 setSwallowedWidget(0); // Set default size if 'mFace' is Swallow.
194}
195
196
197OJanusWidget::~OJanusWidget()
198{
199 delete mPageList;
200 mPageList = 0;
201 delete mTitleList;
202 mTitleList = 0;
203}
204
205
206bool OJanusWidget::isValid() const
207{
208 return( mValid );
209}
210
211
212QFrame *OJanusWidget::plainPage()
213{
214 return( mPlainPage );
215}
216
217
218int OJanusWidget::face() const
219{
220 return( mFace );
221}
222
223QWidget *OJanusWidget::FindParent()
224{
225 if( mFace == Tabbed ) {
226 return mTabControl;
227 }
228 else {
229 return this;
230 }
231}
232
233QFrame *OJanusWidget::addPage( const QStringList &items, const QString &header,
234 const QPixmap &pixmap )
235{
236 if( mValid == false )
237 {
238 qDebug( "addPage: Invalid object" );
239 return( 0 );
240 }
241
242 QFrame *page = new QFrame( FindParent(), "page" );
243 addPageWidget( page, items, header, pixmap );
244
245 return page;
246}
247
248void OJanusWidget::pageGone( QObject *obj )
249{
250 removePage( static_cast<QWidget*>( obj ) );
251}
252
253void OJanusWidget::slotReopen( QListViewItem * item )
254{
255 if( item )
256 item->setOpen( true );
257}
258
259QFrame *OJanusWidget::addPage( const QString &itemName, const QString &header,
260 const QPixmap &pixmap )
261{
262 QStringList items;
263 items << itemName;
264 return addPage(items, header, pixmap);
265}
266
267
268
269QVBox *OJanusWidget::addVBoxPage( const QStringList &items,
270 const QString &header,
271 const QPixmap &pixmap )
272{
273 if( mValid == false )
274 {
275 qDebug( "addPage: Invalid object" );
276 return( 0 );
277 }
278
279 QVBox *page = new QVBox(FindParent() , "page" );
280 page->setSpacing( ODialog::spacingHint() );
281 addPageWidget( page, items, header, pixmap );
282
283 return page;
284}
285
286QVBox *OJanusWidget::addVBoxPage( const QString &itemName,
287 const QString &header,
288 const QPixmap &pixmap )
289{
290 QStringList items;
291 items << itemName;
292 return addVBoxPage(items, header, pixmap);
293}
294
295QHBox *OJanusWidget::addHBoxPage( const QStringList &items,
296 const QString &header,
297 const QPixmap &pixmap )
298{
299 if( mValid == false ) {
300 qDebug( "addPage: Invalid object" );
301 return( 0 );
302 }
303
304 QHBox *page = new QHBox(FindParent(), "page");
305 page->setSpacing( ODialog::spacingHint() );
306 addPageWidget( page, items, header, pixmap );
307
308 return page;
309}
310
311QHBox *OJanusWidget::addHBoxPage( const QString &itemName,
312 const QString &header,
313 const QPixmap &pixmap )
314{
315 QStringList items;
316 items << itemName;
317 return addHBoxPage(items, header, pixmap);
318}
319
320QGrid *OJanusWidget::addGridPage( int n, Orientation dir,
321 const QStringList &items,
322 const QString &header,
323 const QPixmap &pixmap )
324{
325 if( mValid == false )
326 {
327 qDebug( "addPage: Invalid object" );
328 return( 0 );
329 }
330
331 QGrid *page = new QGrid( n, dir, FindParent(), "page" );
332 page->setSpacing( ODialog::spacingHint() );
333 addPageWidget( page, items, header, pixmap );
334
335 return page;
336}
337
338
339QGrid *OJanusWidget::addGridPage( int n, Orientation dir,
340 const QString &itemName,
341 const QString &header,
342 const QPixmap &pixmap )
343{
344 QStringList items;
345 items << itemName;
346 return addGridPage(n, dir, items, header, pixmap);
347}
348
349void OJanusWidget::InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page)
350{
351 bool isTop = true;
352 QListViewItem *curTop = 0, *child, *last, *newChild;
353 unsigned int index = 1;
354 QStringList curPath;
355
356 for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it, index++ ) {
357 QString name = (*it);
358 bool isPath = ( index != items.count() );
359
360 // Find the first child.
361 if (isTop) {
362 child = mTreeList->firstChild();
363 }
364 else {
365 child = curTop->firstChild();
366 }
367
368 // Now search for a child with the current Name, and if it we doesn't
369 // find it, then remember the location of the last child.
370 for (last = 0; child && child->text(0) != name ; last = child, child = child->nextSibling());
371
372 if (last == 0 && child == 0) {
373 // This node didn't have any children at all, lets just insert the
374 // new child.
375 if (isTop)
376 newChild = new QListViewItem(mTreeList, name);
377 else
378 newChild = new QListViewItem(curTop, name);
379
380 }
381 else if (child != 0) {
382 // we found the given name in this child.
383 if (!isPath) {
384 qDebug( "The element inserted was already in the TreeList box!" );
385 return;
386 }
387 else {
388 // Ok we found the folder
389 newChild = child;
390 }
391 }
392 else {
393 // the node had some children, but we didn't find the given name
394 if (isTop)
395 newChild = new QListViewItem(mTreeList, last, name);
396 else
397 newChild = new QListViewItem(curTop, last, name);
398 }
399
400 // Now make the element expandable if it is a path component, and make
401 // ready for next loop
402 if (isPath) {
403 newChild->setExpandable(true);
404 curTop = newChild;
405 isTop = false;
406 curPath << name;
407
408 QString key = curPath.join("_/_");
409 if (mFolderIconMap.contains(key)) {
410 QPixmap p = mFolderIconMap[key];
411 newChild->setPixmap(0,p);
412 }
413 }
414 else {
415 if (mShowIconsInTreeList) {
416 newChild->setPixmap(0, pixmap);
417 }
418 mTreeListToPageStack.insert(newChild, page);
419 }
420 }
421}
422
423void OJanusWidget::addPageWidget( QFrame *page, const QStringList &items,
424 const QString &header,const QPixmap &pixmap )
425{
426 connect(page, SIGNAL(destroyed(QObject*)), SLOT(pageGone(QObject*)));
427
428 if( mFace == Tabbed )
429 {
430 mTabControl->addTab (page, items.last());
431 mPageList->append (page);
432 }
433 else if( mFace == TreeList || mFace == IconList )
434 {
435 mPageList->append( page );
436 mPageStack->addWidget( page, 0 );
437
438 if (items.count() == 0) {
439 qDebug( "Invalid QStringList, with zero items" );
440 return;
441 }
442
443 if( mFace == TreeList )
444 {
445 InsertTreeListItem(items, pixmap, page);
446 }
447 else // mFace == IconList
448 {
449 QString itemName = items.last();
450 IconListItem *item = new IconListItem( mIconList, pixmap, itemName );
451 //
452 // 2000-06-01 Espen Sand: If I do this with Qt 2.1.1 all sorts of
453 // strange things happen. With Qt <= 2.1 it worked but now I must
454 // either specify the listbox in the constructor on the item
455 // or as below, not both.
456 // mIconList->insertItem( item );
457 //
458 mIconListToPageStack.insert(item, page);
459 mIconList->invalidateHeight();
460 mIconList->invalidateWidth();
461
462 if (mIconList->isVisible())
463 mIconList->updateWidth();
464 }
465
466 //
467 // Make sure the title label is sufficiently wide
468 //
469 QString lastName = items.last();
470 const QString &title = (header != QString::null ? header : lastName);
471 QRect r = mTitleLabel->fontMetrics().boundingRect( title );
472 if( mTitleLabel->minimumWidth() < r.width() )
473 {
474 mTitleLabel->setMinimumWidth( r.width() );
475 }
476 mTitleList->append( title );
477
478 if( mTitleList->count() == 1 )
479 {
480 showPage(0);
481 }
482 }
483 else
484 {
485 qDebug( "OJanusWidget::addPageWidget: can only add a page in Tabbed, TreeList or IconList modes" );
486 }
487
488}
489
490void OJanusWidget::setFolderIcon(const QStringList &path, const QPixmap &pixmap)
491{
492 QString key = path.join("_/_");
493 mFolderIconMap.insert(key,pixmap);
494}
495
496
497
498bool OJanusWidget::setSwallowedWidget( QWidget *widget )
499{
500 if( mFace != Swallow || mValid == false )
501 {
502 return( false );
503 }
504
505 //
506 // Remove current layout and make a new.
507 //
508 if( mSwallowPage->layout() != 0 )
509 {
510 delete mSwallowPage->layout();
511 }
512 QGridLayout *gbox = new QGridLayout( mSwallowPage, 1, 1, 0 );
513
514 //
515 // Hide old children
516 //
517 QObjectList *l = (QObjectList*)mSwallowPage->children(); // silence please
518 for( uint i=0; i < l->count(); i++ )
519 {
520 QObject *o = l->at(i);
521 if( o->isWidgetType() )
522 {
523 ((QWidget*)o)->hide();
524 }
525 }
526
527 //
528 // Add new child or make default size
529 //
530 if( widget == 0 )
531 {
532 gbox->addRowSpacing(0,100);
533 gbox->addColSpacing(0,100);
534 mSwallowPage->setMinimumSize(100,100);
535 }
536 else
537 {
538 if( widget->parent() != mSwallowPage )
539 {
540 widget->reparent( mSwallowPage, 0, QPoint(0,0) );
541 }
542 gbox->addWidget(widget, 0, 0 );
543 gbox->activate();
544 mSwallowPage->setMinimumSize( widget->minimumSize() );
545 }
546
547 return( true );
548}
549
550bool OJanusWidget::slotShowPage()
551{
552 if( mValid == false )
553 {
554 return( false );
555 }
556
557 if( mFace == TreeList )
558 {
559 QListViewItem *node = mTreeList->selectedItem();
560 if( node == 0 ) { return( false ); }
561
562 QWidget *stackItem = mTreeListToPageStack[node];
563 return showPage(stackItem);
564 }
565 else if( mFace == IconList )
566 {
567 QListBoxItem *node = mIconList->item( mIconList->currentItem() );
568 if( node == 0 ) { return( false ); }
569 QWidget *stackItem = mIconListToPageStack[node];
570 return showPage(stackItem);
571 }
572
573 return( false );
574}
575
576
577bool OJanusWidget::showPage( int index )
578{
579 if( mPageList == 0 || mValid == false )
580 {
581 return( false );
582 }
583 else
584 {
585 return showPage(mPageList->at(index));
586 }
587}
588
589
590bool OJanusWidget::showPage( QWidget *w )
591{
592 if( w == 0 || mValid == false )
593 {
594 return( false );
595 }
596
597 if( mFace == TreeList || mFace == IconList )
598 {
599 mPageStack->raiseWidget( w );
600 mActivePageWidget = w;
601
602 int index = mPageList->findRef( w );
603 mTitleLabel->setText( *mTitleList->at(index) );
604 if( mFace == TreeList )
605 {
606 QMap<QListViewItem *, QWidget *>::Iterator it;
607 for (it = mTreeListToPageStack.begin(); it != mTreeListToPageStack.end(); ++it){
608 QListViewItem *key = it.key();
609 QWidget *val = it.data();
610 if (val == w) {
611 mTreeList->setSelected(key, true );
612 break;
613 }
614 }
615 }
616 else
617 {
618 QMap<QListBoxItem *, QWidget *>::Iterator it;
619 for (it = mIconListToPageStack.begin(); it != mIconListToPageStack.end(); ++it){
620 QListBoxItem *key = it.key();
621 QWidget *val = it.data();
622 if (val == w) {
623 mIconList->setSelected( key, true );
624 break;
625 }
626 }
627
628 //
629 // 2000-02-13 Espen Sand
630 // Don't ask me why (because I don't know). If I select a page
631 // with the mouse the page is not updated until it receives an
632 // event. It seems this event get lost if the mouse is not moved
633 // when released. The timer ensures the update
634 //
635 QTimer::singleShot( 0, mActivePageWidget, SLOT(update()) );
636 }
637 }
638 else if( mFace == Tabbed )
639 {
640 mTabControl->showPage(w);
641 mActivePageWidget = w;
642 }
643 else
644 {
645 return( false );
646 }
647
648 return( true );
649}
650
651
652int OJanusWidget::activePageIndex() const
653{
654 if( mFace == TreeList) {
655 QListViewItem *node = mTreeList->selectedItem();
656 if( node == 0 ) { return -1; }
657 QWidget *stackItem = mTreeListToPageStack[node];
658 return mPageList->findRef(stackItem);
659 }
660 else if (mFace == IconList) {
661 QListBoxItem *node = mIconList->item( mIconList->currentItem() );
662 if( node == 0 ) { return( false ); }
663 QWidget *stackItem = mIconListToPageStack[node];
664 return mPageList->findRef(stackItem);
665 }
666 else if( mFace == Tabbed ) {
667 QWidget *widget = mTabControl->currentPage();
668 return( widget == 0 ? -1 : mPageList->findRef( widget ) );
669 }
670 else {
671 return( -1 );
672 }
673}
674
675
676int OJanusWidget::pageIndex( QWidget *widget ) const
677{
678 if( widget == 0 )
679 {
680 return( -1 );
681 }
682 else if( mFace == TreeList || mFace == IconList )
683 {
684 return( mPageList->findRef( widget ) );
685 }
686 else if( mFace == Tabbed )
687 {
688 //
689 // The user gets the real page widget with addVBoxPage(), addHBoxPage()
690 // and addGridPage() but not with addPage() which returns a child of
691 // the toplevel page. addPage() returns a QFrame so I check for that.
692 //
693 if( widget->isA("QFrame") )
694 {
695 return( mPageList->findRef( widget->parentWidget() ) );
696 }
697 else
698 {
699 return( mPageList->findRef( widget ) );
700 }
701 }
702 else
703 {
704 return( -1 );
705 }
706}
707
708void OJanusWidget::slotFontChanged()
709{
710#ifdef FIXME
711
712 if ( mTitleLabel != 0 )
713 {
714 mTitleLabel->setFont( KGlobalSettings::generalFont() );
715 QFont titleFont( mTitleLabel->font() );
716 titleFont.setBold( true );
717 mTitleLabel->setFont( titleFont );
718 }
719#endif
720
721 if( mFace == IconList )
722 {
723 QFont listFont( mIconList->font() );
724 listFont.setBold( true );
725 mIconList->setFont( listFont );
726 mIconList->invalidateHeight();
727 mIconList->invalidateWidth();
728 }
729}
730
731// makes the treelist behave like the list of kcontrol
732void OJanusWidget::slotItemClicked(QListViewItem *it)
733{
734 if(it && (it->childCount()>0))
735 it->setOpen(!it->isOpen());
736}
737
738void OJanusWidget::setFocus()
739{
740 if( mValid == false ) { return; }
741 if( mFace == TreeList )
742 {
743 mTreeList->setFocus();
744 }
745 if( mFace == IconList )
746 {
747 mIconList->setFocus();
748 }
749 else if( mFace == Tabbed )
750 {
751 mTabControl->setFocus();
752 }
753 else if( mFace == Swallow )
754 {
755 mSwallowPage->setFocus();
756 }
757 else if( mFace == Plain )
758 {
759 mPlainPage->setFocus();
760 }
761}
762
763
764QSize OJanusWidget::minimumSizeHint() const
765{
766 if( mFace == TreeList || mFace == IconList )
767 {
768 QSize s1( ODialog::spacingHint(), ODialog::spacingHint()*2 );
769 QSize s2(0,0);
770 QSize s3(0,0);
771 QSize s4( mPageStack->sizeHint() );
772
773 if( mFace == TreeList )
774 {
775#if QT_VERSION < 300
776 s1.rwidth() += style().splitterWidth();
777#else
778 s1.rwidth() += style().pixelMetric( QStyle::PM_SplitterWidth );
779#endif
780 s2 = mTreeList->minimumSize();
781 }
782 else
783 {
784 mIconList->updateMinimumHeight();
785 mIconList->updateWidth();
786 s2 = mIconList->minimumSize();
787 }
788
789 if( mTitleLabel->isVisible() == true )
790 {
791 s3 += mTitleLabel->sizeHint();
792 s3.rheight() += mTitleSep->minimumSize().height();
793 }
794
795 //
796 // Select the tallest item. It has only effect in IconList mode
797 //
798 int h1 = s1.rheight() + s3.rheight() + s4.height();
799 int h2 = QMAX( h1, s2.rheight() );
800
801 return( QSize( s1.width()+s2.width()+QMAX(s3.width(),s4.width()), h2 ) );
802 }
803 else if( mFace == Tabbed )
804 {
805 return( mTabControl->sizeHint() );
806 }
807 else if( mFace == Swallow )
808 {
809 return( mSwallowPage->minimumSize() );
810 }
811 else if( mFace == Plain )
812 {
813 return( mPlainPage->sizeHint() );
814 }
815 else
816 {
817 return( QSize( 100, 100 ) ); // Should never happen though.
818 }
819
820}
821
822
823QSize OJanusWidget::sizeHint() const
824{
825 return( minimumSizeHint() );
826}
827
828
829void OJanusWidget::setTreeListAutoResize( bool state )
830{
831 if( mFace == TreeList )
832 {
833 mTreeListResizeMode = state == false ?
834 QSplitter::KeepSize : QSplitter::Stretch;
835 QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget());
836 splitter->setResizeMode( mTreeList, mTreeListResizeMode );
837 }
838}
839
840
841void OJanusWidget::setIconListAllVisible( bool state )
842{
843 if( mFace == IconList )
844 {
845 mIconList->setShowAll( state );
846 }
847}
848
849void OJanusWidget::setShowIconsInTreeList( bool state )
850{
851 mShowIconsInTreeList = state;
852}
853
854void OJanusWidget::setRootIsDecorated( bool state )
855{
856 if( mFace == TreeList ) {
857 mTreeList->setRootIsDecorated(state);
858 }
859}
860
861void OJanusWidget::unfoldTreeList( bool persist )
862{
863 if( mFace == TreeList )
864 {
865 if( persist )
866 connect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) );
867 else
868 disconnect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) );
869
870 for( QListViewItem * item = mTreeList->firstChild(); item; item = item->itemBelow() )
871 item->setOpen( true );
872 }
873}
874
875void OJanusWidget::showEvent( QShowEvent * )
876{
877 if( mFace == TreeList )
878 {
879 QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget());
880 splitter->setResizeMode( mTreeList, mTreeListResizeMode );
881 }
882}
883
884
885//
886// 2000-13-02 Espen Sand
887// It should be obvious that this eventfilter must only be
888// be installed on the vertical scrollbar of the mIconList.
889//
890bool OJanusWidget::eventFilter( QObject *o, QEvent *e )
891{
892 if( e->type() == QEvent::Show )
893 {
894 IconListItem *item = (IconListItem*)mIconList->item(0);
895 if( item != 0 )
896 {
897 int lw = item->width( mIconList );
898 int sw = mIconList->verticalScrollBar()->sizeHint().width();
899 mIconList->setFixedWidth( lw+sw+mIconList->frameWidth()*2 );
900 }
901 }
902 else if( e->type() == QEvent::Hide )
903 {
904 IconListItem *item = (IconListItem*)mIconList->item(0);
905 if( item != 0 )
906 {
907 int lw = item->width( mIconList );
908 mIconList->setFixedWidth( lw+mIconList->frameWidth()*2 );
909 }
910 }
911 return QWidget::eventFilter( o, e );
912}
913
914
915
916//
917// Code for the icon list box
918//
919
920
921OJanusWidget::IconListBox::IconListBox( QWidget *parent, const char *name,
922 WFlags f )
923 :QListBox( parent, name, f ), mShowAll(false), mHeightValid(false),
924 mWidthValid(false)
925{
926}
927
928
929void OJanusWidget::IconListBox::updateMinimumHeight()
930{
931 if( mShowAll == true && mHeightValid == false )
932 {
933 int h = frameWidth()*2;
934 for( QListBoxItem *i = item(0); i != 0; i = i->next() )
935 {
936 h += i->height( this );
937 }
938 setMinimumHeight( h );
939 mHeightValid = true;
940 }
941}
942
943
944void OJanusWidget::IconListBox::updateWidth()
945{
946 if( mWidthValid == false )
947 {
948 int maxWidth = 10;
949 for( QListBoxItem *i = item(0); i != 0; i = i->next() )
950 {
951 int w = ((IconListItem *)i)->width(this);
952 maxWidth = QMAX( w, maxWidth );
953 }
954
955 for( QListBoxItem *i = item(0); i != 0; i = i->next() )
956 {
957 ((IconListItem *)i)->expandMinimumWidth( maxWidth );
958 }
959
960 if( verticalScrollBar()->isVisible() )
961 {
962 maxWidth += verticalScrollBar()->sizeHint().width();
963 }
964
965 setFixedWidth( maxWidth + frameWidth()*2 );
966 mWidthValid = true;
967 }
968}
969
970
971void OJanusWidget::IconListBox::invalidateHeight()
972{
973 mHeightValid = false;
974}
975
976
977void OJanusWidget::IconListBox::invalidateWidth()
978{
979 mWidthValid = false;
980}
981
982
983void OJanusWidget::IconListBox::setShowAll( bool showAll )
984{
985 mShowAll = showAll;
986 mHeightValid = false;
987}
988
989
990
991OJanusWidget::IconListItem::IconListItem( QListBox *listbox, const QPixmap &pixmap,
992 const QString &text )
993 : QListBoxItem( listbox )
994{
995 mPixmap = pixmap;
996 if( mPixmap.isNull() == true )
997 {
998 mPixmap = defaultPixmap();
999 }
1000 setText( text );
1001 mMinimumWidth = 0;
1002}
1003
1004
1005int OJanusWidget::IconListItem::expandMinimumWidth( int width )
1006{
1007 mMinimumWidth = QMAX( mMinimumWidth, width );
1008 return( mMinimumWidth );
1009}
1010
1011
1012const QPixmap &OJanusWidget::IconListItem::defaultPixmap()
1013{
1014 static QPixmap *pix=0;
1015 if( pix == 0 )
1016 {
1017 pix = new QPixmap( 32, 32 );
1018 QPainter p( pix );
1019 p.eraseRect( 0, 0, pix->width(), pix->height() );
1020 p.setPen( Qt::red );
1021 p.drawRect ( 0, 0, pix->width(), pix->height() );
1022 p.end();
1023
1024 QBitmap mask( pix->width(), pix->height(), true );
1025 mask.fill( Qt::black );
1026 p.begin( &mask );
1027 p.setPen( Qt::white );
1028 p.drawRect ( 0, 0, pix->width(), pix->height() );
1029 p.end();
1030
1031 pix->setMask( mask );
1032 }
1033 return( *pix );
1034}
1035
1036
1037void OJanusWidget::IconListItem::paint( QPainter *painter )
1038{
1039 QFontMetrics fm = painter->fontMetrics();
1040 //int wt = fm.boundingRect(text()).width();
1041 int wp = mPixmap.width();
1042 int ht = fm.lineSpacing();
1043 int hp = mPixmap.height();
1044
1045 painter->drawPixmap( (mMinimumWidth-wp)/2, 5, mPixmap );
1046 if( text().isEmpty() == false )
1047 {
1048 painter->drawText( 0, hp+7, mMinimumWidth, ht, Qt::AlignCenter, text() );
1049 }
1050}
1051
1052int OJanusWidget::IconListItem::height( const QListBox *lb ) const
1053{
1054 if( text().isEmpty() == true )
1055 {
1056 return( mPixmap.height() );
1057 }
1058 else
1059 {
1060 return( mPixmap.height() + lb->fontMetrics().lineSpacing()+10 );
1061 }
1062}
1063
1064
1065int OJanusWidget::IconListItem::width( const QListBox *lb ) const
1066{
1067 int wt = lb->fontMetrics().boundingRect(text()).width()+10;
1068 int wp = mPixmap.width() + 10;
1069 int w = QMAX( wt, wp );
1070 return( QMAX( w, mMinimumWidth ) );
1071}
1072
1073// Just remove the page from our stack of widgets. Do not modify the given widget in
1074// any way. No memory leak occurs as parent is not changed.
1075// Make this virtual in KDE 4.0.
1076// Ravikiran Rajagopal <ravi@ee.eng.ohio-state.edu>
1077void OJanusWidget::removePage( QWidget *page )
1078{
1079 if (!mPageList || !mPageList->containsRef(page))
1080 return;
1081
1082 int index = mPageList->findRef( page );
1083 if ( mTitleList )
1084 mTitleList->remove(mTitleList->at(index));
1085
1086 mPageList->removeRef(page);
1087
1088 if ( mFace == TreeList )
1089 {
1090 QMap<QListViewItem*, QWidget *>::Iterator i;
1091 for( i = mTreeListToPageStack.begin(); i != mTreeListToPageStack.end(); ++i )
1092 if (i.data()==page)
1093 {
1094 delete i.key();
1095 mPageStack->removeWidget(page);
1096 mTreeListToPageStack.remove(i);
1097 break;
1098 }
1099 }
1100 else if ( mFace == IconList )
1101 {
1102 QMap<QListBoxItem*, QWidget *>::Iterator i;
1103 for( i = mIconListToPageStack.begin(); i != mIconListToPageStack.end(); ++i )
1104 if (i.data()==page)
1105 {
1106 delete i.key();
1107 mPageStack->removeWidget(page);
1108 mIconListToPageStack.remove(i);
1109 break;
1110 }
1111 }
1112 else // Tabbed
1113 {
1114 mTabControl->removePage(page);
1115 }
1116}
diff --git a/libopie2/qt3/opieui/ojanuswidget.h b/libopie2/qt3/opieui/ojanuswidget.h
new file mode 100644
index 0000000..b601b8c
--- a/dev/null
+++ b/libopie2/qt3/opieui/ojanuswidget.h
@@ -0,0 +1,551 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 Copyright (C) 1999-2000 Espen Sand (espen@kde.org)
6 =.
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#ifndef OJANUSWIDGET_H
34#define OJANUSWIDGET_H
35
36#include <qptrlist.h>
37#include <qpixmap.h>
38#include <qlistbox.h>
39#include <qmap.h>
40#include <qsplitter.h>
41#include <qstringlist.h>
42
43class QGrid;
44class QHBox;
45class QLabel;
46class QTabWidget;
47class QVBox;
48class QWidgetStack;
49class OSeparator;
50class QListView;
51class QListViewItem;
52
53/**
54 * Provides a number of ready to use layouts (faces). It is used
55 * as an internal widget in @ref KDialogBase, but can also used as a
56 * widget of its own.
57 *
58 * It provides TreeList, IconList, Tabbed, Plain and Swallow layouts.
59 *
60 * The TreeList face provides a list in the left area and pages in the
61 * right. The area are separated by a movable splitter. The style is somewhat
62 * similar to the layout in the Control Center. A page is raised by
63 * selecting the corresponding tree list item.
64 *
65 * The IconList face provides an icon list in the left area and pages in the
66 * right. For each entry the Icon is on top with the text below. The style
67 * is somewhat similar to the layout of the Eudora configuation dialog box.
68 * A page is raised by selecting the corresponding icon list item. The
69 * preferred icon size is 32x32 pixels.
70 *
71 * The Tabbed face is a common tabbed widget. The procedure for creating a
72 * page is similar for creating a TreeList. This has the advantage that if
73 * your widget contain too many pages it is trivial to convert it into a
74 * TreeList. Just change the face in the KJanusWidget constructor to
75 * KJanusWidget::TreeList and you have a tree list layout instead.
76 *
77 * The Plain face provides an empty widget (QFrame) where you can place your
78 * widgets. The KJanusWidget makes no assumptions regarding the contents so
79 * you are free to add whatever you want.
80 *
81 * The Swallow face is provided in order to simplify the usage of existing
82 * widgets and to allow changing the visible widget. You specify the widget
83 * to be displayed by @ref #setSwallowedWidget(). Your widget will be
84 * reparented inside the widget. You can specify a Null (0) widget. A empty
85 * space is then displayed.
86 *
87 * For all modes it is important that you specify the @ref QWidget::minimumSize()
88 * on the page, plain widget or the swallowed widget. If you use a QLayout
89 * on the page, plain widget or the swallowed widget this will be taken care
90 * of automatically. The size is used when the KJanusWidget determines its
91 * own minimum size. You get the minimum size by using the
92 * @ref #minimumSizeHint() or @ref #sizeHint() methods.
93 *
94 * Pages that have been added in TreeList, IconList or Tabbed mode can be
95 * removed by simply deleting the page.
96 *
97 * @short Easy to use widget with many layouts
98 * @author Espen Sand (espen@kde.org)
99 */
100class OJanusWidget : public QWidget
101{
102 Q_OBJECT
103
104 private:
105
106 class IconListBox : public QListBox
107 {
108 public:
109 IconListBox( QWidget *parent=0, const char *name=0, WFlags f=0 );
110 void updateMinimumHeight();
111 void updateWidth();
112 void invalidateHeight();
113 void invalidateWidth();
114 void setShowAll( bool showAll );
115
116 private:
117 bool mShowAll;
118 bool mHeightValid;
119 bool mWidthValid;
120 };
121
122 public:
123
124 enum Face
125 {
126 TreeList = 0,
127 Tabbed,
128 Plain,
129 Swallow,
130 IconList
131 };
132
133 public:
134
135 /**
136 * Constructor where you specify the face.
137 *
138 * @param parent Parent of the widget.
139 * @param name Widget name.
140 * @param int face The kind of dialog, Use TreeList, Tabbed, Plain or
141 * Swallow.
142 */
143 OJanusWidget( QWidget *parent=0, const char *name=0, int face=Plain );
144
145 /**
146 * Destructor.
147 */
148 ~OJanusWidget();
149
150 /**
151 * Raises the page which was added by @ref addPage().
152 *
153 * @param index The index of the page you want to raise.
154 */
155 virtual bool showPage( int index );
156
157 /**
158 * Returns the index of the page that are currently displayed.
159 *
160 * @return The index or -1 if the face is not Tabbed, TreeList or
161 * IconList.
162 */
163 virtual int activePageIndex() const;
164
165 /**
166 * Use this to verify
167 * that no memory allocation failed.
168 *
169 * @return true if the widget was properly created.
170 */
171 virtual bool isValid() const;
172
173 /**
174 * Returns the face type.
175 *
176 * @return The face type.
177 */
178 virtual int face() const;
179
180 /**
181 * Returns the minimum size that must be made available for the widget
182 * so that UIs can be displayed properly
183 *
184 * @return The minimum size.
185 */
186 virtual QSize minimumSizeHint() const;
187
188 /**
189 * Returns the recommended size for the widget in order to be displayed
190 * properly.
191 *
192 * @return The recommended size.
193 */
194 virtual QSize sizeHint() const;
195
196 /**
197 * Returns the empty widget that is available in Plain mode.
198 *
199 * @return The widget or 0 if the face in not Plain.
200 */
201 virtual QFrame *plainPage();
202
203 /**
204 * Add a new page when the class is used in TreeList, IconList or Tabbed
205 * mode. The returned widget is empty and you must add your widgets
206 * as children to this widget. In most cases you must create a layout
207 * manager and associate it with this widget as well.
208 *
209 * Deleting the returned frame will cause the listitem or tab to be
210 * removed (you can re-add a page with the same name later.
211 *
212 * @param item String used in the list or Tab item.
213 * @param header A longer string used in TreeList and IconList mode to
214 * describe the contents of a page. If empty, the item string
215 * will be used instead.
216 * @param pixmap Used in IconList mode or in TreeList mode. You should
217 * prefer a pixmap with size 32x32 pixels.
218 *
219 * @return The empty page or 0 if the face is not TreeList, IconList or
220 * Tabbed.
221 */
222 virtual QFrame *addPage(const QString &item,const QString &header=QString::null,
223 const QPixmap &pixmap=QPixmap() );
224
225 /**
226 * This is like addPage just above, with the difference that the first
227 * element is a list of strings. These strings are used to form a path
228 * of folders down to the given page. The initial elements are names
229 * for the folders, while the last element is the name of the page.
230 * Note: This does yet only work for the TreeList face. Later this may
231 * be added for the IconList face too. In other faces than the
232 * TreeList, all the strings except the last one is ignored.
233 * Deleting the returned frame will cause the listitem or tab to be
234 * removed (you can re-add a page with the same name later.
235 *
236 * Deleting the returned frame will cause the listitem or tab to be
237 * removed (you can re-add a page with the same name later.
238 **/
239 virtual QFrame *addPage(const QStringList &items, const QString &header=QString::null,
240 const QPixmap &pixmap=QPixmap() );
241
242 /**
243 * Add a new page when the class is used in TreeList, IconList or Tabbed
244 * mode. The returned widget is empty and you must add your widgets
245 * as children to this widget. The returned widget is a @ref QVBox
246 * so it contains a QVBoxLayout layout that lines up the child widgets
247 * are vertically.
248 *
249 * Deleting the returned frame will cause the listitem or tab to be
250 * removed (you can re-add a page with the same name later.
251 *
252 * @param item String used in the list or Tab item.
253 * @param header A longer string used in TreeList and IconList mode to
254 * describe the contents of a page. If empty, the item string
255 * will be used instead.
256 * @param pixmap Used in IconList mode or in TreeList mode. You should
257 * prefer a pixmap with size 32x32 pixels.
258 *
259 * @return The empty page or 0 if the face is not TreeList, IconList or
260 * Tabbed. */
261 virtual QVBox *addVBoxPage( const QString &item,
262 const QString &header=QString::null,
263 const QPixmap &pixmap=QPixmap() );
264
265 /**
266 * This is like addVBoxPage just above, with the difference that the first
267 * element is a list of strings. These strings are used to form a path
268 * of folders down to the given page. The initial elements are names
269 * for the folders, while the last element is the name of the page.
270 * Note: This does yet only work for the TreeList face. Later this may
271 * be added for the IconList face too. In other faces than the
272 * TreeList, all the strings except the last one is ignored.
273 *
274 * Deleting the returned frame will cause the listitem or tab to be
275 * removed (you can re-add a page with the same name later.
276 **/
277 virtual QVBox *addVBoxPage( const QStringList &items,
278 const QString &header=QString::null,
279 const QPixmap &pixmap=QPixmap() );
280
281 /**
282 * Add a new page when the class is used in TreeList, IconList or Tabbed
283 * mode. The returned widget is empty and you must add your widgets
284 * as children to this widget. The returned widget is a @ref QHBox
285 * so it contains a QHBoxLayout layout that lines up the child widgets
286 * are horizontally.
287 *
288 * Deleting the returned frame will cause the listitem or tab to be
289 * removed (you can re-add a page with the same name later.
290 *
291 * @param item String used in the list or Tab item.
292 * @param header A longer string used in TreeList and IconList mode to
293 * describe the contents of a page. If empty, the item string
294 * will be used instead.
295 * @param pixmap Used in IconList mode or in TreeList mode. You should
296 * prefer a pixmap with size 32x32 pixels.
297 *
298 * @return The empty page or 0 if the face is not TreeList, IconList or
299 * Tabbed.
300 */
301 virtual QHBox *addHBoxPage( const QString &itemName,
302 const QString &header=QString::null,
303 const QPixmap &pixmap=QPixmap() );
304
305 /**
306 * This is like addHBoxPage just above, with the difference that the first
307 * element is a list of strings. These strings are used to form a path
308 * of folders down to the given page. The initial elements are names
309 * for the folders, while the last element is the name of the page.
310 * Note: This does yet only work for the TreeList face. Later this may
311 * be added for the IconList face too. In other faces than the
312 * TreeList, all the strings except the last one is ignored.
313 *
314 * Deleting the returned frame will cause the listitem or tab to be
315 * removed (you can re-add a page with the same name later.
316 **/
317 virtual QHBox *addHBoxPage( const QStringList &items,
318 const QString &header=QString::null,
319 const QPixmap &pixmap=QPixmap() );
320
321 /**
322 * Add a new page when the class is used in either TreeList or Tabbed
323 * mode. The returned widget is empty and you must add your widgets
324 * as children to this widget. The returned widget is a @ref QGrid
325 * so it contains a QGridLayout layout that places up the child widgets
326 * in a grid.
327 *
328 * Deleting the returned frame will cause the listitem or tab to be
329 * removed (you can re-add a page with the same name later.
330 *
331 * @param n Specifies the number of columns if 'dir' is QGrid::Horizontal
332 * or the number of rows if 'dir' is QGrid::Vertical.
333 * @param dir Can be QGrid::Horizontal or QGrid::Vertical.
334 * @param item String used in the list or Tab item.
335 * @param header A longer string used in TreeList and IconList mode to
336 * describe the contents of a page. If empty, the item string
337 * will be used instead.
338 * @param pixmap Used in IconList mode or in TreeList mode. You should
339 * prefer a pixmap with size 32x32 pixels.
340 *
341 * @return The empty page or 0 if the face is not TreeList, IconList or
342 * Tabbed.
343 */
344 virtual QGrid *addGridPage( int n, Orientation dir,
345 const QString &itemName,
346 const QString &header=QString::null,
347 const QPixmap &pixmap=QPixmap() );
348
349 /**
350 * This is like addGridPage just above, with the difference that the first
351 * element is a list of strings. These strings are used to form a path
352 * of folders down to the given page. The initial elements are names
353 * for the folders, while the last element is the name of the page.
354 * Note: This does yet only work for the TreeList face. Later this may
355 * be added for the IconList face too. In other faces than the
356 * TreeList, all the strings except the last one is ignored.
357 *
358 * Deleting the returned frame will cause the listitem or tab to be
359 * removed (you can re-add a page with the same name later.
360 **/
361 virtual QGrid *addGridPage( int n, Orientation dir,
362 const QStringList &items,
363 const QString &header=QString::null,
364 const QPixmap &pixmap=QPixmap() );
365
366 /**
367 * @short Removes a page created with @ref addPage, @ref addVBoxPage,
368 * @ref addHBoxPage or @ref addGridPage. If the page has already
369 * been deleted or has already been removed, nothing happens. The widget
370 * itself is not deleted.
371 *
372 * @param page The widget returned by @ref addPage , @ref addVBoxPage ,
373 * @ref addHBoxPage or @ref addGridPage .
374 */
375 void removePage( QWidget *page );
376
377
378 /**
379 * Returns the index of a page created with @ref addPage ,
380 * @ref addVBoxPage , @ref addHBoxPage or @ref addGridPage .
381 * You can can compare this index with the value returned from
382 * @ref activePageIndex if you need to do some page specific actions
383 * in your code.
384 *
385 * The returned index will never change so you can safely use this
386 * function once and save the value.
387 *
388 * @param widget The widget returned by @ref addPage , @ref addVBoxPage ,
389 * @ref addHBoxPage or @ref addGridPage .
390 *
391 * @return The index or -1 if the face is not Tabbed, TreeList or
392 * IconList
393 */
394 virtual int pageIndex( QWidget *widget ) const;
395
396 /**
397 * Defines the widget to be swallowed.
398 *
399 * This method can be used several
400 * times. Only the latest defined widget will be shown.
401 *
402 * @param widget The widget to be swallowed. If 0, then an empty rectangle
403 * is displayed.
404 */
405 virtual bool setSwallowedWidget( QWidget *widget );
406
407 /**
408 * This function has only effect in TreeList mode.
409 *
410 * Defines how the tree list is resized when the widget is resized
411 * horizontally. By default the tree list keeps its width when the
412 * widget becomes wider.
413 *
414 * @param state The resize mode. If false (default) the TreeList keeps
415 * its current width when the widget becomes wider.
416 */
417 virtual void setTreeListAutoResize( bool state );
418
419 /**
420 * This function has only effect in TreeList mode.
421 *
422 * This tells the widgets whether the icons given in the @ref addPage,
423 * @ref addVBoxPage, @ref addHBoxPage, or @ref addGridPage methods should
424 * be shown in the TreeList.
425 *
426 * Note: This method must be called before calling any of the methods
427 * which add icons to the page.
428 *
429 * @param state If true the icons are shown.
430 **/
431 virtual void setShowIconsInTreeList(bool state);
432
433 /**
434 * This function has only effect in TreeList mode.
435 *
436 * This tells the widgets whether the root should be decorated.
437 * For details see @ref QListView::setRootIsDecorated
438 *
439 * @param state Root will be decorated if true.
440 **/
441 virtual void setRootIsDecorated( bool state );
442
443 /**
444 * This function has only effect in TreeList mode.
445 *
446 * This tells the TreeList to unfold the whole tree so that all entries
447 * are visible.
448 *
449 * If the list is empty when you call this method newly created entries
450 * will not automatically be opened. If the @p persist flag is set opened
451 * entries cannot be closed again, though.
452 *
453 * @param persist If true the tree always stays unfolded.
454 * @since 3.2
455 */
456 /*virtual*/ void unfoldTreeList( bool persist = false ); //### KDE4 BIC add virtual
457
458 /**
459 * This function has only effect in IconList mode.
460 *
461 * Defines how the icon list widget is displayed. By default it is
462 * the widgets in the pages that decide the minimum height
463 * of the toplevel widget. A vertical scrollbar can be used in
464 * the icon list area.
465 *
466 * @param state The visibility mode. If true, the minimum height is
467 * adjusted so that every icon in the list is visible at the
468 * same time. The vertical scrollbar will never be visible.
469 */
470 virtual void setIconListAllVisible( bool state );
471
472 /**
473 * Sets the icon used in TreeList Mode for the given path.
474 * @param path The path for which this icon should be shown.
475 * @param pixmap The icon used.
476 **/
477 virtual void setFolderIcon(const QStringList &path, const QPixmap &pixmap);
478
479 signals:
480 void aboutToShowPage(QWidget *page);
481
482 public slots:
483 /**
484 * Give the keyboard input focus to the widget.
485 */
486 virtual void setFocus();
487
488 protected:
489 /**
490 * Reimplemented to handle the splitter width when the the face
491 * is TreeList
492 */
493 virtual void showEvent( QShowEvent * );
494
495 /**
496 * This function is used internally when in IconList mode. If you
497 * reimplement this class a make your own event filter, make sure to
498 * call this function from your filter.
499 *
500 * @param o Object that has received an event.
501 * @param e The event.
502 */
503 virtual bool eventFilter( QObject *o, QEvent *e );
504
505 private slots:
506 bool slotShowPage();
507 void slotFontChanged();
508 void slotItemClicked(QListViewItem *it);
509 void pageGone(QObject *obj); // signal from the added page's "destroyed" signal
510 void slotReopen(QListViewItem *item);
511
512 protected:
513 bool showPage( QWidget *w );
514 void addPageWidget( QFrame *page, const QStringList &items,
515 const QString &header, const QPixmap &pixmap );
516 void InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page);
517 QWidget *FindParent();
518
519 private:
520 bool mValid;
521
522 QPtrList<QWidget> *mPageList;
523 QStringList *mTitleList;
524
525 int mFace;
526 QListView *mTreeList;
527 IconListBox *mIconList;
528 QWidgetStack *mPageStack;
529 QLabel *mTitleLabel;
530 QTabWidget *mTabControl;
531 QFrame *mPlainPage;
532 QWidget *mSwallowPage;
533 QWidget *mActivePageWidget;
534 OSeparator *mTitleSep;
535 QSplitter::ResizeMode mTreeListResizeMode;
536 bool mShowIconsInTreeList;
537 QMap<QListViewItem *, QWidget *> mTreeListToPageStack;
538 QMap<QListBoxItem *, QWidget *> mIconListToPageStack;
539 QMap<QString, QPixmap> mFolderIconMap;
540 QMap<QString, QStringList> mChildrenNames;
541 QMap<QString, QWidget *> mChildPages;
542
543 public:
544 class IconListItem;
545
546 private:
547 class OJanusWidgetPrivate;
548 OJanusWidgetPrivate *d;
549};
550
551#endif
diff --git a/libopie2/qt3/opieui/olineedit.cpp b/libopie2/qt3/opieui/olineedit.cpp
new file mode 100644
index 0000000..9cb0cff
--- a/dev/null
+++ b/libopie2/qt3/opieui/olineedit.cpp
@@ -0,0 +1,729 @@
1/*
2 This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
3 is part of the Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org>, Dawit Alemayehu <adawit@kde.org>
4 Opie Project Copyright (C) 1999 Preston Brown <pbrown@kde.org>, Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
5 Copyright (C) 1997 Sven Radej (sven.radej@iname.com)
6 =.
7 .=l. Originally part of the KDE Project
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 <qapplication.h>
36#include <qclipboard.h>
37#include <qtimer.h>
38#include <qpopupmenu.h>
39
40/* OPIE */
41
42#include <opie2/ocompletionbox.h>
43#include <opie2/olineedit.h>
44#include <opie2/oglobalsettings.h>
45
46typedef QString KURL; //FIXME: Revise for Opie
47
48/*======================================================================================
49 * OLineEditPrivate
50 *======================================================================================*/
51
52class OLineEdit::OLineEditPrivate
53{
54public:
55 OLineEditPrivate()
56 {
57 grabReturnKeyEvents = false;
58 handleURLDrops = true;
59 completionBox = 0L;
60 }
61 ~OLineEditPrivate()
62 {
63 delete completionBox;
64 }
65
66 bool grabReturnKeyEvents;
67 bool handleURLDrops;
68 OCompletionBox *completionBox;
69};
70
71
72/*======================================================================================
73 * OLineEdit
74 *======================================================================================*/
75
76OLineEdit::OLineEdit( const QString &string, QWidget *parent, const char *name )
77 : QLineEdit( string, parent, name )
78{
79 init();
80}
81
82OLineEdit::OLineEdit( QWidget *parent, const char *name )
83 : QLineEdit( parent, name )
84{
85 init();
86}
87
88OLineEdit::~OLineEdit ()
89{
90 delete d;
91}
92
93void OLineEdit::init()
94{
95 d = new OLineEditPrivate;
96 possibleTripleClick = false;
97 // Enable the context menu by default.
98 setContextMenuEnabled( true );
99 //OCursor::setAutoHideCursor( this, true, true );
100 installEventFilter( this );
101}
102
103void OLineEdit::setCompletionMode( OGlobalSettings::Completion mode )
104{
105 OGlobalSettings::Completion oldMode = completionMode();
106 if ( oldMode != mode && oldMode == OGlobalSettings::CompletionPopup &&
107 d->completionBox && d->completionBox->isVisible() )
108 d->completionBox->hide();
109
110 // If the widgets echo mode is not Normal, no completion
111 // feature will be enabled even if one is requested.
112 if ( echoMode() != QLineEdit::Normal )
113 mode = OGlobalSettings::CompletionNone; // Override the request.
114
115 OCompletionBase::setCompletionMode( mode );
116}
117
118void OLineEdit::setCompletedText( const QString& t, bool marked )
119{
120 QString txt = text();
121 if ( t != txt )
122 {
123 int curpos = marked ? txt.length() : t.length();
124 validateAndSet( t, curpos, curpos, t.length() );
125 }
126}
127
128void OLineEdit::setCompletedText( const QString& text )
129{
130 OGlobalSettings::Completion mode = completionMode();
131 bool marked = ( mode == OGlobalSettings::CompletionAuto ||
132 mode == OGlobalSettings::CompletionMan ||
133 mode == OGlobalSettings::CompletionPopup );
134 setCompletedText( text, marked );
135}
136
137void OLineEdit::rotateText( OCompletionBase::KeyBindingType type )
138{
139 OCompletion* comp = compObj();
140 if ( comp &&
141 (type == OCompletionBase::PrevCompletionMatch ||
142 type == OCompletionBase::NextCompletionMatch ) )
143 {
144 QString input = (type == OCompletionBase::PrevCompletionMatch) ? comp->previousMatch() : comp->nextMatch();
145 // Skip rotation if previous/next match is null or the same text
146 if ( input.isNull() || input == displayText() )
147 return;
148 #if QT_VERSION > 290
149 setCompletedText( input, hasSelectedText() );
150 #else
151 setCompletedText( input, hasMarkedText() );
152 #endif
153 }
154}
155
156void OLineEdit::makeCompletion( const QString& text )
157{
158 OCompletion *comp = compObj();
159 if ( !comp )
160 return; // No completion object...
161
162 QString match = comp->makeCompletion( text );
163 OGlobalSettings::Completion mode = completionMode();
164 if ( mode == OGlobalSettings::CompletionPopup )
165 {
166 if ( match.isNull() )
167 {
168 if ( d->completionBox ) {
169 d->completionBox->hide();
170 d->completionBox->clear();
171 }
172 }
173 else
174 setCompletedItems( comp->allMatches() );
175 }
176 else
177 {
178 // all other completion modes
179 // If no match or the same match, simply return without completing.
180 if ( match.isNull() || match == text )
181 return;
182
183 setCompletedText( match );
184 }
185}
186
187void OLineEdit::setReadOnly(bool readOnly)
188{
189 QPalette p = palette();
190 if (readOnly)
191 {
192 QColor color = p.color(QPalette::Disabled, QColorGroup::Background);
193 p.setColor(QColorGroup::Base, color);
194 p.setColor(QColorGroup::Background, color);
195 }
196 else
197 {
198 QColor color = p.color(QPalette::Normal, QColorGroup::Base);
199 p.setColor(QColorGroup::Base, color);
200 p.setColor(QColorGroup::Background, color);
201 }
202 setPalette(p);
203
204 QLineEdit::setReadOnly (readOnly);
205}
206
207void OLineEdit::keyPressEvent( QKeyEvent *e )
208{
209 qDebug( "OLineEdit::keyPressEvent()" );
210
211 /*
212
213 KKey key( e );
214
215 if ( KStdAccel::copy().contains( key ) ) {
216 copy();
217 return;
218 }
219 else if ( KStdAccel::paste().contains( key ) ) {
220 paste();
221 return;
222 }
223 else if ( KStdAccel::cut().contains( key ) ) {
224 cut();
225 return;
226 }
227 else if ( KStdAccel::undo().contains( key ) ) {
228 undo();
229 return;
230 }
231 else if ( KStdAccel::redo().contains( key ) ) {
232 redo();
233 return;
234 }
235 else if ( KStdAccel::deleteWordBack().contains( key ) )
236 {
237 cursorWordBackward(TRUE);
238 if ( hasSelectedText() )
239 del();
240
241 e->accept();
242 return;
243 }
244 else if ( KStdAccel::deleteWordForward().contains( key ) )
245 {
246 // Workaround for QT bug where
247 cursorWordForward(TRUE);
248 if ( hasSelectedText() )
249 del();
250
251 e->accept();
252 return;
253 }
254 */
255
256 // Filter key-events if EchoMode is normal &
257 // completion mode is not set to CompletionNone
258 if ( echoMode() == QLineEdit::Normal &&
259 completionMode() != OGlobalSettings::CompletionNone )
260 {
261 KeyBindingMap keys = getKeyBindings();
262 OGlobalSettings::Completion mode = completionMode();
263 bool noModifier = (e->state() == NoButton || e->state()== ShiftButton);
264
265 if ( (mode == OGlobalSettings::CompletionAuto ||
266 mode == OGlobalSettings::CompletionMan) && noModifier )
267 {
268 QString keycode = e->text();
269 if ( !keycode.isNull() && keycode.unicode()->isPrint() )
270 {
271 QLineEdit::keyPressEvent ( e );
272 QString txt = text();
273 int len = txt.length();
274 #if QT_VERSION > 290
275 if ( !hasSelectedText() && len && cursorPosition() == len )
276 #else
277 if ( !hasMarkedText() && len && cursorPosition() == len )
278 #endif
279 {
280 if ( emitSignals() )
281 emit completion( txt );
282 if ( handleSignals() )
283 makeCompletion( txt );
284 e->accept();
285 }
286 return;
287 }
288 }
289
290 else if ( mode == OGlobalSettings::CompletionPopup && noModifier )
291 {
292 qDebug( "OLineEdit::keyPressEvent() - global settings = CompletionPopup & noModifier" );
293
294 QString old_txt = text();
295 QLineEdit::keyPressEvent ( e );
296 QString txt = text();
297 int len = txt.length();
298 QString keycode = e->text();
299
300
301 if ( txt != old_txt && len && cursorPosition() == len &&
302 ( (!keycode.isNull() && keycode.unicode()->isPrint()) ||
303 e->key() == Key_Backspace ) )
304 {
305 if ( emitSignals() )
306 emit completion( txt ); // emit when requested...
307 if ( handleSignals() )
308 makeCompletion( txt ); // handle when requested...
309 e->accept();
310 }
311 else if (!len && d->completionBox && d->completionBox->isVisible())
312 d->completionBox->hide();
313
314 return;
315 }
316
317 /*else if ( mode == OGlobalSettings::CompletionShell )
318 {
319 // Handles completion.
320 KShortcut cut;
321 if ( keys[TextCompletion].isNull() )
322 cut = KStdAccel::shortcut(KStdAccel::TextCompletion);
323 else
324 cut = keys[TextCompletion];
325
326 if ( cut.contains( key ) )
327 {
328 // Emit completion if the completion mode is CompletionShell
329 // and the cursor is at the end of the string.
330 QString txt = text();
331 int len = txt.length();
332 if ( cursorPosition() == len && len != 0 )
333 {
334 if ( emitSignals() )
335 emit completion( txt );
336 if ( handleSignals() )
337 makeCompletion( txt );
338 return;
339 }
340 }
341 else if ( d->completionBox )
342 d->completionBox->hide();
343 }
344
345 // handle rotation
346 if ( mode != OGlobalSettings::CompletionNone )
347 {
348 // Handles previous match
349 KShortcut cut;
350 if ( keys[PrevCompletionMatch].isNull() )
351 cut = KStdAccel::shortcut(KStdAccel::PrevCompletion);
352 else
353 cut = keys[PrevCompletionMatch];
354
355 if ( cut.contains( key ) )
356 {
357 if ( emitSignals() )
358 emit textRotation( OCompletionBase::PrevCompletionMatch );
359 if ( handleSignals() )
360 rotateText( OCompletionBase::PrevCompletionMatch );
361 return;
362 }
363
364 // Handles next match
365 if ( keys[NextCompletionMatch].isNull() )
366 cut = KStdAccel::key(KStdAccel::NextCompletion);
367 else
368 cut = keys[NextCompletionMatch];
369
370 if ( cut.contains( key ) )
371 {
372 if ( emitSignals() )
373 emit textRotation( OCompletionBase::NextCompletionMatch );
374 if ( handleSignals() )
375 rotateText( OCompletionBase::NextCompletionMatch );
376 return;
377 }
378 }
379
380 // substring completion
381 if ( compObj() )
382 {
383 KShortcut cut;
384 if ( keys[SubstringCompletion].isNull() )
385 cut = KStdAccel::shortcut(KStdAccel::SubstringCompletion);
386 else
387 cut = keys[SubstringCompletion];
388
389 if ( cut.contains( key ) )
390 {
391 if ( emitSignals() )
392 emit substringCompletion( text() );
393 if ( handleSignals() )
394 {
395 setCompletedItems( compObj()->substringCompletion(text()));
396 e->accept();
397 }
398 return;
399 }
400 } */
401 }
402
403 // Let QLineEdit handle any other keys events.
404 QLineEdit::keyPressEvent ( e );
405}
406
407void OLineEdit::mouseDoubleClickEvent( QMouseEvent* e )
408{
409 if ( e->button() == Qt::LeftButton )
410 {
411 possibleTripleClick=true;
412 QTimer::singleShot( QApplication::doubleClickInterval(),this,
413 SLOT(tripleClickTimeout()) );
414 }
415 QLineEdit::mouseDoubleClickEvent( e );
416}
417
418void OLineEdit::mousePressEvent( QMouseEvent* e )
419{
420 if ( possibleTripleClick && e->button() == Qt::LeftButton )
421 {
422 selectAll();
423 return;
424 }
425 QLineEdit::mousePressEvent( e );
426}
427
428void OLineEdit::tripleClickTimeout()
429{
430 possibleTripleClick=false;
431}
432
433QPopupMenu *OLineEdit::createPopupMenu()
434{
435 // Return if popup menu is not enabled !!
436 if ( !m_bEnableMenu )
437 return 0;
438
439 #if QT_VERSION > 290
440 QPopupMenu *popup = QLineEdit::createPopupMenu();
441 #else
442 QPopupMenu *popup = new QPopupMenu();
443 #warning OLineEdit is not fully functional on Qt2
444 #endif
445
446 // completion object is present.
447 if ( compObj() )
448 {
449 QPopupMenu *subMenu = new QPopupMenu( popup );
450 connect( subMenu, SIGNAL( activated( int ) ),
451 this, SLOT( completionMenuActivated( int ) ) );
452
453 popup->insertSeparator();
454 //popup->insertItem( SmallIconSet("completion"), i18n("Text Completion"),
455 // subMenu );
456
457 popup->insertItem( tr("Text Completion"), subMenu );
458
459 subMenu->insertItem( tr("None"), NoCompletion );
460 subMenu->insertItem( tr("Manual"), ShellCompletion );
461 subMenu->insertItem( tr("Automatic"), AutoCompletion );
462 subMenu->insertItem( tr("Dropdown List"), PopupCompletion );
463 subMenu->insertItem( tr("Short Automatic"), SemiAutoCompletion );
464
465 //subMenu->setAccel( KStdAccel::completion(), ShellCompletion );
466 subMenu->setAccel( Key_Tab, ShellCompletion );
467
468 OGlobalSettings::Completion mode = completionMode();
469 subMenu->setItemChecked( NoCompletion,
470 mode == OGlobalSettings::CompletionNone );
471 subMenu->setItemChecked( ShellCompletion,
472 mode == OGlobalSettings::CompletionShell );
473 subMenu->setItemChecked( PopupCompletion,
474 mode == OGlobalSettings::CompletionPopup );
475 subMenu->setItemChecked( AutoCompletion,
476 mode == OGlobalSettings::CompletionAuto );
477 subMenu->setItemChecked( SemiAutoCompletion,
478 mode == OGlobalSettings::CompletionMan );
479 if ( mode != OGlobalSettings::completionMode() )
480 {
481 subMenu->insertSeparator();
482 subMenu->insertItem( tr("Default"), Default );
483 }
484 }
485 // ### do we really need this? Yes, Please do not remove! This
486 // allows applications to extend the popup menu without having to
487 // inherit from this class! (DA)
488 emit aboutToShowContextMenu( popup );
489
490 return popup;
491}
492
493void OLineEdit::completionMenuActivated( int id )
494{
495 OGlobalSettings::Completion oldMode = completionMode();
496
497 switch ( id )
498 {
499 case Default:
500 setCompletionMode( OGlobalSettings::completionMode() ); break;
501 case NoCompletion:
502 setCompletionMode( OGlobalSettings::CompletionNone ); break;
503 case AutoCompletion:
504 setCompletionMode( OGlobalSettings::CompletionAuto ); break;
505 case SemiAutoCompletion:
506 setCompletionMode( OGlobalSettings::CompletionMan ); break;
507 case ShellCompletion:
508 setCompletionMode( OGlobalSettings::CompletionShell ); break;
509 case PopupCompletion:
510 setCompletionMode( OGlobalSettings::CompletionPopup ); break;
511 default: return;
512 }
513
514 if ( oldMode != completionMode() )
515 {
516 if ( oldMode == OGlobalSettings::CompletionPopup &&
517 d->completionBox && d->completionBox->isVisible() )
518 d->completionBox->hide();
519 emit completionModeChanged( completionMode() );
520 }
521}
522
523/*void OLineEdit::dropEvent(QDropEvent *e)
524{
525 KURL::List urlList;
526 if( d->handleURLDrops && KURLDrag::decode( e, urlList ) )
527 {
528 QString dropText = text();
529 KURL::List::ConstIterator it;
530 for( it = urlList.begin() ; it != urlList.end() ; ++it )
531 {
532 if(!dropText.isEmpty())
533 dropText+=' ';
534
535 dropText += (*it).prettyURL();
536 }
537
538 validateAndSet( dropText, dropText.length(), 0, 0);
539
540 e->accept();
541 }
542 else
543 QLineEdit::dropEvent(e);
544}*/
545
546bool OLineEdit::eventFilter( QObject* o, QEvent* ev )
547{
548 if( o == this )
549 {
550 //OCursor::autoHideEventFilter( this, ev );
551 if ( ev->type() == QEvent::AccelOverride )
552 {
553 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
554 // if (overrideAccel (e))
555 // {
556 // e->accept();
557 // return true;
558 // }
559 }
560 else if( ev->type() == QEvent::KeyPress )
561 {
562 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
563
564 if( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
565 {
566 bool trap = d->completionBox && d->completionBox->isVisible();
567
568 // Qt will emit returnPressed() itself if we return false
569 if ( d->grabReturnKeyEvents || trap )
570 emit QLineEdit::returnPressed();
571
572 emit returnPressed( displayText() );
573
574 if ( trap )
575 d->completionBox->hide();
576
577 // Eat the event if the user asked for it, or if a completionbox was visible
578 return d->grabReturnKeyEvents || trap;
579 }
580 }
581 }
582 return QLineEdit::eventFilter( o, ev );
583}
584
585
586void OLineEdit::setURLDropsEnabled(bool enable)
587{
588 d->handleURLDrops=enable;
589}
590
591bool OLineEdit::isURLDropsEnabled() const
592{
593 return d->handleURLDrops;
594}
595
596void OLineEdit::setTrapReturnKey( bool grab )
597{
598 d->grabReturnKeyEvents = grab;
599}
600
601bool OLineEdit::trapReturnKey() const
602{
603 return d->grabReturnKeyEvents;
604}
605
606/*void OLineEdit::setURL( const KURL& url )
607{
608 QLineEdit::setText( url.prettyURL() );
609}*/
610
611void OLineEdit::makeCompletionBox()
612{
613 if ( d->completionBox )
614 return;
615
616 d->completionBox = new OCompletionBox( this, "completion box" );
617 if ( handleSignals() )
618 {
619 connect( d->completionBox, SIGNAL(highlighted( const QString& )),
620 SLOT(setText( const QString& )) );
621 connect( d->completionBox, SIGNAL(userCancelled( const QString& )),
622 SLOT(setText( const QString& )) );
623
624 // Nice lil' hacklet ;) KComboBox doesn't know when the completionbox
625 // is created (childEvent() is even more hacky, IMHO), so we simply
626 // forward the completionbox' activated signal from here.
627 if ( parentWidget() && parentWidget()->inherits("KComboBox") )
628 connect( d->completionBox, SIGNAL( activated( const QString& )),
629 parentWidget(), SIGNAL( activated( const QString & )));
630 }
631}
632
633/*bool OLineEdit::overrideAccel (const QKeyEvent* e)
634{
635 KShortcut scKey;
636
637 KKey key( e );
638 KeyBindingMap keys = getKeyBindings();
639
640 if (keys[TextCompletion].isNull())
641 scKey = KStdAccel::shortcut(KStdAccel::TextCompletion);
642 else
643 scKey = keys[TextCompletion];
644
645 if (scKey.contains( key ))
646 return true;
647
648 if (keys[NextCompletionMatch].isNull())
649 scKey = KStdAccel::shortcut(KStdAccel::NextCompletion);
650 else
651 scKey = keys[NextCompletionMatch];
652
653 if (scKey.contains( key ))
654 return true;
655
656 if (keys[PrevCompletionMatch].isNull())
657 scKey = KStdAccel::shortcut(KStdAccel::PrevCompletion);
658 else
659 scKey = keys[PrevCompletionMatch];
660
661 if (scKey.contains( key ))
662 return true;
663
664 if (KStdAccel::deleteWordBack().contains( key ))
665 return true;
666 if (KStdAccel::deleteWordForward().contains( key ))
667 return true;
668
669 if (d->completionBox && d->completionBox->isVisible ())
670 if (e->key () == Key_Backtab)
671 return true;
672
673 return false;
674}*/
675
676void OLineEdit::setCompletedItems( const QStringList& items )
677{
678 QString txt = text();
679 if ( !items.isEmpty() &&
680 !(items.count() == 1 && txt == items.first()) )
681 {
682 if ( !d->completionBox )
683 makeCompletionBox();
684
685 if ( !txt.isEmpty() )
686 d->completionBox->setCancelledText( txt );
687 d->completionBox->setItems( items );
688 d->completionBox->popup();
689 }
690 else
691 {
692 if ( d->completionBox && d->completionBox->isVisible() )
693 d->completionBox->hide();
694 }
695}
696
697OCompletionBox * OLineEdit::completionBox( bool create )
698{
699 if ( create )
700 makeCompletionBox();
701
702 return d->completionBox;
703}
704
705void OLineEdit::setCompletionObject( OCompletion* comp, bool hsig )
706{
707 OCompletion *oldComp = compObj();
708 if ( oldComp && handleSignals() )
709 disconnect( oldComp, SIGNAL( matches( const QStringList& )),
710 this, SLOT( setCompletedItems( const QStringList& )));
711
712 if ( comp && hsig )
713 connect( comp, SIGNAL( matches( const QStringList& )),
714 this, SLOT( setCompletedItems( const QStringList& )));
715
716 OCompletionBase::setCompletionObject( comp, hsig );
717}
718
719// QWidget::create() turns off mouse-Tracking which would break auto-hiding
720void OLineEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
721{
722 QLineEdit::create( id, initializeWindow, destroyOldWindow );
723 //OCursor::setAutoHideCursor( this, true, true );
724}
725
726void OLineEdit::clear()
727{
728 setText( QString::null );
729}
diff --git a/libopie2/qt3/opieui/olineedit.h b/libopie2/qt3/opieui/olineedit.h
new file mode 100644
index 0000000..ecfca27
--- a/dev/null
+++ b/libopie2/qt3/opieui/olineedit.h
@@ -0,0 +1,498 @@
1/*
2 This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
3 is part of the Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org>, Dawit Alemayehu <adawit@kde.org>
4 Opie Project Copyright (C) 1999 Preston Brown <pbrown@kde.org>, Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
5 Copyright (C) 1997 Sven Radej (sven.radej@iname.com)
6 =.
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#ifndef OLINEEDIT_H
34#define OLINEEDIT_H
35
36/* QT */
37
38#include <qlineedit.h>
39
40/* OPIE */
41
42#include <opie2/ocompletion.h>
43#include <opie2/ocompletionbase.h>
44
45class QPopupMenu;
46
47class OCompletionBox;
48typedef QString KURL; //class KURL;
49
50/**
51 * An enhanced QLineEdit widget for inputting text.
52 *
53 * @sect Detail
54 *
55 * This widget inherits from @ref QLineEdit and implements the following
56 * additional functionalities: q completion object that provides both
57 * automatic and manual text completion as well as multiple match iteration
58 * features, configurable key-bindings to activate these features and a
59 * popup-menu item that can be used to allow the user to set text completion
60 * modes on the fly based on their preference.
61 *
62 * To support these new features OLineEdit also emits a few more
63 * additional signals. These are: @ref completion( const QString& ),
64 * textRotation( KeyBindingType ), and @ref returnPressed( const QString& ).
65 * The completion signal can be connected to a slot that will assist the
66 * user in filling out the remaining text. The text rotation signal is
67 * intended to be used to iterate through the list of all possible matches
68 * whenever there is more than one match for the entered text. The
69 * @p returnPressed( const QString& ) signals are the same as QLineEdit's
70 * except it provides the current text in the widget as its argument whenever
71 * appropriate.
72 *
73 * This widget by default creates a completion object when you invoke
74 * the @ref completionObject( bool ) member function for the first time or
75 * use @ref setCompletionObject( OCompletion*, bool ) to assign your own
76 * completion object. Additionally, to make this widget more functional,
77 * OLineEdit will by default handle the text rotation and completion
78 * events internally when a completion object is created through either one
79 * of the methods mentioned above. If you do not need this functionality,
80 * simply use @ref OCompletionBase::setHandleSignals( bool ) or set the
81 * boolean parameter in the above functions to FALSE.
82 *
83 * The default key-bindings for completion and rotation is determined
84 * from the global settings in @ref OStdAccel. These values, however,
85 * can be overriden locally by invoking @ref OCompletionBase::setKeyBinding().
86 * The values can easily be reverted back to the default setting, by simply
87 * calling @ref useGlobalSettings(). An alternate method would be to default
88 * individual key-bindings by usning @ref setKeyBinding() with the default
89 * second argument.
90 *
91 * NOTE that if the @p EchoMode for this widget is set to something other
92 * than @p QLineEdit::Normal, the completion mode will always be defaulted
93 * to @ref PGlobalSettings::CompletionNone. This is done purposefully to guard
94 * against protected entries such as passwords being cached in @ref OCompletion's
95 * list. Hence, if the @p EchoMode is not @ref QLineEdit::Normal, the completion
96 * mode is automatically disabled.
97 *
98 * @sect Useage
99 *
100 * To enable the basic completion feature :
101 *
102 * <pre>
103 * OLineEdit *edit = new OLineEdit( this, "mywidget" );
104 * OCompletion *comp = edit->completionObject();
105 * // Fill the completion object with a list of possible matches
106 * QStringList list;
107 * list << "mickeyl@handhelds.org" << "mickey@tm.informatik.uni-frankfurt.de>" << "mickey@Vanille.de";
108 * comp->setItems( list );
109 * // Connect to the return pressed signal (optional)
110 * connect(edit,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
111 * </pre>
112 *
113 * To use a customized completion objects or your
114 * own completion object :
115 *
116 * <pre>
117 * OLineEdit *edit = new OLineEdit( this,"mywidget" );
118 * KURLCompletion *comp = new KURLCompletion();
119 * edit->setCompletionObject( comp );
120 * // Connect to the return pressed signal - optional
121 * connect(edit,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
122 * </pre>
123 *
124 * Note that you have to either delete the allocated completion object
125 * when you don't need it anymore, or call
126 * setAutoDeleteCompletionObject( true );
127 *
128 * @sect Miscellaneous function calls :
129 *
130 * <pre>
131 * // Tell the widget not to handle completion and
132 * // iteration internally.
133 * edit->setHandleSignals( false );
134 * // Set your own completion key for manual completions.
135 * edit->setKeyBinding( OCompletionBase::TextCompletion, Qt::End );
136 * // Hide the context (popup) menu
137 * edit->setContextMenuEnabled( false );
138 * // Temporarly disable signal emitions
139 * // (both completion & iteration signals)
140 * edit->disableSignals();
141 * // Default the key-bindings to system settings.
142 * edit->useGlobalKeyBindings();
143 * </pre>
144 *
145 * @short An enhanced single line input widget.
146 * @author Dawit Alemayehu <adawit@kde.org>
147 * @author Opie adaption by Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
148 */
149
150class OLineEdit : public QLineEdit, public OCompletionBase
151{
152 friend class OComboBox;
153
154 Q_OBJECT
155 Q_PROPERTY( bool contextMenuEnabled READ isContextMenuEnabled WRITE setContextMenuEnabled )
156 Q_PROPERTY( bool urlDropsEnabled READ isURLDropsEnabled WRITE setURLDropsEnabled )
157
158public:
159
160 /**
161 * Constructs a OLineEdit object with a default text, a parent,
162 * and a name.
163 *
164 * @param string Text to be shown in the edit widget.
165 * @param parent The parent object of this widget.
166 * @param name the name of this widget
167 */
168 OLineEdit( const QString &string, QWidget *parent, const char *name = 0 );
169
170 /**
171 * Constructs a OLineEdit object with a parent and a name.
172 *
173 * @param string Text to be shown in the edit widget.
174 * @param parent The parent object of this widget.
175 * @param name The name of this widget.
176 */
177 OLineEdit ( QWidget *parent=0, const char *name=0 );
178
179 /**
180 * Destructor.
181 */
182 virtual ~OLineEdit ();
183
184 /**
185 * Sets @p url into the lineedit. It uses @ref KURL::prettyURL() so
186 * that the url is properly decoded for displaying.
187 */
188 void setURL( const KURL& url );
189
190 /**
191 * Puts the text cursor at the end of the string.
192 *
193 * This method is deprecated. Use @ref QLineEdit::end()
194 * instead.
195 *
196 * @deprecated
197 * @ref QLineEdit::end()
198 */
199 void cursorAtEnd() { end( false ); }
200
201 /**
202 * Re-implemented from @ref OCompletionBase for internal reasons.
203 *
204 * This function is re-implemented in order to make sure that
205 * the EchoMode is acceptable before we set the completion mode.
206 *
207 * See @ref OCompletionBase::setCompletionMode
208 */
209 virtual void setCompletionMode( OGlobalSettings::Completion mode );
210
211 /**
212 * Enables/disables the popup (context) menu.
213 *
214 * Note that when this function is invoked with its argument
215 * set to @p true, then both the context menu and the completion
216 * menu item are enabled. If you do not want to the completion
217 * item to be visible simply invoke @ref hideModechanger() right
218 * after calling this method. Also by default, the context
219 * menu is automatically created if this widget is editable. Thus
220 * you need to call this function with the argument set to false
221 * if you do not want this behaviour.
222 *
223 * @param showMenu If @p true, show the context menu.
224 */
225 virtual void setContextMenuEnabled( bool showMenu ) { m_bEnableMenu = showMenu; }
226
227 /**
228 * Returns @p true when the context menu is enabled.
229 */
230 bool isContextMenuEnabled() const { return m_bEnableMenu; }
231
232 /**
233 * Enables/Disables handling of URL drops. If enabled and the user
234 * drops an URL, the decoded URL will be inserted. Otherwise the default
235 * behaviour of QLineEdit is used, which inserts the encoded URL.
236 *
237 * @param enable If @p true, insert decoded URLs
238 */
239 void setURLDropsEnabled( bool enable );
240
241 /**
242 * Returns @p true when decoded URL drops are enabled
243 */
244 bool isURLDropsEnabled() const;
245
246 /**
247 * By default, OLineEdit recognizes @p Key_Return and @p Key_Enter and emits
248 * the @ref returnPressed() signals, but it also lets the event pass,
249 * for example causing a dialog's default-button to be called.
250 *
251 * Call this method with @p trap = @p true to make @p OLineEdit stop these
252 * events. The signals will still be emitted of course.
253 *
254 * @see trapReturnKey()
255 */
256 void setTrapReturnKey( bool trap );
257
258 /**
259 * @returns @p true if keyevents of @p Key_Return or
260 * @p Key_Enter will be stopped or if they will be propagated.
261 *
262 * @see setTrapReturnKey ()
263 */
264 bool trapReturnKey() const;
265
266 /**
267 * Re-implemented for internal reasons. API not affected.
268 *
269 * @reimplemented
270 */
271 virtual bool eventFilter( QObject *, QEvent * );
272
273 /**
274 * @returns the completion-box, that is used in completion mode
275 * @ref KGlobalSettings::CompletionPopup.
276 * This method will create a completion-box if none is there, yet.
277 *
278 * @param create Set this to false if you don't want the box to be created
279 * i.e. to test if it is available.
280 */
281 OCompletionBox * completionBox( bool create = true );
282
283 /**
284 * Reimplemented for internal reasons, the API is not affected.
285 */
286 virtual void setCompletionObject( OCompletion *, bool hsig = true );
287
288
289signals:
290
291 /**
292 * Emitted when the user presses the return key.
293 *
294 * The argument is the current text. Note that this
295 * signal is @em not emitted if the widget's @p EchoMode is set to
296 * @ref QLineEdit::EchoMode.
297 */
298 void returnPressed( const QString& );
299
300 /**
301 * Emitted when the completion key is pressed.
302 *
303 * Please note that this signal is @em not emitted if the
304 * completion mode is set to @p CompletionNone or @p EchoMode is
305 * @em normal.
306 */
307 void completion( const QString& );
308
309 /**
310 * Emitted when the shortcut for substring completion is pressed.
311 */
312 void substringCompletion( const QString& );
313
314 /**
315 * Emitted when the text rotation key-bindings are pressed.
316 *
317 * The argument indicates which key-binding was pressed.
318 * In OLineEdit's case this can be either one of two values:
319 * @ref PrevCompletionMatch or @ref NextCompletionMatch. See
320 * @ref OCompletionBase::setKeyBinding for details.
321 *
322 * Note that this signal is @em not emitted if the completion
323 * mode is set to @p KGlobalSettings::CompletionNone or @p echoMode() is @em not normal.
324 */
325 void textRotation( OCompletionBase::KeyBindingType );
326
327 /**
328 * Emitted when the user changed the completion mode by using the
329 * popupmenu.
330 */
331 void completionModeChanged( OGlobalSettings::Completion );
332
333 /**
334 * Emitted before the context menu is displayed.
335 *
336 * The signal allows you to add your own entries into the
337 * the context menu that is created on demand.
338 *
339 * NOTE: Do not store the pointer to the QPopupMenu
340 * provided through since it is created and deleted
341 * on demand.
342 *
343 * @param the context menu about to be displayed
344 */
345 void aboutToShowContextMenu( QPopupMenu* );
346
347public slots:
348
349 /**
350 * Re-implemented for internal reasons. API not changed.
351 */
352 virtual void setReadOnly(bool);
353
354 /**
355 * Iterates through all possible matches of the completed text or
356 * the history list.
357 *
358 * This function simply iterates over all possible matches in case
359 * multimple matches are found as a result of a text completion request.
360 * It will have no effect if only a single match is found.
361 *
362 * @param type The key-binding invoked.
363 */
364 void rotateText( OCompletionBase::KeyBindingType /* type */ );
365
366 /**
367 * See @ref OCompletionBase::setCompletedText.
368 */
369 virtual void setCompletedText( const QString& );
370
371 /**
372 * Sets @p items into the completion-box if @ref completionMode() is
373 * CompletionPopup. The popup will be shown immediately.
374 */
375 void setCompletedItems( const QStringList& items );
376
377 /**
378 * Reimplemented to workaround a buggy QLineEdit::clear()
379 * (changing the clipboard to the text we just had in the lineedit)
380 */
381 virtual void clear();
382
383protected slots:
384
385 /**
386 * Completes the remaining text with a matching one from
387 * a given list.
388 */
389 virtual void makeCompletion( const QString& );
390
391 /**
392 * @deprecated. Will be removed in the next major release!
393 */
394 void slotAboutToShow() {}
395
396 /**
397 * @deprecated. Will be removed in the next major release!
398 */
399 void slotCancelled() {}
400
401protected:
402
403 /**
404 * Re-implemented for internal reasons. API not affected.
405 *
406 * See @ref QLineEdit::keyPressEvent().
407 */
408 virtual void keyPressEvent( QKeyEvent * );
409
410 /**
411 * Re-implemented for internal reasons. API not affected.
412 *
413 * See @ref QLineEdit::mousePressEvent().
414 */
415 virtual void mousePressEvent( QMouseEvent * );
416
417 /**
418 * Re-implemented for internal reasons. API not affected.
419 *
420 * See @ref QWidget::mouseDoubleClickEvent().
421 */
422 virtual void mouseDoubleClickEvent( QMouseEvent * );
423
424 /**
425 * Re-implemented for internal reasons. API not affected.
426 *
427 * See @ref QLineEdit::createPopupMenu().
428 */
429 virtual QPopupMenu *createPopupMenu();
430
431 /**
432 * Re-implemented to handle URI drops.
433 *
434 * See @ref QLineEdit::dropEvent().
435 */
436 //virtual void dropEvent( QDropEvent * );
437
438 /*
439 * This function simply sets the lineedit text and
440 * highlights the text appropriately if the boolean
441 * value is set to true.
442 *
443 * @param text
444 * @param marked
445 */
446 virtual void setCompletedText( const QString& /*text*/, bool /*marked*/ );
447
448 /**
449 * Reimplemented for internal reasons, the API is not affected.
450 */
451 virtual void create( WId = 0, bool initializeWindow = true,
452 bool destroyOldWindow = true );
453
454private slots:
455 void completionMenuActivated( int id );
456 void tripleClickTimeout(); // resets possibleTripleClick
457
458private:
459 // Constants that represent the ID's of the popup menu.
460 // TODO: See if we can replace this mess with KActionMenu
461 // in the future though it's working lovely.
462 enum MenuID {
463 Default = 42,
464 NoCompletion,
465 AutoCompletion,
466 ShellCompletion,
467 PopupCompletion,
468 SemiAutoCompletion
469 };
470
471 /**
472 * Initializes variables. Called from the constructors.
473 */
474 void init();
475
476 /**
477 * Creates the completion box
478 */
479 void makeCompletionBox();
480
481 /**
482 * Checks whether we should/should not consume a key used as
483 * an accelerator.
484 */
485 //bool overrideAccel (const QKeyEvent* e);
486
487 bool m_bEnableMenu;
488
489 bool possibleTripleClick; // set in mousePressEvent, deleted in tripleClickTimeout
490
491protected:
492 //virtual void virtual_hook( int id, void* data );
493private:
494 class OLineEditPrivate;
495 OLineEditPrivate *d;
496};
497
498#endif