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( !copySqueezedText(true))
00400 QLineEdit::copy();
00401 }
00402
00403 bool KLineEdit::copySqueezedText(bool clipboard) const
00404 {
00405 if (!d->squeezedText.isEmpty() && d->squeezedStart)
00406 {
00407 int start, end;
00408 KLineEdit *that = const_cast<KLineEdit *>(this);
00409 if (!that->getSelection(&start, &end))
00410 return false;
00411 if (start >= d->squeezedStart+3)
00412 start = start - 3 - d->squeezedStart + d->squeezedEnd;
00413 else if (start > d->squeezedStart)
00414 start = d->squeezedStart;
00415 if (end >= d->squeezedStart+3)
00416 end = end - 3 - d->squeezedStart + d->squeezedEnd;
00417 else if (end > d->squeezedStart)
00418 end = d->squeezedEnd;
00419 if (start == end)
00420 return false;
00421 QString t = d->squeezedText;
00422 t = t.mid(start, end - start);
00423 disconnect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0);
00424 QApplication::clipboard()->setText( t, clipboard ? QClipboard::Clipboard : QClipboard::Selection );
00425 connect( QApplication::clipboard(), SIGNAL(selectionChanged()), this,
00426 SLOT(clipboardChanged()) );
00427 return true;
00428 }
00429 return false;
00430 }
00431
00432 void KLineEdit::resizeEvent( QResizeEvent * ev )
00433 {
00434 if (!d->squeezedText.isEmpty())
00435 setSqueezedText();
00436
00437 QLineEdit::resizeEvent(ev);
00438 }
00439
00440 void KLineEdit::keyPressEvent( QKeyEvent *e )
00441 {
00442 KKey key( e );
00443
00444 if ( KStdAccel::copy().contains( key ) )
00445 {
00446 copy();
00447 return;
00448 }
00449 else if ( KStdAccel::paste().contains( key ) )
00450 {
00451 paste();
00452 return;
00453 }
00454 else if ( KStdAccel::pasteSelection().contains( key ) )
00455 {
00456 QString text = QApplication::clipboard()->text( QClipboard::Selection);
00457 insert( text );
00458 deselect();
00459 return;
00460 }
00461
00462 else if ( KStdAccel::cut().contains( key ) )
00463 {
00464 cut();
00465 return;
00466 }
00467 else if ( KStdAccel::undo().contains( key ) )
00468 {
00469 undo();
00470 return;
00471 }
00472 else if ( KStdAccel::redo().contains( key ) )
00473 {
00474 redo();
00475 return;
00476 }
00477 else if ( KStdAccel::deleteWordBack().contains( key ) )
00478 {
00479 cursorWordBackward(true);
00480 if ( hasSelectedText() )
00481 del();
00482
00483 e->accept();
00484 return;
00485 }
00486 else if ( KStdAccel::deleteWordForward().contains( key ) )
00487 {
00488
00489 cursorWordForward(true);
00490 if ( hasSelectedText() )
00491 del();
00492
00493 e->accept();
00494 return;
00495 }
00496 else if ( KStdAccel::backwardWord().contains( key ) )
00497 {
00498 cursorWordBackward(false);
00499 e->accept();
00500 return;
00501 }
00502 else if ( KStdAccel::forwardWord().contains( key ) )
00503 {
00504 cursorWordForward(false);
00505 e->accept();
00506 return;
00507 }
00508 else if ( KStdAccel::beginningOfLine().contains( key ) )
00509 {
00510 home(false);
00511 e->accept();
00512 return;
00513 }
00514 else if ( KStdAccel::endOfLine().contains( key ) )
00515 {
00516 end(false);
00517 e->accept();
00518 return;
00519 }
00520
00521
00522
00523
00524 if ( echoMode() == QLineEdit::Normal &&
00525 completionMode() != KGlobalSettings::CompletionNone )
00526 {
00527 KeyBindingMap keys = getKeyBindings();
00528 KGlobalSettings::Completion mode = completionMode();
00529 bool noModifier = (e->state() == NoButton ||
00530 e->state() == ShiftButton ||
00531 e->state() == Keypad);
00532
00533 if ( (mode == KGlobalSettings::CompletionAuto ||
00534 mode == KGlobalSettings::CompletionPopupAuto ||
00535 mode == KGlobalSettings::CompletionMan) && noModifier )
00536 {
00537 if ( !d->userSelection && hasSelectedText() &&
00538 ( e->key() == Key_Right || e->key() == Key_Left ) &&
00539 e->state()==NoButton )
00540 {
00541 QString old_txt = text();
00542 d->disableRestoreSelection = true;
00543 int start,end;
00544 getSelection(&start, &end);
00545
00546 deselect();
00547 QLineEdit::keyPressEvent ( e );
00548 int cPosition=cursorPosition();
00549 if (e->key() ==Key_Right && cPosition > start )
00550 validateAndSet(old_txt, cPosition, cPosition, old_txt.length());
00551 else
00552 validateAndSet(old_txt, cPosition, start, old_txt.length());
00553
00554 d->disableRestoreSelection = false;
00555 return;
00556 }
00557
00558 if ( e->key() == Key_Escape )
00559 {
00560 if (hasSelectedText() && !d->userSelection )
00561 {
00562 del();
00563 setUserSelection(true);
00564 }
00565
00566
00567
00568 e->ignore();
00569 return;
00570 }
00571
00572 }
00573
00574 if ( (mode == KGlobalSettings::CompletionAuto ||
00575 mode == KGlobalSettings::CompletionMan) && noModifier )
00576 {
00577 QString keycode = e->text();
00578 if ( !keycode.isEmpty() && (keycode.unicode()->isPrint() ||
00579 e->key() == Key_Backspace || e->key() == Key_Delete ) )
00580 {
00581 bool hasUserSelection=d->userSelection;
00582 bool hadSelection=hasSelectedText();
00583
00584 bool cursorNotAtEnd=false;
00585
00586 int start,end;
00587 getSelection(&start, &end);
00588 int cPos = cursorPosition();
00589
00590
00591
00592
00593
00594 if ( hadSelection && !hasUserSelection && start>cPos )
00595 {
00596 del();
00597 setCursorPosition(cPos);
00598 cursorNotAtEnd=true;
00599 }
00600
00601 d->disableRestoreSelection = true;
00602 QLineEdit::keyPressEvent ( e );
00603 d->disableRestoreSelection = false;
00604
00605 QString txt = text();
00606 int len = txt.length();
00607 if ( !hasSelectedText() && len )
00608 {
00609 if ( e->key() == Key_Backspace )
00610 {
00611 if ( hadSelection && !hasUserSelection && !cursorNotAtEnd )
00612 {
00613 backspace();
00614 txt = text();
00615 len = txt.length();
00616 }
00617
00618 if ( !d->backspacePerformsCompletion || !len )
00619 d->autoSuggest = false;
00620 }
00621
00622 if (e->key() == Key_Delete )
00623 d->autoSuggest=false;
00624
00625 if ( emitSignals() )
00626 emit completion( txt );
00627
00628 if ( handleSignals() )
00629 makeCompletion( txt );
00630
00631 if( (e->key() == Key_Backspace || e->key() == Key_Delete) )
00632 d->autoSuggest=true;
00633
00634 e->accept();
00635 }
00636
00637 return;
00638 }
00639
00640 }
00641
00642 else if (( mode == KGlobalSettings::CompletionPopup ||
00643 mode == KGlobalSettings::CompletionPopupAuto ) &&
00644 noModifier && !e->text().isEmpty() )
00645 {
00646 QString old_txt = text();
00647 bool hasUserSelection=d->userSelection;
00648 bool hadSelection=hasSelectedText();
00649 bool cursorNotAtEnd=false;
00650
00651 int start,end;
00652 getSelection(&start, &end);
00653 int cPos = cursorPosition();
00654 QString keycode = e->text();
00655
00656
00657
00658
00659
00660 if (hadSelection && !hasUserSelection && start>cPos &&
00661 ( (!keycode.isEmpty() && keycode.unicode()->isPrint()) ||
00662 e->key() == Key_Backspace || e->key() == Key_Delete ) )
00663 {
00664 del();
00665 setCursorPosition(cPos);
00666 cursorNotAtEnd=true;
00667 }
00668
00669 uint selectedLength=selectedText().length();
00670
00671 d->disableRestoreSelection = true;
00672 QLineEdit::keyPressEvent ( e );
00673 d->disableRestoreSelection = false;
00674
00675 if (( selectedLength != selectedText().length() ) && !hasUserSelection )
00676 slotRestoreSelectionColors();
00677
00678 QString txt = text();
00679 int len = txt.length();
00680
00681 if ( txt != old_txt && len &&
00682 ( (!keycode.isEmpty() && keycode.unicode()->isPrint()) ||
00683 e->key() == Key_Backspace || e->key() == Key_Delete) )
00684 {
00685 if ( e->key() == Key_Backspace )
00686 {
00687 if ( hadSelection && !hasUserSelection && !cursorNotAtEnd )
00688 {
00689 backspace();
00690 txt = text();
00691 len = txt.length();
00692 }
00693
00694 if ( !d->backspacePerformsCompletion )
00695 d->autoSuggest = false;
00696 }
00697
00698 if (e->key() == Key_Delete )
00699 d->autoSuggest=false;
00700
00701 if ( d->completionBox )
00702 d->completionBox->setCancelledText( txt );
00703
00704 if ( emitSignals() )
00705 emit completion( txt );
00706
00707 if ( handleSignals() ) {
00708 makeCompletion( txt );
00709 }
00710
00711 if ( (e->key() == Key_Backspace || e->key() == Key_Delete ) &&
00712 mode == KGlobalSettings::CompletionPopupAuto )
00713 d->autoSuggest=true;
00714
00715 e->accept();
00716 }
00717 else if (!len && d->completionBox && d->completionBox->isVisible())
00718 d->completionBox->hide();
00719
00720 return;
00721 }
00722
00723 else if ( mode == KGlobalSettings::CompletionShell )
00724 {
00725
00726 KShortcut cut;
00727 if ( keys[TextCompletion].isNull() )
00728 cut = KStdAccel::shortcut(KStdAccel::TextCompletion);
00729 else
00730 cut = keys[TextCompletion];
00731
00732 if ( cut.contains( key ) )
00733 {
00734
00735
00736 QString txt = text();
00737 int len = txt.length();
00738 if ( cursorPosition() == len && len != 0 )
00739 {
00740 if ( emitSignals() )
00741 emit completion( txt );
00742 if ( handleSignals() )
00743 makeCompletion( txt );
00744 return;
00745 }
00746 }
00747 else if ( d->completionBox )
00748 d->completionBox->hide();
00749 }
00750
00751
00752 if ( mode != KGlobalSettings::CompletionNone )
00753 {
00754
00755 KShortcut cut;
00756 if ( keys[PrevCompletionMatch].isNull() )
00757 cut = KStdAccel::shortcut(KStdAccel::PrevCompletion);
00758 else
00759 cut = keys[PrevCompletionMatch];
00760
00761 if ( cut.contains( key ) )
00762 {
00763 if ( emitSignals() )
00764 emit textRotation( KCompletionBase::PrevCompletionMatch );
00765 if ( handleSignals() )
00766 rotateText( KCompletionBase::PrevCompletionMatch );
00767 return;
00768 }
00769
00770
00771 if ( keys[NextCompletionMatch].isNull() )
00772 cut = KStdAccel::shortcut(KStdAccel::NextCompletion);
00773 else
00774 cut = keys[NextCompletionMatch];
00775
00776 if ( cut.contains( key ) )
00777 {
00778 if ( emitSignals() )
00779 emit textRotation( KCompletionBase::NextCompletionMatch );
00780 if ( handleSignals() )
00781 rotateText( KCompletionBase::NextCompletionMatch );
00782 return;
00783 }
00784 }
00785
00786
00787 if ( compObj() )
00788 {
00789 KShortcut cut;
00790 if ( keys[SubstringCompletion].isNull() )
00791 cut = KStdAccel::shortcut(KStdAccel::SubstringCompletion);
00792 else
00793 cut = keys[SubstringCompletion];
00794
00795 if ( cut.contains( key ) )
00796 {
00797 if ( emitSignals() )
00798 emit substringCompletion( text() );
00799 if ( handleSignals() )
00800 {
00801 setCompletedItems( compObj()->substringCompletion(text()));
00802 e->accept();
00803 }
00804 return;
00805 }
00806 }
00807 }
00808
00809 uint selectedLength = selectedText().length();
00810
00811
00812 QLineEdit::keyPressEvent ( e );
00813
00814 if ( selectedLength != selectedText().length() )
00815 slotRestoreSelectionColors();
00816 }
00817
00818 void KLineEdit::mouseDoubleClickEvent( QMouseEvent* e )
00819 {
00820 if ( e->button() == Qt::LeftButton )
00821 {
00822 possibleTripleClick=true;
00823 QTimer::singleShot( QApplication::doubleClickInterval(),this,
00824 SLOT(tripleClickTimeout()) );
00825 }
00826 QLineEdit::mouseDoubleClickEvent( e );
00827 }
00828
00829 void KLineEdit::mousePressEvent( QMouseEvent* e )
00830 {
00831 if ( possibleTripleClick && e->button() == Qt::LeftButton )
00832 {
00833 selectAll();
00834 e->accept();
00835 return;
00836 }
00837 QLineEdit::mousePressEvent( e );
00838 }
00839
00840 void KLineEdit::mouseReleaseEvent( QMouseEvent* e )
00841 {
00842 QLineEdit::mouseReleaseEvent( e );
00843 if (QApplication::clipboard()->supportsSelection() ) {
00844 if ( e->button() == LeftButton ) {
00845
00846 copySqueezedText( false );
00847 }
00848 }
00849 }
00850
00851 void KLineEdit::tripleClickTimeout()
00852 {
00853 possibleTripleClick=false;
00854 }
00855
00856 void KLineEdit::contextMenuEvent( QContextMenuEvent * e )
00857 {
00858 if ( m_bEnableMenu )
00859 QLineEdit::contextMenuEvent( e );
00860 }
00861
00862 QPopupMenu *KLineEdit::createPopupMenu()
00863 {
00864 enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelectAll };
00865
00866 QPopupMenu *popup = QLineEdit::createPopupMenu();
00867
00868 int id = popup->idAt(0);
00869 popup->changeItem( id - IdUndo, SmallIconSet("undo"), popup->text( id - IdUndo) );
00870 popup->changeItem( id - IdRedo, SmallIconSet("redo"), popup->text( id - IdRedo) );
00871 popup->changeItem( id - IdCut, SmallIconSet("editcut"), popup->text( id - IdCut) );
00872 popup->changeItem( id - IdCopy, SmallIconSet("editcopy"), popup->text( id - IdCopy) );
00873 popup->changeItem( id - IdPaste, SmallIconSet("editpaste"), popup->text( id - IdPaste) );
00874 popup->changeItem( id - IdClear, SmallIconSet("editclear"), popup->text( id - IdClear) );
00875
00876
00877
00878
00879 if ( compObj() && !isReadOnly() && kapp->authorize("lineedit_text_completion") )
00880 {
00881 QPopupMenu *subMenu = new QPopupMenu( popup );
00882 connect( subMenu, SIGNAL( activated( int ) ),
00883 this, SLOT( completionMenuActivated( int ) ) );
00884
00885 popup->insertSeparator();
00886 popup->insertItem( SmallIconSet("completion"), i18n("Text Completion"),
00887 subMenu );
00888
00889 subMenu->insertItem( i18n("None"), NoCompletion );
00890 subMenu->insertItem( i18n("Manual"), ShellCompletion );
00891 subMenu->insertItem( i18n("Automatic"), AutoCompletion );
00892 subMenu->insertItem( i18n("Dropdown List"), PopupCompletion );
00893 subMenu->insertItem( i18n("Short Automatic"), ShortAutoCompletion );
00894 subMenu->insertItem( i18n("Dropdown List && Automatic"), PopupAutoCompletion );
00895
00896 subMenu->setAccel( KStdAccel::completion(), ShellCompletion );
00897
00898 KGlobalSettings::Completion mode = completionMode();
00899 subMenu->setItemChecked( NoCompletion,
00900 mode == KGlobalSettings::CompletionNone );
00901 subMenu->setItemChecked( ShellCompletion,
00902 mode == KGlobalSettings::CompletionShell );
00903 subMenu->setItemChecked( PopupCompletion,
00904 mode == KGlobalSettings::CompletionPopup );
00905 subMenu->setItemChecked( AutoCompletion,
00906 mode == KGlobalSettings::CompletionAuto );
00907 subMenu->setItemChecked( ShortAutoCompletion,
00908 mode == KGlobalSettings::CompletionMan );
00909 subMenu->setItemChecked( PopupAutoCompletion,
00910 mode == KGlobalSettings::CompletionPopupAuto );
00911 if ( mode != KGlobalSettings::completionMode() )
00912 {
00913 subMenu->insertSeparator();
00914 subMenu->insertItem( i18n("Default"), Default );
00915 }
00916 }
00917
00918
00919
00920
00921 emit aboutToShowContextMenu( popup );
00922
00923 return popup;
00924 }
00925
00926 void KLineEdit::completionMenuActivated( int id )
00927 {
00928 KGlobalSettings::Completion oldMode = completionMode();
00929
00930 switch ( id )
00931 {
00932 case Default:
00933 setCompletionMode( KGlobalSettings::completionMode() );
00934 break;
00935 case NoCompletion:
00936 setCompletionMode( KGlobalSettings::CompletionNone );
00937 break;
00938 case AutoCompletion:
00939 setCompletionMode( KGlobalSettings::CompletionAuto );
00940 break;
00941 case ShortAutoCompletion:
00942 setCompletionMode( KGlobalSettings::CompletionMan );
00943 break;
00944 case ShellCompletion:
00945 setCompletionMode( KGlobalSettings::CompletionShell );
00946 break;
00947 case PopupCompletion:
00948 setCompletionMode( KGlobalSettings::CompletionPopup );
00949 break;
00950 case PopupAutoCompletion:
00951 setCompletionMode( KGlobalSettings::CompletionPopupAuto );
00952 break;
00953 default:
00954 return;
00955 }
00956
00957 if ( oldMode != completionMode() )
00958 {
00959 if ( (oldMode == KGlobalSettings::CompletionPopup ||
00960 oldMode == KGlobalSettings::CompletionPopupAuto ) &&
00961 d->completionBox && d->completionBox->isVisible() )
00962 d->completionBox->hide();
00963 emit completionModeChanged( completionMode() );
00964 }
00965 }
00966
00967 void KLineEdit::drawContents( QPainter *p )
00968 {
00969 QLineEdit::drawContents( p );
00970
00971 if ( d->drawClickMsg && !hasFocus() ) {
00972 QPen tmp = p->pen();
00973 p->setPen( palette().color( QPalette::Disabled, QColorGroup::Text ) );
00974 QRect cr = contentsRect();
00975
00976
00977 cr.rLeft() += 3;
00978 p->drawText( cr, AlignAuto | AlignVCenter, d->clickMessage );
00979 p->setPen( tmp );
00980 }
00981 }
00982
00983 void KLineEdit::dropEvent(QDropEvent *e)
00984 {
00985 d->drawClickMsg = false;
00986 KURL::List urlList;
00987 if( d->handleURLDrops && KURLDrag::decode( e, urlList ) )
00988 {
00989 QString dropText = text();
00990 KURL::List::ConstIterator it;
00991 for( it = urlList.begin() ; it != urlList.end() ; ++it )
00992 {
00993 if(!dropText.isEmpty())
00994 dropText+=' ';
00995
00996 dropText += (*it).prettyURL();
00997 }
00998
00999 validateAndSet( dropText, dropText.length(), 0, 0);
01000
01001 e->accept();
01002 }
01003 else
01004 QLineEdit::dropEvent(e);
01005 }
01006
01007 bool KLineEdit::eventFilter( QObject* o, QEvent* ev )
01008 {
01009 if( o == this )
01010 {
01011 KCursor::autoHideEventFilter( this, ev );
01012 if ( ev->type() == QEvent::AccelOverride )
01013 {
01014 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
01015 if (overrideAccel (e))
01016 {
01017 e->accept();
01018 return true;
01019 }
01020 }
01021 else if( ev->type() == QEvent::KeyPress )
01022 {
01023 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
01024
01025 if( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
01026 {
01027 bool trap = d->completionBox && d->completionBox->isVisible();
01028
01029 bool stopEvent = trap || (d->grabReturnKeyEvents &&
01030 (e->state() == NoButton ||
01031 e->state() == Keypad));
01032
01033
01034 if ( stopEvent )
01035 {
01036 emit QLineEdit::returnPressed();
01037 e->accept ();
01038 }
01039
01040 emit returnPressed( displayText() );
01041
01042 if ( trap )
01043 {
01044 d->completionBox->hide();
01045 deselect();
01046 setCursorPosition(text().length());
01047 }
01048
01049
01050 return stopEvent;
01051 }
01052 }
01053 }
01054 return QLineEdit::eventFilter( o, ev );
01055 }
01056
01057
01058 void KLineEdit::setURLDropsEnabled(bool enable)
01059 {
01060 d->handleURLDrops=enable;
01061 }
01062
01063 bool KLineEdit::isURLDropsEnabled() const
01064 {
01065 return d->handleURLDrops;
01066 }
01067
01068 void KLineEdit::setTrapReturnKey( bool grab )
01069 {
01070 d->grabReturnKeyEvents = grab;
01071 }
01072
01073 bool KLineEdit::trapReturnKey() const
01074 {
01075 return d->grabReturnKeyEvents;
01076 }
01077
01078 void KLineEdit::setURL( const KURL& url )
01079 {
01080 setText( url.prettyURL() );
01081 }
01082
01083 void KLineEdit::setCompletionBox( KCompletionBox *box )
01084 {
01085 if ( d->completionBox )
01086 return;
01087
01088 d->completionBox = box;
01089 if ( handleSignals() )
01090 {
01091 connect( d->completionBox, SIGNAL(highlighted( const QString& )),
01092 SLOT(setTextWorkaround( const QString& )) );
01093 connect( d->completionBox, SIGNAL(userCancelled( const QString& )),
01094 SLOT(userCancelled( const QString& )) );
01095
01096
01097 connect( d->completionBox, SIGNAL( activated( const QString& )),
01098 SIGNAL(completionBoxActivated( const QString& )) );
01099 }
01100 }
01101
01102 void KLineEdit::userCancelled(const QString & cancelText)
01103 {
01104 if ( completionMode() != KGlobalSettings::CompletionPopupAuto )
01105 {
01106
01107 setText(cancelText);
01108 }
01109 else if (hasSelectedText() )
01110 {
01111 if (d->userSelection)
01112 deselect();
01113 else
01114 {
01115 d->autoSuggest=false;
01116 int start,end;
01117 getSelection(&start, &end);
01118 QString s=text().remove(start, end-start+1);
01119 validateAndSet(s,start,s.length(),s.length());
01120 d->autoSuggest=true;
01121 }
01122 }
01123 }
01124
01125 bool KLineEdit::overrideAccel (const QKeyEvent* e)
01126 {
01127 KShortcut scKey;
01128
01129 KKey key( e );
01130 KeyBindingMap keys = getKeyBindings();
01131
01132 if (keys[TextCompletion].isNull())
01133 scKey = KStdAccel::shortcut(KStdAccel::TextCompletion);
01134 else
01135 scKey = keys[TextCompletion];
01136
01137 if (scKey.contains( key ))
01138 return true;
01139
01140 if (keys[NextCompletionMatch].isNull())
01141 scKey = KStdAccel::shortcut(KStdAccel::NextCompletion);
01142 else
01143 scKey = keys[NextCompletionMatch];
01144
01145 if (scKey.contains( key ))
01146 return true;
01147
01148 if (keys[PrevCompletionMatch].isNull())
01149 scKey = KStdAccel::shortcut(KStdAccel::PrevCompletion);
01150 else
01151 scKey = keys[PrevCompletionMatch];
01152
01153 if (scKey.contains( key ))
01154 return true;
01155
01156
01157 if ( KStdAccel::copy().contains( key ) )
01158 return true;
01159 else if ( KStdAccel::paste().contains( key ) )
01160 return true;
01161 else if ( KStdAccel::cut().contains( key ) )
01162 return true;
01163 else if ( KStdAccel::undo().contains( key ) )
01164 return true;
01165 else if ( KStdAccel::redo().contains( key ) )
01166 return true;
01167 else if (KStdAccel::deleteWordBack().contains( key ))
01168 return true;
01169 else if (KStdAccel::deleteWordForward().contains( key ))
01170 return true;
01171 else if (KStdAccel::forwardWord().contains( key ))
01172 return true;
01173 else if (KStdAccel::backwardWord().contains( key ))
01174 return true;
01175 else if (KStdAccel::beginningOfLine().contains( key ))
01176 return true;
01177 else if (KStdAccel::endOfLine().contains( key ))
01178 return true;
01179
01180 if (d->completionBox && d->completionBox->isVisible ())
01181 {
01182 int key = e->key();
01183 ButtonState state = e->state();
01184 if ((key == Key_Backtab || key == Key_Tab) &&
01185 (state == NoButton || (state & ShiftButton)))
01186 {
01187 return true;
01188 }
01189 }
01190
01191
01192 return false;
01193 }
01194
01195 void KLineEdit::setCompletedItems( const QStringList& items )
01196 {
01197 setCompletedItems( items, true );
01198 }
01199
01200 void KLineEdit::setCompletedItems( const QStringList& items, bool autoSuggest )
01201 {
01202 QString txt;
01203 if ( d->completionBox && d->completionBox->isVisible() ) {
01204
01205
01206 txt = completionBox()->cancelledText();
01207 } else {
01208 txt = text();
01209 }
01210
01211 if ( !items.isEmpty() &&
01212 !(items.count() == 1 && txt == items.first()) )
01213 {
01214
01215 completionBox();
01216
01217 if ( d->completionBox->isVisible() )
01218 {
01219 bool wasSelected = d->completionBox->isSelected( d->completionBox->currentItem() );
01220 const QString currentSelection = d->completionBox->currentText();
01221 d->completionBox->setItems( items );
01222 QListBoxItem* item = d->completionBox->findItem( currentSelection, Qt::ExactMatch );
01223
01224
01225
01226 if( !item || !wasSelected )
01227 {
01228 wasSelected = false;
01229 item = d->completionBox->item( 0 );
01230 }
01231 if ( item )
01232 {
01233 d->completionBox->blockSignals( true );
01234 d->completionBox->setCurrentItem( item );
01235 d->completionBox->setSelected( item, wasSelected );
01236 d->completionBox->blockSignals( false );
01237 }
01238 }
01239 else
01240 {
01241 if ( !txt.isEmpty() )
01242 d->completionBox->setCancelledText( txt );
01243 d->completionBox->setItems( items );
01244 d->completionBox->popup();
01245 }
01246
01247 if ( d->autoSuggest && autoSuggest )
01248 {
01249 int index = items.first().find( txt );
01250 QString newText = items.first().mid( index );
01251 setUserSelection(false);
01252 setCompletedText(newText,true);
01253 }
01254 }
01255 else
01256 {
01257 if ( d->completionBox && d->completionBox->isVisible() )
01258 d->completionBox->hide();
01259 }
01260 }
01261
01262 KCompletionBox * KLineEdit::completionBox( bool create )
01263 {
01264 if ( create && !d->completionBox ) {
01265 setCompletionBox( new KCompletionBox( this, "completion box" ) );
01266 d->completionBox->setFont(font());
01267 }
01268
01269 return d->completionBox;
01270 }
01271
01272 void KLineEdit::setCompletionObject( KCompletion* comp, bool hsig )
01273 {
01274 KCompletion *oldComp = compObj();
01275 if ( oldComp && handleSignals() )
01276 disconnect( oldComp, SIGNAL( matches( const QStringList& )),
01277 this, SLOT( setCompletedItems( const QStringList& )));
01278
01279 if ( comp && hsig )
01280 connect( comp, SIGNAL( matches( const QStringList& )),
01281 this, SLOT( setCompletedItems( const QStringList& )));
01282
01283 KCompletionBase::setCompletionObject( comp, hsig );
01284 }
01285
01286
01287 void KLineEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
01288 {
01289 QLineEdit::create( id, initializeWindow, destroyOldWindow );
01290 KCursor::setAutoHideCursor( this, true, true );
01291 }
01292
01293 void KLineEdit::setUserSelection(bool userSelection)
01294 {
01295 QPalette p = palette();
01296
01297 if (userSelection)
01298 {
01299 p.setColor(QColorGroup::Highlight, d->previousHighlightColor);
01300 p.setColor(QColorGroup::HighlightedText, d->previousHighlightedTextColor);
01301 }
01302 else
01303 {
01304 QColor color=p.color(QPalette::Disabled, QColorGroup::Text);
01305 p.setColor(QColorGroup::HighlightedText, color);
01306 color=p.color(QPalette::Active, QColorGroup::Base);
01307 p.setColor(QColorGroup::Highlight, color);
01308 }
01309
01310 d->userSelection=userSelection;
01311 setPalette(p);
01312 }
01313
01314 void KLineEdit::slotRestoreSelectionColors()
01315 {
01316 if (d->disableRestoreSelection)
01317 return;
01318
01319 setUserSelection(true);
01320 }
01321
01322 void KLineEdit::clear()
01323 {
01324 setText( QString::null );
01325 }
01326
01327 void KLineEdit::setTextWorkaround( const QString& text )
01328 {
01329 setText( text );
01330 end( false );
01331 }
01332
01333 QString KLineEdit::originalText() const
01334 {
01335 if ( d->enableSqueezedText && isReadOnly() )
01336 return d->squeezedText;
01337
01338 return text();
01339 }
01340
01341 void KLineEdit::focusInEvent( QFocusEvent* ev)
01342 {
01343 if ( d->drawClickMsg ) {
01344 d->drawClickMsg = false;
01345 update();
01346 }
01347
01348
01349 if ( ev->reason() == QFocusEvent::Tab && inputMask().isNull() && hasSelectedText() )
01350 return;
01351
01352 QLineEdit::focusInEvent(ev);
01353 }
01354
01355 void KLineEdit::focusOutEvent( QFocusEvent* ev)
01356 {
01357 if ( text().isEmpty() && !d->clickMessage.isEmpty() ) {
01358 d->drawClickMsg = true;
01359 update();
01360 }
01361 QLineEdit::focusOutEvent( ev );
01362 }
01363
01364 bool KLineEdit::autoSuggest() const
01365 {
01366 return d->autoSuggest;
01367 }
01368
01369 void KLineEdit::setClickMessage( const QString &msg )
01370 {
01371 d->clickMessage = msg;
01372 update();
01373 }
01374
01375 QString KLineEdit::clickMessage() const
01376 {
01377 return d->clickMessage;
01378 }
01379
01380
01381 void KLineEdit::virtual_hook( int id, void* data )
01382 { KCompletionBase::virtual_hook( id, data ); }