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