summaryrefslogtreecommitdiff
path: root/libopie2/qt3/opieui/ocombobox.cpp
Side-by-side diff
Diffstat (limited to 'libopie2/qt3/opieui/ocombobox.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/qt3/opieui/ocombobox.cpp666
1 files changed, 666 insertions, 0 deletions
diff --git a/libopie2/qt3/opieui/ocombobox.cpp b/libopie2/qt3/opieui/ocombobox.cpp
new file mode 100644
index 0000000..a1dd5f5
--- a/dev/null
+++ b/libopie2/qt3/opieui/ocombobox.cpp
@@ -0,0 +1,666 @@
+/*
+ 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();
+}
+