summaryrefslogtreecommitdiff
path: root/libopie2/qt3/opieui/olineedit.cpp
Unidiff
Diffstat (limited to 'libopie2/qt3/opieui/olineedit.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/qt3/opieui/olineedit.cpp729
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 @@
1/*
2 This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
3 is part of the Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org>, Dawit Alemayehu <adawit@kde.org>
4 Opie Project Copyright (C) 1999 Preston Brown <pbrown@kde.org>, Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
5 Copyright (C) 1997 Sven Radej (sven.radej@iname.com)
6 =.
7 .=l. Originally part of the KDE Project
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33/* QT */
34
35#include <qapplication.h>
36#include <qclipboard.h>
37#include <qtimer.h>
38#include <qpopupmenu.h>
39
40/* OPIE */
41
42#include <opie2/ocompletionbox.h>
43#include <opie2/olineedit.h>
44#include <opie2/oglobalsettings.h>
45
46typedef QString KURL; //FIXME: Revise for Opie
47
48/*======================================================================================
49 * OLineEditPrivate
50 *======================================================================================*/
51
52class OLineEdit::OLineEditPrivate
53{
54public:
55 OLineEditPrivate()
56 {
57 grabReturnKeyEvents = false;
58 handleURLDrops = true;
59 completionBox = 0L;
60 }
61 ~OLineEditPrivate()
62 {
63 delete completionBox;
64 }
65
66 bool grabReturnKeyEvents;
67 bool handleURLDrops;
68 OCompletionBox *completionBox;
69};
70
71
72/*======================================================================================
73 * OLineEdit
74 *======================================================================================*/
75
76OLineEdit::OLineEdit( const QString &string, QWidget *parent, const char *name )
77 : QLineEdit( string, parent, name )
78{
79 init();
80}
81
82OLineEdit::OLineEdit( QWidget *parent, const char *name )
83 : QLineEdit( parent, name )
84{
85 init();
86}
87
88OLineEdit::~OLineEdit ()
89{
90 delete d;
91}
92
93void OLineEdit::init()
94{
95 d = new OLineEditPrivate;
96 possibleTripleClick = false;
97 // Enable the context menu by default.
98 setContextMenuEnabled( true );
99 //OCursor::setAutoHideCursor( this, true, true );
100 installEventFilter( this );
101}
102
103void OLineEdit::setCompletionMode( OGlobalSettings::Completion mode )
104{
105 OGlobalSettings::Completion oldMode = completionMode();
106 if ( oldMode != mode && oldMode == OGlobalSettings::CompletionPopup &&
107 d->completionBox && d->completionBox->isVisible() )
108 d->completionBox->hide();
109
110 // If the widgets echo mode is not Normal, no completion
111 // feature will be enabled even if one is requested.
112 if ( echoMode() != QLineEdit::Normal )
113 mode = OGlobalSettings::CompletionNone; // Override the request.
114
115 OCompletionBase::setCompletionMode( mode );
116}
117
118void OLineEdit::setCompletedText( const QString& t, bool marked )
119{
120 QString txt = text();
121 if ( t != txt )
122 {
123 int curpos = marked ? txt.length() : t.length();
124 validateAndSet( t, curpos, curpos, t.length() );
125 }
126}
127
128void OLineEdit::setCompletedText( const QString& text )
129{
130 OGlobalSettings::Completion mode = completionMode();
131 bool marked = ( mode == OGlobalSettings::CompletionAuto ||
132 mode == OGlobalSettings::CompletionMan ||
133 mode == OGlobalSettings::CompletionPopup );
134 setCompletedText( text, marked );
135}
136
137void OLineEdit::rotateText( OCompletionBase::KeyBindingType type )
138{
139 OCompletion* comp = compObj();
140 if ( comp &&
141 (type == OCompletionBase::PrevCompletionMatch ||
142 type == OCompletionBase::NextCompletionMatch ) )
143 {
144 QString input = (type == OCompletionBase::PrevCompletionMatch) ? comp->previousMatch() : comp->nextMatch();
145 // Skip rotation if previous/next match is null or the same text
146 if ( input.isNull() || input == displayText() )
147 return;
148 #if QT_VERSION > 290
149 setCompletedText( input, hasSelectedText() );
150 #else
151 setCompletedText( input, hasMarkedText() );
152 #endif
153 }
154}
155
156void OLineEdit::makeCompletion( const QString& text )
157{
158 OCompletion *comp = compObj();
159 if ( !comp )
160 return; // No completion object...
161
162 QString match = comp->makeCompletion( text );
163 OGlobalSettings::Completion mode = completionMode();
164 if ( mode == OGlobalSettings::CompletionPopup )
165 {
166 if ( match.isNull() )
167 {
168 if ( d->completionBox ) {
169 d->completionBox->hide();
170 d->completionBox->clear();
171 }
172 }
173 else
174 setCompletedItems( comp->allMatches() );
175 }
176 else
177 {
178 // all other completion modes
179 // If no match or the same match, simply return without completing.
180 if ( match.isNull() || match == text )
181 return;
182
183 setCompletedText( match );
184 }
185}
186
187void OLineEdit::setReadOnly(bool readOnly)
188{
189 QPalette p = palette();
190 if (readOnly)
191 {
192 QColor color = p.color(QPalette::Disabled, QColorGroup::Background);
193 p.setColor(QColorGroup::Base, color);
194 p.setColor(QColorGroup::Background, color);
195 }
196 else
197 {
198 QColor color = p.color(QPalette::Normal, QColorGroup::Base);
199 p.setColor(QColorGroup::Base, color);
200 p.setColor(QColorGroup::Background, color);
201 }
202 setPalette(p);
203
204 QLineEdit::setReadOnly (readOnly);
205}
206
207void OLineEdit::keyPressEvent( QKeyEvent *e )
208{
209 qDebug( "OLineEdit::keyPressEvent()" );
210
211 /*
212
213 KKey key( e );
214
215 if ( KStdAccel::copy().contains( key ) ) {
216 copy();
217 return;
218 }
219 else if ( KStdAccel::paste().contains( key ) ) {
220 paste();
221 return;
222 }
223 else if ( KStdAccel::cut().contains( key ) ) {
224 cut();
225 return;
226 }
227 else if ( KStdAccel::undo().contains( key ) ) {
228 undo();
229 return;
230 }
231 else if ( KStdAccel::redo().contains( key ) ) {
232 redo();
233 return;
234 }
235 else if ( KStdAccel::deleteWordBack().contains( key ) )
236 {
237 cursorWordBackward(TRUE);
238 if ( hasSelectedText() )
239 del();
240
241 e->accept();
242 return;
243 }
244 else if ( KStdAccel::deleteWordForward().contains( key ) )
245 {
246 // Workaround for QT bug where
247 cursorWordForward(TRUE);
248 if ( hasSelectedText() )
249 del();
250
251 e->accept();
252 return;
253 }
254 */
255
256 // Filter key-events if EchoMode is normal &
257 // completion mode is not set to CompletionNone
258 if ( echoMode() == QLineEdit::Normal &&
259 completionMode() != OGlobalSettings::CompletionNone )
260 {
261 KeyBindingMap keys = getKeyBindings();
262 OGlobalSettings::Completion mode = completionMode();
263 bool noModifier = (e->state() == NoButton || e->state()== ShiftButton);
264
265 if ( (mode == OGlobalSettings::CompletionAuto ||
266 mode == OGlobalSettings::CompletionMan) && noModifier )
267 {
268 QString keycode = e->text();
269 if ( !keycode.isNull() && keycode.unicode()->isPrint() )
270 {
271 QLineEdit::keyPressEvent ( e );
272 QString txt = text();
273 int len = txt.length();
274 #if QT_VERSION > 290
275 if ( !hasSelectedText() && len && cursorPosition() == len )
276 #else
277 if ( !hasMarkedText() && len && cursorPosition() == len )
278 #endif
279 {
280 if ( emitSignals() )
281 emit completion( txt );
282 if ( handleSignals() )
283 makeCompletion( txt );
284 e->accept();
285 }
286 return;
287 }
288 }
289
290 else if ( mode == OGlobalSettings::CompletionPopup && noModifier )
291 {
292 qDebug( "OLineEdit::keyPressEvent() - global settings = CompletionPopup & noModifier" );
293
294 QString old_txt = text();
295 QLineEdit::keyPressEvent ( e );
296 QString txt = text();
297 int len = txt.length();
298 QString keycode = e->text();
299
300
301 if ( txt != old_txt && len && cursorPosition() == len &&
302 ( (!keycode.isNull() && keycode.unicode()->isPrint()) ||
303 e->key() == Key_Backspace ) )
304 {
305 if ( emitSignals() )
306 emit completion( txt ); // emit when requested...
307 if ( handleSignals() )
308 makeCompletion( txt ); // handle when requested...
309 e->accept();
310 }
311 else if (!len && d->completionBox && d->completionBox->isVisible())
312 d->completionBox->hide();
313
314 return;
315 }
316
317 /*else if ( mode == OGlobalSettings::CompletionShell )
318 {
319 // Handles completion.
320 KShortcut cut;
321 if ( keys[TextCompletion].isNull() )
322 cut = KStdAccel::shortcut(KStdAccel::TextCompletion);
323 else
324 cut = keys[TextCompletion];
325
326 if ( cut.contains( key ) )
327 {
328 // Emit completion if the completion mode is CompletionShell
329 // and the cursor is at the end of the string.
330 QString txt = text();
331 int len = txt.length();
332 if ( cursorPosition() == len && len != 0 )
333 {
334 if ( emitSignals() )
335 emit completion( txt );
336 if ( handleSignals() )
337 makeCompletion( txt );
338 return;
339 }
340 }
341 else if ( d->completionBox )
342 d->completionBox->hide();
343 }
344
345 // handle rotation
346 if ( mode != OGlobalSettings::CompletionNone )
347 {
348 // Handles previous match
349 KShortcut cut;
350 if ( keys[PrevCompletionMatch].isNull() )
351 cut = KStdAccel::shortcut(KStdAccel::PrevCompletion);
352 else
353 cut = keys[PrevCompletionMatch];
354
355 if ( cut.contains( key ) )
356 {
357 if ( emitSignals() )
358 emit textRotation( OCompletionBase::PrevCompletionMatch );
359 if ( handleSignals() )
360 rotateText( OCompletionBase::PrevCompletionMatch );
361 return;
362 }
363
364 // Handles next match
365 if ( keys[NextCompletionMatch].isNull() )
366 cut = KStdAccel::key(KStdAccel::NextCompletion);
367 else
368 cut = keys[NextCompletionMatch];
369
370 if ( cut.contains( key ) )
371 {
372 if ( emitSignals() )
373 emit textRotation( OCompletionBase::NextCompletionMatch );
374 if ( handleSignals() )
375 rotateText( OCompletionBase::NextCompletionMatch );
376 return;
377 }
378 }
379
380 // substring completion
381 if ( compObj() )
382 {
383 KShortcut cut;
384 if ( keys[SubstringCompletion].isNull() )
385 cut = KStdAccel::shortcut(KStdAccel::SubstringCompletion);
386 else
387 cut = keys[SubstringCompletion];
388
389 if ( cut.contains( key ) )
390 {
391 if ( emitSignals() )
392 emit substringCompletion( text() );
393 if ( handleSignals() )
394 {
395 setCompletedItems( compObj()->substringCompletion(text()));
396 e->accept();
397 }
398 return;
399 }
400 } */
401 }
402
403 // Let QLineEdit handle any other keys events.
404 QLineEdit::keyPressEvent ( e );
405}
406
407void OLineEdit::mouseDoubleClickEvent( QMouseEvent* e )
408{
409 if ( e->button() == Qt::LeftButton )
410 {
411 possibleTripleClick=true;
412 QTimer::singleShot( QApplication::doubleClickInterval(),this,
413 SLOT(tripleClickTimeout()) );
414 }
415 QLineEdit::mouseDoubleClickEvent( e );
416}
417
418void OLineEdit::mousePressEvent( QMouseEvent* e )
419{
420 if ( possibleTripleClick && e->button() == Qt::LeftButton )
421 {
422 selectAll();
423 return;
424 }
425 QLineEdit::mousePressEvent( e );
426}
427
428void OLineEdit::tripleClickTimeout()
429{
430 possibleTripleClick=false;
431}
432
433QPopupMenu *OLineEdit::createPopupMenu()
434{
435 // Return if popup menu is not enabled !!
436 if ( !m_bEnableMenu )
437 return 0;
438
439 #if QT_VERSION > 290
440 QPopupMenu *popup = QLineEdit::createPopupMenu();
441 #else
442 QPopupMenu *popup = new QPopupMenu();
443 #warning OLineEdit is not fully functional on Qt2
444 #endif
445
446 // completion object is present.
447 if ( compObj() )
448 {
449 QPopupMenu *subMenu = new QPopupMenu( popup );
450 connect( subMenu, SIGNAL( activated( int ) ),
451 this, SLOT( completionMenuActivated( int ) ) );
452
453 popup->insertSeparator();
454 //popup->insertItem( SmallIconSet("completion"), i18n("Text Completion"),
455 // subMenu );
456
457 popup->insertItem( tr("Text Completion"), subMenu );
458
459 subMenu->insertItem( tr("None"), NoCompletion );
460 subMenu->insertItem( tr("Manual"), ShellCompletion );
461 subMenu->insertItem( tr("Automatic"), AutoCompletion );
462 subMenu->insertItem( tr("Dropdown List"), PopupCompletion );
463 subMenu->insertItem( tr("Short Automatic"), SemiAutoCompletion );
464
465 //subMenu->setAccel( KStdAccel::completion(), ShellCompletion );
466 subMenu->setAccel( Key_Tab, ShellCompletion );
467
468 OGlobalSettings::Completion mode = completionMode();
469 subMenu->setItemChecked( NoCompletion,
470 mode == OGlobalSettings::CompletionNone );
471 subMenu->setItemChecked( ShellCompletion,
472 mode == OGlobalSettings::CompletionShell );
473 subMenu->setItemChecked( PopupCompletion,
474 mode == OGlobalSettings::CompletionPopup );
475 subMenu->setItemChecked( AutoCompletion,
476 mode == OGlobalSettings::CompletionAuto );
477 subMenu->setItemChecked( SemiAutoCompletion,
478 mode == OGlobalSettings::CompletionMan );
479 if ( mode != OGlobalSettings::completionMode() )
480 {
481 subMenu->insertSeparator();
482 subMenu->insertItem( tr("Default"), Default );
483 }
484 }
485 // ### do we really need this? Yes, Please do not remove! This
486 // allows applications to extend the popup menu without having to
487 // inherit from this class! (DA)
488 emit aboutToShowContextMenu( popup );
489
490 return popup;
491}
492
493void OLineEdit::completionMenuActivated( int id )
494{
495 OGlobalSettings::Completion oldMode = completionMode();
496
497 switch ( id )
498 {
499 case Default:
500 setCompletionMode( OGlobalSettings::completionMode() ); break;
501 case NoCompletion:
502 setCompletionMode( OGlobalSettings::CompletionNone ); break;
503 case AutoCompletion:
504 setCompletionMode( OGlobalSettings::CompletionAuto ); break;
505 case SemiAutoCompletion:
506 setCompletionMode( OGlobalSettings::CompletionMan ); break;
507 case ShellCompletion:
508 setCompletionMode( OGlobalSettings::CompletionShell ); break;
509 case PopupCompletion:
510 setCompletionMode( OGlobalSettings::CompletionPopup ); break;
511 default: return;
512 }
513
514 if ( oldMode != completionMode() )
515 {
516 if ( oldMode == OGlobalSettings::CompletionPopup &&
517 d->completionBox && d->completionBox->isVisible() )
518 d->completionBox->hide();
519 emit completionModeChanged( completionMode() );
520 }
521}
522
523/*void OLineEdit::dropEvent(QDropEvent *e)
524{
525 KURL::List urlList;
526 if( d->handleURLDrops && KURLDrag::decode( e, urlList ) )
527 {
528 QString dropText = text();
529 KURL::List::ConstIterator it;
530 for( it = urlList.begin() ; it != urlList.end() ; ++it )
531 {
532 if(!dropText.isEmpty())
533 dropText+=' ';
534
535 dropText += (*it).prettyURL();
536 }
537
538 validateAndSet( dropText, dropText.length(), 0, 0);
539
540 e->accept();
541 }
542 else
543 QLineEdit::dropEvent(e);
544}*/
545
546bool OLineEdit::eventFilter( QObject* o, QEvent* ev )
547{
548 if( o == this )
549 {
550 //OCursor::autoHideEventFilter( this, ev );
551 if ( ev->type() == QEvent::AccelOverride )
552 {
553 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
554 // if (overrideAccel (e))
555 // {
556 // e->accept();
557 // return true;
558 // }
559 }
560 else if( ev->type() == QEvent::KeyPress )
561 {
562 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
563
564 if( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
565 {
566 bool trap = d->completionBox && d->completionBox->isVisible();
567
568 // Qt will emit returnPressed() itself if we return false
569 if ( d->grabReturnKeyEvents || trap )
570 emit QLineEdit::returnPressed();
571
572 emit returnPressed( displayText() );
573
574 if ( trap )
575 d->completionBox->hide();
576
577 // Eat the event if the user asked for it, or if a completionbox was visible
578 return d->grabReturnKeyEvents || trap;
579 }
580 }
581 }
582 return QLineEdit::eventFilter( o, ev );
583}
584
585
586void OLineEdit::setURLDropsEnabled(bool enable)
587{
588 d->handleURLDrops=enable;
589}
590
591bool OLineEdit::isURLDropsEnabled() const
592{
593 return d->handleURLDrops;
594}
595
596void OLineEdit::setTrapReturnKey( bool grab )
597{
598 d->grabReturnKeyEvents = grab;
599}
600
601bool OLineEdit::trapReturnKey() const
602{
603 return d->grabReturnKeyEvents;
604}
605
606/*void OLineEdit::setURL( const KURL& url )
607{
608 QLineEdit::setText( url.prettyURL() );
609}*/
610
611void OLineEdit::makeCompletionBox()
612{
613 if ( d->completionBox )
614 return;
615
616 d->completionBox = new OCompletionBox( this, "completion box" );
617 if ( handleSignals() )
618 {
619 connect( d->completionBox, SIGNAL(highlighted( const QString& )),
620 SLOT(setText( const QString& )) );
621 connect( d->completionBox, SIGNAL(userCancelled( const QString& )),
622 SLOT(setText( const QString& )) );
623
624 // Nice lil' hacklet ;) KComboBox doesn't know when the completionbox
625 // is created (childEvent() is even more hacky, IMHO), so we simply
626 // forward the completionbox' activated signal from here.
627 if ( parentWidget() && parentWidget()->inherits("KComboBox") )
628 connect( d->completionBox, SIGNAL( activated( const QString& )),
629 parentWidget(), SIGNAL( activated( const QString & )));
630 }
631}
632
633/*bool OLineEdit::overrideAccel (const QKeyEvent* e)
634{
635 KShortcut scKey;
636
637 KKey key( e );
638 KeyBindingMap keys = getKeyBindings();
639
640 if (keys[TextCompletion].isNull())
641 scKey = KStdAccel::shortcut(KStdAccel::TextCompletion);
642 else
643 scKey = keys[TextCompletion];
644
645 if (scKey.contains( key ))
646 return true;
647
648 if (keys[NextCompletionMatch].isNull())
649 scKey = KStdAccel::shortcut(KStdAccel::NextCompletion);
650 else
651 scKey = keys[NextCompletionMatch];
652
653 if (scKey.contains( key ))
654 return true;
655
656 if (keys[PrevCompletionMatch].isNull())
657 scKey = KStdAccel::shortcut(KStdAccel::PrevCompletion);
658 else
659 scKey = keys[PrevCompletionMatch];
660
661 if (scKey.contains( key ))
662 return true;
663
664 if (KStdAccel::deleteWordBack().contains( key ))
665 return true;
666 if (KStdAccel::deleteWordForward().contains( key ))
667 return true;
668
669 if (d->completionBox && d->completionBox->isVisible ())
670 if (e->key () == Key_Backtab)
671 return true;
672
673 return false;
674}*/
675
676void OLineEdit::setCompletedItems( const QStringList& items )
677{
678 QString txt = text();
679 if ( !items.isEmpty() &&
680 !(items.count() == 1 && txt == items.first()) )
681 {
682 if ( !d->completionBox )
683 makeCompletionBox();
684
685 if ( !txt.isEmpty() )
686 d->completionBox->setCancelledText( txt );
687 d->completionBox->setItems( items );
688 d->completionBox->popup();
689 }
690 else
691 {
692 if ( d->completionBox && d->completionBox->isVisible() )
693 d->completionBox->hide();
694 }
695}
696
697OCompletionBox * OLineEdit::completionBox( bool create )
698{
699 if ( create )
700 makeCompletionBox();
701
702 return d->completionBox;
703}
704
705void OLineEdit::setCompletionObject( OCompletion* comp, bool hsig )
706{
707 OCompletion *oldComp = compObj();
708 if ( oldComp && handleSignals() )
709 disconnect( oldComp, SIGNAL( matches( const QStringList& )),
710 this, SLOT( setCompletedItems( const QStringList& )));
711
712 if ( comp && hsig )
713 connect( comp, SIGNAL( matches( const QStringList& )),
714 this, SLOT( setCompletedItems( const QStringList& )));
715
716 OCompletionBase::setCompletionObject( comp, hsig );
717}
718
719// QWidget::create() turns off mouse-Tracking which would break auto-hiding
720void OLineEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
721{
722 QLineEdit::create( id, initializeWindow, destroyOldWindow );
723 //OCursor::setAutoHideCursor( this, true, true );
724}
725
726void OLineEdit::clear()
727{
728 setText( QString::null );
729}