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 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
00441
00442 else if ( e->key() == Key_Insert &&
00443 (e->state() == (ShiftButton | ControlButton)) )
00444 {
00445 #if QT_VERSION >= 0x030100
00446 QString text = QApplication::clipboard()->text( QClipboard::Selection);
00447 #else
00448 QClipboard *clip = QApplication::clipboard();
00449 bool oldMode = clip->selectionModeEnabled();
00450 clip->setSelectionMode( true );
00451 QString text = QApplication::clipboard()->text();
00452 clip->setSelectionMode( oldMode );
00453 #endif
00454
00455 insert( text );
00456 deselect();
00457 return;
00458 }
00459
00460 else if ( KStdAccel::cut().contains( key ) )
00461 {
00462 cut();
00463 return;
00464 }
00465 else if ( KStdAccel::undo().contains( key ) )
00466 {
00467 undo();
00468 return;
00469 }
00470 else if ( KStdAccel::redo().contains( key ) )
00471 {
00472 redo();
00473 return;
00474 }
00475 else if ( KStdAccel::deleteWordBack().contains( key ) )
00476 {
00477 cursorWordBackward(true);
00478 if ( hasSelectedText() )
00479 del();
00480
00481 e->accept();
00482 return;
00483 }
00484 else if ( KStdAccel::deleteWordForward().contains( key ) )
00485 {
00486
00487 cursorWordForward(true);
00488 if ( hasSelectedText() )
00489 del();
00490
00491 e->accept();
00492 return;
00493 }
00494
00495
00496
00497
00498 if ( echoMode() == QLineEdit::Normal &&
00499 completionMode() != KGlobalSettings::CompletionNone )
00500 {
00501 KeyBindingMap keys = getKeyBindings();
00502 KGlobalSettings::Completion mode = completionMode();
00503 bool noModifier = (e->state() == NoButton ||
00504 e->state() == ShiftButton ||
00505 e->state() == Keypad);
00506
00507 if ( (mode == KGlobalSettings::CompletionAuto ||
00508 mode == KGlobalSettings::CompletionPopupAuto ||
00509 mode == KGlobalSettings::CompletionMan) && noModifier )
00510 {
00511 if ( !d->userSelection && hasSelectedText() &&
00512 ( e->key() == Key_Right || e->key() == Key_Left ) &&
00513 e->state()==NoButton )
00514 {
00515 QString old_txt = text();
00516 d->disableRestoreSelection = true;
00517 int start,end;
00518 getSelection(&start, &end);
00519
00520 deselect();
00521 QLineEdit::keyPressEvent ( e );
00522 int cPosition=cursorPosition();
00523 if (e->key() ==Key_Right && cPosition > start )
00524 validateAndSet(old_txt, cPosition, cPosition, old_txt.length());
00525 else
00526 validateAndSet(old_txt, cPosition, start, old_txt.length());
00527
00528 d->disableRestoreSelection = false;
00529 return;
00530 }
00531
00532 if ( e->key() == Key_Escape )
00533 {
00534 if (hasSelectedText() && !d->userSelection )
00535 {
00536 del();
00537 setUserSelection(true);
00538 }
00539
00540
00541
00542 e->ignore();
00543 return;
00544 }
00545
00546 }
00547
00548 if ( (mode == KGlobalSettings::CompletionAuto ||
00549 mode == KGlobalSettings::CompletionMan) && noModifier )
00550 {
00551 QString keycode = e->text();
00552 if ( !keycode.isEmpty() && (keycode.unicode()->isPrint() ||
00553 e->key() == Key_Backspace || e->key() == Key_Delete ) )
00554 {
00555 bool hasUserSelection=d->userSelection;
00556 bool hadSelection=hasSelectedText();
00557
00558 bool cursorNotAtEnd=false;
00559
00560 int start,end;
00561 getSelection(&start, &end);
00562 int cPos = cursorPosition();
00563
00564
00565
00566
00567
00568 if ( hadSelection && !hasUserSelection && start>cPos )
00569 {
00570 del();
00571 setCursorPosition(cPos);
00572 cursorNotAtEnd=true;
00573 }
00574
00575 d->disableRestoreSelection = true;
00576 QLineEdit::keyPressEvent ( e );
00577 d->disableRestoreSelection = false;
00578
00579 QString txt = text();
00580 int len = txt.length();
00581 if ( !hasSelectedText() && len )
00582 {
00583 if ( e->key() == Key_Backspace )
00584 {
00585 if ( hadSelection && !hasUserSelection && !cursorNotAtEnd )
00586 {
00587 backspace();
00588 txt = text();
00589 len = txt.length();
00590 }
00591
00592 if ( !d->backspacePerformsCompletion || !len )
00593 d->autoSuggest = false;
00594 }
00595
00596 if (e->key() == Key_Delete )
00597 d->autoSuggest=false;
00598
00599 if ( emitSignals() )
00600 emit completion( txt );
00601
00602 if ( handleSignals() )
00603 makeCompletion( txt );
00604
00605 if( (e->key() == Key_Backspace || e->key() == Key_Delete) )
00606 d->autoSuggest=true;
00607
00608 e->accept();
00609 }
00610
00611 return;
00612 }
00613
00614 }
00615
00616 else if (( mode == KGlobalSettings::CompletionPopup ||
00617 mode == KGlobalSettings::CompletionPopupAuto ) &&
00618 noModifier && !e->text().isEmpty() )
00619 {
00620 QString old_txt = text();
00621
00622 bool hasUserSelection=d->userSelection;
00623 bool hadSelection=hasSelectedText();
00624 bool cursorNotAtEnd=false;
00625
00626 int start,end;
00627 getSelection(&start, &end);
00628 int cPos = cursorPosition();
00629 QString keycode = e->text();
00630
00631
00632
00633
00634
00635 if (hadSelection && !hasUserSelection && start>cPos &&
00636 ( (!keycode.isEmpty() && keycode.unicode()->isPrint()) ||
00637 e->key() == Key_Backspace || e->key() == Key_Delete ) )
00638 {
00639 del();
00640 setCursorPosition(cPos);
00641 cursorNotAtEnd=true;
00642 }
00643
00644 uint selectedLength=selectedText().length();
00645
00646 d->disableRestoreSelection = true;
00647 QLineEdit::keyPressEvent ( e );
00648 d->disableRestoreSelection = false;
00649
00650 if (( selectedLength != selectedText().length() ) && !hasUserSelection )
00651 slotRestoreSelectionColors();
00652
00653 QString txt = text();
00654 int len = txt.length();
00655
00656 if ( txt != old_txt && len &&
00657 ( (!keycode.isEmpty() && keycode.unicode()->isPrint()) ||
00658 e->key() == Key_Backspace || e->key() == Key_Delete) )
00659 {
00660 if ( e->key() == Key_Backspace )
00661 {
00662 if ( hadSelection && !hasUserSelection && !cursorNotAtEnd )
00663 {
00664 backspace();
00665 txt = text();
00666 len = txt.length();
00667 }
00668
00669 if ( !d->backspacePerformsCompletion )
00670 d->autoSuggest = false;
00671 }
00672
00673 if (e->key() == Key_Delete )
00674 d->autoSuggest=false;
00675
00676 if ( emitSignals() )
00677 emit completion( txt );
00678
00679 if ( handleSignals() )
00680 makeCompletion( txt );
00681
00682 if ( (e->key() == Key_Backspace || e->key() == Key_Delete ) &&
00683 mode == KGlobalSettings::CompletionPopupAuto )
00684 d->autoSuggest=true;
00685
00686 e->accept();
00687 }
00688 else if (!len && d->completionBox && d->completionBox->isVisible())
00689 d->completionBox->hide();
00690
00691 return;
00692 }
00693
00694 else if ( mode == KGlobalSettings::CompletionShell )
00695 {
00696
00697 KShortcut cut;
00698 if ( keys[TextCompletion].isNull() )
00699 cut = KStdAccel::shortcut(KStdAccel::TextCompletion);
00700 else
00701 cut = keys[TextCompletion];
00702
00703 if ( cut.contains( key ) )
00704 {
00705
00706
00707 QString txt = text();
00708 int len = txt.length();
00709 if ( cursorPosition() == len && len != 0 )
00710 {
00711 if ( emitSignals() )
00712 emit completion( txt );
00713 if ( handleSignals() )
00714 makeCompletion( txt );
00715 return;
00716 }
00717 }
00718 else if ( d->completionBox )
00719 d->completionBox->hide();
00720 }
00721
00722
00723 if ( mode != KGlobalSettings::CompletionNone )
00724 {
00725
00726 KShortcut cut;
00727 if ( keys[PrevCompletionMatch].isNull() )
00728 cut = KStdAccel::shortcut(KStdAccel::PrevCompletion);
00729 else
00730 cut = keys[PrevCompletionMatch];
00731
00732 if ( cut.contains( key ) )
00733 {
00734 if ( emitSignals() )
00735 emit textRotation( KCompletionBase::PrevCompletionMatch );
00736 if ( handleSignals() )
00737 rotateText( KCompletionBase::PrevCompletionMatch );
00738 return;
00739 }
00740
00741
00742 if ( keys[NextCompletionMatch].isNull() )
00743 cut = KStdAccel::shortcut(KStdAccel::NextCompletion);
00744 else
00745 cut = keys[NextCompletionMatch];
00746
00747 if ( cut.contains( key ) )
00748 {
00749 if ( emitSignals() )
00750 emit textRotation( KCompletionBase::NextCompletionMatch );
00751 if ( handleSignals() )
00752 rotateText( KCompletionBase::NextCompletionMatch );
00753 return;
00754 }
00755 }
00756
00757
00758 if ( compObj() )
00759 {
00760 KShortcut cut;
00761 if ( keys[SubstringCompletion].isNull() )
00762 cut = KStdAccel::shortcut(KStdAccel::SubstringCompletion);
00763 else
00764 cut = keys[SubstringCompletion];
00765
00766 if ( cut.contains( key ) )
00767 {
00768 if ( emitSignals() )
00769 emit substringCompletion( text() );
00770 if ( handleSignals() )
00771 {
00772 setCompletedItems( compObj()->substringCompletion(text()));
00773 e->accept();
00774 }
00775 return;
00776 }
00777 }
00778 }
00779
00780 uint selectedLength = selectedText().length();
00781
00782
00783 QLineEdit::keyPressEvent ( e );
00784
00785 if ( selectedLength != selectedText().length() )
00786 slotRestoreSelectionColors();
00787 }
00788
00789 void KLineEdit::mouseDoubleClickEvent( QMouseEvent* e )
00790 {
00791 if ( e->button() == Qt::LeftButton )
00792 {
00793 possibleTripleClick=true;
00794 QTimer::singleShot( QApplication::doubleClickInterval(),this,
00795 SLOT(tripleClickTimeout()) );
00796 }
00797 QLineEdit::mouseDoubleClickEvent( e );
00798 }
00799
00800 void KLineEdit::mousePressEvent( QMouseEvent* e )
00801 {
00802 if ( possibleTripleClick && e->button() == Qt::LeftButton )
00803 {
00804 selectAll();
00805 e->accept();
00806 return;
00807 }
00808 QLineEdit::mousePressEvent( e );
00809 }
00810
00811 void KLineEdit::tripleClickTimeout()
00812 {
00813 possibleTripleClick=false;
00814 }
00815
00816 QPopupMenu *KLineEdit::createPopupMenu()
00817 {
00818
00819 if ( !m_bEnableMenu )
00820 return 0;
00821
00822 QPopupMenu *popup = QLineEdit::createPopupMenu();
00823
00824
00825
00826
00827 if ( compObj() && !isReadOnly() && kapp->authorize("lineedit_text_completion") )
00828 {
00829 QPopupMenu *subMenu = new QPopupMenu( popup );
00830 connect( subMenu, SIGNAL( activated( int ) ),
00831 this, SLOT( completionMenuActivated( int ) ) );
00832
00833 popup->insertSeparator();
00834 popup->insertItem( SmallIconSet("completion"), i18n("Text Completion"),
00835 subMenu );
00836
00837 subMenu->insertItem( i18n("None"), NoCompletion );
00838 subMenu->insertItem( i18n("Manual"), ShellCompletion );
00839 subMenu->insertItem( i18n("Automatic"), AutoCompletion );
00840 subMenu->insertItem( i18n("Dropdown List"), PopupCompletion );
00841 subMenu->insertItem( i18n("Short Automatic"), ShortAutoCompletion );
00842 subMenu->insertItem( i18n("Dropdown List && Automatic"), PopupAutoCompletion );
00843
00844 subMenu->setAccel( KStdAccel::completion(), ShellCompletion );
00845
00846 KGlobalSettings::Completion mode = completionMode();
00847 subMenu->setItemChecked( NoCompletion,
00848 mode == KGlobalSettings::CompletionNone );
00849 subMenu->setItemChecked( ShellCompletion,
00850 mode == KGlobalSettings::CompletionShell );
00851 subMenu->setItemChecked( PopupCompletion,
00852 mode == KGlobalSettings::CompletionPopup );
00853 subMenu->setItemChecked( AutoCompletion,
00854 mode == KGlobalSettings::CompletionAuto );
00855 subMenu->setItemChecked( ShortAutoCompletion,
00856 mode == KGlobalSettings::CompletionMan );
00857 subMenu->setItemChecked( PopupAutoCompletion,
00858 mode == KGlobalSettings::CompletionPopupAuto );
00859 if ( mode != KGlobalSettings::completionMode() )
00860 {
00861 subMenu->insertSeparator();
00862 subMenu->insertItem( i18n("Default"), Default );
00863 }
00864 }
00865
00866
00867
00868
00869 emit aboutToShowContextMenu( popup );
00870
00871 return popup;
00872 }
00873
00874 void KLineEdit::completionMenuActivated( int id )
00875 {
00876 KGlobalSettings::Completion oldMode = completionMode();
00877
00878 switch ( id )
00879 {
00880 case Default:
00881 setCompletionMode( KGlobalSettings::completionMode() );
00882 break;
00883 case NoCompletion:
00884 setCompletionMode( KGlobalSettings::CompletionNone );
00885 break;
00886 case AutoCompletion:
00887 setCompletionMode( KGlobalSettings::CompletionAuto );
00888 break;
00889 case ShortAutoCompletion:
00890 setCompletionMode( KGlobalSettings::CompletionMan );
00891 break;
00892 case ShellCompletion:
00893 setCompletionMode( KGlobalSettings::CompletionShell );
00894 break;
00895 case PopupCompletion:
00896 setCompletionMode( KGlobalSettings::CompletionPopup );
00897 break;
00898 case PopupAutoCompletion:
00899 setCompletionMode( KGlobalSettings::CompletionPopupAuto );
00900 break;
00901 default:
00902 return;
00903 }
00904
00905 if ( oldMode != completionMode() )
00906 {
00907 if ( (oldMode == KGlobalSettings::CompletionPopup ||
00908 oldMode == KGlobalSettings::CompletionPopupAuto ) &&
00909 d->completionBox && d->completionBox->isVisible() )
00910 d->completionBox->hide();
00911 emit completionModeChanged( completionMode() );
00912 }
00913 }
00914
00915 void KLineEdit::dropEvent(QDropEvent *e)
00916 {
00917 KURL::List urlList;
00918 if( d->handleURLDrops && KURLDrag::decode( e, urlList ) )
00919 {
00920 QString dropText = text();
00921 KURL::List::ConstIterator it;
00922 for( it = urlList.begin() ; it != urlList.end() ; ++it )
00923 {
00924 if(!dropText.isEmpty())
00925 dropText+=' ';
00926
00927 dropText += (*it).prettyURL();
00928 }
00929
00930 validateAndSet( dropText, dropText.length(), 0, 0);
00931
00932 e->accept();
00933 }
00934 else
00935 QLineEdit::dropEvent(e);
00936 }
00937
00938 bool KLineEdit::eventFilter( QObject* o, QEvent* ev )
00939 {
00940 if( o == this )
00941 {
00942 KCursor::autoHideEventFilter( this, ev );
00943 if ( ev->type() == QEvent::AccelOverride )
00944 {
00945 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
00946 if (overrideAccel (e))
00947 {
00948 e->accept();
00949 return true;
00950 }
00951 }
00952 else if( ev->type() == QEvent::KeyPress )
00953 {
00954 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
00955
00956 if( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
00957 {
00958 bool trap = d->completionBox && d->completionBox->isVisible();
00959
00960 bool stopEvent = trap || (d->grabReturnKeyEvents &&
00961 (e->state() == NoButton ||
00962 e->state() == Keypad));
00963
00964
00965 if ( stopEvent )
00966 {
00967 emit QLineEdit::returnPressed();
00968 e->accept ();
00969 }
00970
00971 emit returnPressed( displayText() );
00972
00973 if ( trap )
00974 {
00975 d->completionBox->hide();
00976 deselect();
00977 setCursorPosition(text().length());
00978 }
00979
00980
00981 return stopEvent;
00982 }
00983 }
00984 }
00985 return QLineEdit::eventFilter( o, ev );
00986 }
00987
00988
00989 void KLineEdit::setURLDropsEnabled(bool enable)
00990 {
00991 d->handleURLDrops=enable;
00992 }
00993
00994 bool KLineEdit::isURLDropsEnabled() const
00995 {
00996 return d->handleURLDrops;
00997 }
00998
00999 void KLineEdit::setTrapReturnKey( bool grab )
01000 {
01001 d->grabReturnKeyEvents = grab;
01002 }
01003
01004 bool KLineEdit::trapReturnKey() const
01005 {
01006 return d->grabReturnKeyEvents;
01007 }
01008
01009 void KLineEdit::setURL( const KURL& url )
01010 {
01011 QLineEdit::setText( url.prettyURL() );
01012 }
01013
01014 void KLineEdit::makeCompletionBox()
01015 {
01016 if ( d->completionBox )
01017 return;
01018
01019 d->completionBox = new KCompletionBox( this, "completion box" );
01020 if ( handleSignals() )
01021 {
01022 connect( d->completionBox, SIGNAL(highlighted( const QString& )),
01023 SLOT(setTextWorkaround( const QString& )) );
01024 connect( d->completionBox, SIGNAL(userCancelled( const QString& )),
01025 SLOT(userCancelled( const QString& )) );
01026
01027 connect( d->completionBox, SIGNAL( activated( const QString& )),
01028 SIGNAL(completionBoxActivated( const QString& )) );
01029 }
01030 }
01031
01032 void KLineEdit::userCancelled(const QString & cancelText)
01033 {
01034 if ( completionMode() != KGlobalSettings::CompletionPopupAuto )
01035 {
01036 setText(cancelText);
01037 }
01038 else if (hasSelectedText() )
01039 {
01040 if (d->userSelection)
01041 deselect();
01042 else
01043 {
01044 d->autoSuggest=false;
01045 int start,end;
01046 getSelection(&start, &end);
01047 QString s=text().remove(start, end-start+1);
01048 validateAndSet(s,start,s.length(),s.length());
01049 d->autoSuggest=true;
01050 }
01051 }
01052 }
01053
01054 bool KLineEdit::overrideAccel (const QKeyEvent* e)
01055 {
01056 KShortcut scKey;
01057
01058 KKey key( e );
01059 KeyBindingMap keys = getKeyBindings();
01060
01061 if (keys[TextCompletion].isNull())
01062 scKey = KStdAccel::shortcut(KStdAccel::TextCompletion);
01063 else
01064 scKey = keys[TextCompletion];
01065
01066 if (scKey.contains( key ))
01067 return true;
01068
01069 if (keys[NextCompletionMatch].isNull())
01070 scKey = KStdAccel::shortcut(KStdAccel::NextCompletion);
01071 else
01072 scKey = keys[NextCompletionMatch];
01073
01074 if (scKey.contains( key ))
01075 return true;
01076
01077 if (keys[PrevCompletionMatch].isNull())
01078 scKey = KStdAccel::shortcut(KStdAccel::PrevCompletion);
01079 else
01080 scKey = keys[PrevCompletionMatch];
01081
01082 if (scKey.contains( key ))
01083 return true;
01084
01085
01086 if ( KStdAccel::copy().contains( key ) )
01087 return true;
01088 else if ( KStdAccel::paste().contains( key ) )
01089 return true;
01090 else if ( KStdAccel::cut().contains( key ) )
01091 return true;
01092 else if ( KStdAccel::undo().contains( key ) )
01093 return true;
01094 else if ( KStdAccel::redo().contains( key ) )
01095 return true;
01096 else if (KStdAccel::deleteWordBack().contains( key ))
01097 return true;
01098 else if (KStdAccel::deleteWordForward().contains( key ))
01099 return true;
01100
01101 if (d->completionBox && d->completionBox->isVisible ())
01102 {
01103 int key = e->key();
01104 ButtonState state = e->state();
01105 if ((key == Key_Backtab || key == Key_Tab) &&
01106 (state == NoButton || (state & ShiftButton)))
01107 {
01108 return true;
01109 }
01110 }
01111
01112
01113 return false;
01114 }
01115
01116 void KLineEdit::setCompletedItems( const QStringList& items )
01117 {
01118 QString txt = text();
01119
01120 if ( !items.isEmpty() &&
01121 !(items.count() == 1 && txt == items.first()) )
01122 {
01123 if ( !d->completionBox )
01124 makeCompletionBox();
01125
01126 if ( !txt.isEmpty() )
01127 d->completionBox->setCancelledText( txt );
01128
01129 d->completionBox->setItems( items );
01130 d->completionBox->popup();
01131
01132 if ( d->autoSuggest )
01133 {
01134 int index = items.first().find( txt );
01135 QString newText = items.first().mid( index );
01136 setUserSelection(false);
01137 setCompletedText(newText,true);
01138 }
01139 }
01140 else
01141 {
01142 if ( d->completionBox && d->completionBox->isVisible() )
01143 d->completionBox->hide();
01144 }
01145 }
01146
01147 KCompletionBox * KLineEdit::completionBox( bool create )
01148 {
01149 if ( create )
01150 makeCompletionBox();
01151
01152 return d->completionBox;
01153 }
01154
01155 void KLineEdit::setCompletionObject( KCompletion* comp, bool hsig )
01156 {
01157 KCompletion *oldComp = compObj();
01158 if ( oldComp && handleSignals() )
01159 disconnect( oldComp, SIGNAL( matches( const QStringList& )),
01160 this, SLOT( setCompletedItems( const QStringList& )));
01161
01162 if ( comp && hsig )
01163 connect( comp, SIGNAL( matches( const QStringList& )),
01164 this, SLOT( setCompletedItems( const QStringList& )));
01165
01166 KCompletionBase::setCompletionObject( comp, hsig );
01167 }
01168
01169
01170 void KLineEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
01171 {
01172 QLineEdit::create( id, initializeWindow, destroyOldWindow );
01173 KCursor::setAutoHideCursor( this, true, true );
01174 }
01175
01176 void KLineEdit::setUserSelection(bool userSelection)
01177 {
01178 QPalette p = palette();
01179
01180 if (userSelection)
01181 {
01182 p.setColor(QColorGroup::Highlight, d->previousHighlightColor);
01183 p.setColor(QColorGroup::HighlightedText, d->previousHighlightedTextColor);
01184 }
01185 else
01186 {
01187 QColor color=p.color(QPalette::Disabled, QColorGroup::Text);
01188 p.setColor(QColorGroup::HighlightedText, color);
01189 color=p.color(QPalette::Active, QColorGroup::Base);
01190 p.setColor(QColorGroup::Highlight, color);
01191 }
01192
01193 d->userSelection=userSelection;
01194 setPalette(p);
01195 }
01196
01197 void KLineEdit::slotRestoreSelectionColors()
01198 {
01199 if (d->disableRestoreSelection)
01200 return;
01201
01202 setUserSelection(true);
01203 }
01204
01205 void KLineEdit::clear()
01206 {
01207 setText( QString::null );
01208 }
01209
01210 void KLineEdit::setTextWorkaround( const QString& text )
01211 {
01212 setText( text );
01213 end( false );
01214 }
01215
01216 QString KLineEdit::originalText() const
01217 {
01218 if ( d->enableSqueezedText && isReadOnly() )
01219 return d->squeezedText;
01220
01221 return text();
01222 }
01223
01224 void KLineEdit::virtual_hook( int id, void* data )
01225 { KCompletionBase::virtual_hook( id, data ); }