Diffstat (limited to 'libopie2/qt3/opieui/olineedit.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libopie2/qt3/opieui/olineedit.cpp | 729 |
1 files changed, 729 insertions, 0 deletions
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 ); +} |