00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <qclipboard.h>
00029 #include <qpainter.h>
00030 #include <qtimer.h>
00031
00032 #include <kconfig.h>
00033 #include <qtooltip.h>
00034 #include <kcursor.h>
00035 #include <klocale.h>
00036 #include <kstdaccel.h>
00037 #include <kpopupmenu.h>
00038 #include <kdebug.h>
00039 #include <kcompletionbox.h>
00040 #include <kurl.h>
00041 #include <kurldrag.h>
00042 #include <kiconloader.h>
00043 #include <kapplication.h>
00044
00045 #include "klineedit.h"
00046 #include "klineedit.moc"
00047
00048
00049 class KLineEdit::KLineEditPrivate
00050 {
00051 public:
00052 KLineEditPrivate()
00053 {
00054 completionBox = 0L;
00055 handleURLDrops = true;
00056 grabReturnKeyEvents = false;
00057
00058 userSelection = true;
00059 autoSuggest = false;
00060 disableRestoreSelection = false;
00061 enableSqueezedText = false;
00062
00063 if ( !initialized )
00064 {
00065 KConfigGroup config( KGlobal::config(), "General" );
00066 backspacePerformsCompletion = config.readBoolEntry( "Backspace performs completion", false );
00067
00068 initialized = true;
00069 }
00070
00071 }
00072
00073 ~KLineEditPrivate()
00074 {
00075
00076
00077 }
00078
00079 static bool initialized;
00080 static bool backspacePerformsCompletion;
00081
00082 QColor previousHighlightColor;
00083 QColor previousHighlightedTextColor;
00084
00085 bool userSelection: 1;
00086 bool autoSuggest : 1;
00087 bool disableRestoreSelection: 1;
00088 bool handleURLDrops:1;
00089 bool grabReturnKeyEvents:1;
00090 bool enableSqueezedText:1;
00091
00092 int squeezedEnd;
00093 int squeezedStart;
00094 BackgroundMode bgMode;
00095 QString squeezedText;
00096 KCompletionBox *completionBox;
00097
00098 QString clickMessage;
00099 bool drawClickMsg:1;
00100 };
00101
00102 bool KLineEdit::KLineEditPrivate::backspacePerformsCompletion = false;
00103 bool KLineEdit::KLineEditPrivate::initialized = false;
00104
00105
00106 KLineEdit::KLineEdit( const QString &string, QWidget *parent, const char *name )
00107 :QLineEdit( string, parent, name )
00108 {
00109 init();
00110 }
00111
00112 KLineEdit::KLineEdit( QWidget *parent, const char *name )
00113 :QLineEdit( parent, name )
00114 {
00115 init();
00116 }
00117
00118 KLineEdit::~KLineEdit ()
00119 {
00120 delete d;
00121 d = 0;
00122 }
00123
00124 void KLineEdit::init()
00125 {
00126 d = new KLineEditPrivate;
00127 possibleTripleClick = false;
00128 d->bgMode = backgroundMode ();
00129
00130
00131 KLineEdit::setContextMenuEnabled( true );
00132 KCursor::setAutoHideCursor( this, true, true );
00133 installEventFilter( this );
00134
00135 KGlobalSettings::Completion mode = completionMode();
00136 d->autoSuggest = (mode == KGlobalSettings::CompletionMan ||
00137 mode == KGlobalSettings::CompletionPopupAuto ||
00138 mode == KGlobalSettings::CompletionAuto);
00139 connect( this, SIGNAL(selectionChanged()), this, SLOT(slotRestoreSelectionColors()));
00140
00141 QPalette p = palette();
00142 if ( !d->previousHighlightedTextColor.isValid() )
00143 d->previousHighlightedTextColor=p.color(QPalette::Normal,QColorGroup::HighlightedText);
00144 if ( !d->previousHighlightColor.isValid() )
00145 d->previousHighlightColor=p.color(QPalette::Normal,QColorGroup::Highlight);
00146
00147 d->drawClickMsg = false;
00148 }
00149
00150 void KLineEdit::setCompletionMode( KGlobalSettings::Completion mode )
00151 {
00152 KGlobalSettings::Completion oldMode = completionMode();
00153
00154 if ( oldMode != mode && (oldMode == KGlobalSettings::CompletionPopup ||
00155 oldMode == KGlobalSettings::CompletionPopupAuto ) &&
00156 d->completionBox && d->completionBox->isVisible() )
00157 d->completionBox->hide();
00158
00159
00160
00161 if ( echoMode() != QLineEdit::Normal )
00162 mode = KGlobalSettings::CompletionNone;
00163
00164 if ( kapp && !kapp->authorize("lineedit_text_completion") )
00165 mode = KGlobalSettings::CompletionNone;
00166
00167 if ( mode == KGlobalSettings::CompletionPopupAuto ||
00168 mode == KGlobalSettings::CompletionAuto ||
00169 mode == KGlobalSettings::CompletionMan )
00170 d->autoSuggest = true;
00171 else
00172 d->autoSuggest = false;
00173
00174 KCompletionBase::setCompletionMode( mode );
00175 }
00176
00177 void KLineEdit::setCompletedText( const QString& t, bool marked )
00178 {
00179 if ( !d->autoSuggest )
00180 return;
00181
00182 QString txt = text();
00183
00184 if ( t != txt )
00185 {
00186 int start = marked ? txt.length() : t.length();
00187 validateAndSet( t, cursorPosition(), start, t.length() );
00188 setUserSelection(false);
00189 }
00190 else
00191 setUserSelection(true);
00192
00193 }
00194
00195 void KLineEdit::setCompletedText( const QString& text )
00196 {
00197 KGlobalSettings::Completion mode = completionMode();
00198 bool marked = ( mode == KGlobalSettings::CompletionAuto ||
00199 mode == KGlobalSettings::CompletionMan ||
00200 mode == KGlobalSettings::CompletionPopup ||
00201 mode == KGlobalSettings::CompletionPopupAuto );
00202 setCompletedText( text, marked );
00203 }
00204
00205 void KLineEdit::rotateText( KCompletionBase::KeyBindingType type )
00206 {
00207 KCompletion* comp = compObj();
00208 if ( comp &&
00209 (type == KCompletionBase::PrevCompletionMatch ||
00210 type == KCompletionBase::NextCompletionMatch ) )
00211 {
00212 QString input;
00213
00214 if (type == KCompletionBase::PrevCompletionMatch)
00215 comp->previousMatch();
00216 else
00217 comp->nextMatch();
00218
00219
00220 if ( input.isNull() || input == displayText() )
00221 return;
00222 setCompletedText( input, hasSelectedText() );
00223 }
00224 }
00225
00226 void KLineEdit::makeCompletion( const QString& text )
00227 {
00228 KCompletion *comp = compObj();
00229 KGlobalSettings::Completion mode = completionMode();
00230
00231 if ( !comp || mode == KGlobalSettings::CompletionNone )
00232 return;
00233
00234 QString match = comp->makeCompletion( text );
00235
00236 if ( mode == KGlobalSettings::CompletionPopup ||
00237 mode == KGlobalSettings::CompletionPopupAuto )
00238 {
00239 if ( match.isNull() )
00240 {
00241 if ( d->completionBox )
00242 {
00243 d->completionBox->hide();
00244 d->completionBox->clear();
00245 }
00246 }
00247 else
00248 setCompletedItems( comp->allMatches() );
00249 }
00250 else
00251 {
00252
00253
00254 if ( match.isNull() || match == text )
00255 return;
00256
00257 if ( mode != KGlobalSettings::CompletionShell )
00258 setUserSelection(false);
00259
00260 if ( d->autoSuggest )
00261 setCompletedText( match );
00262 }
00263 }
00264
00265 void KLineEdit::setReadOnly(bool readOnly)
00266 {
00267
00268 if (readOnly == isReadOnly ())
00269 return;
00270
00271 QLineEdit::setReadOnly (readOnly);
00272
00273 if (readOnly)
00274 {
00275 d->bgMode = backgroundMode ();
00276 setBackgroundMode (Qt::PaletteBackground);
00277 if (d->enableSqueezedText && d->squeezedText.isEmpty())
00278 {
00279 d->squeezedText = text();
00280 setSqueezedText();
00281 }
00282 }
00283 else
00284 {
00285 if (!d->squeezedText.isEmpty())
00286 {
00287 setText(d->squeezedText);
00288 d->squeezedText = QString::null;
00289 }
00290 setBackgroundMode (d->bgMode);
00291 }
00292 }
00293
00294 void KLineEdit::setSqueezedText( const QString &text)
00295 {
00296 setEnableSqueezedText(true);
00297 setText(text);
00298 }
00299
00300 void KLineEdit::setEnableSqueezedText( bool enable )
00301 {
00302 d->enableSqueezedText = enable;
00303 }
00304
00305 bool KLineEdit::isSqueezedTextEnabled() const
00306 {
00307 return d->enableSqueezedText;
00308 }
00309
00310 void KLineEdit::setText( const QString& text )
00311 {
00312 d->drawClickMsg = text.isEmpty() && !d->clickMessage.isEmpty();
00313 update();
00314
00315 if( d->enableSqueezedText && isReadOnly() )
00316 {
00317 d->squeezedText = text;
00318 setSqueezedText();
00319 return;
00320 }
00321
00322 QLineEdit::setText( text );
00323 }
00324
00325 void KLineEdit::setSqueezedText()
00326 {
00327 d->squeezedStart = 0;
00328 d->squeezedEnd = 0;
00329 QString fullText = d->squeezedText;
00330 QFontMetrics fm(fontMetrics());
00331 int labelWidth = size().width() - 2*frameWidth() - 2;
00332 int textWidth = fm.width(fullText);
00333
00334 if (textWidth > labelWidth)
00335 {
00336
00337 QString squeezedText = "...";
00338 int squeezedWidth = fm.width(squeezedText);
00339
00340
00341 int letters = fullText.length() * (labelWidth - squeezedWidth) / textWidth / 2;
00342 squeezedText = fullText.left(letters) + "..." + fullText.right(letters);
00343 squeezedWidth = fm.width(squeezedText);
00344
00345 if (squeezedWidth < labelWidth)
00346 {
00347
00348
00349 do
00350 {
00351 letters++;
00352 squeezedText = fullText.left(letters) + "..." + fullText.right(letters);
00353 squeezedWidth = fm.width(squeezedText);
00354 } while (squeezedWidth < labelWidth);
00355 letters--;
00356 squeezedText = fullText.left(letters) + "..." + fullText.right(letters);
00357 }
00358 else if (squeezedWidth > labelWidth)
00359 {
00360
00361
00362 do
00363 {
00364 letters--;
00365 squeezedText = fullText.left(letters) + "..." + fullText.right(letters);
00366 squeezedWidth = fm.width(squeezedText);
00367 } while (squeezedWidth > labelWidth);
00368 }
00369
00370 if (letters < 5)
00371 {
00372
00373 QLineEdit::setText(fullText);
00374 }
00375 else
00376 {
00377 QLineEdit::setText(squeezedText);
00378 d->squeezedStart = letters;
00379 d->squeezedEnd = fullText.length() - letters;
00380 }
00381
00382 QToolTip::remove( this );
00383 QToolTip::add( this, fullText );
00384
00385 }
00386 else
00387 {
00388 QLineEdit::setText(fullText);
00389
00390 QToolTip::remove( this );
00391 QToolTip::hide();
00392 }
00393
00394 setCursorPosition(0);
00395 }
00396
00397 void KLineEdit::copy() const
00398 {
00399 if (!d->squeezedText.isEmpty() && d->squeezedStart)
00400 {
00401 int start, end;
00402 KLineEdit *that = const_cast<KLineEdit *>(this);
00403 if (!that->getSelection(&start, &end))
00404 return;
00405 if (start >= d->squeezedStart+3)
00406 start = start - 3 - d->squeezedStart + d->squeezedEnd;
00407 else if (start > d->squeezedStart)
00408 start = d->squeezedStart;
00409 if (end >= d->squeezedStart+3)
00410 end = end - 3 - d->squeezedStart + d->squeezedEnd;
00411 else if (end > d->squeezedStart)
00412 end = d->squeezedEnd;
00413 if (start == end)
00414 return;
00415 QString t = d->squeezedText;
00416 t = t.mid(start, end - start);
00417 disconnect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0);
00418 QApplication::clipboard()->setText( t );
00419 connect( QApplication::clipboard(), SIGNAL(selectionChanged()), this,
00420 SLOT(clipboardChanged()) );
00421 return;
00422 }
00423
00424 QLineEdit::copy();
00425 }
00426
00427 void KLineEdit::resizeEvent( QResizeEvent * ev )
00428 {
00429 if (!d->squeezedText.isEmpty())
00430 setSqueezedText();
00431
00432 QLineEdit::resizeEvent(ev);
00433 }
00434
00435 void KLineEdit::keyPressEvent( QKeyEvent *e )
00436 {
00437 KKey key( e );
00438
00439 if ( KStdAccel::copy().contains( key ) )
00440 {
00441 copy();
00442 return;
00443 }
00444 else if ( KStdAccel::paste().contains( key ) )
00445 {
00446 paste();
00447 return;
00448 }
00449 else if ( KStdAccel::pasteSelection().contains( key ) )
00450 {
00451 QString text = QApplication::clipboard()->text( QClipboard::Selection);
00452 insert( text );
00453 deselect();
00454 return;
00455 }
00456
00457 else if ( KStdAccel::cut().contains( key ) )
00458 {
00459 cut();
00460 return;
00461 }
00462 else if ( KStdAccel::undo().contains( key ) )
00463 {
00464 undo();
00465 return;
00466 }
00467 else if ( KStdAccel::redo().contains( key ) )
00468 {
00469 redo();
00470 return;
00471 }
00472 else if ( KStdAccel::deleteWordBack().contains( key ) )
00473 {
00474 cursorWordBackward(true);
00475 if ( hasSelectedText() )
00476 del();
00477
00478 e->accept();
00479 return;
00480 }
00481 else if ( KStdAccel::deleteWordForward().contains( key ) )
00482 {
00483
00484 cursorWordForward(true);
00485 if ( hasSelectedText() )
00486 del();
00487
00488 e->accept();
00489 return;
00490 }
00491 else if ( KStdAccel::backwardWord().contains( key ) )
00492 {
00493 cursorWordBackward(false);
00494 e->accept();
00495 return;
00496 }
00497 else if ( KStdAccel::forwardWord().contains( key ) )
00498 {
00499 cursorWordForward(false);
00500 e->accept();
00501 return;
00502 }
00503 else if ( KStdAccel::beginningOfLine().contains( key ) )
00504 {
00505 home(false);
00506 e->accept();
00507 return;
00508 }
00509 else if ( KStdAccel::endOfLine().contains( key ) )
00510 {
00511 end(false);
00512 e->accept();
00513 return;
00514 }
00515
00516
00517
00518
00519 if ( echoMode() == QLineEdit::Normal &&
00520 completionMode() != KGlobalSettings::CompletionNone )
00521 {
00522 KeyBindingMap keys = getKeyBindings();
00523 KGlobalSettings::Completion mode = completionMode();
00524 bool noModifier = (e->state() == NoButton ||
00525 e->state() == ShiftButton ||
00526 e->state() == Keypad);
00527
00528 if ( (mode == KGlobalSettings::CompletionAuto ||
00529 mode == KGlobalSettings::CompletionPopupAuto ||
00530 mode == KGlobalSettings::CompletionMan) && noModifier )
00531 {
00532 if ( !d->userSelection && hasSelectedText() &&
00533 ( e->key() == Key_Right || e->key() == Key_Left ) &&
00534 e->state()==NoButton )
00535 {
00536 QString old_txt = text();
00537 d->disableRestoreSelection = true;
00538 int start,end;
00539 getSelection(&start, &end);
00540
00541 deselect();
00542 QLineEdit::keyPressEvent ( e );
00543 int cPosition=cursorPosition();
00544 if (e->key() ==Key_Right && cPosition > start )
00545 validateAndSet(old_txt, cPosition, cPosition, old_txt.length());
00546 else
00547 validateAndSet(old_txt, cPosition, start, old_txt.length());
00548
00549 d->disableRestoreSelection = false;
00550 return;
00551 }
00552
00553 if ( e->key() == Key_Escape )
00554 {
00555 if (hasSelectedText() && !d->userSelection )
00556 {
00557 del();
00558 setUserSelection(true);
00559 }
00560
00561
00562
00563 e->ignore();
00564 return;
00565 }
00566
00567 }
00568
00569 if ( (mode == KGlobalSettings::CompletionAuto ||
00570 mode == KGlobalSettings::CompletionMan) && noModifier )
00571 {
00572 QString keycode = e->text();
00573 if ( !keycode.isEmpty() && (keycode.unicode()->isPrint() ||
00574 e->key() == Key_Backspace || e->key() == Key_Delete ) )
00575 {
00576 bool hasUserSelection=d->userSelection;
00577 bool hadSelection=hasSelectedText();
00578
00579 bool cursorNotAtEnd=false;
00580
00581 int start,end;
00582 getSelection(&start, &end);
00583 int cPos = cursorPosition();
00584
00585
00586
00587
00588
00589 if ( hadSelection && !hasUserSelection && start>cPos )
00590 {
00591 del();
00592 setCursorPosition(cPos);
00593 cursorNotAtEnd=true;
00594 }
00595
00596 d->disableRestoreSelection = true;
00597 QLineEdit::keyPressEvent ( e );
00598 d->disableRestoreSelection = false;
00599
00600 QString txt = text();
00601 int len = txt.length();
00602 if ( !hasSelectedText() && len )
00603 {
00604 if ( e->key() == Key_Backspace )
00605 {
00606 if ( hadSelection && !hasUserSelection && !cursorNotAtEnd )
00607 {
00608 backspace();
00609 txt = text();
00610 len = txt.length();
00611 }
00612
00613 if ( !d->backspacePerformsCompletion || !len )
00614 d->autoSuggest = false;
00615 }
00616
00617 if (e->key() == Key_Delete )
00618 d->autoSuggest=false;
00619
00620 if ( emitSignals() )
00621 emit completion( txt );
00622
00623 if ( handleSignals() )
00624 makeCompletion( txt );
00625
00626 if( (e->key() == Key_Backspace || e->key() == Key_Delete) )
00627 d->autoSuggest=true;
00628
00629 e->accept();
00630 }
00631
00632 return;
00633 }
00634
00635 }
00636
00637 else if (( mode == KGlobalSettings::CompletionPopup ||
00638 mode == KGlobalSettings::CompletionPopupAuto ) &&
00639 noModifier && !e->text().isEmpty() )
00640 {
00641 QString old_txt = text();
00642 bool hasUserSelection=d->userSelection;
00643 bool hadSelection=hasSelectedText();
00644 bool cursorNotAtEnd=false;
00645
00646 int start,end;
00647 getSelection(&start, &end);
00648 int cPos = cursorPosition();
00649 QString keycode = e->text();
00650
00651
00652
00653
00654
00655 if (hadSelection && !hasUserSelection && start>cPos &&
00656 ( (!keycode.isEmpty() && keycode.unicode()->isPrint()) ||
00657 e->key() == Key_Backspace || e->key() == Key_Delete ) )
00658 {
00659 del();
00660 setCursorPosition(cPos);
00661 cursorNotAtEnd=true;
00662 }
00663
00664 uint selectedLength=selectedText().length();
00665
00666 d->disableRestoreSelection = true;
00667 QLineEdit::keyPressEvent ( e );
00668 d->disableRestoreSelection = false;
00669
00670 if (( selectedLength != selectedText().length() ) && !hasUserSelection )
00671 slotRestoreSelectionColors();
00672
00673 QString txt = text();
00674 int len = txt.length();
00675
00676 if ( txt != old_txt && len &&
00677 ( (!keycode.isEmpty() && keycode.unicode()->isPrint()) ||
00678 e->key() == Key_Backspace || e->key() == Key_Delete) )
00679 {
00680 if ( e->key() == Key_Backspace )
00681 {
00682 if ( hadSelection && !hasUserSelection && !cursorNotAtEnd )
00683 {
00684 backspace();
00685 txt = text();
00686 len = txt.length();
00687 }
00688
00689 if ( !d->backspacePerformsCompletion )
00690 d->autoSuggest = false;
00691 }
00692
00693 if (e->key() == Key_Delete )
00694 d->autoSuggest=false;
00695
00696 if ( d->completionBox )
00697 d->completionBox->setCancelledText( txt );
00698
00699 if ( emitSignals() )
00700 emit completion( txt );
00701
00702 if ( handleSignals() ) {
00703 makeCompletion( txt );
00704 }
00705
00706 if ( (e->key() == Key_Backspace || e->key() == Key_Delete ) &&
00707 mode == KGlobalSettings::CompletionPopupAuto )
00708 d->autoSuggest=true;
00709
00710 e->accept();
00711 }
00712 else if (!len && d->completionBox && d->completionBox->isVisible())
00713 d->completionBox->hide();
00714
00715 return;
00716 }
00717
00718 else if ( mode == KGlobalSettings::CompletionShell )
00719 {
00720
00721 KShortcut cut;
00722 if ( keys[TextCompletion].isNull() )
00723 cut = KStdAccel::shortcut(KStdAccel::TextCompletion);
00724 else
00725 cut = keys[TextCompletion];
00726
00727 if ( cut.contains( key ) )
00728 {
00729
00730
00731 QString txt = text();
00732 int len = txt.length();
00733 if ( cursorPosition() == len && len != 0 )
00734 {
00735 if ( emitSignals() )
00736 emit completion( txt );
00737 if ( handleSignals() )
00738 makeCompletion( txt );
00739 return;
00740 }
00741 }
00742 else if ( d->completionBox )
00743 d->completionBox->hide();
00744 }
00745
00746
00747 if ( mode != KGlobalSettings::CompletionNone )
00748 {
00749
00750 KShortcut cut;
00751 if ( keys[PrevCompletionMatch].isNull() )
00752 cut = KStdAccel::shortcut(KStdAccel::PrevCompletion);
00753 else
00754 cut = keys[PrevCompletionMatch];
00755
00756 if ( cut.contains( key ) )
00757 {
00758 if ( emitSignals() )
00759 emit textRotation( KCompletionBase::PrevCompletionMatch );
00760 if ( handleSignals() )
00761 rotateText( KCompletionBase::PrevCompletionMatch );
00762 return;
00763 }
00764
00765
00766 if ( keys[NextCompletionMatch].isNull() )
00767 cut = KStdAccel::shortcut(KStdAccel::NextCompletion);
00768 else
00769 cut = keys[NextCompletionMatch];
00770
00771 if ( cut.contains( key ) )
00772 {
00773 if ( emitSignals() )
00774 emit textRotation( KCompletionBase::NextCompletionMatch );
00775 if ( handleSignals() )
00776 rotateText( KCompletionBase::NextCompletionMatch );
00777 return;
00778 }
00779 }
00780
00781
00782 if ( compObj() )
00783 {
00784 KShortcut cut;
00785 if ( keys[SubstringCompletion].isNull() )
00786 cut = KStdAccel::shortcut(KStdAccel::SubstringCompletion);
00787 else
00788 cut = keys[SubstringCompletion];
00789
00790 if ( cut.contains( key ) )
00791 {
00792 if ( emitSignals() )
00793 emit substringCompletion( text() );
00794 if ( handleSignals() )
00795 {
00796 setCompletedItems( compObj()->substringCompletion(text()));
00797 e->accept();
00798 }
00799 return;
00800 }
00801 }
00802 }
00803
00804 uint selectedLength = selectedText().length();
00805
00806
00807 QLineEdit::keyPressEvent ( e );
00808
00809 if ( selectedLength != selectedText().length() )
00810 slotRestoreSelectionColors();
00811 }
00812
00813 void KLineEdit::mouseDoubleClickEvent( QMouseEvent* e )
00814 {
00815 if ( e->button() == Qt::LeftButton )
00816 {
00817 possibleTripleClick=true;
00818 QTimer::singleShot( QApplication::doubleClickInterval(),this,
00819 SLOT(tripleClickTimeout()) );
00820 }
00821 QLineEdit::mouseDoubleClickEvent( e );
00822 }
00823
00824 void KLineEdit::mousePressEvent( QMouseEvent* e )
00825 {
00826 if ( possibleTripleClick && e->button() == Qt::LeftButton )
00827 {
00828 selectAll();
00829 e->accept();
00830 return;
00831 }
00832 QLineEdit::mousePressEvent( e );
00833 }
00834
00835 void KLineEdit::tripleClickTimeout()
00836 {
00837 possibleTripleClick=false;
00838 }
00839
00840 void KLineEdit::contextMenuEvent( QContextMenuEvent * e )
00841 {
00842 if ( m_bEnableMenu )
00843 QLineEdit::contextMenuEvent( e );
00844 }
00845
00846 QPopupMenu *KLineEdit::createPopupMenu()
00847 {
00848 enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelectAll };
00849
00850 QPopupMenu *popup = QLineEdit::createPopupMenu();
00851
00852 int id = popup->idAt(0);
00853 popup->changeItem( id - IdUndo, SmallIconSet("undo"), popup->text( id - IdUndo) );
00854 popup->changeItem( id - IdRedo, SmallIconSet("redo"), popup->text( id - IdRedo) );
00855 popup->changeItem( id - IdCut, SmallIconSet("editcut"), popup->text( id - IdCut) );
00856 popup->changeItem( id - IdCopy, SmallIconSet("editcopy"), popup->text( id - IdCopy) );
00857 popup->changeItem( id - IdPaste, SmallIconSet("editpaste"), popup->text( id - IdPaste) );
00858 popup->changeItem( id - IdClear, SmallIconSet("editclear"), popup->text( id - IdClear) );
00859
00860
00861
00862
00863 if ( compObj() && !isReadOnly() && kapp->authorize("lineedit_text_completion") )
00864 {
00865 QPopupMenu *subMenu = new QPopupMenu( popup );
00866 connect( subMenu, SIGNAL( activated( int ) ),
00867 this, SLOT( completionMenuActivated( int ) ) );
00868
00869 popup->insertSeparator();
00870 popup->insertItem( SmallIconSet("completion"), i18n("Text Completion"),
00871 subMenu );
00872
00873 subMenu->insertItem( i18n("None"), NoCompletion );
00874 subMenu->insertItem( i18n("Manual"), ShellCompletion );
00875 subMenu->insertItem( i18n("Automatic"), AutoCompletion );
00876 subMenu->insertItem( i18n("Dropdown List"), PopupCompletion );
00877 subMenu->insertItem( i18n("Short Automatic"), ShortAutoCompletion );
00878 subMenu->insertItem( i18n("Dropdown List && Automatic"), PopupAutoCompletion );
00879
00880 subMenu->setAccel( KStdAccel::completion(), ShellCompletion );
00881
00882 KGlobalSettings::Completion mode = completionMode();
00883 subMenu->setItemChecked( NoCompletion,
00884 mode == KGlobalSettings::CompletionNone );
00885 subMenu->setItemChecked( ShellCompletion,
00886 mode == KGlobalSettings::CompletionShell );
00887 subMenu->setItemChecked( PopupCompletion,
00888 mode == KGlobalSettings::CompletionPopup );
00889 subMenu->setItemChecked( AutoCompletion,
00890 mode == KGlobalSettings::CompletionAuto );
00891 subMenu->setItemChecked( ShortAutoCompletion,
00892 mode == KGlobalSettings::CompletionMan );
00893 subMenu->setItemChecked( PopupAutoCompletion,
00894 mode == KGlobalSettings::CompletionPopupAuto );
00895 if ( mode != KGlobalSettings::completionMode() )
00896 {
00897 subMenu->insertSeparator();
00898 subMenu->insertItem( i18n("Default"), Default );
00899 }
00900 }
00901
00902
00903
00904
00905 emit aboutToShowContextMenu( popup );
00906
00907 return popup;
00908 }
00909
00910 void KLineEdit::completionMenuActivated( int id )
00911 {
00912 KGlobalSettings::Completion oldMode = completionMode();
00913
00914 switch ( id )
00915 {
00916 case Default:
00917 setCompletionMode( KGlobalSettings::completionMode() );
00918 break;
00919 case NoCompletion:
00920 setCompletionMode( KGlobalSettings::CompletionNone );
00921 break;
00922 case AutoCompletion:
00923 setCompletionMode( KGlobalSettings::CompletionAuto );
00924 break;
00925 case ShortAutoCompletion:
00926 setCompletionMode( KGlobalSettings::CompletionMan );
00927 break;
00928 case ShellCompletion:
00929 setCompletionMode( KGlobalSettings::CompletionShell );
00930 break;
00931 case PopupCompletion:
00932 setCompletionMode( KGlobalSettings::CompletionPopup );
00933 break;
00934 case PopupAutoCompletion:
00935 setCompletionMode( KGlobalSettings::CompletionPopupAuto );
00936 break;
00937 default:
00938 return;
00939 }
00940
00941 if ( oldMode != completionMode() )
00942 {
00943 if ( (oldMode == KGlobalSettings::CompletionPopup ||
00944 oldMode == KGlobalSettings::CompletionPopupAuto ) &&
00945 d->completionBox && d->completionBox->isVisible() )
00946 d->completionBox->hide();
00947 emit completionModeChanged( completionMode() );
00948 }
00949 }
00950
00951 void KLineEdit::drawContents( QPainter *p )
00952 {
00953 QLineEdit::drawContents( p );
00954
00955 if ( d->drawClickMsg && !hasFocus() ) {
00956 QPen tmp = p->pen();
00957 p->setPen( palette().color( QPalette::Disabled, QColorGroup::Text ) );
00958 QRect cr = contentsRect();
00959
00960
00961 cr.rLeft() += 3;
00962 p->drawText( cr, AlignAuto | AlignVCenter, d->clickMessage );
00963 p->setPen( tmp );
00964 }
00965 }
00966
00967 void KLineEdit::dropEvent(QDropEvent *e)
00968 {
00969 d->drawClickMsg = false;
00970 KURL::List urlList;
00971 if( d->handleURLDrops && KURLDrag::decode( e, urlList ) )
00972 {
00973 QString dropText = text();
00974 KURL::List::ConstIterator it;
00975 for( it = urlList.begin() ; it != urlList.end() ; ++it )
00976 {
00977 if(!dropText.isEmpty())
00978 dropText+=' ';
00979
00980 dropText += (*it).prettyURL();
00981 }
00982
00983 validateAndSet( dropText, dropText.length(), 0, 0);
00984
00985 e->accept();
00986 }
00987 else
00988 QLineEdit::dropEvent(e);
00989 }
00990
00991 bool KLineEdit::eventFilter( QObject* o, QEvent* ev )
00992 {
00993 if( o == this )
00994 {
00995 KCursor::autoHideEventFilter( this, ev );
00996 if ( ev->type() == QEvent::AccelOverride )
00997 {
00998 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
00999 if (overrideAccel (e))
01000 {
01001 e->accept();
01002 return true;
01003 }
01004 }
01005 else if( ev->type() == QEvent::KeyPress )
01006 {
01007 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
01008
01009 if( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
01010 {
01011 bool trap = d->completionBox && d->completionBox->isVisible();
01012
01013 bool stopEvent = trap || (d->grabReturnKeyEvents &&
01014 (e->state() == NoButton ||
01015 e->state() == Keypad));
01016
01017
01018 if ( stopEvent )
01019 {
01020 emit QLineEdit::returnPressed();
01021 e->accept ();
01022 }
01023
01024 emit returnPressed( displayText() );
01025
01026 if ( trap )
01027 {
01028 d->completionBox->hide();
01029 deselect();
01030 setCursorPosition(text().length());
01031 }
01032
01033
01034 return stopEvent;
01035 }
01036 }
01037 }
01038 return QLineEdit::eventFilter( o, ev );
01039 }
01040
01041
01042 void KLineEdit::setURLDropsEnabled(bool enable)
01043 {
01044 d->handleURLDrops=enable;
01045 }
01046
01047 bool KLineEdit::isURLDropsEnabled() const
01048 {
01049 return d->handleURLDrops;
01050 }
01051
01052 void KLineEdit::setTrapReturnKey( bool grab )
01053 {
01054 d->grabReturnKeyEvents = grab;
01055 }
01056
01057 bool KLineEdit::trapReturnKey() const
01058 {
01059 return d->grabReturnKeyEvents;
01060 }
01061
01062 void KLineEdit::setURL( const KURL& url )
01063 {
01064 setText( url.prettyURL() );
01065 }
01066
01067 void KLineEdit::setCompletionBox( KCompletionBox *box )
01068 {
01069 if ( d->completionBox )
01070 return;
01071
01072 d->completionBox = box;
01073 if ( handleSignals() )
01074 {
01075 connect( d->completionBox, SIGNAL(highlighted( const QString& )),
01076 SLOT(setTextWorkaround( const QString& )) );
01077 connect( d->completionBox, SIGNAL(userCancelled( const QString& )),
01078 SLOT(userCancelled( const QString& )) );
01079
01080
01081 connect( d->completionBox, SIGNAL( activated( const QString& )),
01082 SIGNAL(completionBoxActivated( const QString& )) );
01083 }
01084 }
01085
01086 void KLineEdit::userCancelled(const QString & cancelText)
01087 {
01088 if ( completionMode() != KGlobalSettings::CompletionPopupAuto )
01089 {
01090
01091 setText(cancelText);
01092 }
01093 else if (hasSelectedText() )
01094 {
01095 if (d->userSelection)
01096 deselect();
01097 else
01098 {
01099 d->autoSuggest=false;
01100 int start,end;
01101 getSelection(&start, &end);
01102 QString s=text().remove(start, end-start+1);
01103 validateAndSet(s,start,s.length(),s.length());
01104 d->autoSuggest=true;
01105 }
01106 }
01107 }
01108
01109 bool KLineEdit::overrideAccel (const QKeyEvent* e)
01110 {
01111 KShortcut scKey;
01112
01113 KKey key( e );
01114 KeyBindingMap keys = getKeyBindings();
01115
01116 if (keys[TextCompletion].isNull())
01117 scKey = KStdAccel::shortcut(KStdAccel::TextCompletion);
01118 else
01119 scKey = keys[TextCompletion];
01120
01121 if (scKey.contains( key ))
01122 return true;
01123
01124 if (keys[NextCompletionMatch].isNull())
01125 scKey = KStdAccel::shortcut(KStdAccel::NextCompletion);
01126 else
01127 scKey = keys[NextCompletionMatch];
01128
01129 if (scKey.contains( key ))
01130 return true;
01131
01132 if (keys[PrevCompletionMatch].isNull())
01133 scKey = KStdAccel::shortcut(KStdAccel::PrevCompletion);
01134 else
01135 scKey = keys[PrevCompletionMatch];
01136
01137 if (scKey.contains( key ))
01138 return true;
01139
01140
01141 if ( KStdAccel::copy().contains( key ) )
01142 return true;
01143 else if ( KStdAccel::paste().contains( key ) )
01144 return true;
01145 else if ( KStdAccel::cut().contains( key ) )
01146 return true;
01147 else if ( KStdAccel::undo().contains( key ) )
01148 return true;
01149 else if ( KStdAccel::redo().contains( key ) )
01150 return true;
01151 else if (KStdAccel::deleteWordBack().contains( key ))
01152 return true;
01153 else if (KStdAccel::deleteWordForward().contains( key ))
01154 return true;
01155 else if (KStdAccel::forwardWord().contains( key ))
01156 return true;
01157 else if (KStdAccel::backwardWord().contains( key ))
01158 return true;
01159 else if (KStdAccel::beginningOfLine().contains( key ))
01160 return true;
01161 else if (KStdAccel::endOfLine().contains( key ))
01162 return true;
01163
01164 if (d->completionBox && d->completionBox->isVisible ())
01165 {
01166 int key = e->key();
01167 ButtonState state = e->state();
01168 if ((key == Key_Backtab || key == Key_Tab) &&
01169 (state == NoButton || (state & ShiftButton)))
01170 {
01171 return true;
01172 }
01173 }
01174
01175
01176 return false;
01177 }
01178
01179 void KLineEdit::setCompletedItems( const QStringList& items )
01180 {
01181 setCompletedItems( items, true );
01182 }
01183
01184 void KLineEdit::setCompletedItems( const QStringList& items, bool autoSuggest )
01185 {
01186 QString txt;
01187 if ( d->completionBox && d->completionBox->isVisible() ) {
01188
01189
01190 txt = completionBox()->cancelledText();
01191 } else {
01192 txt = text();
01193 }
01194
01195 if ( !items.isEmpty() &&
01196 !(items.count() == 1 && txt == items.first()) )
01197 {
01198
01199 completionBox();
01200
01201 if ( d->completionBox->isVisible() )
01202 {
01203 bool wasSelected = d->completionBox->isSelected( d->completionBox->currentItem() );
01204 const QString currentSelection = d->completionBox->currentText();
01205 d->completionBox->setItems( items );
01206 QListBoxItem* item = d->completionBox->findItem( currentSelection, Qt::ExactMatch );
01207
01208
01209
01210 if( !item || !wasSelected )
01211 {
01212 wasSelected = false;
01213 item = d->completionBox->item( 0 );
01214 }
01215 if ( item )
01216 {
01217 d->completionBox->blockSignals( true );
01218 d->completionBox->setCurrentItem( item );
01219 d->completionBox->setSelected( item, wasSelected );
01220 d->completionBox->blockSignals( false );
01221 }
01222 }
01223 else
01224 {
01225 if ( !txt.isEmpty() )
01226 d->completionBox->setCancelledText( txt );
01227 d->completionBox->setItems( items );
01228 d->completionBox->popup();
01229 }
01230
01231 if ( d->autoSuggest && autoSuggest )
01232 {
01233 int index = items.first().find( txt );
01234 QString newText = items.first().mid( index );
01235 setUserSelection(false);
01236 setCompletedText(newText,true);
01237 }
01238 }
01239 else
01240 {
01241 if ( d->completionBox && d->completionBox->isVisible() )
01242 d->completionBox->hide();
01243 }
01244 }
01245
01246 KCompletionBox * KLineEdit::completionBox( bool create )
01247 {
01248 if ( create && !d->completionBox ) {
01249 setCompletionBox( new KCompletionBox( this, "completion box" ) );
01250 d->completionBox->setFont(font());
01251 }
01252
01253 return d->completionBox;
01254 }
01255
01256 void KLineEdit::setCompletionObject( KCompletion* comp, bool hsig )
01257 {
01258 KCompletion *oldComp = compObj();
01259 if ( oldComp && handleSignals() )
01260 disconnect( oldComp, SIGNAL( matches( const QStringList& )),
01261 this, SLOT( setCompletedItems( const QStringList& )));
01262
01263 if ( comp && hsig )
01264 connect( comp, SIGNAL( matches( const QStringList& )),
01265 this, SLOT( setCompletedItems( const QStringList& )));
01266
01267 KCompletionBase::setCompletionObject( comp, hsig );
01268 }
01269
01270
01271 void KLineEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
01272 {
01273 QLineEdit::create( id, initializeWindow, destroyOldWindow );
01274 KCursor::setAutoHideCursor( this, true, true );
01275 }
01276
01277 void KLineEdit::setUserSelection(bool userSelection)
01278 {
01279 QPalette p = palette();
01280
01281 if (userSelection)
01282 {
01283 p.setColor(QColorGroup::Highlight, d->previousHighlightColor);
01284 p.setColor(QColorGroup::HighlightedText, d->previousHighlightedTextColor);
01285 }
01286 else
01287 {
01288 QColor color=p.color(QPalette::Disabled, QColorGroup::Text);
01289 p.setColor(QColorGroup::HighlightedText, color);
01290 color=p.color(QPalette::Active, QColorGroup::Base);
01291 p.setColor(QColorGroup::Highlight, color);
01292 }
01293
01294 d->userSelection=userSelection;
01295 setPalette(p);
01296 }
01297
01298 void KLineEdit::slotRestoreSelectionColors()
01299 {
01300 if (d->disableRestoreSelection)
01301 return;
01302
01303 setUserSelection(true);
01304 }
01305
01306 void KLineEdit::clear()
01307 {
01308 setText( QString::null );
01309 }
01310
01311 void KLineEdit::setTextWorkaround( const QString& text )
01312 {
01313 setText( text );
01314 end( false );
01315 }
01316
01317 QString KLineEdit::originalText() const
01318 {
01319 if ( d->enableSqueezedText && isReadOnly() )
01320 return d->squeezedText;
01321
01322 return text();
01323 }
01324
01325 void KLineEdit::focusInEvent( QFocusEvent* ev)
01326 {
01327 if ( d->drawClickMsg ) {
01328 d->drawClickMsg = false;
01329 update();
01330 }
01331
01332
01333 if ( ev->reason() == QFocusEvent::Tab && inputMask().isNull() && hasSelectedText() )
01334 return;
01335
01336 QLineEdit::focusInEvent(ev);
01337 }
01338
01339 void KLineEdit::focusOutEvent( QFocusEvent* ev)
01340 {
01341 if ( text().isEmpty() && !d->clickMessage.isEmpty() ) {
01342 d->drawClickMsg = true;
01343 update();
01344 }
01345 QLineEdit::focusOutEvent( ev );
01346 }
01347
01348 bool KLineEdit::autoSuggest() const
01349 {
01350 return d->autoSuggest;
01351 }
01352
01353 void KLineEdit::setClickMessage( const QString &msg )
01354 {
01355 d->clickMessage = msg;
01356 update();
01357 }
01358
01359 QString KLineEdit::clickMessage() const
01360 {
01361 return d->clickMessage;
01362 }
01363
01364
01365 void KLineEdit::virtual_hook( int id, void* data )
01366 { KCompletionBase::virtual_hook( id, data ); }