summaryrefslogtreecommitdiff
path: root/libopie2/qt3/opieui
authormickeyl <mickeyl>2003-03-28 15:11:52 (UTC)
committer mickeyl <mickeyl>2003-03-28 15:11:52 (UTC)
commit11304d02942e9fa493e4e80943a828f9c65f6772 (patch) (side-by-side diff)
treea0223c10c067e1afc70d15c2b82be3f3c15e41ae /libopie2/qt3/opieui
parentb271d575fa05cf570a1a829136517761bd47e69b (diff)
downloadopie-11304d02942e9fa493e4e80943a828f9c65f6772.zip
opie-11304d02942e9fa493e4e80943a828f9c65f6772.tar.gz
opie-11304d02942e9fa493e4e80943a828f9c65f6772.tar.bz2
skeleton and the start of libopie2, please read README, ROADMAP and STATUS and comment...
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 @@
+/*
+ This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ is part of the Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+ Opie Project Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
+
+ =. Originally part of the KDE Project
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* QT */
+
+#include <qclipboard.h>
+#include <qlistbox.h>
+#include <qpopupmenu.h>
+
+/* OPIE */
+
+#include <opie2/ocompletionbox.h>
+#include <opie2/olineedit.h>
+#include <opie2/opixmapprovider.h>
+#include <opie2/ocombobox.h>
+
+/*======================================================================================
+ * OComboBoxPrivate
+ *======================================================================================*/
+
+class OComboBox::OComboBoxPrivate
+{
+public:
+ OComboBoxPrivate()
+ {
+ olineEdit = 0L;
+ }
+ ~OComboBoxPrivate()
+ {
+ }
+
+ OLineEdit *olineEdit;
+};
+
+/*======================================================================================
+ * OComboBox
+ *======================================================================================*/
+
+OComboBox::OComboBox( QWidget *parent, const char *name )
+ : QComboBox( parent, name )
+{
+ init();
+}
+
+OComboBox::OComboBox( bool rw, QWidget *parent, const char *name )
+ : QComboBox( rw, parent, name )
+{
+ init();
+
+ if ( rw )
+ {
+ OLineEdit *edit = new OLineEdit( this, "combo lineedit" );
+ setLineEdit( edit );
+ }
+}
+
+OComboBox::~OComboBox()
+{
+ delete d;
+}
+
+void OComboBox::init()
+{
+ d = new OComboBoxPrivate;
+
+ // Permanently set some parameters in the parent object.
+ QComboBox::setAutoCompletion( false );
+
+ // Initialize enable popup menu to false.
+ // Below it will be enabled if the widget
+ // is editable.
+ m_bEnableMenu = false;
+
+ m_trapReturnKey = false;
+
+ // Enable context menu by default if widget
+ // is editable.
+ setContextMenuEnabled( true );
+
+ // for wheelscrolling
+ installEventFilter( this );
+ if ( lineEdit() )
+ lineEdit()->installEventFilter( this );
+}
+
+
+bool OComboBox::contains( const QString& _text ) const
+{
+ if ( _text.isEmpty() )
+ return false;
+
+ for (int i = 0; i < count(); i++ ) {
+ if ( text(i) == _text )
+ return true;
+ }
+ return false;
+}
+
+void OComboBox::setAutoCompletion( bool autocomplete )
+{
+ if ( d->olineEdit )
+ {
+ if ( autocomplete )
+ {
+ d->olineEdit->setCompletionMode( OGlobalSettings::CompletionAuto );
+ setCompletionMode( OGlobalSettings::CompletionAuto );
+ }
+ else
+ {
+ d->olineEdit->setCompletionMode( OGlobalSettings::completionMode() );
+ setCompletionMode( OGlobalSettings::completionMode() );
+ }
+ }
+}
+
+void OComboBox::setContextMenuEnabled( bool showMenu )
+{
+ if( d->olineEdit )
+ {
+ d->olineEdit->setContextMenuEnabled( showMenu );
+ m_bEnableMenu = showMenu;
+ }
+}
+
+/*
+void OComboBox::setURLDropsEnabled( bool enable )
+{
+ if ( d->olineEdit )
+ d->olineEdit->setURLDropsEnabled( enable );
+}
+
+bool OComboBox::isURLDropsEnabled() const
+{
+ return d->olineEdit && d->olineEdit->isURLDropsEnabled();
+}
+*/
+
+void OComboBox::setCompletedText( const QString& text, bool marked )
+{
+ if ( d->olineEdit )
+ d->olineEdit->setCompletedText( text, marked );
+}
+
+void OComboBox::setCompletedText( const QString& text )
+{
+ if ( d->olineEdit )
+ d->olineEdit->setCompletedText( text );
+}
+
+void OComboBox::makeCompletion( const QString& text )
+{
+ if( d->olineEdit )
+ d->olineEdit->makeCompletion( text );
+
+ else // read-only combo completion
+ {
+ if( text.isNull() || !listBox() )
+ return;
+
+ int index = listBox()->index( listBox()->findItem( text ) );
+ if( index >= 0 ) {
+ setCurrentItem( index );
+ }
+ }
+}
+
+void OComboBox::rotateText( OCompletionBase::KeyBindingType type )
+{
+ if ( d->olineEdit )
+ d->olineEdit->rotateText( type );
+}
+
+bool OComboBox::eventFilter( QObject* o, QEvent* ev )
+{
+ QLineEdit *edit = lineEdit();
+
+ int type = ev->type();
+
+ if ( o == edit )
+ {
+ //OCursor::autoHideEventFilter( edit, ev );
+
+ if ( type == QEvent::KeyPress )
+ {
+ QKeyEvent *e = static_cast<QKeyEvent *>( ev );
+
+ if ( e->key() == Key_Return || e->key() == Key_Enter)
+ {
+ // On Return pressed event, emit both
+ // returnPressed(const QString&) and returnPressed() signals
+ emit returnPressed();
+ emit returnPressed( currentText() );
+ if ( d->olineEdit && d->olineEdit->completionBox(false) &&
+ d->olineEdit->completionBox()->isVisible() )
+ d->olineEdit->completionBox()->hide();
+
+ return m_trapReturnKey;
+ }
+ }
+ }
+
+
+ // wheel-scrolling changes the current item
+ if ( type == QEvent::Wheel ) {
+ if ( !listBox() || listBox()->isHidden() ) {
+ QWheelEvent *e = static_cast<QWheelEvent*>( ev );
+ static const int WHEEL_DELTA = 120;
+ int skipItems = e->delta() / WHEEL_DELTA;
+ if ( e->state() & ControlButton ) // fast skipping
+ skipItems *= 10;
+
+ int newItem = currentItem() - skipItems;
+
+ if ( newItem < 0 )
+ newItem = 0;
+ else if ( newItem >= count() )
+ newItem = count() -1;
+
+ setCurrentItem( newItem );
+ if ( !text( newItem ).isNull() )
+ emit activated( text( newItem ) );
+ emit activated( newItem );
+ e->accept();
+ return true;
+ }
+ }
+
+ return QComboBox::eventFilter( o, ev );
+}
+
+void OComboBox::setTrapReturnKey( bool grab )
+{
+ m_trapReturnKey = grab;
+}
+
+bool OComboBox::trapReturnKey() const
+{
+ return m_trapReturnKey;
+}
+
+/*
+void OComboBox::setEditURL( const OURL& url )
+{
+ QComboBox::setEditText( url.prettyURL() );
+}
+
+void OComboBox::insertURL( const OURL& url, int index )
+{
+ QComboBox::insertItem( url.prettyURL(), index );
+}
+
+void OComboBox::insertURL( const QPixmap& pixmap, const OURL& url, int index )
+{
+ QComboBox::insertItem( pixmap, url.prettyURL(), index );
+}
+
+void OComboBox::changeURL( const OURL& url, int index )
+{
+ QComboBox::changeItem( url.prettyURL(), index );
+}
+
+void OComboBox::changeURL( const QPixmap& pixmap, const OURL& url, int index )
+{
+ QComboBox::changeItem( pixmap, url.prettyURL(), index );
+}
+*/
+
+
+void OComboBox::setCompletedItems( const QStringList& items )
+{
+ if ( d->olineEdit )
+ d->olineEdit->setCompletedItems( items );
+}
+
+
+OCompletionBox * OComboBox::completionBox( bool create )
+{
+ if ( d->olineEdit )
+ return d->olineEdit->completionBox( create );
+ return 0;
+}
+
+// QWidget::create() turns off mouse-Tracking which would break auto-hiding
+void OComboBox::create( WId id, bool initializeWindow, bool destroyOldWindow )
+{
+ QComboBox::create( id, initializeWindow, destroyOldWindow );
+ //OCursor::setAutoHideCursor( lineEdit(), true, true );
+}
+
+void OComboBox::setLineEdit( OLineEdit *edit )
+{
+ #if QT_VERSION > 290
+ QComboBox::setLineEdit( edit );
+ d->olineEdit = dynamic_cast<OLineEdit*>( edit );
+ setDelegate( d->olineEdit );
+
+ // forward some signals. We only emit returnPressed() ourselves.
+ if ( d->olineEdit ) {
+ connect( d->olineEdit, SIGNAL( completion( const QString& )),
+ SIGNAL( completion( const QString& )) );
+ connect( d->olineEdit, SIGNAL( substringCompletion( const QString& )),
+ SIGNAL( substringCompletion( const QString& )) );
+ connect( d->olineEdit,
+ SIGNAL( textRotation( OCompletionBase::KeyBindingType )),
+ SIGNAL( textRotation( OCompletionBase::KeyBindingType )) );
+ connect( d->olineEdit,
+ SIGNAL( completionModeChanged( OGlobalSettings::Completion )),
+ SIGNAL( completionModeChanged( OGlobalSettings::Completion)));
+
+ connect( d->olineEdit,
+ SIGNAL( aboutToShowContextMenu( QPopupMenu * )),
+ SIGNAL( aboutToShowContextMenu( QPopupMenu * )) );
+ }
+ #else
+ #warning OComboBox is not fully functional with Qt2
+ #endif
+}
+
+// Temporary functions until QT3 appears. - Seth Chaiklin 20 may 2001
+void OComboBox::deleteWordForward()
+{
+ lineEdit()->cursorWordForward(TRUE);
+ #if QT_VERSION > 290
+ if ( lineEdit()->hasSelectedText() )
+ #else
+ if ( lineEdit()->hasMarkedText() )
+ #endif
+ {
+ lineEdit()->del();
+ }
+}
+
+void OComboBox::deleteWordBack()
+{
+ lineEdit()->cursorWordBackward(TRUE);
+ #if QT_VERSION > 290
+ if ( lineEdit()->hasSelectedText() )
+ #else
+ if ( lineEdit()->hasMarkedText() )
+ #endif
+ {
+ lineEdit()->del();
+ }
+}
+
+void OComboBox::setCurrentItem( const QString& item, bool insert, int index )
+{
+ int sel = -1;
+ for (int i = 0; i < count(); ++i)
+ if (text(i) == item)
+ {
+ sel = i;
+ break;
+ }
+ if (sel == -1 && insert)
+ {
+ insertItem(item, index);
+ if (index >= 0)
+ sel = index;
+ else
+ sel = count() - 1;
+ }
+ setCurrentItem(sel);
+}
+
+void OComboBox::setCurrentItem(int index)
+{
+ QComboBox::setCurrentItem(index);
+}
+
+
+/*======================================================================================
+ * OHistoryCombo
+ *======================================================================================*/
+
+// we are always read-write
+OHistoryCombo::OHistoryCombo( QWidget *parent, const char *name )
+ : OComboBox( true, parent, name )
+{
+ init( true ); // using completion
+}
+
+// we are always read-write
+OHistoryCombo::OHistoryCombo( bool useCompletion,
+ QWidget *parent, const char *name )
+ : OComboBox( true, parent, name )
+{
+ init( useCompletion );
+}
+
+void OHistoryCombo::init( bool useCompletion )
+{
+ if ( useCompletion )
+ completionObject()->setOrder( OCompletion::Weighted );
+
+ setInsertionPolicy( NoInsertion );
+ myIterateIndex = -1;
+ myRotated = false;
+ myPixProvider = 0L;
+
+ connect( this, SIGNAL(aboutToShowContextMenu(QPopupMenu*)),
+ SLOT(addContextMenuItems(QPopupMenu*)) );
+ connect( this, SIGNAL( activated(int) ), SLOT( slotReset() ));
+ connect( this, SIGNAL( returnPressed(const QString&) ), SLOT(slotReset()));
+}
+
+OHistoryCombo::~OHistoryCombo()
+{
+ delete myPixProvider;
+}
+
+void OHistoryCombo::setHistoryItems( QStringList items,
+ bool setCompletionList )
+{
+ OComboBox::clear();
+
+ // limit to maxCount()
+ while ( (int) items.count() > maxCount() && !items.isEmpty() )
+ items.remove( items.begin() );
+
+ insertItems( items );
+
+ if ( setCompletionList && useCompletion() ) {
+ // we don't have any weighting information here ;(
+ OCompletion *comp = completionObject();
+ comp->setOrder( OCompletion::Insertion );
+ comp->setItems( items );
+ comp->setOrder( OCompletion::Weighted );
+ }
+
+ clearEdit();
+}
+
+QStringList OHistoryCombo::historyItems() const
+{
+ QStringList list;
+ for ( int i = 0; i < count(); i++ )
+ list.append( text( i ) );
+
+ return list;
+}
+
+void OHistoryCombo::clearHistory()
+{
+ OComboBox::clear();
+ if ( useCompletion() )
+ completionObject()->clear();
+}
+
+void OHistoryCombo::addContextMenuItems( QPopupMenu* menu )
+{
+ if ( menu &&!lineEdit()->text().isEmpty())
+ {
+ menu->insertSeparator();
+ menu->insertItem( tr("Empty Contents"), this, SLOT( slotClear()));
+ }
+}
+
+void OHistoryCombo::addToHistory( const QString& item )
+{
+ if ( item.isEmpty() || (count() > 0 && item == text(0) ))
+ return;
+
+ // remove all existing items before adding
+ if ( !duplicatesEnabled() ) {
+ for ( int i = 0; i < count(); i++ ) {
+ if ( text( i ) == item )
+ removeItem( i );
+ }
+ }
+
+ // now add the item
+ if ( myPixProvider )
+ //insertItem( myPixProvider->pixmapFor(item, KIcon::SizeSmall), item, 0);
+ insertItem( myPixProvider->pixmapFor(item, 16), item, 0);
+ else
+ insertItem( item, 0 );
+
+ int last;
+ QString rmItem;
+
+ bool useComp = useCompletion();
+ while ( count() > maxCount() && count() > 0 ) {
+ // remove the last item, as long as we are longer than maxCount()
+ // remove the removed item from the completionObject if it isn't
+ // anymore available at all in the combobox.
+ last = count() - 1;
+ rmItem = text( last );
+ removeItem( last );
+ if ( useComp && !contains( rmItem ) )
+ completionObject()->removeItem( rmItem );
+ }
+
+ if ( useComp )
+ completionObject()->addItem( item );
+}
+
+bool OHistoryCombo::removeFromHistory( const QString& item )
+{
+ if ( item.isEmpty() )
+ return false;
+
+ bool removed = false;
+ QString temp = currentText();
+ for ( int i = 0; i < count(); i++ ) {
+ while ( item == text( i ) ) {
+ removed = true;
+ removeItem( i );
+ }
+ }
+
+ if ( removed && useCompletion() )
+ completionObject()->removeItem( item );
+
+ setEditText( temp );
+ return removed;
+}
+
+void OHistoryCombo::keyPressEvent( QKeyEvent *e )
+{
+ // save the current text in the lineedit
+ if ( myIterateIndex == -1 )
+ myText = currentText();
+
+ // going up in the history, rotating when reaching QListBox::count()
+ //if ( OStdAccel::isEqual( e, OStdAccel::rotateUp() ) ) {
+ if ( e->key() == Qt::Key_Up ) {
+ myIterateIndex++;
+
+ // skip duplicates/empty items
+ while ( myIterateIndex < count()-1 &&
+ (currentText() == text( myIterateIndex ) ||
+ text( myIterateIndex ).isEmpty()) )
+ myIterateIndex++;
+
+ if ( myIterateIndex >= count() ) {
+ myRotated = true;
+ myIterateIndex = -1;
+
+ // if the typed text is the same as the first item, skip the first
+ if ( myText == text(0) )
+ myIterateIndex = 0;
+
+ setEditText( myText );
+ }
+ else
+ setEditText( text( myIterateIndex ));
+ }
+
+
+ // going down in the history, no rotation possible. Last item will be
+ // the text that was in the lineedit before Up was called.
+ //else if ( OStdAccel::isEqual( e, OStdAccel::rotateDown() ) ) {
+ else if ( e->key() == Qt::Key_Down ) {
+ myIterateIndex--;
+
+ // skip duplicates/empty items
+ while ( myIterateIndex >= 0 &&
+ (currentText() == text( myIterateIndex ) ||
+ text( myIterateIndex ).isEmpty()) )
+ myIterateIndex--;
+
+
+ if ( myIterateIndex < 0 ) {
+ if ( myRotated && myIterateIndex == -2 ) {
+ myRotated = false;
+ myIterateIndex = count() - 1;
+ setEditText( text(myIterateIndex) );
+ }
+ else { // bottom of history
+ if ( myIterateIndex == -2 ) {
+ qDebug( "ONotifyClient is not implemented yet." );
+ //ONotifyClient::event( ONotifyClient::notification,
+ // i18n("No further item in the history."));
+ }
+
+ myIterateIndex = -1;
+ if ( currentText() != myText )
+ setEditText( myText );
+ }
+ }
+ else
+ setEditText( text( myIterateIndex ));
+ }
+
+ else
+ OComboBox::keyPressEvent( e );
+}
+
+void OHistoryCombo::slotReset()
+{
+ myIterateIndex = -1;
+ myRotated = false;
+}
+
+
+void OHistoryCombo::setPixmapProvider( OPixmapProvider *prov )
+{
+ if ( myPixProvider == prov )
+ return;
+
+ delete myPixProvider;
+ myPixProvider = prov;
+
+ // re-insert all the items with/without pixmap
+ // I would prefer to use changeItem(), but that doesn't honour the pixmap
+ // when using an editable combobox (what we do)
+ if ( count() > 0 ) {
+ QStringList items( historyItems() );
+ clear();
+ insertItems( items );
+ }
+}
+
+void OHistoryCombo::insertItems( const QStringList& items )
+{
+ QStringList::ConstIterator it = items.begin();
+ QString item;
+ while ( it != items.end() ) {
+ item = *it;
+ if ( !item.isEmpty() ) { // only insert non-empty items
+ if ( myPixProvider )
+ // insertItem( myPixProvider->pixmapFor(item, OIcon::SizeSmall), item );
+ insertItem( myPixProvider->pixmapFor(item, 16), item );
+ else
+ insertItem( item );
+ }
+ ++it;
+ }
+}
+
+void OHistoryCombo::slotClear()
+{
+ clearHistory();
+ emit cleared();
+}
+
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 @@
+/*
+ This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ is part of the Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+ Opie Project Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
+
+ =. Originally part of the KDE projects
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OCOMBOBOX_H
+#define OCOMBOBOX_H
+
+/* QT */
+
+#include <qcombobox.h>
+
+/* OPIE */
+
+#include <opie2/olineedit.h>
+#include <opie2/ocompletion.h>
+#include <opie2/ocompletionbase.h>
+
+/* FORWARDS */
+
+class QListBoxItem;
+class QPopupMenu;
+class OCompletionBox;
+typedef QString OURL;
+
+/**
+ * A combined button, line-edit and a popup list widget.
+ *
+ * @sect Detail
+ *
+ * This widget inherits from @ref QComboBox and implements
+ * the following additional functionalities: a completion
+ * object that provides both automatic and manual text
+ * completion as well as text rotation features, configurable
+ * key-bindings to activate these features, and a popup-menu
+ * item that can be used to allow the user to set text completion
+ * modes on the fly based on their preference.
+ *
+ * To support these new features OComboBox also emits a few
+ * more additional signals as well. The main ones are the
+ * @ref completion( const QString& ) and @ref textRotation( KeyBindingType )
+ * signals. The completion signal is intended to be connected to a slot
+ * that will assist the user in filling out the remaining text while
+ * the rotation signals is intended to be used to traverse through all
+ * possible matches whenever text completion results in multiple matches.
+ * The @ref returnPressed() and @ref returnPressed( const QString& )
+ * signal is emitted when the user presses the Enter/Return key.
+ *
+ * This widget by default creates a completion object when you invoke
+ * the @ref completionObject( bool ) member function for the first time
+ * or use @ref setCompletionObject( OCompletion*, bool ) to assign your
+ * own completion object. Additionally, to make this widget more functional,
+ * OComboBox will by default handle the text rotation and completion
+ * events internally whenever a completion object is created through either
+ * one of the methods mentioned above. If you do not need this functionality,
+ * simply use @ref OCompletionBase::setHandleSignals( bool ) or alternatively
+ * set the boolean parameter in the above methods to FALSE.
+ *
+ * The default key-bindings for completion and rotation is determined
+ * from the global settings in @ref OStdAccel. These values, however,
+ * can be overriden locally by invoking @ref OCompletionBase::setKeyBinding().
+ * The values can easily be reverted back to the default setting, by simply
+ * calling @ref useGlobalSettings(). An alternate method would be to default
+ * individual key-bindings by usning @ref setKeyBinding() with the default
+ * second argument.
+ *
+ * Note that if this widget is not editable ( i.e. select-only ), then only
+ * one completion mode, @p CompletionAuto, will work. All the other modes are
+ * simply ignored. The @p CompletionAuto mode in this case allows you to
+ * automatically select an item from the list by trying to match the pressed
+ * keycode with the first letter of the enteries in the combo box.
+ *
+ * @sect Useage
+ *
+ * To enable the basic completion feature:
+ *
+ * <pre>
+ * OComboBox *combo = new OComboBox( true, this, "mywidget" );
+ * OCompletion *comp = combo->completionObject();
+ * // Connect to the return pressed signal - optional
+ * connect(combo,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
+ * </pre>
+ *
+ * To use your own completion object:
+ *
+ * <pre>
+ * OComboBox *combo = new OComboBox( this,"mywidget" );
+ * OURLCompletion *comp = new OURLCompletion();
+ * combo->setCompletionObject( comp );
+ * // Connect to the return pressed signal - optional
+ * connect(combo,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
+ * </pre>
+ *
+ * Note that you have to either delete the allocated completion object
+ * when you don't need it anymore, or call
+ * setAutoDeleteCompletionObject( true );
+ *
+ * Miscellaneous function calls:
+ *
+ * <pre>
+ * // Tell the widget not to handle completion and rotation
+ * combo->setHandleSignals( false );
+ * // Set your own completion key for manual completions.
+ * combo->setKeyBinding( OCompletionBase::TextCompletion, Qt::End );
+ * // Hide the context (popup) menu
+ * combo->setContextMenuEnabled( false );
+ * // Temporarly disable signal emition
+ * combo->disableSignals();
+ * // Default the all key-bindings to their system-wide settings.
+ * combo->useGlobalKeyBindings();
+ * </pre>
+ *
+ * @short An enhanced combo box.
+ * @author Dawit Alemayehu <adawit@kde.org>
+ */
+class OComboBox : public QComboBox, public OCompletionBase
+{
+ Q_OBJECT
+
+ //Q_PROPERTY( bool autoCompletion READ autoCompletion WRITE setAutoCompletion )
+ //Q_PROPERTY( bool contextMenuEnabled READ isContextMenuEnabled WRITE setContextMenuEnabled )
+ //Q_PROPERTY( bool urlDropsEnabled READ isURLDropsEnabled WRITE setURLDropsEnabled )
+
+public:
+
+ /**
+ * Constructs a read-only or rather select-only combo box with a
+ * parent object and a name.
+ *
+ * @param parent The parent object of this widget
+ * @param name The name of this widget
+ */
+ OComboBox( QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Constructs a "read-write" or "read-only" combo box depending on
+ * the value of the first argument( @p rw ) with a parent, a
+ * name.
+ *
+ * @param rw When @p true, widget will be editable.
+ * @param parent The parent object of this widget.
+ * @param name The name of this widget.
+ */
+ OComboBox( bool rw, QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Destructor.
+ */
+ virtual ~OComboBox();
+
+ /**
+ * Sets @p url into the edit field of the combobox. It uses
+ * @ref OURL::prettyURL() so that the url is properly decoded for
+ * displaying.
+ */
+ //void setEditURL( const OURL& url );
+
+ /**
+ * Inserts @p url at position @p index into the combobox. The item will
+ * be appended if @p index is negative. @ref OURL::prettyURL() is used
+ * so that the url is properly decoded for displaying.
+ */
+ //void insertURL( const OURL& url, int index = -1 );
+
+ /**
+ * Inserts @p url with the pixmap &p pixmap at position @p index into
+ * the combobox. The item will be appended if @p index is negative.
+ * @ref OURL::prettyURL() is used so that the url is properly decoded
+ * for displaying.
+ */
+ //void insertURL( const QPixmap& pixmap, const OURL& url, int index = -1 );
+
+ /**
+ * Replaces the item at position @p index with @p url.
+ * @ref OURL::prettyURL() is used so that the url is properly decoded
+ * for displaying.
+ */
+ //void changeURL( const OURL& url, int index );
+
+ /**
+ * Replaces the item at position @p index with @p url and pixmap @p pixmap.
+ * @ref OURL::prettyURL() is used so that the url is properly decoded
+ * for displaying.
+ */
+ //void changeURL( const QPixmap& pixmap, const OURL& url, int index );
+
+ /**
+ * Returns the current cursor position.
+ *
+ * This method always returns a -1 if the combo-box is @em not
+ * editable (read-write).
+ *
+ * @return Current cursor position.
+ */
+ int cursorPosition() const { return ( lineEdit() ) ? lineEdit()->cursorPosition() : -1; }
+
+ /**
+ * Re-implemented from @ref QComboBox.
+ *
+ * If @p true, the completion mode will be set to automatic.
+ * Otherwise, it is defaulted to the global setting. This
+ * method has been replaced by the more comprehensive
+ * @ref setCompletionMode().
+ *
+ * @param autocomplete Flag to enable/disable automatic completion mode.
+ */
+ virtual void setAutoCompletion( bool autocomplete );
+
+ /**
+ * Re-implemented from QComboBox.
+ *
+ * Returns @p true if the current completion mode is set
+ * to automatic. See its more comprehensive replacement
+ * @ref completionMode().
+ *
+ * @return @p true when completion mode is automatic.
+ */
+ bool autoCompletion() const {
+ return completionMode() == OGlobalSettings::CompletionAuto;
+ }
+
+ /**
+ * Enables or disable the popup (context) menu.
+ *
+ * This method only works if this widget is editable, i.e.
+ * read-write and allows you to enable/disable the context
+ * menu. It does nothing if invoked for a none-editable
+ * combo-box. Note that by default the mode changer item
+ * is made visiable whenever the context menu is enabled.
+ * Use @ref hideModechanger() if you want to hide this
+ * item. Also by default, the context menu is created if
+ * this widget is editable. Call this function with the
+ * argument set to false to disable the popup menu.
+ *
+ * @param showMenu If @p true, show the context menu.
+ * @param showMode If @p true, show the mode changer.
+ */
+ virtual void setContextMenuEnabled( bool showMenu );
+
+ /**
+ * Returns @p true when the context menu is enabled.
+ */
+ bool isContextMenuEnabled() const { return m_bEnableMenu; }
+
+ /**
+ * Enables/Disables handling of URL drops. If enabled and the user
+ * drops an URL, the decoded URL will be inserted. Otherwise the default
+ * behaviour of QComboBox is used, which inserts the encoded URL.
+ *
+ * @param enable If @p true, insert decoded URLs
+ */
+ //void setURLDropsEnabled( bool enable );
+
+ /**
+ * Returns @p true when decoded URL drops are enabled
+ */
+ //bool isURLDropsEnabled() const;
+
+ /**
+ * Convenience method which iterates over all items and checks if
+ * any of them is equal to @p text.
+ *
+ * If @p text is an empty string, @p false
+ * is returned.
+ *
+ * @return @p true if an item with the string @p text is in the combobox.
+ */
+ bool contains( const QString& text ) const;
+
+ /**
+ * By default, OComboBox recognizes Key_Return and Key_Enter
+ * and emits
+ * the @ref returnPressed() signals, but it also lets the event pass,
+ * for example causing a dialog's default-button to be called.
+ *
+ * Call this method with @p trap equal to true to make OComboBox
+ * stop these
+ * events. The signals will still be emitted of course.
+ *
+ * Only affects read-writable comboboxes.
+ *
+ * @see setTrapReturnKey()
+ */
+ void setTrapReturnKey( bool trap );
+
+ /**
+ * @return @p true if keyevents of Key_Return or Key_Enter will
+ * be stopped or if they will be propagated.
+ *
+ * @see setTrapReturnKey ()
+ */
+ bool trapReturnKey() const;
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * @reimplemented
+ */
+ virtual bool eventFilter( QObject *, QEvent * );
+
+ /**
+ * @returns the completion-box, that is used in completion mode
+ * @ref OGlobalSettings::CompletionPopup and @ref OGlobalSettings::CompletionPopupAuto.
+ * This method will create a completion-box by calling
+ * @ref OLineEdit::completionBox, if none is there, yet.
+ *
+ * @param create Set this to false if you don't want the box to be created
+ * i.e. to test if it is available.
+ */
+ OCompletionBox * completionBox( bool create = true );
+
+ virtual void setLineEdit( OLineEdit * );
+
+signals:
+ /**
+ * Emitted when the user presses the Enter key.
+ *
+ * Note that this signal is only
+ * emitted if this widget is editable.
+ */
+ void returnPressed();
+
+ /**
+ * Emitted when the user presses
+ * the Enter key.
+ *
+ * The argument is the current
+ * text being edited. This signal is just like
+ * @ref returnPressed() except it contains the
+ * current text as its argument.
+ *
+ * Note that this signal is only emitted if this
+ * widget is editable.
+ */
+ void returnPressed( const QString& );
+
+ /**
+ * This signal is emitted when the completion key
+ * is pressed.
+ *
+ * The argument is the current text
+ * being edited.
+ *
+ * Note that this signal is @em not available if this
+ * widget is non-editable or the completion mode is
+ * set to @p OGlobalSettings::CompletionNone.
+ */
+ void completion( const QString& );
+
+ /**
+ * Emitted when the shortcut for substring completion is pressed.
+ */
+ void substringCompletion( const QString& );
+
+ /**
+ * Emitted when the text rotation key-bindings are pressed.
+ *
+ * The argument indicates which key-binding was pressed.
+ * In this case this can be either one of four values:
+ * @p PrevCompletionMatch, @p NextCompletionMatch, @p RotateUp or
+ * @p RotateDown. See @ref OCompletionBase::setKeyBinding() for
+ * details.
+ *
+ * Note that this signal is @em NOT emitted if the completion
+ * mode is set to CompletionNone.
+ */
+ void textRotation( OCompletionBase::KeyBindingType );
+
+ /**
+ * Emitted when the user changed the completion mode by using the
+ * popupmenu.
+ */
+ void completionModeChanged( OGlobalSettings::Completion );
+
+ /**
+ * Emitted before the context menu is displayed.
+ *
+ * The signal allows you to add your own entries into the
+ * the context menu that is created on demand.
+ *
+ * NOTE: Do not store the pointer to the QPopupMenu
+ * provided through since it is created and deleted
+ * on demand.
+ *
+ * @param the context menu about to be displayed
+ */
+ void aboutToShowContextMenu( QPopupMenu * );
+
+public slots:
+
+ /**
+ * Iterates through all possible matches of the completed text
+ * or the history list.
+ *
+ * Depending on the value of the argument, this function either
+ * iterates through the history list of this widget or the all
+ * possible matches in whenever multiple matches result from a
+ * text completion request. Note that the all-possible-match
+ * iteration will not work if there are no previous matches, i.e.
+ * no text has been completed and the *nix shell history list
+ * rotation is only available if the insertion policy for this
+ * widget is set either @p QComobBox::AtTop or @p QComboBox::AtBottom.
+ * For other insertion modes whatever has been typed by the user
+ * when the rotation event was initiated will be lost.
+ *
+ * @param type The key-binding invoked.
+ */
+ void rotateText( OCompletionBase::KeyBindingType /* type */ );
+
+ /**
+ * Sets the completed text in the line-edit appropriately.
+ *
+ * This function is an implementation for
+ * @ref OCompletionBase::setCompletedText.
+ */
+ virtual void setCompletedText( const QString& );
+
+ /**
+ * Sets @p items into the completion-box if @ref completionMode() is
+ * CompletionPopup. The popup will be shown immediately.
+ */
+ void setCompletedItems( const QStringList& items );
+
+ public:
+ /**
+ * Selects the first item that matches @p item. If there is no such item,
+ * it is inserted at position @p index if @p insert is true. Otherwise,
+ * no item is selected.
+ */
+ void setCurrentItem( const QString& item, bool insert = false, int index = -1 );
+ void setCurrentItem(int index);
+
+protected slots:
+
+ /**
+ * @deprecated.
+ */
+ virtual void itemSelected( QListBoxItem* ) {};
+
+ /**
+ * Completes text according to the completion mode.
+ *
+ * Note: this method is @p not invoked if the completion mode is
+ * set to CompletionNone. Also if the mode is set to @p CompletionShell
+ * and multiple matches are found, this method will complete the
+ * text to the first match with a beep to inidicate that there are
+ * more matches. Then any successive completion key event iterates
+ * through the remaining matches. This way the rotation functionality
+ * is left to iterate through the list as usual.
+ */
+ virtual void makeCompletion( const QString& );
+
+protected:
+ /*
+ * This function simply sets the lineedit text and
+ * highlights the text appropriately if the boolean
+ * value is set to true.
+ *
+ * @param
+ * @param
+ */
+ virtual void setCompletedText( const QString& /* */, bool /*marked*/ );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void create( WId = 0, bool initializeWindow = true,
+ bool destroyOldWindow = true );
+
+private:
+ // Constants that represent the ID's of the popup menu.
+ // TODO: See if we can replace this mess with OActionMenu
+ // in the future though this is working lovely.
+ enum MenuID {
+ Default=0,
+ Cut,
+ Copy,
+ Paste,
+ Clear,
+ Unselect,
+ SelectAll,
+ NoCompletion,
+ AutoCompletion,
+ ShellCompletion,
+ PopupCompletion,
+ SemiAutoCompletion
+ };
+
+ /**
+ * Initializes the variables upon construction.
+ */
+ void init();
+ /**
+ * Temporary functions to delete words back and foward until
+ * alternatives are available in QT3 (Seth Chaiklin, 21 may 2001)
+ */
+ void deleteWordBack();
+ void deleteWordForward();
+
+ bool m_bEnableMenu;
+
+ // indicating if we should stop return-key events from propagating
+ bool m_trapReturnKey;
+
+//protected:
+// virtual void virtual_hook( int id, void* data );
+private:
+ class OComboBoxPrivate;
+ OComboBoxPrivate *d;
+};
+
+
+class OPixmapProvider;
+
+/**
+ * A combobox which implements a history like a unix shell. You can navigate
+ * through all the items by using the Up or Down arrows (configurable of
+ * course). Additionally, weighted completion is available. So you should
+ * load and save the completion list to preserve the weighting between
+ * sessions.
+ *
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+ * @short A combobox for offering a history and completion
+ */
+class OHistoryCombo : public OComboBox
+{
+ Q_OBJECT
+ Q_PROPERTY( QStringList historyItems READ historyItems WRITE setHistoryItems )
+
+public:
+ /**
+ * Constructs a "read-write" combobox. A read-only history combobox
+ * doesn't make much sense, so it is only available as read-write.
+ * Completion will be used automatically for the items in the combo.
+ *
+ * The insertion-policy is set to NoInsertion, you have to add the items
+ * yourself via the slot @ref addToHistory. If you want every item added,
+ * use
+ *
+ * <pre>
+ * connect( combo, SIGNAL( activated( const QString& )),
+ * combo, SLOT( addToHistory( const QString& )));
+ * </pre>
+ *
+ * Use @ref QComboBox::setMaxCount() to limit the history.
+ *
+ * @p parent the parent object of this widget.
+ * @p name the name of this widget.
+ */
+ OHistoryCombo( QWidget *parent = 0L, const char *name = 0L );
+
+ // ### merge these two constructors
+ /**
+ * Same as the previous constructor, but additionally has the option
+ * to specify whether you want to let OHistoryCombo handle completion
+ * or not. If set to @p true, OHistoryCombo will sync the completion to the
+ * contents of the combobox.
+ */
+ OHistoryCombo( bool useCompletion,
+ QWidget *parent = 0L, const char *name = 0L );
+
+ /**
+ * Destructs the combo, the completion-object and the pixmap-provider
+ */
+ ~OHistoryCombo();
+
+ /**
+ * Inserts @p items into the combobox. @p items might get
+ * truncated if it is longer than @ref maxCount()
+ *
+ * @see #historyItems
+ */
+ inline void setHistoryItems( QStringList items ) {
+ setHistoryItems(items, false);
+ }
+
+ /**
+ * Inserts @p items into the combobox. @p items might get
+ * truncated if it is longer than @ref maxCount()
+ *
+ * Set @p setCompletionList to true, if you don't have a list of
+ * completions. This tells OHistoryCombo to use all the items for the
+ * completion object as well.
+ * You won't have the benefit of weighted completion though, so normally
+ * you should do something like
+ * <pre>
+ * OConfig *config = kapp->config();
+ * QStringList list;
+ *
+ * // load the history and completion list after creating the history combo
+ * list = config->readListEntry( "Completion list" );
+ * combo->completionObject()->setItems( list );
+ * list = config->readListEntry( "History list" );
+ * combo->setHistoryItems( list );
+ *
+ * [...]
+ *
+ * // save the history and completion list when the history combo is
+ * // destroyed
+ * list = combo->completionObject()->items()
+ * config->writeEntry( "Completion list", list );
+ * list = combo->historyItems();
+ * config->writeEntry( "History list", list );
+ * </pre>
+ *
+ * Be sure to use different names for saving with OConfig if you have more
+ * than one OHistoryCombo.
+ *
+ * Note: When @p setCompletionList is true, the items are inserted into the
+ * OCompletion object with mode OCompletion::Insertion and the mode is set
+ * to OCompletion::Weighted afterwards.
+ *
+ * @see #historyItems
+ * @see OComboBox::completionObject
+ * @see OCompletion::setItems
+ * @see OCompletion::items
+ */
+ void setHistoryItems( QStringList items, bool setCompletionList );
+
+ /**
+ * Returns the list of history items. Empty, when this is not a read-write
+ * combobox.
+ *
+ * @see #setHistoryItems
+ */
+ QStringList historyItems() const;
+
+ /**
+ * Removes all items named @p item.
+ *
+ * @return @p true if at least one item was removed.
+ *
+ * @see #addToHistory
+ */
+ bool removeFromHistory( const QString& item );
+
+ /**
+ * Sets a pixmap provider, so that items in the combobox can have a pixmap.
+ * @ref OPixmapProvider is just an abstract class with the one pure virtual
+ * method @ref OPixmapProvider::pixmapFor(). This method is called whenever
+ * an item is added to the OHistoryComboBox. Implement it to return your
+ * own custom pixmaps, or use the @ref OURLPixmapProvider from libkio,
+ * which uses @ref OMimeType::pixmapForURL to resolve icons.
+ *
+ * Set @p prov to 0L if you want to disable pixmaps. Default no pixmaps.
+ *
+ * @see #pixmapProvider
+ */
+ void setPixmapProvider( OPixmapProvider *prov );
+
+ /**
+ * @returns the current pixmap provider.
+ * @see #setPixmapProvider
+ * @see OPixmapProvider
+ */
+ OPixmapProvider * pixmapProvider() const { return myPixProvider; }
+
+ /**
+ * Resets the current position of the up/down history. Call this
+ * when you manually call @ref setCurrentItem() or @ref clearEdit().
+ */
+ void reset() { slotReset(); }
+
+public slots:
+ /**
+ * Adds an item to the end of the history list and to the completion list.
+ * If @ref maxCount() is reached, the first item of the list will be
+ * removed.
+ *
+ * If the last inserted item is the same as @p item, it will not be
+ * inserted again.
+ *
+ * If @ref duplicatesEnabled() is false, any equal existing item will be
+ * removed before @p item is added.
+ *
+ * Note: By using this method and not the Q and OComboBox insertItem()
+ * methods, you make sure that the combobox stays in sync with the
+ * completion. It would be annoying if completion would give an item
+ * not in the combobox, and vice versa.
+ *
+ * @see #removeFromHistory
+ * @see QComboBox::setDuplicatesEnabled
+ */
+ void addToHistory( const QString& item );
+
+ /**
+ * Clears the history and the completion list.
+ */
+ void clearHistory();
+
+signals:
+ /**
+ * Emitted when the history was cleared by the entry in the popup menu.
+ */
+ void cleared();
+
+protected:
+ /**
+ * Handling key-events, the shortcuts to rotate the items.
+ */
+ virtual void keyPressEvent( QKeyEvent * );
+
+
+ /**
+ * Inserts @p items into the combo, honouring @ref pixmapProvider()
+ * Does not update the completionObject.
+ *
+ * Note: @ref duplicatesEnabled() is not honored here.
+ *
+ * Called from @ref setHistoryItems() and @ref setPixmapProvider()
+ */
+ void insertItems( const QStringList& items );
+
+ /**
+ * @returns if we can modify the completion object or not.
+ */
+ bool useCompletion() const { return compObj() != 0L; }
+
+private slots:
+ /**
+ * Resets the iterate index to -1
+ */
+ void slotReset();
+
+ /**
+ * Called from the popupmenu,
+ * calls clearHistory() and emits cleared()
+ */
+ void slotClear();
+
+ /**
+ * Appends our own context menu entry.
+ */
+ void addContextMenuItems( QPopupMenu* );
+
+private:
+ void init( bool useCompletion );
+
+ /**
+ * The current position (index) in the combobox, used for Up and Down
+ */
+ int myIterateIndex;
+
+ /**
+ * The text typed before Up or Down was pressed.
+ */
+ QString myText;
+
+ /**
+ * Indicates that the user at least once rotated Up through the entire list
+ * Needed to allow going back after rotation.
+ */
+ bool myRotated;
+ OPixmapProvider *myPixProvider;
+
+private:
+ class OHistoryComboPrivate;
+ OHistoryComboPrivate *d;
+};
+
+
+#endif
+
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 @@
+/*
+ This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ is part of the Copyright (C) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
+ Opie Project Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de>
+ Copyright (C) 2000,2001 Dawit Alemayehu <adawit@kde.org>
+ =.
+ .=l. Originally part of the KDE Project
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include <qapplication.h>
+#include <qevent.h>
+#include <qstyle.h>
+
+#include <opie2/ocompletionbox.h>
+
+#define OListBox QListBox
+
+class OCompletionBox::OCompletionBoxPrivate
+{
+public:
+ QWidget *m_parent; // necessary to set the focus back
+ QString cancelText;
+ bool tabHandling;
+ bool down_workaround;
+};
+
+OCompletionBox::OCompletionBox( QWidget *parent, const char *name )
+ :OListBox( parent, name, WType_Popup )
+{
+ d = new OCompletionBoxPrivate;
+ d->m_parent = parent;
+ d->tabHandling = true;
+ d->down_workaround = false;
+
+ setColumnMode( 1 );
+ setLineWidth( 1 );
+ setFrameStyle( QFrame::Box | QFrame::Plain );
+
+ if ( parent )
+ setFocusProxy( parent );
+ else
+ setFocusPolicy( NoFocus );
+
+ setVScrollBarMode( Auto );
+ setHScrollBarMode( AlwaysOff );
+
+ connect( this, SIGNAL( doubleClicked( QListBoxItem * )),
+ SLOT( slotActivated( QListBoxItem * )) );
+
+ // grmbl, just QListBox workarounds :[ Thanks Volker.
+ connect( this, SIGNAL( currentChanged( QListBoxItem * )),
+ SLOT( slotCurrentChanged() ));
+ connect( this, SIGNAL( clicked( QListBoxItem * )),
+ SLOT( slotItemClicked( QListBoxItem * )) );
+}
+
+OCompletionBox::~OCompletionBox()
+{
+ d->m_parent = 0L;
+ delete d;
+}
+
+QStringList OCompletionBox::items() const
+{
+ QStringList list;
+ for ( uint i = 0; i < count(); i++ ) {
+ list.append( text( i ) );
+ }
+ return list;
+}
+
+void OCompletionBox::slotActivated( QListBoxItem *item )
+{
+ if ( !item )
+ return;
+
+ hide();
+ emit activated( item->text() );
+}
+
+bool OCompletionBox::eventFilter( QObject *o, QEvent *e )
+{
+ int type = e->type();
+
+ if ( o == d->m_parent ) {
+ if ( isVisible() ) {
+ if ( type == QEvent::KeyPress ) {
+ QKeyEvent *ev = static_cast<QKeyEvent *>( e );
+ switch ( ev->key() ) {
+ case Key_BackTab:
+ if ( d->tabHandling ) {
+ up();
+ ev->accept();
+ return true;
+ }
+ break;
+ case Key_Tab:
+ if ( d->tabHandling ) {
+ down(); // Only on TAB!!
+ ev->accept();
+ return true;
+ }
+ break;
+ case Key_Down:
+ down();
+ ev->accept();
+ return true;
+ case Key_Up:
+ up();
+ ev->accept();
+ return true;
+ case Key_Prior:
+ pageUp();
+ ev->accept();
+ return true;
+ case Key_Next:
+ pageDown();
+ ev->accept();
+ return true;
+ case Key_Escape:
+ cancelled();
+ ev->accept();
+ return true;
+ case Key_Enter:
+ case Key_Return:
+ if ( ev->state() & ShiftButton ) {
+ hide();
+ ev->accept(); // Consume the Enter event
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else if ( type == QEvent::AccelOverride ) {
+ // Override any acceleartors that match
+ // the key sequences we use here...
+ QKeyEvent *ev = static_cast<QKeyEvent *>( e );
+ switch ( ev->key() ) {
+ case Key_Tab:
+ case Key_BackTab:
+ case Key_Down:
+ case Key_Up:
+ case Key_Prior:
+ case Key_Next:
+ case Key_Escape:
+ case Key_Enter:
+ case Key_Return:
+ ev->accept();
+ return true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // parent loses focus or gets a click -> we hide
+ else if ( type == QEvent::FocusOut || type == QEvent::Resize ||
+ type == QEvent::Close || type == QEvent::Hide ||
+ type == QEvent::Move ) {
+ hide();
+ }
+ else if ( type == QEvent::Move )
+ move( d->m_parent->mapToGlobal(QPoint(0, d->m_parent->height())));
+ else if ( type == QEvent::Resize )
+ resize( sizeHint() );
+ }
+ }
+
+ // any mouse-click on something else than "this" makes us hide
+ else if ( type == QEvent::MouseButtonPress ) {
+ QMouseEvent *ev = static_cast<QMouseEvent *>( e );
+ if ( !rect().contains( ev->pos() )) // this widget
+ hide();
+ }
+
+ return OListBox::eventFilter( o, e );
+}
+
+
+void OCompletionBox::popup()
+{
+ if ( count() == 0 )
+ hide();
+ else {
+ ensureCurrentVisible();
+ bool block = signalsBlocked();
+ blockSignals( true );
+ setCurrentItem( 0 );
+ blockSignals( block );
+ clearSelection();
+ if ( !isVisible() )
+ show();
+ else if ( size().height() < sizeHint().height() )
+ resize( sizeHint() );
+ }
+}
+
+void OCompletionBox::show()
+{
+ resize( sizeHint() );
+
+ if ( d->m_parent )
+ {
+ //QDesktopWidget *screen = QApplication::desktop();
+ QWidget *screen = QApplication::desktop();
+
+ QPoint orig = d->m_parent->mapToGlobal( QPoint(0, d->m_parent->height()) );
+ int x = orig.x();
+ int y = orig.y();
+
+ if ( x + width() > screen->width() )
+ x = screen->width() - width();
+ if (y + height() > screen->height() )
+ y = y - height() - d->m_parent->height();
+
+ move( x, y);
+ qApp->installEventFilter( this );
+ }
+
+ // ### we shouldn't need to call this, but without this, the scrollbars
+ // are pretty b0rked.
+ //triggerUpdate( true );
+
+ OListBox::show();
+}
+
+void OCompletionBox::hide()
+{
+ if ( d->m_parent )
+ qApp->removeEventFilter( this );
+ d->cancelText = QString::null;
+ OListBox::hide();
+}
+
+QSize OCompletionBox::sizeHint() const
+{
+ int ih = itemHeight();
+ int h = QMIN( 15 * ih, (int) count() * ih ) +1;
+ h = QMAX( h, OListBox::minimumSizeHint().height() );
+
+ int w = (d->m_parent) ? d->m_parent->width() : OListBox::minimumSizeHint().width();
+ w = QMAX( OListBox::minimumSizeHint().width(), w );
+ return QSize( w, h );
+}
+
+void OCompletionBox::down()
+{
+ int i = currentItem();
+
+ if ( i == 0 && d->down_workaround ) {
+ d->down_workaround = false;
+ setCurrentItem( 0 );
+ setSelected( 0, true );
+ emit highlighted( currentText() );
+ }
+
+ else if ( i < (int) count() - 1 )
+ setCurrentItem( i + 1 );
+}
+
+void OCompletionBox::up()
+{
+ if ( currentItem() > 0 )
+ setCurrentItem( currentItem() - 1 );
+}
+
+void OCompletionBox::pageDown()
+{
+ int i = currentItem() + numItemsVisible();
+ i = i > (int)count() - 1 ? (int)count() - 1 : i;
+ setCurrentItem( i );
+}
+
+void OCompletionBox::pageUp()
+{
+ int i = currentItem() - numItemsVisible();
+ i = i < 0 ? 0 : i;
+ setCurrentItem( i );
+}
+
+void OCompletionBox::home()
+{
+ setCurrentItem( 0 );
+}
+
+void OCompletionBox::end()
+{
+ setCurrentItem( count() -1 );
+}
+
+void OCompletionBox::setTabHandling( bool enable )
+{
+ d->tabHandling = enable;
+}
+
+bool OCompletionBox::isTabHandling() const
+{
+ return d->tabHandling;
+}
+
+void OCompletionBox::setCancelledText( const QString& text )
+{
+ d->cancelText = text;
+}
+
+QString OCompletionBox::cancelledText() const
+{
+ return d->cancelText;
+}
+
+void OCompletionBox::cancelled()
+{
+ if ( !d->cancelText.isNull() )
+ emit userCancelled( d->cancelText );
+ if ( isVisible() )
+ hide();
+}
+
+class OCompletionBoxItem : public QListBoxItem
+{
+public:
+ void reuse( const QString &text ) { setText( text ); }
+};
+
+
+void OCompletionBox::insertItems( const QStringList& items, int index )
+{
+ bool block = signalsBlocked();
+ blockSignals( true );
+ insertStringList( items, index );
+ blockSignals( block );
+ d->down_workaround = true;
+}
+
+void OCompletionBox::setItems( const QStringList& items )
+{
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ QListBoxItem* item = firstItem();
+ if ( !item ) {
+ insertStringList( items );
+ }
+ else {
+ for ( QStringList::ConstIterator it = items.begin(); it != items.end(); it++) {
+ if ( item ) {
+ ((OCompletionBoxItem*)item)->reuse( *it );
+ item = item->next();
+ }
+ else {
+ insertItem( new QListBoxText( *it ) );
+ }
+ }
+ QListBoxItem* tmp = item;
+ while ( (item = tmp ) ) {
+ tmp = item->next();
+ delete item;
+ }
+ triggerUpdate( false );
+ }
+
+ blockSignals( block );
+ d->down_workaround = true;
+}
+
+void OCompletionBox::slotCurrentChanged()
+{
+ d->down_workaround = false;
+}
+
+void OCompletionBox::slotItemClicked( QListBoxItem *item )
+{
+ if ( item )
+ {
+ if ( d->down_workaround ) {
+ d->down_workaround = false;
+ emit highlighted( item->text() );
+ }
+
+ hide();
+ emit activated( item->text() );
+ }
+}
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 @@
+/*
+ This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ is part of the Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+ Opie Project Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de>
+
+ =. Originally part of the KDE Project
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OCOMPLETIONBOX_H
+#define OCOMPLETIONBOX_H
+
+class QEvent;
+#include <qstringlist.h>
+#include <qlistbox.h>
+
+// ML: Until we don't have an own OListBox, we use the QListBox
+#define OListBox QListBox
+
+/**
+ * A little utility class for "completion-widgets", like @ref OLineEdit or
+ * @ref OComboBox. OCompletionBox is a listbox, displayed as a rectangle without
+ * any window decoration, usually directly under the lineedit or combobox.
+ * It is filled with all possible matches for a completion, so the user
+ * can select the one he wants.
+ *
+ * It is used when OGlobalSettings::Completion == CompletionPopup or CompletionPopupAuto.
+ *
+ * @short A helper widget for "completion-widgets" (OLineEdit, OComboBox))
+ * @short Adapted for the Opie project by Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+ *
+ */
+class OCompletionBox : public OListBox
+{
+ Q_OBJECT
+ Q_PROPERTY( bool isTabHandling READ isTabHandling WRITE setTabHandling )
+ Q_PROPERTY(QString cancelledText READ cancelledText WRITE setCancelledText)
+
+public:
+ /**
+ * Constructs a OCompletionBox.
+ *
+ * Notice: the parent needs to be always 0L,
+ * so you can't specify it in the constructor. Because of that, Qt's
+ * auto-deletion does not take place, so you have to explicitly delete
+ * this widget when you don't need it anymore.
+ *
+ * The parent widget is used to give the focus back when pressing the
+ * up-button on the very first item.
+ */
+ OCompletionBox( QWidget *parent, const char *name = 0 );
+
+ /**
+ * Destroys the box
+ */
+ ~OCompletionBox();
+
+ virtual QSize sizeHint() const;
+
+public slots:
+ /**
+ * Returns a list of all items currently in the box.
+ */
+ QStringList items() const;
+
+ /**
+ * Inserts @p items into the box. Does not clear the items before.
+ * @p index determines at which position @p items will be inserted.
+ * (defaults to appending them at the end)
+ */
+ void insertItems( const QStringList& items, int index = -1 );
+
+ /**
+ * Clears the box and inserts @p items.
+ */
+ void setItems( const QStringList& items );
+
+ /**
+ * Adjusts the size of the box to fit the width of the parent given in the
+ * constructor and pops it up at the most appropriate place, relative to
+ * the parent.
+ *
+ * Depending on the screensize and the position of the parent, this may
+ * be a different place, however the default is to pop it up and the
+ * lower left corner of the parent.
+ *
+ * Make sure to hide() the box when appropriate.
+ */
+ virtual void popup();
+
+ /**
+ * Makes this widget (when visible) capture Tab-key events to traverse the
+ * items in the dropdown list.
+ *
+ * Default off, as it conflicts with the usual behavior of Tab to traverse
+ * widgets. It is useful for cases like Konqueror's Location Bar, though.
+ *
+ * @see #isTabHandling
+ */
+ void setTabHandling( bool enable );
+
+ /**
+ * @returns true if this widget is handling Tab-key events to traverse the
+ * items in the dropdown list, otherwise false.
+ *
+ * Default is false.
+ *
+ * @see #setTabHandling
+ */
+ bool isTabHandling() const;
+
+ /**
+ * Sets the text to be emitted if the user chooses not to
+ * pick from the available matches.
+ *
+ * If the cancelled text is not set through this function, the
+ * @ref userCancelled signal will not be emitted.
+ *
+ * @see userCancelled( const QString& )
+ * @param txt the text to be emitted if the user cancels this box
+ */
+ void setCancelledText( const QString& );
+
+ /**
+ * @returns the text set via @ref setCancelledText() or QString::null.
+ */
+ QString cancelledText() const;
+
+ /**
+ * Moves the selection one line down or select the first item if nothing is selected yet.
+ */
+ void down();
+
+ /**
+ * Moves the selection one line up or select the first item if nothing is selected yet.
+ */
+ void up();
+
+ /**
+ * Moves the selection one page down.
+ */
+ void pageDown();
+
+ /**
+ * Moves the selection one page up.
+ */
+ void pageUp();
+
+ /**
+ * Moves the selection up to the first item.
+ */
+ void home();
+
+ /**
+ * Moves the selection down to the last item.
+ */
+ void end();
+
+ /**
+ * Re-implemented for internal reasons. API is unaffected.
+ */
+ virtual void show();
+
+ /**
+ * Re-implemented for internal reasons. API is unaffected.
+ */
+ virtual void hide();
+
+signals:
+ /**
+ * Emitted when an item was selected, contains the text of
+ * the selected item.
+ */
+ void activated( const QString& );
+
+ /**
+ * Emitted whenever the user chooses to ignore the available
+ * selections and close the this box.
+ */
+ void userCancelled( const QString& );
+
+protected:
+ /**
+ * Reimplemented from OListBox to get events from the viewport (to hide
+ * this widget on mouse-click, Escape-presses, etc.
+ */
+ virtual bool eventFilter( QObject *, QEvent * );
+
+protected slots:
+ /**
+ * Called when an item was activated. Emits
+ * @ref activated() with the item.
+ */
+ virtual void slotActivated( QListBoxItem * );
+
+private slots:
+ void slotSetCurrentItem( QListBoxItem *i ) { setCurrentItem( i ); } // grrr
+ void slotCurrentChanged();
+ void cancelled();
+ void slotItemClicked( QListBoxItem * );
+
+private:
+ class OCompletionBoxPrivate;
+ OCompletionBoxPrivate* d;
+};
+
+
+#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 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org>
+ 2000, 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/* QT */
+
+#include <qstringlist.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qlistbox.h>
+#include <qwhatsthis.h>
+#include <qlabel.h>
+
+/* OPIE */
+
+#include <opie2/ocombobox.h>
+#include <opie2/odialog.h>
+#include <opie2/olineedit.h>
+#include <opie2/oeditlistbox.h>
+
+/* UNIX */
+
+#include <assert.h>
+
+/*======================================================================================
+ * OEditListBoxPrivate
+ *======================================================================================*/
+
+class OEditListBoxPrivate
+{
+public:
+ bool m_checkAtEntering;
+ int buttons;
+};
+
+/*======================================================================================
+ * OEditListBox
+ *======================================================================================*/
+
+OEditListBox::OEditListBox(QWidget *parent, const char *name,
+ bool checkAtEntering, int buttons )
+ :QGroupBox(parent, name )
+{
+ init( checkAtEntering, buttons );
+}
+
+OEditListBox::OEditListBox(const QString& title, QWidget *parent,
+ const char *name, bool checkAtEntering, int buttons)
+ :QGroupBox(title, parent, name )
+{
+ init( checkAtEntering, buttons );
+}
+
+OEditListBox::OEditListBox(const QString& title, const CustomEditor& custom,
+ QWidget *parent, const char *name,
+ bool checkAtEntering, int buttons)
+ :QGroupBox(title, parent, name )
+{
+ m_lineEdit = custom.lineEdit();
+ init( checkAtEntering, buttons, custom.representationWidget() );
+}
+
+OEditListBox::~OEditListBox()
+{
+ delete d;
+ d=0;
+}
+
+void OEditListBox::init( bool checkAtEntering, int buttons,
+ QWidget *representationWidget )
+{
+ d=new OEditListBoxPrivate;
+ d->m_checkAtEntering=checkAtEntering;
+ d->buttons = buttons;
+
+ int lostButtons = 0;
+ if ( (buttons & Add) == 0 )
+ lostButtons++;
+ if ( (buttons & Remove) == 0 )
+ lostButtons++;
+ if ( (buttons & UpDown) == 0 )
+ lostButtons += 2;
+
+
+ servNewButton = servRemoveButton = servUpButton = servDownButton = 0L;
+ setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,
+ QSizePolicy::MinimumExpanding));
+
+ QWidget * gb = this;
+ QGridLayout * grid = new QGridLayout(gb, 7 - lostButtons, 2,
+ ODialog::marginHint(),
+ ODialog::spacingHint());
+ grid->addRowSpacing(0, fontMetrics().lineSpacing());
+ for ( int i = 1; i < 7 - lostButtons; i++ )
+ grid->setRowStretch(i, 1);
+
+ grid->setMargin(15);
+
+ if ( representationWidget )
+ representationWidget->reparent( gb, QPoint(0,0) );
+ else
+ m_lineEdit=new OLineEdit(gb);
+
+ m_listBox = new QListBox(gb);
+
+ QWidget *editingWidget = representationWidget ?
+ representationWidget : m_lineEdit;
+ grid->addMultiCellWidget(editingWidget,1,1,0,1);
+ grid->addMultiCellWidget(m_listBox, 2, 6 - lostButtons, 0, 0);
+ int row = 2;
+ if ( buttons & Add ) {
+ servNewButton = new QPushButton(tr("&Add"), gb);
+ servNewButton->setEnabled(false);
+ connect(servNewButton, SIGNAL(clicked()), SLOT(addItem()));
+
+ grid->addWidget(servNewButton, row++, 1);
+ }
+
+ if ( buttons & Remove ) {
+ servRemoveButton = new QPushButton(tr("&Remove"), gb);
+ servRemoveButton->setEnabled(false);
+ connect(servRemoveButton, SIGNAL(clicked()), SLOT(removeItem()));
+
+ grid->addWidget(servRemoveButton, row++, 1);
+ }
+
+ if ( buttons & UpDown ) {
+ servUpButton = new QPushButton(tr("Move &Up"), gb);
+ servUpButton->setEnabled(false);
+ connect(servUpButton, SIGNAL(clicked()), SLOT(moveItemUp()));
+
+ servDownButton = new QPushButton(tr("Move &Down"), gb);
+ servDownButton->setEnabled(false);
+ connect(servDownButton, SIGNAL(clicked()), SLOT(moveItemDown()));
+
+ grid->addWidget(servUpButton, row++, 1);
+ grid->addWidget(servDownButton, row++, 1);
+ }
+
+ connect(m_lineEdit,SIGNAL(textChanged(const QString&)),this,SLOT(typedSomething(const QString&)));
+ m_lineEdit->setTrapReturnKey(true);
+ connect(m_lineEdit,SIGNAL(returnPressed()),this,SLOT(addItem()));
+ connect(m_listBox, SIGNAL(highlighted(int)), SLOT(enableMoveButtons(int)));
+
+ // maybe supplied lineedit has some text already
+ typedSomething( m_lineEdit->text() );
+}
+
+void OEditListBox::typedSomething(const QString& text)
+{
+ if(currentItem() >= 0) {
+ if(currentText() != m_lineEdit->text())
+ {
+ // IMHO changeItem() shouldn't do anything with the value
+ // of currentItem() ... like changing it or emitting signals ...
+ // but TT disagree with me on this one (it's been that way since ages ... grrr)
+ bool block = m_listBox->signalsBlocked();
+ m_listBox->blockSignals( true );
+ m_listBox->changeItem(text, currentItem());
+ m_listBox->blockSignals( block );
+ emit changed();
+ }
+ }
+
+ if ( !servNewButton )
+ return;
+
+ if (!d->m_checkAtEntering)
+ servNewButton->setEnabled(!text.isEmpty());
+ else
+ {
+ if (text.isEmpty())
+ {
+ servNewButton->setEnabled(false);
+ }
+ else
+ {
+ #if QT_VERSION > 290
+ StringComparisonMode mode = (StringComparisonMode) (ExactMatch | CaseSensitive );
+ bool enable = (m_listBox->findItem( text, mode ) == 0L);
+ #else
+ bool enable = (m_listBox->findItem( text ) == 0L);
+ #endif
+ servNewButton->setEnabled( enable );
+ }
+ }
+}
+
+void OEditListBox::moveItemUp()
+{
+ if (!m_listBox->isEnabled())
+ {
+ //ONotifyClient::beep();
+ return;
+ }
+
+ unsigned int selIndex = m_listBox->currentItem();
+ if (selIndex == 0)
+ {
+ //ONotifyClient::beep();
+ return;
+ }
+
+ QListBoxItem *selItem = m_listBox->item(selIndex);
+ m_listBox->takeItem(selItem);
+ m_listBox->insertItem(selItem, selIndex-1);
+ m_listBox->setCurrentItem(selIndex - 1);
+
+ emit changed();
+}
+
+void OEditListBox::moveItemDown()
+{
+ if (!m_listBox->isEnabled())
+ {
+ //ONotifyClient::beep();
+ return;
+ }
+
+ unsigned int selIndex = m_listBox->currentItem();
+ if (selIndex == m_listBox->count() - 1)
+ {
+ //ONotifyClient::beep();
+ return;
+ }
+
+ QListBoxItem *selItem = m_listBox->item(selIndex);
+ m_listBox->takeItem(selItem);
+ m_listBox->insertItem(selItem, selIndex+1);
+ m_listBox->setCurrentItem(selIndex + 1);
+
+ emit changed();
+}
+
+void OEditListBox::addItem()
+{
+ // when m_checkAtEntering is true, the add-button is disabled, but this
+ // slot can still be called through Key_Return/Key_Enter. So we guard
+ // against this.
+ if ( !servNewButton || !servNewButton->isEnabled() )
+ return;
+
+ const QString& currentTextLE=m_lineEdit->text();
+ bool alreadyInList(false);
+ //if we didn't check for dupes at the inserting we have to do it now
+ if (!d->m_checkAtEntering)
+ {
+ // first check current item instead of dumb iterating the entire list
+ if ( m_listBox->currentText() == currentTextLE )
+ alreadyInList = true;
+ else
+ {
+ #if QT_VERSION > 290
+ StringComparisonMode mode = (StringComparisonMode) (ExactMatch | CaseSensitive );
+ alreadyInList =(m_listBox->findItem(currentTextLE, mode) != 0);
+ #else
+ alreadyInList =(m_listBox->findItem(currentTextLE) != 0);
+ #endif
+ }
+ }
+
+ if ( servNewButton )
+ servNewButton->setEnabled(false);
+
+ bool block = m_lineEdit->signalsBlocked();
+ m_lineEdit->blockSignals(true);
+ m_lineEdit->clear();
+ m_lineEdit->blockSignals(block);
+
+ m_listBox->setSelected(currentItem(), false);
+
+ if (!alreadyInList)
+ {
+ block = m_listBox->signalsBlocked();
+ m_listBox->blockSignals( true );
+ m_listBox->insertItem(currentTextLE);
+ m_listBox->blockSignals( block );
+ emit changed();
+ emit added( currentTextLE );
+ }
+}
+
+int OEditListBox::currentItem() const
+{
+ int nr = m_listBox->currentItem();
+ #if QT_VERSION > 290
+ if(nr >= 0 && !m_listBox->item(nr)->isSelected()) return -1;
+ #else
+ if(nr >= 0 && !m_listBox->isSelected(m_listBox->item(nr))) return -1;
+ #endif
+ return nr;
+}
+
+void OEditListBox::removeItem()
+{
+ int selected = m_listBox->currentItem();
+
+ if ( selected >= 0 )
+ {
+ QString removedText = m_listBox->currentText();
+
+ m_listBox->removeItem( selected );
+ if ( count() > 0 )
+ m_listBox->setSelected( QMIN( selected, count() - 1 ), true );
+
+ emit changed();
+ emit removed( removedText );
+ }
+
+ if ( servRemoveButton && m_listBox->currentItem() == -1 )
+ servRemoveButton->setEnabled(false);
+}
+
+void OEditListBox::enableMoveButtons(int index)
+{
+ // Update the lineEdit when we select a different line.
+ if(currentText() != m_lineEdit->text())
+ m_lineEdit->setText(currentText());
+
+ bool moveEnabled = servUpButton && servDownButton;
+
+ if (moveEnabled )
+ {
+ if (m_listBox->count() <= 1)
+ {
+ servUpButton->setEnabled(false);
+ servDownButton->setEnabled(false);
+ }
+ else if ((uint) index == (m_listBox->count() - 1))
+ {
+ servUpButton->setEnabled(true);
+ servDownButton->setEnabled(false);
+ }
+ else if (index == 0)
+ {
+ servUpButton->setEnabled(false);
+ servDownButton->setEnabled(true);
+ }
+ else
+ {
+ servUpButton->setEnabled(true);
+ servDownButton->setEnabled(true);
+ }
+ }
+
+ if ( servRemoveButton )
+ servRemoveButton->setEnabled(true);
+}
+
+void OEditListBox::clear()
+{
+ m_lineEdit->clear();
+ m_listBox->clear();
+ emit changed();
+}
+
+void OEditListBox::insertStringList(const QStringList& list, int index)
+{
+ m_listBox->insertStringList(list,index);
+}
+
+void OEditListBox::insertStrList(const QStrList* list, int index)
+{
+ m_listBox->insertStrList(list,index);
+}
+
+void OEditListBox::insertStrList(const QStrList& list, int index)
+{
+ m_listBox->insertStrList(list,index);
+}
+
+void OEditListBox::insertStrList(const char ** list, int numStrings, int index)
+{
+ m_listBox->insertStrList(list,numStrings,index);
+}
+
+QStringList OEditListBox::items() const
+{
+ QStringList list;
+ for ( uint i = 0; i < m_listBox->count(); i++ )
+ list.append( m_listBox->text( i ));
+
+ return list;
+}
+
+void OEditListBox::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+
+/*======================================================================================
+ * CustomEditor
+ *======================================================================================*/
+
+OEditListBox::CustomEditor::CustomEditor( OComboBox *combo )
+{
+ m_representationWidget = combo;
+ m_lineEdit = dynamic_cast<OLineEdit*>( combo->lineEdit() );
+ assert( m_lineEdit );
+}
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 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef OEDITLISTBOX_H
+#define OEDITLISTBOX_H
+
+#include <qgroupbox.h>
+#include <qlistbox.h>
+
+class OLineEdit;
+class OComboBox;
+class QPushButton;
+
+#if QT_VERSION < 300
+ enum StringComparisonMode {
+ CaseSensitive = 0x00001, // 0 0001
+ BeginsWith = 0x00002, // 0 0010
+ EndsWith = 0x00004, // 0 0100
+ Contains = 0x00008, // 0 1000
+ ExactMatch = 0x00010 // 1 0000
+ };
+#endif
+
+class OEditListBoxPrivate;
+/**
+ * An editable listbox
+ *
+ * This class provides a editable listbox ;-), this means
+ * a listbox which is accompanied by a line edit to enter new
+ * items into the listbox and pushbuttons to add and remove
+ * items from the listbox and two buttons to move items up and down.
+ */
+class OEditListBox : public QGroupBox
+{
+ Q_OBJECT
+
+public:
+ /// @since 3.1
+ class CustomEditor
+ {
+ public:
+ CustomEditor()
+ : m_representationWidget( 0L ),
+ m_lineEdit( 0L ) {}
+ CustomEditor( QWidget *repWidget, OLineEdit *edit )
+ : m_representationWidget( repWidget ),
+ m_lineEdit( edit ) {}
+ CustomEditor( OComboBox *combo );
+
+ void setRepresentationWidget( QWidget *repWidget ) {
+ m_representationWidget = repWidget;
+ }
+ void setLineEdit( OLineEdit *edit ) {
+ m_lineEdit = edit;
+ }
+
+ virtual QWidget *representationWidget() const {
+ return m_representationWidget;
+ }
+ virtual OLineEdit *lineEdit() const {
+ return m_lineEdit;
+ }
+
+ protected:
+ QWidget *m_representationWidget;
+ OLineEdit *m_lineEdit;
+ };
+
+ public:
+
+ /**
+ * Enumeration of the buttons, the listbox offers. Specify them in the
+ * constructor in the buttons parameter.
+ */
+ enum Button { Add = 1, Remove = 2, UpDown = 4, All = Add|Remove|UpDown };
+
+ /**
+ * Create an editable listbox.
+ *
+ * If @p checkAtEntering is true, after every character you type
+ * in the line edit OEditListBox will enable or disable
+ * the Add-button, depending whether the current content of the
+ * line edit is already in the listbox. Maybe this can become a
+ * performance hit with large lists on slow machines.
+ * If @p checkAtEntering is false,
+ * it will be checked if you press the Add-button. It is not
+ * possible to enter items twice into the listbox.
+ */
+ OEditListBox(QWidget *parent = 0, const char *name = 0,
+ bool checkAtEntering=false, int buttons = All );
+ /**
+ * Create an editable listbox.
+ *
+ * The same as the other constructor, additionally it takes
+ * @title, which will be the title of the frame around the listbox.
+ */
+ OEditListBox(const QString& title, QWidget *parent = 0,
+ const char *name = 0, bool checkAtEntering=false,
+ int buttons = All );
+
+ /**
+ * Another constructor, which allows to use a custom editing widget
+ * instead of the standard OLineEdit widget. E.g. you can use a
+ * @ref OURLRequester or a @ref OComboBox as input widget. The custom
+ * editor must consist of a lineedit and optionally another widget that
+ * is used as representation. A OComboBox or a OURLRequester have a
+ * OLineEdit as child-widget for example, so the OComboBox is used as
+ * the representation widget.
+ *
+ * @see OURLRequester::customEditor()
+ * @since 3.1
+ */
+ OEditListBox( const QString& title,
+ const CustomEditor &customEditor,
+ QWidget *parent = 0, const char *name = 0,
+ bool checkAtEntering = false, int buttons = All );
+
+ virtual ~OEditListBox();
+
+ /**
+ * Return a pointer to the embedded QListBox.
+ */
+ QListBox* listBox() const { return m_listBox; }
+ /**
+ * Return a pointer to the embedded QLineEdit.
+ */
+ OLineEdit* lineEdit() const { return m_lineEdit; }
+ /**
+ * Return a pointer to the Add button
+ */
+ QPushButton* addButton() const { return servNewButton; }
+ /**
+ * Return a pointer to the Remove button
+ */
+ QPushButton* removeButton() const { return servRemoveButton; }
+ /**
+ * Return a pointer to the Up button
+ */
+ QPushButton* upButton() const { return servUpButton; }
+ /**
+ * Return a pointer to the Down button
+ */
+ QPushButton* downButton() const { return servDownButton; }
+
+ /**
+ * See @ref QListBox::count()
+ */
+ int count() const { return int(m_listBox->count()); }
+ /**
+ * See @ref QListBox::insertStringList()
+ */
+ void insertStringList(const QStringList& list, int index=-1);
+ /**
+ * See @ref QListBox::insertStringList()
+ */
+ void insertStrList(const QStrList* list, int index=-1);
+ /**
+ * See @ref QListBox::insertStrList()
+ */
+ void insertStrList(const QStrList& list, int index=-1);
+ /**
+ * See @ref QListBox::insertStrList()
+ */
+ void insertStrList(const char ** list, int numStrings=-1, int index=-1);
+ /**
+ * See @ref QListBox::insertItem()
+ */
+ void insertItem(const QString& text, int index=-1) {m_listBox->insertItem(text,index);}
+ /**
+ * Clears both the listbox and the line edit.
+ */
+ void clear();
+ /**
+ * See @ref QListBox::text()
+ */
+ QString text(int index) const { return m_listBox->text(index); }
+ /**
+ * See @ref QListBox::currentItem()
+ */
+ int currentItem() const;
+ /**
+ * See @ref QListBox::currentText()
+ */
+ QString currentText() const { return m_listBox->currentText(); }
+
+ /**
+ * @returns a stringlist of all items in the listbox
+ */
+ QStringList items() const;
+
+ signals:
+ void changed();
+
+ /**
+ * This signal is emitted when the user adds a new string to the list,
+ * the parameter is the added string.
+ * @since 3.2
+ */
+ void added( const QString & text );
+
+ /**
+ * This signal is emitted when the user removes a string from the list,
+ * the parameter is the removed string.
+ * @since 3.2
+ */
+ void removed( const QString & text );
+
+ protected slots:
+ //the names should be self-explaining
+ void moveItemUp();
+ void moveItemDown();
+ void addItem();
+ void removeItem();
+ void enableMoveButtons(int index);
+ void typedSomething(const QString& text);
+
+ private:
+ QListBox *m_listBox;
+ QPushButton *servUpButton, *servDownButton;
+ QPushButton *servNewButton, *servRemoveButton;
+ OLineEdit *m_lineEdit;
+
+ //this is called in both ctors, to avoid code duplication
+ void init( bool checkAtEntering, int buttons,
+ QWidget *representationWidget = 0L );
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ //our lovely private d-pointer
+ OEditListBoxPrivate *d;
+};
+
+#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 @@
+/*
+                 This file is part of the Opie Project
+
+ Originally part of the KDE project
+ (C) 1999-2000 Espen Sand (espensa@online.no)
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* QT */
+
+#include <qbitmap.h>
+#include <qgrid.h>
+#include <qhbox.h>
+#include <qheader.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qobjectlist.h>
+#include <qpixmap.h>
+#include <qlistview.h>
+#include <qsplitter.h>
+#include <qtabwidget.h>
+#include <qvbox.h>
+#include <qwidgetstack.h>
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qstyle.h>
+
+/* OPIE */
+
+#include <opie2/odialog.h>
+#include <opie2/oseparator.h>
+#include <opie2/ojanuswidget.h>
+
+/*======================================================================================
+ * IconListItem
+ *======================================================================================*/
+
+class OJanusWidget::IconListItem : public QListBoxItem
+{
+ public:
+ IconListItem( QListBox *listbox, const QPixmap &pixmap,
+ const QString &text );
+ virtual int height( const QListBox *lb ) const;
+ virtual int width( const QListBox *lb ) const;
+ int expandMinimumWidth( int width );
+
+ protected:
+ const QPixmap &defaultPixmap();
+ void paint( QPainter *painter );
+
+ private:
+ QPixmap mPixmap;
+ int mMinimumWidth;
+};
+
+template class QPtrList<QListViewItem>;
+
+/*======================================================================================
+ * OJanusWidget
+ *======================================================================================*/
+
+OJanusWidget::OJanusWidget( QWidget *parent, const char *name, int face )
+ : QWidget( parent, name, 0 ),
+ mValid(false), mPageList(0),
+ mTitleList(0), mFace(face), mTitleLabel(0), mActivePageWidget(0),
+ mShowIconsInTreeList(false), d(0)
+{
+ QVBoxLayout *topLayout = new QVBoxLayout( this );
+
+ if( mFace == TreeList || mFace == IconList )
+ {
+ mPageList = new QPtrList<QWidget>;
+ mTitleList = new QStringList();
+
+ QFrame *page;
+ if( mFace == TreeList )
+ {
+ QSplitter *splitter = new QSplitter( this );
+ topLayout->addWidget( splitter, 10 );
+ mTreeListResizeMode = QSplitter::KeepSize;
+
+ mTreeList = new QListView( splitter );
+ mTreeList->addColumn( QString::fromLatin1("") );
+ mTreeList->header()->hide();
+ mTreeList->setRootIsDecorated(true);
+ mTreeList->setSorting( -1 );
+ connect( mTreeList, SIGNAL(selectionChanged()), SLOT(slotShowPage()) );
+ connect( mTreeList, SIGNAL(clicked(QListViewItem *)), SLOT(slotItemClicked(QListViewItem *)));
+
+ //
+ // Page area. Title at top with a separator below and a pagestack using
+ // all available space at bottom.
+ //
+ QFrame *p = new QFrame( splitter );
+
+ QHBoxLayout *hbox = new QHBoxLayout( p, 0, 0 );
+ hbox->addSpacing( ODialog::spacingHint() );
+
+ page = new QFrame( p );
+ hbox->addWidget( page, 10 );
+ }
+ else
+ {
+ QHBoxLayout *hbox = new QHBoxLayout( topLayout );
+ mIconList = new IconListBox( this );
+
+ QFont listFont( mIconList->font() );
+ listFont.setBold( true );
+ mIconList->setFont( listFont );
+
+ mIconList->verticalScrollBar()->installEventFilter( this );
+ hbox->addWidget( mIconList );
+ connect( mIconList, SIGNAL(selectionChanged()), SLOT(slotShowPage()));
+ hbox->addSpacing( ODialog::spacingHint() );
+ page = new QFrame( this );
+ hbox->addWidget( page, 10 );
+ }
+
+ //
+ // Rest of page area. Title at top with a separator below and a
+ // pagestack using all available space at bottom.
+ //
+
+ QVBoxLayout *vbox = new QVBoxLayout( page, 0, ODialog::spacingHint() );
+
+ mTitleLabel = new QLabel( QString::fromLatin1("Empty page"), page, "OJanusWidgetTitleLabel" );
+ vbox->addWidget( mTitleLabel );
+
+ QFont titleFont( mTitleLabel->font() );
+ titleFont.setBold( true );
+ mTitleLabel->setFont( titleFont );
+
+ mTitleSep = new OSeparator( page );
+ mTitleSep->setFrameStyle( QFrame::HLine|QFrame::Plain );
+ vbox->addWidget( mTitleSep );
+
+ mPageStack = new QWidgetStack( page );
+ connect(mPageStack, SIGNAL(aboutToShow(QWidget *)),
+ this, SIGNAL(aboutToShowPage(QWidget *)));
+ vbox->addWidget( mPageStack, 10 );
+ }
+ else if( mFace == Tabbed )
+ {
+ mPageList = new QPtrList<QWidget>;
+
+ mTabControl = new QTabWidget( this );
+ mTabControl->setMargin (ODialog::marginHint());
+ topLayout->addWidget( mTabControl, 10 );
+ }
+ else if( mFace == Swallow )
+ {
+ mSwallowPage = new QWidget( this );
+ topLayout->addWidget( mSwallowPage, 10 );
+ }
+ else
+ {
+ mFace = Plain;
+ mPlainPage = new QFrame( this );
+ topLayout->addWidget( mPlainPage, 10 );
+ }
+
+ /* FIXME: Revise for Opie
+ if ( kapp )
+ connect(kapp,SIGNAL(kdisplayFontChanged()),SLOT(slotFontChanged()));
+ */
+
+ mValid = true;
+
+ setSwallowedWidget(0); // Set default size if 'mFace' is Swallow.
+}
+
+
+OJanusWidget::~OJanusWidget()
+{
+ delete mPageList;
+ mPageList = 0;
+ delete mTitleList;
+ mTitleList = 0;
+}
+
+
+bool OJanusWidget::isValid() const
+{
+ return( mValid );
+}
+
+
+QFrame *OJanusWidget::plainPage()
+{
+ return( mPlainPage );
+}
+
+
+int OJanusWidget::face() const
+{
+ return( mFace );
+}
+
+QWidget *OJanusWidget::FindParent()
+{
+ if( mFace == Tabbed ) {
+ return mTabControl;
+ }
+ else {
+ return this;
+ }
+}
+
+QFrame *OJanusWidget::addPage( const QStringList &items, const QString &header,
+ const QPixmap &pixmap )
+{
+ if( mValid == false )
+ {
+ qDebug( "addPage: Invalid object" );
+ return( 0 );
+ }
+
+ QFrame *page = new QFrame( FindParent(), "page" );
+ addPageWidget( page, items, header, pixmap );
+
+ return page;
+}
+
+void OJanusWidget::pageGone( QObject *obj )
+{
+ removePage( static_cast<QWidget*>( obj ) );
+}
+
+void OJanusWidget::slotReopen( QListViewItem * item )
+{
+ if( item )
+ item->setOpen( true );
+}
+
+QFrame *OJanusWidget::addPage( const QString &itemName, const QString &header,
+ const QPixmap &pixmap )
+{
+ QStringList items;
+ items << itemName;
+ return addPage(items, header, pixmap);
+}
+
+
+
+QVBox *OJanusWidget::addVBoxPage( const QStringList &items,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ if( mValid == false )
+ {
+ qDebug( "addPage: Invalid object" );
+ return( 0 );
+ }
+
+ QVBox *page = new QVBox(FindParent() , "page" );
+ page->setSpacing( ODialog::spacingHint() );
+ addPageWidget( page, items, header, pixmap );
+
+ return page;
+}
+
+QVBox *OJanusWidget::addVBoxPage( const QString &itemName,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ QStringList items;
+ items << itemName;
+ return addVBoxPage(items, header, pixmap);
+}
+
+QHBox *OJanusWidget::addHBoxPage( const QStringList &items,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ if( mValid == false ) {
+ qDebug( "addPage: Invalid object" );
+ return( 0 );
+ }
+
+ QHBox *page = new QHBox(FindParent(), "page");
+ page->setSpacing( ODialog::spacingHint() );
+ addPageWidget( page, items, header, pixmap );
+
+ return page;
+}
+
+QHBox *OJanusWidget::addHBoxPage( const QString &itemName,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ QStringList items;
+ items << itemName;
+ return addHBoxPage(items, header, pixmap);
+}
+
+QGrid *OJanusWidget::addGridPage( int n, Orientation dir,
+ const QStringList &items,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ if( mValid == false )
+ {
+ qDebug( "addPage: Invalid object" );
+ return( 0 );
+ }
+
+ QGrid *page = new QGrid( n, dir, FindParent(), "page" );
+ page->setSpacing( ODialog::spacingHint() );
+ addPageWidget( page, items, header, pixmap );
+
+ return page;
+}
+
+
+QGrid *OJanusWidget::addGridPage( int n, Orientation dir,
+ const QString &itemName,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ QStringList items;
+ items << itemName;
+ return addGridPage(n, dir, items, header, pixmap);
+}
+
+void OJanusWidget::InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page)
+{
+ bool isTop = true;
+ QListViewItem *curTop = 0, *child, *last, *newChild;
+ unsigned int index = 1;
+ QStringList curPath;
+
+ for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it, index++ ) {
+ QString name = (*it);
+ bool isPath = ( index != items.count() );
+
+ // Find the first child.
+ if (isTop) {
+ child = mTreeList->firstChild();
+ }
+ else {
+ child = curTop->firstChild();
+ }
+
+ // Now search for a child with the current Name, and if it we doesn't
+ // find it, then remember the location of the last child.
+ for (last = 0; child && child->text(0) != name ; last = child, child = child->nextSibling());
+
+ if (last == 0 && child == 0) {
+ // This node didn't have any children at all, lets just insert the
+ // new child.
+ if (isTop)
+ newChild = new QListViewItem(mTreeList, name);
+ else
+ newChild = new QListViewItem(curTop, name);
+
+ }
+ else if (child != 0) {
+ // we found the given name in this child.
+ if (!isPath) {
+ qDebug( "The element inserted was already in the TreeList box!" );
+ return;
+ }
+ else {
+ // Ok we found the folder
+ newChild = child;
+ }
+ }
+ else {
+ // the node had some children, but we didn't find the given name
+ if (isTop)
+ newChild = new QListViewItem(mTreeList, last, name);
+ else
+ newChild = new QListViewItem(curTop, last, name);
+ }
+
+ // Now make the element expandable if it is a path component, and make
+ // ready for next loop
+ if (isPath) {
+ newChild->setExpandable(true);
+ curTop = newChild;
+ isTop = false;
+ curPath << name;
+
+ QString key = curPath.join("_/_");
+ if (mFolderIconMap.contains(key)) {
+ QPixmap p = mFolderIconMap[key];
+ newChild->setPixmap(0,p);
+ }
+ }
+ else {
+ if (mShowIconsInTreeList) {
+ newChild->setPixmap(0, pixmap);
+ }
+ mTreeListToPageStack.insert(newChild, page);
+ }
+ }
+}
+
+void OJanusWidget::addPageWidget( QFrame *page, const QStringList &items,
+ const QString &header,const QPixmap &pixmap )
+{
+ connect(page, SIGNAL(destroyed(QObject*)), SLOT(pageGone(QObject*)));
+
+ if( mFace == Tabbed )
+ {
+ mTabControl->addTab (page, items.last());
+ mPageList->append (page);
+ }
+ else if( mFace == TreeList || mFace == IconList )
+ {
+ mPageList->append( page );
+ mPageStack->addWidget( page, 0 );
+
+ if (items.count() == 0) {
+ qDebug( "Invalid QStringList, with zero items" );
+ return;
+ }
+
+ if( mFace == TreeList )
+ {
+ InsertTreeListItem(items, pixmap, page);
+ }
+ else // mFace == IconList
+ {
+ QString itemName = items.last();
+ IconListItem *item = new IconListItem( mIconList, pixmap, itemName );
+ //
+ // 2000-06-01 Espen Sand: If I do this with Qt 2.1.1 all sorts of
+ // strange things happen. With Qt <= 2.1 it worked but now I must
+ // either specify the listbox in the constructor on the item
+ // or as below, not both.
+ // mIconList->insertItem( item );
+ //
+ mIconListToPageStack.insert(item, page);
+ mIconList->invalidateHeight();
+ mIconList->invalidateWidth();
+
+ if (mIconList->isVisible())
+ mIconList->updateWidth();
+ }
+
+ //
+ // Make sure the title label is sufficiently wide
+ //
+ QString lastName = items.last();
+ const QString &title = (header != QString::null ? header : lastName);
+ QRect r = mTitleLabel->fontMetrics().boundingRect( title );
+ if( mTitleLabel->minimumWidth() < r.width() )
+ {
+ mTitleLabel->setMinimumWidth( r.width() );
+ }
+ mTitleList->append( title );
+
+ if( mTitleList->count() == 1 )
+ {
+ showPage(0);
+ }
+ }
+ else
+ {
+ qDebug( "OJanusWidget::addPageWidget: can only add a page in Tabbed, TreeList or IconList modes" );
+ }
+
+}
+
+void OJanusWidget::setFolderIcon(const QStringList &path, const QPixmap &pixmap)
+{
+ QString key = path.join("_/_");
+ mFolderIconMap.insert(key,pixmap);
+}
+
+
+
+bool OJanusWidget::setSwallowedWidget( QWidget *widget )
+{
+ if( mFace != Swallow || mValid == false )
+ {
+ return( false );
+ }
+
+ //
+ // Remove current layout and make a new.
+ //
+ if( mSwallowPage->layout() != 0 )
+ {
+ delete mSwallowPage->layout();
+ }
+ QGridLayout *gbox = new QGridLayout( mSwallowPage, 1, 1, 0 );
+
+ //
+ // Hide old children
+ //
+ QObjectList *l = (QObjectList*)mSwallowPage->children(); // silence please
+ for( uint i=0; i < l->count(); i++ )
+ {
+ QObject *o = l->at(i);
+ if( o->isWidgetType() )
+ {
+ ((QWidget*)o)->hide();
+ }
+ }
+
+ //
+ // Add new child or make default size
+ //
+ if( widget == 0 )
+ {
+ gbox->addRowSpacing(0,100);
+ gbox->addColSpacing(0,100);
+ mSwallowPage->setMinimumSize(100,100);
+ }
+ else
+ {
+ if( widget->parent() != mSwallowPage )
+ {
+ widget->reparent( mSwallowPage, 0, QPoint(0,0) );
+ }
+ gbox->addWidget(widget, 0, 0 );
+ gbox->activate();
+ mSwallowPage->setMinimumSize( widget->minimumSize() );
+ }
+
+ return( true );
+}
+
+bool OJanusWidget::slotShowPage()
+{
+ if( mValid == false )
+ {
+ return( false );
+ }
+
+ if( mFace == TreeList )
+ {
+ QListViewItem *node = mTreeList->selectedItem();
+ if( node == 0 ) { return( false ); }
+
+ QWidget *stackItem = mTreeListToPageStack[node];
+ return showPage(stackItem);
+ }
+ else if( mFace == IconList )
+ {
+ QListBoxItem *node = mIconList->item( mIconList->currentItem() );
+ if( node == 0 ) { return( false ); }
+ QWidget *stackItem = mIconListToPageStack[node];
+ return showPage(stackItem);
+ }
+
+ return( false );
+}
+
+
+bool OJanusWidget::showPage( int index )
+{
+ if( mPageList == 0 || mValid == false )
+ {
+ return( false );
+ }
+ else
+ {
+ return showPage(mPageList->at(index));
+ }
+}
+
+
+bool OJanusWidget::showPage( QWidget *w )
+{
+ if( w == 0 || mValid == false )
+ {
+ return( false );
+ }
+
+ if( mFace == TreeList || mFace == IconList )
+ {
+ mPageStack->raiseWidget( w );
+ mActivePageWidget = w;
+
+ int index = mPageList->findRef( w );
+ mTitleLabel->setText( *mTitleList->at(index) );
+ if( mFace == TreeList )
+ {
+ QMap<QListViewItem *, QWidget *>::Iterator it;
+ for (it = mTreeListToPageStack.begin(); it != mTreeListToPageStack.end(); ++it){
+ QListViewItem *key = it.key();
+ QWidget *val = it.data();
+ if (val == w) {
+ mTreeList->setSelected(key, true );
+ break;
+ }
+ }
+ }
+ else
+ {
+ QMap<QListBoxItem *, QWidget *>::Iterator it;
+ for (it = mIconListToPageStack.begin(); it != mIconListToPageStack.end(); ++it){
+ QListBoxItem *key = it.key();
+ QWidget *val = it.data();
+ if (val == w) {
+ mIconList->setSelected( key, true );
+ break;
+ }
+ }
+
+ //
+ // 2000-02-13 Espen Sand
+ // Don't ask me why (because I don't know). If I select a page
+ // with the mouse the page is not updated until it receives an
+ // event. It seems this event get lost if the mouse is not moved
+ // when released. The timer ensures the update
+ //
+ QTimer::singleShot( 0, mActivePageWidget, SLOT(update()) );
+ }
+ }
+ else if( mFace == Tabbed )
+ {
+ mTabControl->showPage(w);
+ mActivePageWidget = w;
+ }
+ else
+ {
+ return( false );
+ }
+
+ return( true );
+}
+
+
+int OJanusWidget::activePageIndex() const
+{
+ if( mFace == TreeList) {
+ QListViewItem *node = mTreeList->selectedItem();
+ if( node == 0 ) { return -1; }
+ QWidget *stackItem = mTreeListToPageStack[node];
+ return mPageList->findRef(stackItem);
+ }
+ else if (mFace == IconList) {
+ QListBoxItem *node = mIconList->item( mIconList->currentItem() );
+ if( node == 0 ) { return( false ); }
+ QWidget *stackItem = mIconListToPageStack[node];
+ return mPageList->findRef(stackItem);
+ }
+ else if( mFace == Tabbed ) {
+ QWidget *widget = mTabControl->currentPage();
+ return( widget == 0 ? -1 : mPageList->findRef( widget ) );
+ }
+ else {
+ return( -1 );
+ }
+}
+
+
+int OJanusWidget::pageIndex( QWidget *widget ) const
+{
+ if( widget == 0 )
+ {
+ return( -1 );
+ }
+ else if( mFace == TreeList || mFace == IconList )
+ {
+ return( mPageList->findRef( widget ) );
+ }
+ else if( mFace == Tabbed )
+ {
+ //
+ // The user gets the real page widget with addVBoxPage(), addHBoxPage()
+ // and addGridPage() but not with addPage() which returns a child of
+ // the toplevel page. addPage() returns a QFrame so I check for that.
+ //
+ if( widget->isA("QFrame") )
+ {
+ return( mPageList->findRef( widget->parentWidget() ) );
+ }
+ else
+ {
+ return( mPageList->findRef( widget ) );
+ }
+ }
+ else
+ {
+ return( -1 );
+ }
+}
+
+void OJanusWidget::slotFontChanged()
+{
+#ifdef FIXME
+
+ if ( mTitleLabel != 0 )
+ {
+ mTitleLabel->setFont( KGlobalSettings::generalFont() );
+ QFont titleFont( mTitleLabel->font() );
+ titleFont.setBold( true );
+ mTitleLabel->setFont( titleFont );
+ }
+#endif
+
+ if( mFace == IconList )
+ {
+ QFont listFont( mIconList->font() );
+ listFont.setBold( true );
+ mIconList->setFont( listFont );
+ mIconList->invalidateHeight();
+ mIconList->invalidateWidth();
+ }
+}
+
+// makes the treelist behave like the list of kcontrol
+void OJanusWidget::slotItemClicked(QListViewItem *it)
+{
+ if(it && (it->childCount()>0))
+ it->setOpen(!it->isOpen());
+}
+
+void OJanusWidget::setFocus()
+{
+ if( mValid == false ) { return; }
+ if( mFace == TreeList )
+ {
+ mTreeList->setFocus();
+ }
+ if( mFace == IconList )
+ {
+ mIconList->setFocus();
+ }
+ else if( mFace == Tabbed )
+ {
+ mTabControl->setFocus();
+ }
+ else if( mFace == Swallow )
+ {
+ mSwallowPage->setFocus();
+ }
+ else if( mFace == Plain )
+ {
+ mPlainPage->setFocus();
+ }
+}
+
+
+QSize OJanusWidget::minimumSizeHint() const
+{
+ if( mFace == TreeList || mFace == IconList )
+ {
+ QSize s1( ODialog::spacingHint(), ODialog::spacingHint()*2 );
+ QSize s2(0,0);
+ QSize s3(0,0);
+ QSize s4( mPageStack->sizeHint() );
+
+ if( mFace == TreeList )
+ {
+#if QT_VERSION < 300
+ s1.rwidth() += style().splitterWidth();
+#else
+ s1.rwidth() += style().pixelMetric( QStyle::PM_SplitterWidth );
+#endif
+ s2 = mTreeList->minimumSize();
+ }
+ else
+ {
+ mIconList->updateMinimumHeight();
+ mIconList->updateWidth();
+ s2 = mIconList->minimumSize();
+ }
+
+ if( mTitleLabel->isVisible() == true )
+ {
+ s3 += mTitleLabel->sizeHint();
+ s3.rheight() += mTitleSep->minimumSize().height();
+ }
+
+ //
+ // Select the tallest item. It has only effect in IconList mode
+ //
+ int h1 = s1.rheight() + s3.rheight() + s4.height();
+ int h2 = QMAX( h1, s2.rheight() );
+
+ return( QSize( s1.width()+s2.width()+QMAX(s3.width(),s4.width()), h2 ) );
+ }
+ else if( mFace == Tabbed )
+ {
+ return( mTabControl->sizeHint() );
+ }
+ else if( mFace == Swallow )
+ {
+ return( mSwallowPage->minimumSize() );
+ }
+ else if( mFace == Plain )
+ {
+ return( mPlainPage->sizeHint() );
+ }
+ else
+ {
+ return( QSize( 100, 100 ) ); // Should never happen though.
+ }
+
+}
+
+
+QSize OJanusWidget::sizeHint() const
+{
+ return( minimumSizeHint() );
+}
+
+
+void OJanusWidget::setTreeListAutoResize( bool state )
+{
+ if( mFace == TreeList )
+ {
+ mTreeListResizeMode = state == false ?
+ QSplitter::KeepSize : QSplitter::Stretch;
+ QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget());
+ splitter->setResizeMode( mTreeList, mTreeListResizeMode );
+ }
+}
+
+
+void OJanusWidget::setIconListAllVisible( bool state )
+{
+ if( mFace == IconList )
+ {
+ mIconList->setShowAll( state );
+ }
+}
+
+void OJanusWidget::setShowIconsInTreeList( bool state )
+{
+ mShowIconsInTreeList = state;
+}
+
+void OJanusWidget::setRootIsDecorated( bool state )
+{
+ if( mFace == TreeList ) {
+ mTreeList->setRootIsDecorated(state);
+ }
+}
+
+void OJanusWidget::unfoldTreeList( bool persist )
+{
+ if( mFace == TreeList )
+ {
+ if( persist )
+ connect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) );
+ else
+ disconnect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) );
+
+ for( QListViewItem * item = mTreeList->firstChild(); item; item = item->itemBelow() )
+ item->setOpen( true );
+ }
+}
+
+void OJanusWidget::showEvent( QShowEvent * )
+{
+ if( mFace == TreeList )
+ {
+ QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget());
+ splitter->setResizeMode( mTreeList, mTreeListResizeMode );
+ }
+}
+
+
+//
+// 2000-13-02 Espen Sand
+// It should be obvious that this eventfilter must only be
+// be installed on the vertical scrollbar of the mIconList.
+//
+bool OJanusWidget::eventFilter( QObject *o, QEvent *e )
+{
+ if( e->type() == QEvent::Show )
+ {
+ IconListItem *item = (IconListItem*)mIconList->item(0);
+ if( item != 0 )
+ {
+ int lw = item->width( mIconList );
+ int sw = mIconList->verticalScrollBar()->sizeHint().width();
+ mIconList->setFixedWidth( lw+sw+mIconList->frameWidth()*2 );
+ }
+ }
+ else if( e->type() == QEvent::Hide )
+ {
+ IconListItem *item = (IconListItem*)mIconList->item(0);
+ if( item != 0 )
+ {
+ int lw = item->width( mIconList );
+ mIconList->setFixedWidth( lw+mIconList->frameWidth()*2 );
+ }
+ }
+ return QWidget::eventFilter( o, e );
+}
+
+
+
+//
+// Code for the icon list box
+//
+
+
+OJanusWidget::IconListBox::IconListBox( QWidget *parent, const char *name,
+ WFlags f )
+ :QListBox( parent, name, f ), mShowAll(false), mHeightValid(false),
+ mWidthValid(false)
+{
+}
+
+
+void OJanusWidget::IconListBox::updateMinimumHeight()
+{
+ if( mShowAll == true && mHeightValid == false )
+ {
+ int h = frameWidth()*2;
+ for( QListBoxItem *i = item(0); i != 0; i = i->next() )
+ {
+ h += i->height( this );
+ }
+ setMinimumHeight( h );
+ mHeightValid = true;
+ }
+}
+
+
+void OJanusWidget::IconListBox::updateWidth()
+{
+ if( mWidthValid == false )
+ {
+ int maxWidth = 10;
+ for( QListBoxItem *i = item(0); i != 0; i = i->next() )
+ {
+ int w = ((IconListItem *)i)->width(this);
+ maxWidth = QMAX( w, maxWidth );
+ }
+
+ for( QListBoxItem *i = item(0); i != 0; i = i->next() )
+ {
+ ((IconListItem *)i)->expandMinimumWidth( maxWidth );
+ }
+
+ if( verticalScrollBar()->isVisible() )
+ {
+ maxWidth += verticalScrollBar()->sizeHint().width();
+ }
+
+ setFixedWidth( maxWidth + frameWidth()*2 );
+ mWidthValid = true;
+ }
+}
+
+
+void OJanusWidget::IconListBox::invalidateHeight()
+{
+ mHeightValid = false;
+}
+
+
+void OJanusWidget::IconListBox::invalidateWidth()
+{
+ mWidthValid = false;
+}
+
+
+void OJanusWidget::IconListBox::setShowAll( bool showAll )
+{
+ mShowAll = showAll;
+ mHeightValid = false;
+}
+
+
+
+OJanusWidget::IconListItem::IconListItem( QListBox *listbox, const QPixmap &pixmap,
+ const QString &text )
+ : QListBoxItem( listbox )
+{
+ mPixmap = pixmap;
+ if( mPixmap.isNull() == true )
+ {
+ mPixmap = defaultPixmap();
+ }
+ setText( text );
+ mMinimumWidth = 0;
+}
+
+
+int OJanusWidget::IconListItem::expandMinimumWidth( int width )
+{
+ mMinimumWidth = QMAX( mMinimumWidth, width );
+ return( mMinimumWidth );
+}
+
+
+const QPixmap &OJanusWidget::IconListItem::defaultPixmap()
+{
+ static QPixmap *pix=0;
+ if( pix == 0 )
+ {
+ pix = new QPixmap( 32, 32 );
+ QPainter p( pix );
+ p.eraseRect( 0, 0, pix->width(), pix->height() );
+ p.setPen( Qt::red );
+ p.drawRect ( 0, 0, pix->width(), pix->height() );
+ p.end();
+
+ QBitmap mask( pix->width(), pix->height(), true );
+ mask.fill( Qt::black );
+ p.begin( &mask );
+ p.setPen( Qt::white );
+ p.drawRect ( 0, 0, pix->width(), pix->height() );
+ p.end();
+
+ pix->setMask( mask );
+ }
+ return( *pix );
+}
+
+
+void OJanusWidget::IconListItem::paint( QPainter *painter )
+{
+ QFontMetrics fm = painter->fontMetrics();
+ //int wt = fm.boundingRect(text()).width();
+ int wp = mPixmap.width();
+ int ht = fm.lineSpacing();
+ int hp = mPixmap.height();
+
+ painter->drawPixmap( (mMinimumWidth-wp)/2, 5, mPixmap );
+ if( text().isEmpty() == false )
+ {
+ painter->drawText( 0, hp+7, mMinimumWidth, ht, Qt::AlignCenter, text() );
+ }
+}
+
+int OJanusWidget::IconListItem::height( const QListBox *lb ) const
+{
+ if( text().isEmpty() == true )
+ {
+ return( mPixmap.height() );
+ }
+ else
+ {
+ return( mPixmap.height() + lb->fontMetrics().lineSpacing()+10 );
+ }
+}
+
+
+int OJanusWidget::IconListItem::width( const QListBox *lb ) const
+{
+ int wt = lb->fontMetrics().boundingRect(text()).width()+10;
+ int wp = mPixmap.width() + 10;
+ int w = QMAX( wt, wp );
+ return( QMAX( w, mMinimumWidth ) );
+}
+
+// Just remove the page from our stack of widgets. Do not modify the given widget in
+// any way. No memory leak occurs as parent is not changed.
+// Make this virtual in KDE 4.0.
+// Ravikiran Rajagopal <ravi@ee.eng.ohio-state.edu>
+void OJanusWidget::removePage( QWidget *page )
+{
+ if (!mPageList || !mPageList->containsRef(page))
+ return;
+
+ int index = mPageList->findRef( page );
+ if ( mTitleList )
+ mTitleList->remove(mTitleList->at(index));
+
+ mPageList->removeRef(page);
+
+ if ( mFace == TreeList )
+ {
+ QMap<QListViewItem*, QWidget *>::Iterator i;
+ for( i = mTreeListToPageStack.begin(); i != mTreeListToPageStack.end(); ++i )
+ if (i.data()==page)
+ {
+ delete i.key();
+ mPageStack->removeWidget(page);
+ mTreeListToPageStack.remove(i);
+ break;
+ }
+ }
+ else if ( mFace == IconList )
+ {
+ QMap<QListBoxItem*, QWidget *>::Iterator i;
+ for( i = mIconListToPageStack.begin(); i != mIconListToPageStack.end(); ++i )
+ if (i.data()==page)
+ {
+ delete i.key();
+ mPageStack->removeWidget(page);
+ mIconListToPageStack.remove(i);
+ break;
+ }
+ }
+ else // Tabbed
+ {
+ mTabControl->removePage(page);
+ }
+}
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 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ Copyright (C) 1999-2000 Espen Sand (espen@kde.org)
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OJANUSWIDGET_H
+#define OJANUSWIDGET_H
+
+#include <qptrlist.h>
+#include <qpixmap.h>
+#include <qlistbox.h>
+#include <qmap.h>
+#include <qsplitter.h>
+#include <qstringlist.h>
+
+class QGrid;
+class QHBox;
+class QLabel;
+class QTabWidget;
+class QVBox;
+class QWidgetStack;
+class OSeparator;
+class QListView;
+class QListViewItem;
+
+/**
+ * Provides a number of ready to use layouts (faces). It is used
+ * as an internal widget in @ref KDialogBase, but can also used as a
+ * widget of its own.
+ *
+ * It provides TreeList, IconList, Tabbed, Plain and Swallow layouts.
+ *
+ * The TreeList face provides a list in the left area and pages in the
+ * right. The area are separated by a movable splitter. The style is somewhat
+ * similar to the layout in the Control Center. A page is raised by
+ * selecting the corresponding tree list item.
+ *
+ * The IconList face provides an icon list in the left area and pages in the
+ * right. For each entry the Icon is on top with the text below. The style
+ * is somewhat similar to the layout of the Eudora configuation dialog box.
+ * A page is raised by selecting the corresponding icon list item. The
+ * preferred icon size is 32x32 pixels.
+ *
+ * The Tabbed face is a common tabbed widget. The procedure for creating a
+ * page is similar for creating a TreeList. This has the advantage that if
+ * your widget contain too many pages it is trivial to convert it into a
+ * TreeList. Just change the face in the KJanusWidget constructor to
+ * KJanusWidget::TreeList and you have a tree list layout instead.
+ *
+ * The Plain face provides an empty widget (QFrame) where you can place your
+ * widgets. The KJanusWidget makes no assumptions regarding the contents so
+ * you are free to add whatever you want.
+ *
+ * The Swallow face is provided in order to simplify the usage of existing
+ * widgets and to allow changing the visible widget. You specify the widget
+ * to be displayed by @ref #setSwallowedWidget(). Your widget will be
+ * reparented inside the widget. You can specify a Null (0) widget. A empty
+ * space is then displayed.
+ *
+ * For all modes it is important that you specify the @ref QWidget::minimumSize()
+ * on the page, plain widget or the swallowed widget. If you use a QLayout
+ * on the page, plain widget or the swallowed widget this will be taken care
+ * of automatically. The size is used when the KJanusWidget determines its
+ * own minimum size. You get the minimum size by using the
+ * @ref #minimumSizeHint() or @ref #sizeHint() methods.
+ *
+ * Pages that have been added in TreeList, IconList or Tabbed mode can be
+ * removed by simply deleting the page.
+ *
+ * @short Easy to use widget with many layouts
+ * @author Espen Sand (espen@kde.org)
+ */
+class OJanusWidget : public QWidget
+{
+ Q_OBJECT
+
+ private:
+
+ class IconListBox : public QListBox
+ {
+ public:
+ IconListBox( QWidget *parent=0, const char *name=0, WFlags f=0 );
+ void updateMinimumHeight();
+ void updateWidth();
+ void invalidateHeight();
+ void invalidateWidth();
+ void setShowAll( bool showAll );
+
+ private:
+ bool mShowAll;
+ bool mHeightValid;
+ bool mWidthValid;
+ };
+
+ public:
+
+ enum Face
+ {
+ TreeList = 0,
+ Tabbed,
+ Plain,
+ Swallow,
+ IconList
+ };
+
+ public:
+
+ /**
+ * Constructor where you specify the face.
+ *
+ * @param parent Parent of the widget.
+ * @param name Widget name.
+ * @param int face The kind of dialog, Use TreeList, Tabbed, Plain or
+ * Swallow.
+ */
+ OJanusWidget( QWidget *parent=0, const char *name=0, int face=Plain );
+
+ /**
+ * Destructor.
+ */
+ ~OJanusWidget();
+
+ /**
+ * Raises the page which was added by @ref addPage().
+ *
+ * @param index The index of the page you want to raise.
+ */
+ virtual bool showPage( int index );
+
+ /**
+ * Returns the index of the page that are currently displayed.
+ *
+ * @return The index or -1 if the face is not Tabbed, TreeList or
+ * IconList.
+ */
+ virtual int activePageIndex() const;
+
+ /**
+ * Use this to verify
+ * that no memory allocation failed.
+ *
+ * @return true if the widget was properly created.
+ */
+ virtual bool isValid() const;
+
+ /**
+ * Returns the face type.
+ *
+ * @return The face type.
+ */
+ virtual int face() const;
+
+ /**
+ * Returns the minimum size that must be made available for the widget
+ * so that UIs can be displayed properly
+ *
+ * @return The minimum size.
+ */
+ virtual QSize minimumSizeHint() const;
+
+ /**
+ * Returns the recommended size for the widget in order to be displayed
+ * properly.
+ *
+ * @return The recommended size.
+ */
+ virtual QSize sizeHint() const;
+
+ /**
+ * Returns the empty widget that is available in Plain mode.
+ *
+ * @return The widget or 0 if the face in not Plain.
+ */
+ virtual QFrame *plainPage();
+
+ /**
+ * Add a new page when the class is used in TreeList, IconList or Tabbed
+ * mode. The returned widget is empty and you must add your widgets
+ * as children to this widget. In most cases you must create a layout
+ * manager and associate it with this widget as well.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * @param item String used in the list or Tab item.
+ * @param header A longer string used in TreeList and IconList mode to
+ * describe the contents of a page. If empty, the item string
+ * will be used instead.
+ * @param pixmap Used in IconList mode or in TreeList mode. You should
+ * prefer a pixmap with size 32x32 pixels.
+ *
+ * @return The empty page or 0 if the face is not TreeList, IconList or
+ * Tabbed.
+ */
+ virtual QFrame *addPage(const QString &item,const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addPage just above, with the difference that the first
+ * element is a list of strings. These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the TreeList face. Later this may
+ * be added for the IconList face too. In other faces than the
+ * TreeList, all the strings except the last one is ignored.
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ **/
+ virtual QFrame *addPage(const QStringList &items, const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * Add a new page when the class is used in TreeList, IconList or Tabbed
+ * mode. The returned widget is empty and you must add your widgets
+ * as children to this widget. The returned widget is a @ref QVBox
+ * so it contains a QVBoxLayout layout that lines up the child widgets
+ * are vertically.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * @param item String used in the list or Tab item.
+ * @param header A longer string used in TreeList and IconList mode to
+ * describe the contents of a page. If empty, the item string
+ * will be used instead.
+ * @param pixmap Used in IconList mode or in TreeList mode. You should
+ * prefer a pixmap with size 32x32 pixels.
+ *
+ * @return The empty page or 0 if the face is not TreeList, IconList or
+ * Tabbed. */
+ virtual QVBox *addVBoxPage( const QString &item,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addVBoxPage just above, with the difference that the first
+ * element is a list of strings. These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the TreeList face. Later this may
+ * be added for the IconList face too. In other faces than the
+ * TreeList, all the strings except the last one is ignored.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ **/
+ virtual QVBox *addVBoxPage( const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * Add a new page when the class is used in TreeList, IconList or Tabbed
+ * mode. The returned widget is empty and you must add your widgets
+ * as children to this widget. The returned widget is a @ref QHBox
+ * so it contains a QHBoxLayout layout that lines up the child widgets
+ * are horizontally.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * @param item String used in the list or Tab item.
+ * @param header A longer string used in TreeList and IconList mode to
+ * describe the contents of a page. If empty, the item string
+ * will be used instead.
+ * @param pixmap Used in IconList mode or in TreeList mode. You should
+ * prefer a pixmap with size 32x32 pixels.
+ *
+ * @return The empty page or 0 if the face is not TreeList, IconList or
+ * Tabbed.
+ */
+ virtual QHBox *addHBoxPage( const QString &itemName,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addHBoxPage just above, with the difference that the first
+ * element is a list of strings. These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the TreeList face. Later this may
+ * be added for the IconList face too. In other faces than the
+ * TreeList, all the strings except the last one is ignored.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ **/
+ virtual QHBox *addHBoxPage( const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * Add a new page when the class is used in either TreeList or Tabbed
+ * mode. The returned widget is empty and you must add your widgets
+ * as children to this widget. The returned widget is a @ref QGrid
+ * so it contains a QGridLayout layout that places up the child widgets
+ * in a grid.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * @param n Specifies the number of columns if 'dir' is QGrid::Horizontal
+ * or the number of rows if 'dir' is QGrid::Vertical.
+ * @param dir Can be QGrid::Horizontal or QGrid::Vertical.
+ * @param item String used in the list or Tab item.
+ * @param header A longer string used in TreeList and IconList mode to
+ * describe the contents of a page. If empty, the item string
+ * will be used instead.
+ * @param pixmap Used in IconList mode or in TreeList mode. You should
+ * prefer a pixmap with size 32x32 pixels.
+ *
+ * @return The empty page or 0 if the face is not TreeList, IconList or
+ * Tabbed.
+ */
+ virtual QGrid *addGridPage( int n, Orientation dir,
+ const QString &itemName,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addGridPage just above, with the difference that the first
+ * element is a list of strings. These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the TreeList face. Later this may
+ * be added for the IconList face too. In other faces than the
+ * TreeList, all the strings except the last one is ignored.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ **/
+ virtual QGrid *addGridPage( int n, Orientation dir,
+ const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * @short Removes a page created with @ref addPage, @ref addVBoxPage,
+ * @ref addHBoxPage or @ref addGridPage. If the page has already
+ * been deleted or has already been removed, nothing happens. The widget
+ * itself is not deleted.
+ *
+ * @param page The widget returned by @ref addPage , @ref addVBoxPage ,
+ * @ref addHBoxPage or @ref addGridPage .
+ */
+ void removePage( QWidget *page );
+
+
+ /**
+ * Returns the index of a page created with @ref addPage ,
+ * @ref addVBoxPage , @ref addHBoxPage or @ref addGridPage .
+ * You can can compare this index with the value returned from
+ * @ref activePageIndex if you need to do some page specific actions
+ * in your code.
+ *
+ * The returned index will never change so you can safely use this
+ * function once and save the value.
+ *
+ * @param widget The widget returned by @ref addPage , @ref addVBoxPage ,
+ * @ref addHBoxPage or @ref addGridPage .
+ *
+ * @return The index or -1 if the face is not Tabbed, TreeList or
+ * IconList
+ */
+ virtual int pageIndex( QWidget *widget ) const;
+
+ /**
+ * Defines the widget to be swallowed.
+ *
+ * This method can be used several
+ * times. Only the latest defined widget will be shown.
+ *
+ * @param widget The widget to be swallowed. If 0, then an empty rectangle
+ * is displayed.
+ */
+ virtual bool setSwallowedWidget( QWidget *widget );
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * Defines how the tree list is resized when the widget is resized
+ * horizontally. By default the tree list keeps its width when the
+ * widget becomes wider.
+ *
+ * @param state The resize mode. If false (default) the TreeList keeps
+ * its current width when the widget becomes wider.
+ */
+ virtual void setTreeListAutoResize( bool state );
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * This tells the widgets whether the icons given in the @ref addPage,
+ * @ref addVBoxPage, @ref addHBoxPage, or @ref addGridPage methods should
+ * be shown in the TreeList.
+ *
+ * Note: This method must be called before calling any of the methods
+ * which add icons to the page.
+ *
+ * @param state If true the icons are shown.
+ **/
+ virtual void setShowIconsInTreeList(bool state);
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * This tells the widgets whether the root should be decorated.
+ * For details see @ref QListView::setRootIsDecorated
+ *
+ * @param state Root will be decorated if true.
+ **/
+ virtual void setRootIsDecorated( bool state );
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * This tells the TreeList to unfold the whole tree so that all entries
+ * are visible.
+ *
+ * If the list is empty when you call this method newly created entries
+ * will not automatically be opened. If the @p persist flag is set opened
+ * entries cannot be closed again, though.
+ *
+ * @param persist If true the tree always stays unfolded.
+ * @since 3.2
+ */
+ /*virtual*/ void unfoldTreeList( bool persist = false ); //### KDE4 BIC add virtual
+
+ /**
+ * This function has only effect in IconList mode.
+ *
+ * Defines how the icon list widget is displayed. By default it is
+ * the widgets in the pages that decide the minimum height
+ * of the toplevel widget. A vertical scrollbar can be used in
+ * the icon list area.
+ *
+ * @param state The visibility mode. If true, the minimum height is
+ * adjusted so that every icon in the list is visible at the
+ * same time. The vertical scrollbar will never be visible.
+ */
+ virtual void setIconListAllVisible( bool state );
+
+ /**
+ * Sets the icon used in TreeList Mode for the given path.
+ * @param path The path for which this icon should be shown.
+ * @param pixmap The icon used.
+ **/
+ virtual void setFolderIcon(const QStringList &path, const QPixmap &pixmap);
+
+ signals:
+ void aboutToShowPage(QWidget *page);
+
+ public slots:
+ /**
+ * Give the keyboard input focus to the widget.
+ */
+ virtual void setFocus();
+
+ protected:
+ /**
+ * Reimplemented to handle the splitter width when the the face
+ * is TreeList
+ */
+ virtual void showEvent( QShowEvent * );
+
+ /**
+ * This function is used internally when in IconList mode. If you
+ * reimplement this class a make your own event filter, make sure to
+ * call this function from your filter.
+ *
+ * @param o Object that has received an event.
+ * @param e The event.
+ */
+ virtual bool eventFilter( QObject *o, QEvent *e );
+
+ private slots:
+ bool slotShowPage();
+ void slotFontChanged();
+ void slotItemClicked(QListViewItem *it);
+ void pageGone(QObject *obj); // signal from the added page's "destroyed" signal
+ void slotReopen(QListViewItem *item);
+
+ protected:
+ bool showPage( QWidget *w );
+ void addPageWidget( QFrame *page, const QStringList &items,
+ const QString &header, const QPixmap &pixmap );
+ void InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page);
+ QWidget *FindParent();
+
+ private:
+ bool mValid;
+
+ QPtrList<QWidget> *mPageList;
+ QStringList *mTitleList;
+
+ int mFace;
+ QListView *mTreeList;
+ IconListBox *mIconList;
+ QWidgetStack *mPageStack;
+ QLabel *mTitleLabel;
+ QTabWidget *mTabControl;
+ QFrame *mPlainPage;
+ QWidget *mSwallowPage;
+ QWidget *mActivePageWidget;
+ OSeparator *mTitleSep;
+ QSplitter::ResizeMode mTreeListResizeMode;
+ bool mShowIconsInTreeList;
+ QMap<QListViewItem *, QWidget *> mTreeListToPageStack;
+ QMap<QListBoxItem *, QWidget *> mIconListToPageStack;
+ QMap<QString, QPixmap> mFolderIconMap;
+ QMap<QString, QStringList> mChildrenNames;
+ QMap<QString, QWidget *> mChildPages;
+
+ public:
+ class IconListItem;
+
+ private:
+ class OJanusWidgetPrivate;
+ OJanusWidgetPrivate *d;
+};
+
+#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 @@
+/*
+ This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ is part of the Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org>, Dawit Alemayehu <adawit@kde.org>
+ Opie Project Copyright (C) 1999 Preston Brown <pbrown@kde.org>, Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
+ Copyright (C) 1997 Sven Radej (sven.radej@iname.com)
+ =.
+ .=l. Originally part of the KDE Project
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* QT */
+
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qtimer.h>
+#include <qpopupmenu.h>
+
+/* OPIE */
+
+#include <opie2/ocompletionbox.h>
+#include <opie2/olineedit.h>
+#include <opie2/oglobalsettings.h>
+
+typedef QString KURL; //FIXME: Revise for Opie
+
+/*======================================================================================
+ * OLineEditPrivate
+ *======================================================================================*/
+
+class OLineEdit::OLineEditPrivate
+{
+public:
+ OLineEditPrivate()
+ {
+ grabReturnKeyEvents = false;
+ handleURLDrops = true;
+ completionBox = 0L;
+ }
+ ~OLineEditPrivate()
+ {
+ delete completionBox;
+ }
+
+ bool grabReturnKeyEvents;
+ bool handleURLDrops;
+ OCompletionBox *completionBox;
+};
+
+
+/*======================================================================================
+ * OLineEdit
+ *======================================================================================*/
+
+OLineEdit::OLineEdit( const QString &string, QWidget *parent, const char *name )
+ : QLineEdit( string, parent, name )
+{
+ init();
+}
+
+OLineEdit::OLineEdit( QWidget *parent, const char *name )
+ : QLineEdit( parent, name )
+{
+ init();
+}
+
+OLineEdit::~OLineEdit ()
+{
+ delete d;
+}
+
+void OLineEdit::init()
+{
+ d = new OLineEditPrivate;
+ possibleTripleClick = false;
+ // Enable the context menu by default.
+ setContextMenuEnabled( true );
+ //OCursor::setAutoHideCursor( this, true, true );
+ installEventFilter( this );
+}
+
+void OLineEdit::setCompletionMode( OGlobalSettings::Completion mode )
+{
+ OGlobalSettings::Completion oldMode = completionMode();
+ if ( oldMode != mode && oldMode == OGlobalSettings::CompletionPopup &&
+ d->completionBox && d->completionBox->isVisible() )
+ d->completionBox->hide();
+
+ // If the widgets echo mode is not Normal, no completion
+ // feature will be enabled even if one is requested.
+ if ( echoMode() != QLineEdit::Normal )
+ mode = OGlobalSettings::CompletionNone; // Override the request.
+
+ OCompletionBase::setCompletionMode( mode );
+}
+
+void OLineEdit::setCompletedText( const QString& t, bool marked )
+{
+ QString txt = text();
+ if ( t != txt )
+ {
+ int curpos = marked ? txt.length() : t.length();
+ validateAndSet( t, curpos, curpos, t.length() );
+ }
+}
+
+void OLineEdit::setCompletedText( const QString& text )
+{
+ OGlobalSettings::Completion mode = completionMode();
+ bool marked = ( mode == OGlobalSettings::CompletionAuto ||
+ mode == OGlobalSettings::CompletionMan ||
+ mode == OGlobalSettings::CompletionPopup );
+ setCompletedText( text, marked );
+}
+
+void OLineEdit::rotateText( OCompletionBase::KeyBindingType type )
+{
+ OCompletion* comp = compObj();
+ if ( comp &&
+ (type == OCompletionBase::PrevCompletionMatch ||
+ type == OCompletionBase::NextCompletionMatch ) )
+ {
+ QString input = (type == OCompletionBase::PrevCompletionMatch) ? comp->previousMatch() : comp->nextMatch();
+ // Skip rotation if previous/next match is null or the same text
+ if ( input.isNull() || input == displayText() )
+ return;
+ #if QT_VERSION > 290
+ setCompletedText( input, hasSelectedText() );
+ #else
+ setCompletedText( input, hasMarkedText() );
+ #endif
+ }
+}
+
+void OLineEdit::makeCompletion( const QString& text )
+{
+ OCompletion *comp = compObj();
+ if ( !comp )
+ return; // No completion object...
+
+ QString match = comp->makeCompletion( text );
+ OGlobalSettings::Completion mode = completionMode();
+ if ( mode == OGlobalSettings::CompletionPopup )
+ {
+ if ( match.isNull() )
+ {
+ if ( d->completionBox ) {
+ d->completionBox->hide();
+ d->completionBox->clear();
+ }
+ }
+ else
+ setCompletedItems( comp->allMatches() );
+ }
+ else
+ {
+ // all other completion modes
+ // If no match or the same match, simply return without completing.
+ if ( match.isNull() || match == text )
+ return;
+
+ setCompletedText( match );
+ }
+}
+
+void OLineEdit::setReadOnly(bool readOnly)
+{
+ QPalette p = palette();
+ if (readOnly)
+ {
+ QColor color = p.color(QPalette::Disabled, QColorGroup::Background);
+ p.setColor(QColorGroup::Base, color);
+ p.setColor(QColorGroup::Background, color);
+ }
+ else
+ {
+ QColor color = p.color(QPalette::Normal, QColorGroup::Base);
+ p.setColor(QColorGroup::Base, color);
+ p.setColor(QColorGroup::Background, color);
+ }
+ setPalette(p);
+
+ QLineEdit::setReadOnly (readOnly);
+}
+
+void OLineEdit::keyPressEvent( QKeyEvent *e )
+{
+ qDebug( "OLineEdit::keyPressEvent()" );
+
+ /*
+
+ KKey key( e );
+
+ if ( KStdAccel::copy().contains( key ) ) {
+ copy();
+ return;
+ }
+ else if ( KStdAccel::paste().contains( key ) ) {
+ paste();
+ return;
+ }
+ else if ( KStdAccel::cut().contains( key ) ) {
+ cut();
+ return;
+ }
+ else if ( KStdAccel::undo().contains( key ) ) {
+ undo();
+ return;
+ }
+ else if ( KStdAccel::redo().contains( key ) ) {
+ redo();
+ return;
+ }
+ else if ( KStdAccel::deleteWordBack().contains( key ) )
+ {
+ cursorWordBackward(TRUE);
+ if ( hasSelectedText() )
+ del();
+
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::deleteWordForward().contains( key ) )
+ {
+ // Workaround for QT bug where
+ cursorWordForward(TRUE);
+ if ( hasSelectedText() )
+ del();
+
+ e->accept();
+ return;
+ }
+ */
+
+ // Filter key-events if EchoMode is normal &
+ // completion mode is not set to CompletionNone
+ if ( echoMode() == QLineEdit::Normal &&
+ completionMode() != OGlobalSettings::CompletionNone )
+ {
+ KeyBindingMap keys = getKeyBindings();
+ OGlobalSettings::Completion mode = completionMode();
+ bool noModifier = (e->state() == NoButton || e->state()== ShiftButton);
+
+ if ( (mode == OGlobalSettings::CompletionAuto ||
+ mode == OGlobalSettings::CompletionMan) && noModifier )
+ {
+ QString keycode = e->text();
+ if ( !keycode.isNull() && keycode.unicode()->isPrint() )
+ {
+ QLineEdit::keyPressEvent ( e );
+ QString txt = text();
+ int len = txt.length();
+ #if QT_VERSION > 290
+ if ( !hasSelectedText() && len && cursorPosition() == len )
+ #else
+ if ( !hasMarkedText() && len && cursorPosition() == len )
+ #endif
+ {
+ if ( emitSignals() )
+ emit completion( txt );
+ if ( handleSignals() )
+ makeCompletion( txt );
+ e->accept();
+ }
+ return;
+ }
+ }
+
+ else if ( mode == OGlobalSettings::CompletionPopup && noModifier )
+ {
+ qDebug( "OLineEdit::keyPressEvent() - global settings = CompletionPopup & noModifier" );
+
+ QString old_txt = text();
+ QLineEdit::keyPressEvent ( e );
+ QString txt = text();
+ int len = txt.length();
+ QString keycode = e->text();
+
+
+ if ( txt != old_txt && len && cursorPosition() == len &&
+ ( (!keycode.isNull() && keycode.unicode()->isPrint()) ||
+ e->key() == Key_Backspace ) )
+ {
+ if ( emitSignals() )
+ emit completion( txt ); // emit when requested...
+ if ( handleSignals() )
+ makeCompletion( txt ); // handle when requested...
+ e->accept();
+ }
+ else if (!len && d->completionBox && d->completionBox->isVisible())
+ d->completionBox->hide();
+
+ return;
+ }
+
+ /*else if ( mode == OGlobalSettings::CompletionShell )
+ {
+ // Handles completion.
+ KShortcut cut;
+ if ( keys[TextCompletion].isNull() )
+ cut = KStdAccel::shortcut(KStdAccel::TextCompletion);
+ else
+ cut = keys[TextCompletion];
+
+ if ( cut.contains( key ) )
+ {
+ // Emit completion if the completion mode is CompletionShell
+ // and the cursor is at the end of the string.
+ QString txt = text();
+ int len = txt.length();
+ if ( cursorPosition() == len && len != 0 )
+ {
+ if ( emitSignals() )
+ emit completion( txt );
+ if ( handleSignals() )
+ makeCompletion( txt );
+ return;
+ }
+ }
+ else if ( d->completionBox )
+ d->completionBox->hide();
+ }
+
+ // handle rotation
+ if ( mode != OGlobalSettings::CompletionNone )
+ {
+ // Handles previous match
+ KShortcut cut;
+ if ( keys[PrevCompletionMatch].isNull() )
+ cut = KStdAccel::shortcut(KStdAccel::PrevCompletion);
+ else
+ cut = keys[PrevCompletionMatch];
+
+ if ( cut.contains( key ) )
+ {
+ if ( emitSignals() )
+ emit textRotation( OCompletionBase::PrevCompletionMatch );
+ if ( handleSignals() )
+ rotateText( OCompletionBase::PrevCompletionMatch );
+ return;
+ }
+
+ // Handles next match
+ if ( keys[NextCompletionMatch].isNull() )
+ cut = KStdAccel::key(KStdAccel::NextCompletion);
+ else
+ cut = keys[NextCompletionMatch];
+
+ if ( cut.contains( key ) )
+ {
+ if ( emitSignals() )
+ emit textRotation( OCompletionBase::NextCompletionMatch );
+ if ( handleSignals() )
+ rotateText( OCompletionBase::NextCompletionMatch );
+ return;
+ }
+ }
+
+ // substring completion
+ if ( compObj() )
+ {
+ KShortcut cut;
+ if ( keys[SubstringCompletion].isNull() )
+ cut = KStdAccel::shortcut(KStdAccel::SubstringCompletion);
+ else
+ cut = keys[SubstringCompletion];
+
+ if ( cut.contains( key ) )
+ {
+ if ( emitSignals() )
+ emit substringCompletion( text() );
+ if ( handleSignals() )
+ {
+ setCompletedItems( compObj()->substringCompletion(text()));
+ e->accept();
+ }
+ return;
+ }
+ } */
+ }
+
+ // Let QLineEdit handle any other keys events.
+ QLineEdit::keyPressEvent ( e );
+}
+
+void OLineEdit::mouseDoubleClickEvent( QMouseEvent* e )
+{
+ if ( e->button() == Qt::LeftButton )
+ {
+ possibleTripleClick=true;
+ QTimer::singleShot( QApplication::doubleClickInterval(),this,
+ SLOT(tripleClickTimeout()) );
+ }
+ QLineEdit::mouseDoubleClickEvent( e );
+}
+
+void OLineEdit::mousePressEvent( QMouseEvent* e )
+{
+ if ( possibleTripleClick && e->button() == Qt::LeftButton )
+ {
+ selectAll();
+ return;
+ }
+ QLineEdit::mousePressEvent( e );
+}
+
+void OLineEdit::tripleClickTimeout()
+{
+ possibleTripleClick=false;
+}
+
+QPopupMenu *OLineEdit::createPopupMenu()
+{
+ // Return if popup menu is not enabled !!
+ if ( !m_bEnableMenu )
+ return 0;
+
+ #if QT_VERSION > 290
+ QPopupMenu *popup = QLineEdit::createPopupMenu();
+ #else
+ QPopupMenu *popup = new QPopupMenu();
+ #warning OLineEdit is not fully functional on Qt2
+ #endif
+
+ // completion object is present.
+ if ( compObj() )
+ {
+ QPopupMenu *subMenu = new QPopupMenu( popup );
+ connect( subMenu, SIGNAL( activated( int ) ),
+ this, SLOT( completionMenuActivated( int ) ) );
+
+ popup->insertSeparator();
+ //popup->insertItem( SmallIconSet("completion"), i18n("Text Completion"),
+ // subMenu );
+
+ popup->insertItem( tr("Text Completion"), subMenu );
+
+ subMenu->insertItem( tr("None"), NoCompletion );
+ subMenu->insertItem( tr("Manual"), ShellCompletion );
+ subMenu->insertItem( tr("Automatic"), AutoCompletion );
+ subMenu->insertItem( tr("Dropdown List"), PopupCompletion );
+ subMenu->insertItem( tr("Short Automatic"), SemiAutoCompletion );
+
+ //subMenu->setAccel( KStdAccel::completion(), ShellCompletion );
+ subMenu->setAccel( Key_Tab, ShellCompletion );
+
+ OGlobalSettings::Completion mode = completionMode();
+ subMenu->setItemChecked( NoCompletion,
+ mode == OGlobalSettings::CompletionNone );
+ subMenu->setItemChecked( ShellCompletion,
+ mode == OGlobalSettings::CompletionShell );
+ subMenu->setItemChecked( PopupCompletion,
+ mode == OGlobalSettings::CompletionPopup );
+ subMenu->setItemChecked( AutoCompletion,
+ mode == OGlobalSettings::CompletionAuto );
+ subMenu->setItemChecked( SemiAutoCompletion,
+ mode == OGlobalSettings::CompletionMan );
+ if ( mode != OGlobalSettings::completionMode() )
+ {
+ subMenu->insertSeparator();
+ subMenu->insertItem( tr("Default"), Default );
+ }
+ }
+ // ### do we really need this? Yes, Please do not remove! This
+ // allows applications to extend the popup menu without having to
+ // inherit from this class! (DA)
+ emit aboutToShowContextMenu( popup );
+
+ return popup;
+}
+
+void OLineEdit::completionMenuActivated( int id )
+{
+ OGlobalSettings::Completion oldMode = completionMode();
+
+ switch ( id )
+ {
+ case Default:
+ setCompletionMode( OGlobalSettings::completionMode() ); break;
+ case NoCompletion:
+ setCompletionMode( OGlobalSettings::CompletionNone ); break;
+ case AutoCompletion:
+ setCompletionMode( OGlobalSettings::CompletionAuto ); break;
+ case SemiAutoCompletion:
+ setCompletionMode( OGlobalSettings::CompletionMan ); break;
+ case ShellCompletion:
+ setCompletionMode( OGlobalSettings::CompletionShell ); break;
+ case PopupCompletion:
+ setCompletionMode( OGlobalSettings::CompletionPopup ); break;
+ default: return;
+ }
+
+ if ( oldMode != completionMode() )
+ {
+ if ( oldMode == OGlobalSettings::CompletionPopup &&
+ d->completionBox && d->completionBox->isVisible() )
+ d->completionBox->hide();
+ emit completionModeChanged( completionMode() );
+ }
+}
+
+/*void OLineEdit::dropEvent(QDropEvent *e)
+{
+ KURL::List urlList;
+ if( d->handleURLDrops && KURLDrag::decode( e, urlList ) )
+ {
+ QString dropText = text();
+ KURL::List::ConstIterator it;
+ for( it = urlList.begin() ; it != urlList.end() ; ++it )
+ {
+ if(!dropText.isEmpty())
+ dropText+=' ';
+
+ dropText += (*it).prettyURL();
+ }
+
+ validateAndSet( dropText, dropText.length(), 0, 0);
+
+ e->accept();
+ }
+ else
+ QLineEdit::dropEvent(e);
+}*/
+
+bool OLineEdit::eventFilter( QObject* o, QEvent* ev )
+{
+ if( o == this )
+ {
+ //OCursor::autoHideEventFilter( this, ev );
+ if ( ev->type() == QEvent::AccelOverride )
+ {
+ QKeyEvent *e = static_cast<QKeyEvent *>( ev );
+ // if (overrideAccel (e))
+ // {
+ // e->accept();
+ // return true;
+ // }
+ }
+ else if( ev->type() == QEvent::KeyPress )
+ {
+ QKeyEvent *e = static_cast<QKeyEvent *>( ev );
+
+ if( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
+ {
+ bool trap = d->completionBox && d->completionBox->isVisible();
+
+ // Qt will emit returnPressed() itself if we return false
+ if ( d->grabReturnKeyEvents || trap )
+ emit QLineEdit::returnPressed();
+
+ emit returnPressed( displayText() );
+
+ if ( trap )
+ d->completionBox->hide();
+
+ // Eat the event if the user asked for it, or if a completionbox was visible
+ return d->grabReturnKeyEvents || trap;
+ }
+ }
+ }
+ return QLineEdit::eventFilter( o, ev );
+}
+
+
+void OLineEdit::setURLDropsEnabled(bool enable)
+{
+ d->handleURLDrops=enable;
+}
+
+bool OLineEdit::isURLDropsEnabled() const
+{
+ return d->handleURLDrops;
+}
+
+void OLineEdit::setTrapReturnKey( bool grab )
+{
+ d->grabReturnKeyEvents = grab;
+}
+
+bool OLineEdit::trapReturnKey() const
+{
+ return d->grabReturnKeyEvents;
+}
+
+/*void OLineEdit::setURL( const KURL& url )
+{
+ QLineEdit::setText( url.prettyURL() );
+}*/
+
+void OLineEdit::makeCompletionBox()
+{
+ if ( d->completionBox )
+ return;
+
+ d->completionBox = new OCompletionBox( this, "completion box" );
+ if ( handleSignals() )
+ {
+ connect( d->completionBox, SIGNAL(highlighted( const QString& )),
+ SLOT(setText( const QString& )) );
+ connect( d->completionBox, SIGNAL(userCancelled( const QString& )),
+ SLOT(setText( const QString& )) );
+
+ // Nice lil' hacklet ;) KComboBox doesn't know when the completionbox
+ // is created (childEvent() is even more hacky, IMHO), so we simply
+ // forward the completionbox' activated signal from here.
+ if ( parentWidget() && parentWidget()->inherits("KComboBox") )
+ connect( d->completionBox, SIGNAL( activated( const QString& )),
+ parentWidget(), SIGNAL( activated( const QString & )));
+ }
+}
+
+/*bool OLineEdit::overrideAccel (const QKeyEvent* e)
+{
+ KShortcut scKey;
+
+ KKey key( e );
+ KeyBindingMap keys = getKeyBindings();
+
+ if (keys[TextCompletion].isNull())
+ scKey = KStdAccel::shortcut(KStdAccel::TextCompletion);
+ else
+ scKey = keys[TextCompletion];
+
+ if (scKey.contains( key ))
+ return true;
+
+ if (keys[NextCompletionMatch].isNull())
+ scKey = KStdAccel::shortcut(KStdAccel::NextCompletion);
+ else
+ scKey = keys[NextCompletionMatch];
+
+ if (scKey.contains( key ))
+ return true;
+
+ if (keys[PrevCompletionMatch].isNull())
+ scKey = KStdAccel::shortcut(KStdAccel::PrevCompletion);
+ else
+ scKey = keys[PrevCompletionMatch];
+
+ if (scKey.contains( key ))
+ return true;
+
+ if (KStdAccel::deleteWordBack().contains( key ))
+ return true;
+ if (KStdAccel::deleteWordForward().contains( key ))
+ return true;
+
+ if (d->completionBox && d->completionBox->isVisible ())
+ if (e->key () == Key_Backtab)
+ return true;
+
+ return false;
+}*/
+
+void OLineEdit::setCompletedItems( const QStringList& items )
+{
+ QString txt = text();
+ if ( !items.isEmpty() &&
+ !(items.count() == 1 && txt == items.first()) )
+ {
+ if ( !d->completionBox )
+ makeCompletionBox();
+
+ if ( !txt.isEmpty() )
+ d->completionBox->setCancelledText( txt );
+ d->completionBox->setItems( items );
+ d->completionBox->popup();
+ }
+ else
+ {
+ if ( d->completionBox && d->completionBox->isVisible() )
+ d->completionBox->hide();
+ }
+}
+
+OCompletionBox * OLineEdit::completionBox( bool create )
+{
+ if ( create )
+ makeCompletionBox();
+
+ return d->completionBox;
+}
+
+void OLineEdit::setCompletionObject( OCompletion* comp, bool hsig )
+{
+ OCompletion *oldComp = compObj();
+ if ( oldComp && handleSignals() )
+ disconnect( oldComp, SIGNAL( matches( const QStringList& )),
+ this, SLOT( setCompletedItems( const QStringList& )));
+
+ if ( comp && hsig )
+ connect( comp, SIGNAL( matches( const QStringList& )),
+ this, SLOT( setCompletedItems( const QStringList& )));
+
+ OCompletionBase::setCompletionObject( comp, hsig );
+}
+
+// QWidget::create() turns off mouse-Tracking which would break auto-hiding
+void OLineEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
+{
+ QLineEdit::create( id, initializeWindow, destroyOldWindow );
+ //OCursor::setAutoHideCursor( this, true, true );
+}
+
+void OLineEdit::clear()
+{
+ setText( QString::null );
+}
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 @@
+/*
+ This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ is part of the Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org>, Dawit Alemayehu <adawit@kde.org>
+ Opie Project Copyright (C) 1999 Preston Brown <pbrown@kde.org>, Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
+ Copyright (C) 1997 Sven Radej (sven.radej@iname.com)
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OLINEEDIT_H
+#define OLINEEDIT_H
+
+/* QT */
+
+#include <qlineedit.h>
+
+/* OPIE */
+
+#include <opie2/ocompletion.h>
+#include <opie2/ocompletionbase.h>
+
+class QPopupMenu;
+
+class OCompletionBox;
+typedef QString KURL; //class KURL;
+
+/**
+ * An enhanced QLineEdit widget for inputting text.
+ *
+ * @sect Detail
+ *
+ * This widget inherits from @ref QLineEdit and implements the following
+ * additional functionalities: q completion object that provides both
+ * automatic and manual text completion as well as multiple match iteration
+ * features, configurable key-bindings to activate these features and a
+ * popup-menu item that can be used to allow the user to set text completion
+ * modes on the fly based on their preference.
+ *
+ * To support these new features OLineEdit also emits a few more
+ * additional signals. These are: @ref completion( const QString& ),
+ * textRotation( KeyBindingType ), and @ref returnPressed( const QString& ).
+ * The completion signal can be connected to a slot that will assist the
+ * user in filling out the remaining text. The text rotation signal is
+ * intended to be used to iterate through the list of all possible matches
+ * whenever there is more than one match for the entered text. The
+ * @p returnPressed( const QString& ) signals are the same as QLineEdit's
+ * except it provides the current text in the widget as its argument whenever
+ * appropriate.
+ *
+ * This widget by default creates a completion object when you invoke
+ * the @ref completionObject( bool ) member function for the first time or
+ * use @ref setCompletionObject( OCompletion*, bool ) to assign your own
+ * completion object. Additionally, to make this widget more functional,
+ * OLineEdit will by default handle the text rotation and completion
+ * events internally when a completion object is created through either one
+ * of the methods mentioned above. If you do not need this functionality,
+ * simply use @ref OCompletionBase::setHandleSignals( bool ) or set the
+ * boolean parameter in the above functions to FALSE.
+ *
+ * The default key-bindings for completion and rotation is determined
+ * from the global settings in @ref OStdAccel. These values, however,
+ * can be overriden locally by invoking @ref OCompletionBase::setKeyBinding().
+ * The values can easily be reverted back to the default setting, by simply
+ * calling @ref useGlobalSettings(). An alternate method would be to default
+ * individual key-bindings by usning @ref setKeyBinding() with the default
+ * second argument.
+ *
+ * NOTE that if the @p EchoMode for this widget is set to something other
+ * than @p QLineEdit::Normal, the completion mode will always be defaulted
+ * to @ref PGlobalSettings::CompletionNone. This is done purposefully to guard
+ * against protected entries such as passwords being cached in @ref OCompletion's
+ * list. Hence, if the @p EchoMode is not @ref QLineEdit::Normal, the completion
+ * mode is automatically disabled.
+ *
+ * @sect Useage
+ *
+ * To enable the basic completion feature :
+ *
+ * <pre>
+ * OLineEdit *edit = new OLineEdit( this, "mywidget" );
+ * OCompletion *comp = edit->completionObject();
+ * // Fill the completion object with a list of possible matches
+ * QStringList list;
+ * list << "mickeyl@handhelds.org" << "mickey@tm.informatik.uni-frankfurt.de>" << "mickey@Vanille.de";
+ * comp->setItems( list );
+ * // Connect to the return pressed signal (optional)
+ * connect(edit,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
+ * </pre>
+ *
+ * To use a customized completion objects or your
+ * own completion object :
+ *
+ * <pre>
+ * OLineEdit *edit = new OLineEdit( this,"mywidget" );
+ * KURLCompletion *comp = new KURLCompletion();
+ * edit->setCompletionObject( comp );
+ * // Connect to the return pressed signal - optional
+ * connect(edit,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
+ * </pre>
+ *
+ * Note that you have to either delete the allocated completion object
+ * when you don't need it anymore, or call
+ * setAutoDeleteCompletionObject( true );
+ *
+ * @sect Miscellaneous function calls :
+ *
+ * <pre>
+ * // Tell the widget not to handle completion and
+ * // iteration internally.
+ * edit->setHandleSignals( false );
+ * // Set your own completion key for manual completions.
+ * edit->setKeyBinding( OCompletionBase::TextCompletion, Qt::End );
+ * // Hide the context (popup) menu
+ * edit->setContextMenuEnabled( false );
+ * // Temporarly disable signal emitions
+ * // (both completion & iteration signals)
+ * edit->disableSignals();
+ * // Default the key-bindings to system settings.
+ * edit->useGlobalKeyBindings();
+ * </pre>
+ *
+ * @short An enhanced single line input widget.
+ * @author Dawit Alemayehu <adawit@kde.org>
+ * @author Opie adaption by Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ */
+
+class OLineEdit : public QLineEdit, public OCompletionBase
+{
+ friend class OComboBox;
+
+ Q_OBJECT
+ Q_PROPERTY( bool contextMenuEnabled READ isContextMenuEnabled WRITE setContextMenuEnabled )
+ Q_PROPERTY( bool urlDropsEnabled READ isURLDropsEnabled WRITE setURLDropsEnabled )
+
+public:
+
+ /**
+ * Constructs a OLineEdit object with a default text, a parent,
+ * and a name.
+ *
+ * @param string Text to be shown in the edit widget.
+ * @param parent The parent object of this widget.
+ * @param name the name of this widget
+ */
+ OLineEdit( const QString &string, QWidget *parent, const char *name = 0 );
+
+ /**
+ * Constructs a OLineEdit object with a parent and a name.
+ *
+ * @param string Text to be shown in the edit widget.
+ * @param parent The parent object of this widget.
+ * @param name The name of this widget.
+ */
+ OLineEdit ( QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Destructor.
+ */
+ virtual ~OLineEdit ();
+
+ /**
+ * Sets @p url into the lineedit. It uses @ref KURL::prettyURL() so
+ * that the url is properly decoded for displaying.
+ */
+ void setURL( const KURL& url );
+
+ /**
+ * Puts the text cursor at the end of the string.
+ *
+ * This method is deprecated. Use @ref QLineEdit::end()
+ * instead.
+ *
+ * @deprecated
+ * @ref QLineEdit::end()
+ */
+ void cursorAtEnd() { end( false ); }
+
+ /**
+ * Re-implemented from @ref OCompletionBase for internal reasons.
+ *
+ * This function is re-implemented in order to make sure that
+ * the EchoMode is acceptable before we set the completion mode.
+ *
+ * See @ref OCompletionBase::setCompletionMode
+ */
+ virtual void setCompletionMode( OGlobalSettings::Completion mode );
+
+ /**
+ * Enables/disables the popup (context) menu.
+ *
+ * Note that when this function is invoked with its argument
+ * set to @p true, then both the context menu and the completion
+ * menu item are enabled. If you do not want to the completion
+ * item to be visible simply invoke @ref hideModechanger() right
+ * after calling this method. Also by default, the context
+ * menu is automatically created if this widget is editable. Thus
+ * you need to call this function with the argument set to false
+ * if you do not want this behaviour.
+ *
+ * @param showMenu If @p true, show the context menu.
+ */
+ virtual void setContextMenuEnabled( bool showMenu ) { m_bEnableMenu = showMenu; }
+
+ /**
+ * Returns @p true when the context menu is enabled.
+ */
+ bool isContextMenuEnabled() const { return m_bEnableMenu; }
+
+ /**
+ * Enables/Disables handling of URL drops. If enabled and the user
+ * drops an URL, the decoded URL will be inserted. Otherwise the default
+ * behaviour of QLineEdit is used, which inserts the encoded URL.
+ *
+ * @param enable If @p true, insert decoded URLs
+ */
+ void setURLDropsEnabled( bool enable );
+
+ /**
+ * Returns @p true when decoded URL drops are enabled
+ */
+ bool isURLDropsEnabled() const;
+
+ /**
+ * By default, OLineEdit recognizes @p Key_Return and @p Key_Enter and emits
+ * the @ref returnPressed() signals, but it also lets the event pass,
+ * for example causing a dialog's default-button to be called.
+ *
+ * Call this method with @p trap = @p true to make @p OLineEdit stop these
+ * events. The signals will still be emitted of course.
+ *
+ * @see trapReturnKey()
+ */
+ void setTrapReturnKey( bool trap );
+
+ /**
+ * @returns @p true if keyevents of @p Key_Return or
+ * @p Key_Enter will be stopped or if they will be propagated.
+ *
+ * @see setTrapReturnKey ()
+ */
+ bool trapReturnKey() const;
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * @reimplemented
+ */
+ virtual bool eventFilter( QObject *, QEvent * );
+
+ /**
+ * @returns the completion-box, that is used in completion mode
+ * @ref KGlobalSettings::CompletionPopup.
+ * This method will create a completion-box if none is there, yet.
+ *
+ * @param create Set this to false if you don't want the box to be created
+ * i.e. to test if it is available.
+ */
+ OCompletionBox * completionBox( bool create = true );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void setCompletionObject( OCompletion *, bool hsig = true );
+
+
+signals:
+
+ /**
+ * Emitted when the user presses the return key.
+ *
+ * The argument is the current text. Note that this
+ * signal is @em not emitted if the widget's @p EchoMode is set to
+ * @ref QLineEdit::EchoMode.
+ */
+ void returnPressed( const QString& );
+
+ /**
+ * Emitted when the completion key is pressed.
+ *
+ * Please note that this signal is @em not emitted if the
+ * completion mode is set to @p CompletionNone or @p EchoMode is
+ * @em normal.
+ */
+ void completion( const QString& );
+
+ /**
+ * Emitted when the shortcut for substring completion is pressed.
+ */
+ void substringCompletion( const QString& );
+
+ /**
+ * Emitted when the text rotation key-bindings are pressed.
+ *
+ * The argument indicates which key-binding was pressed.
+ * In OLineEdit's case this can be either one of two values:
+ * @ref PrevCompletionMatch or @ref NextCompletionMatch. See
+ * @ref OCompletionBase::setKeyBinding for details.
+ *
+ * Note that this signal is @em not emitted if the completion
+ * mode is set to @p KGlobalSettings::CompletionNone or @p echoMode() is @em not normal.
+ */
+ void textRotation( OCompletionBase::KeyBindingType );
+
+ /**
+ * Emitted when the user changed the completion mode by using the
+ * popupmenu.
+ */
+ void completionModeChanged( OGlobalSettings::Completion );
+
+ /**
+ * Emitted before the context menu is displayed.
+ *
+ * The signal allows you to add your own entries into the
+ * the context menu that is created on demand.
+ *
+ * NOTE: Do not store the pointer to the QPopupMenu
+ * provided through since it is created and deleted
+ * on demand.
+ *
+ * @param the context menu about to be displayed
+ */
+ void aboutToShowContextMenu( QPopupMenu* );
+
+public slots:
+
+ /**
+ * Re-implemented for internal reasons. API not changed.
+ */
+ virtual void setReadOnly(bool);
+
+ /**
+ * Iterates through all possible matches of the completed text or
+ * the history list.
+ *
+ * This function simply iterates over all possible matches in case
+ * multimple matches are found as a result of a text completion request.
+ * It will have no effect if only a single match is found.
+ *
+ * @param type The key-binding invoked.
+ */
+ void rotateText( OCompletionBase::KeyBindingType /* type */ );
+
+ /**
+ * See @ref OCompletionBase::setCompletedText.
+ */
+ virtual void setCompletedText( const QString& );
+
+ /**
+ * Sets @p items into the completion-box if @ref completionMode() is
+ * CompletionPopup. The popup will be shown immediately.
+ */
+ void setCompletedItems( const QStringList& items );
+
+ /**
+ * Reimplemented to workaround a buggy QLineEdit::clear()
+ * (changing the clipboard to the text we just had in the lineedit)
+ */
+ virtual void clear();
+
+protected slots:
+
+ /**
+ * Completes the remaining text with a matching one from
+ * a given list.
+ */
+ virtual void makeCompletion( const QString& );
+
+ /**
+ * @deprecated. Will be removed in the next major release!
+ */
+ void slotAboutToShow() {}
+
+ /**
+ * @deprecated. Will be removed in the next major release!
+ */
+ void slotCancelled() {}
+
+protected:
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See @ref QLineEdit::keyPressEvent().
+ */
+ virtual void keyPressEvent( QKeyEvent * );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See @ref QLineEdit::mousePressEvent().
+ */
+ virtual void mousePressEvent( QMouseEvent * );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See @ref QWidget::mouseDoubleClickEvent().
+ */
+ virtual void mouseDoubleClickEvent( QMouseEvent * );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See @ref QLineEdit::createPopupMenu().
+ */
+ virtual QPopupMenu *createPopupMenu();
+
+ /**
+ * Re-implemented to handle URI drops.
+ *
+ * See @ref QLineEdit::dropEvent().
+ */
+ //virtual void dropEvent( QDropEvent * );
+
+ /*
+ * This function simply sets the lineedit text and
+ * highlights the text appropriately if the boolean
+ * value is set to true.
+ *
+ * @param text
+ * @param marked
+ */
+ virtual void setCompletedText( const QString& /*text*/, bool /*marked*/ );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void create( WId = 0, bool initializeWindow = true,
+ bool destroyOldWindow = true );
+
+private slots:
+ void completionMenuActivated( int id );
+ void tripleClickTimeout(); // resets possibleTripleClick
+
+private:
+ // Constants that represent the ID's of the popup menu.
+ // TODO: See if we can replace this mess with KActionMenu
+ // in the future though it's working lovely.
+ enum MenuID {
+ Default = 42,
+ NoCompletion,
+ AutoCompletion,
+ ShellCompletion,
+ PopupCompletion,
+ SemiAutoCompletion
+ };
+
+ /**
+ * Initializes variables. Called from the constructors.
+ */
+ void init();
+
+ /**
+ * Creates the completion box
+ */
+ void makeCompletionBox();
+
+ /**
+ * Checks whether we should/should not consume a key used as
+ * an accelerator.
+ */
+ //bool overrideAccel (const QKeyEvent* e);
+
+ bool m_bEnableMenu;
+
+ bool possibleTripleClick; // set in mousePressEvent, deleted in tripleClickTimeout
+
+protected:
+ //virtual void virtual_hook( int id, void* data );
+private:
+ class OLineEditPrivate;
+ OLineEditPrivate *d;
+};
+
+#endif