Changeset View
Changeset View
Standalone View
Standalone View
krusader/BookMan/krbookmarkhandler.cpp
Show All 28 Lines | |||||
29 | #include "../Panel/krpanel.h" | 29 | #include "../Panel/krpanel.h" | ||
30 | #include "../Panel/listpanelactions.h" | 30 | #include "../Panel/listpanelactions.h" | ||
31 | 31 | | |||
32 | // QtCore | 32 | // QtCore | ||
33 | #include <QTextStream> | 33 | #include <QTextStream> | ||
34 | #include <QFile> | 34 | #include <QFile> | ||
35 | #include <QEvent> | 35 | #include <QEvent> | ||
36 | #include <QStandardPaths> | 36 | #include <QStandardPaths> | ||
37 | #include <QDebug> | ||||
37 | // QtGui | 38 | // QtGui | ||
38 | #include <QMouseEvent> | 39 | #include <QMouseEvent> | ||
39 | #include <QCursor> | 40 | #include <QCursor> | ||
40 | 41 | | |||
41 | #include <KConfigCore/KSharedConfig> | 42 | #include <KConfigCore/KSharedConfig> | ||
42 | #include <KI18n/KLocalizedString> | 43 | #include <KI18n/KLocalizedString> | ||
43 | #include <KIconThemes/KIconLoader> | 44 | #include <KIconThemes/KIconLoader> | ||
44 | #include <KWidgetsAddons/KMessageBox> | 45 | #include <KWidgetsAddons/KMessageBox> | ||
▲ Show 20 Lines • Show All 278 Lines • ▼ Show 20 Line(s) | |||||
323 | void KrBookmarkHandler::_setQuickSearchText(const QString &text) | 324 | void KrBookmarkHandler::_setQuickSearchText(const QString &text) | ||
324 | { | 325 | { | ||
325 | _quickSearchBar->setText(text); | 326 | _quickSearchBar->setText(text); | ||
326 | 327 | | |||
327 | auto length = text.length(); | 328 | auto length = text.length(); | ||
328 | _quickSearchAction->setVisible(length > 0); | 329 | _quickSearchAction->setVisible(length > 0); | ||
329 | _quickSearchBar->setVisible(length > 0); | 330 | _quickSearchBar->setVisible(length > 0); | ||
330 | if (length == 0) { | 331 | if (length == 0) { | ||
331 | resetShortcuts(); | 332 | qDebug() << "Bookmark search: reset"; | ||
333 | _resetActionTextAndHighlighting(); | ||||
334 | } else { | ||||
335 | qDebug() << "Bookmark search: query =" << text; | ||||
332 | } | 336 | } | ||
333 | } | 337 | } | ||
334 | 338 | | |||
335 | QString KrBookmarkHandler::_quickSearchText() const | 339 | QString KrBookmarkHandler::_quickSearchText() const | ||
336 | { | 340 | { | ||
337 | return _quickSearchBar->text(); | 341 | return _quickSearchBar->text(); | ||
338 | } | 342 | } | ||
339 | 343 | | |||
344 | void KrBookmarkHandler::_highlightAction(QAction *action, bool isMatched) | ||||
345 | { | ||||
346 | auto font = action->font(); | ||||
347 | font.setBold(isMatched); | ||||
348 | action->setFont(font); | ||||
349 | } | ||||
350 | | ||||
340 | void KrBookmarkHandler::populate(QMenu *menu) | 351 | void KrBookmarkHandler::populate(QMenu *menu) | ||
341 | { | 352 | { | ||
342 | _mainBookmarkPopup = menu; | 353 | _mainBookmarkPopup = menu; | ||
343 | menu->clear(); | 354 | menu->clear(); | ||
344 | _specialBookmarks.clear(); | 355 | _specialBookmarks.clear(); | ||
345 | buildMenu(_root, menu); | 356 | buildMenu(_root, menu); | ||
346 | } | 357 | } | ||
347 | 358 | | |||
▲ Show 20 Lines • Show All 157 Lines • ▼ Show 20 Line(s) | |||||
505 | bool KrBookmarkHandler::eventFilter(QObject *obj, QEvent *ev) | 516 | bool KrBookmarkHandler::eventFilter(QObject *obj, QEvent *ev) | ||
506 | { | 517 | { | ||
507 | if (obj->inherits("QMenu") && (ev->type() == QEvent::Show || | 518 | if (obj->inherits("QMenu") && (ev->type() == QEvent::Show || | ||
508 | ev->type() == QEvent::Close)) { | 519 | ev->type() == QEvent::Close)) { | ||
509 | _setQuickSearchText(""); | 520 | _setQuickSearchText(""); | ||
510 | } | 521 | } | ||
511 | 522 | | |||
512 | // Having it occur on keypress is consistent with other shortcuts, | 523 | // Having it occur on keypress is consistent with other shortcuts, | ||
513 | // such as ctrl+w and the '&' bookmark shortcut standard | 524 | // such as Ctrl+W and accelerator keys | ||
514 | // (&movies makes m a shortcut for said bookmark) | | |||
515 | if (ev->type() == QEvent::KeyPress && obj->inherits("QMenu")) { | 525 | if (ev->type() == QEvent::KeyPress && obj->inherits("QMenu")) { | ||
516 | QKeyEvent *kev = static_cast<QKeyEvent *>(ev); | 526 | QKeyEvent *kev = static_cast<QKeyEvent *>(ev); | ||
517 | QMenu *menu = static_cast<QMenu *>(obj); | 527 | QMenu *menu = static_cast<QMenu *>(obj); | ||
518 | QList<QAction *> acts = menu->actions(); | 528 | QList<QAction *> acts = menu->actions(); | ||
529 | bool quickSearchStarted = false; | ||||
519 | 530 | | |||
520 | if (kev->modifiers() != Qt::NoModifier || | 531 | if (kev->modifiers() != Qt::NoModifier || | ||
521 | kev->text().isEmpty() || | 532 | kev->text().isEmpty() || | ||
522 | kev->key() == Qt::Key_Delete) { | 533 | kev->key() == Qt::Key_Delete) { | ||
523 | return QObject::eventFilter(obj, ev); | 534 | return QObject::eventFilter(obj, ev); | ||
524 | } | 535 | } | ||
525 | 536 | | |||
537 | // update quick search text | ||||
526 | if (kev->key() == Qt::Key_Backspace) { | 538 | if (kev->key() == Qt::Key_Backspace) { | ||
527 | auto newSearchText = _quickSearchText(); | 539 | auto newSearchText = _quickSearchText(); | ||
528 | newSearchText.chop(1); | 540 | newSearchText.chop(1); | ||
529 | _setQuickSearchText(newSearchText); | 541 | _setQuickSearchText(newSearchText); | ||
530 | 542 | | |||
531 | if (_quickSearchText().length() == 0) { | 543 | if (_quickSearchText().length() == 0) { | ||
532 | return QObject::eventFilter(obj, ev); | 544 | return QObject::eventFilter(obj, ev); | ||
533 | } | 545 | } | ||
534 | } else { | 546 | } else { | ||
547 | quickSearchStarted = _quickSearchText().length() == 0; | ||||
535 | _setQuickSearchText(_quickSearchText().append(kev->text())); | 548 | _setQuickSearchText(_quickSearchText().append(kev->text())); | ||
536 | } | 549 | } | ||
537 | 550 | | |||
538 | QAction* found = nullptr; | 551 | if (quickSearchStarted) { | ||
539 | const int quickSearchTextLength = _quickSearchText().length(); | 552 | qDebug() << "Bookmark search: started"; | ||
540 | bool solematch; | 553 | } | ||
554 | | ||||
555 | // match actions | ||||
556 | QAction *firstMatch = nullptr; | ||||
557 | int nMatches = 0; | ||||
rade: Should use curly braces too match the rest of the code. | |||||
541 | for (auto act : acts) { | 558 | for (auto act : acts) { | ||
542 | if (act->isSeparator() || act->text() == "") { | 559 | if (act->isSeparator() || act->text() == "") { | ||
543 | continue; | 560 | continue; | ||
544 | } | 561 | } | ||
545 | 562 | | |||
546 | if (quickSearchTextLength == 1 && kev->key() != Qt::Key_Backspace && !kev->text().isEmpty()) { | 563 | if (quickSearchStarted) { | ||
564 | // if the first key press is an accelerator key, let the accelerator handler process this event | ||||
547 | if (act->text().contains('&' + kev->text(), Qt::CaseInsensitive)) { | 565 | if (act->text().contains('&' + kev->text(), Qt::CaseInsensitive)) { | ||
566 | qDebug() << "Bookmark search: hit accelerator key of" << act; | ||||
548 | _setQuickSearchText(""); | 567 | _setQuickSearchText(""); | ||
549 | break; | 568 | break; | ||
550 | } | 569 | } | ||
551 | 570 | | |||
552 | _msNamesWithAccelerators.insert(act, act->text()); | 571 | // strip accelerator keys from actions so they don't interfere with the search key press events | ||
572 | auto text = act->text(); | ||||
573 | _quickSearchOriginalActionTitles.insert(act, text); | ||||
574 | act->setText(KLocalizedString::removeAcceleratorMarker(text)); | ||||
553 | } | 575 | } | ||
554 | 576 | | |||
555 | act->setText(KLocalizedString::removeAcceleratorMarker(act->text())); | 577 | // match prefix of the action text to the query | ||
556 | if (act->text().left(quickSearchTextLength).compare(_quickSearchText(), Qt::CaseInsensitive) == 0) { | 578 | if (act->text().left(_quickSearchText().length()).compare(_quickSearchText(), Qt::CaseInsensitive) == 0) { | ||
557 | act->setText(createShortcutUnderline(act->text(), quickSearchTextLength)); | 579 | _highlightAction(act); | ||
558 | if (!found) { | 580 | if (!firstMatch) { | ||
559 | found = act; | 581 | firstMatch = act; | ||
560 | solematch = true; | | |||
561 | } else { | | |||
562 | solematch = false; | | |||
563 | } | 582 | } | ||
583 | nMatches++; | ||||
584 | } else { | ||||
585 | _highlightAction(act, false); | ||||
564 | } | 586 | } | ||
565 | } | 587 | } | ||
566 | 588 | | |||
567 | if (found && solematch) { | 589 | if (firstMatch) { | ||
568 | if ((bool) found->menu()) { | 590 | qDebug() << "Bookmark search: first match =" << firstMatch->text() << ", number of matches =" << nMatches; | ||
569 | menu->setActiveAction(found); | | |||
570 | } else { | 591 | } else { | ||
571 | found->activate(QAction::Trigger); | 592 | qDebug() << "Bookmark search: no matches"; | ||
572 | } | 593 | } | ||
594 | | ||||
595 | // trigger the matched menu item or set an active item accordingly | ||||
rade: Is there a reason this is not just if (nMatches == 1)? | |||||
596 | if (nMatches == 1) { | ||||
I feel this comment should be removed. It's apparent from the code that this is what is happening. And sparse comments seem to fit how the rest of the file is commented rade: I feel this comment should be removed. It's apparent from the code that this is what is… | |||||
573 | _setQuickSearchText(""); | 597 | _setQuickSearchText(""); | ||
574 | } else if (found && quickSearchTextLength > 1) { | 598 | if ((bool) firstMatch->menu()) { | ||
575 | // & bookmark code will give focus as long as there is only one | 599 | menu->setActiveAction(firstMatch); | ||
576 | // & character | 600 | } else { | ||
577 | menu->setActiveAction(found); | 601 | firstMatch->activate(QAction::Trigger); | ||
602 | } | ||||
603 | } else if (nMatches > 1) { | ||||
This should be moved to ahead of line 596. Otherwise if a match opens a submenu, i.e "popular urls" or a folder, that submenu will be offset from it's parent. This occurs because it's opened then the quicksearchbar hides moving everything up one step. As opposed to hiding the quicksearchbar and _then_ opening the submenu. rade: This should be moved to ahead of line 596. Otherwise if a match opens a submenu, i.e "popular… | |||||
604 | menu->setActiveAction(firstMatch); | ||||
rade: If this is changed to "if (nMatches > 1)" then this comment isn't needed. | |||||
578 | } | 605 | } | ||
579 | } | 606 | } | ||
580 | 607 | | |||
581 | if (ev->type() == QEvent::MouseButtonRelease) { | 608 | if (ev->type() == QEvent::MouseButtonRelease) { | ||
582 | switch (static_cast<QMouseEvent *>(ev)->button()) { | 609 | switch (static_cast<QMouseEvent *>(ev)->button()) { | ||
583 | case Qt::RightButton: | 610 | case Qt::RightButton: | ||
584 | _middleClick = false; | 611 | _middleClick = false; | ||
585 | if (obj->inherits("QMenu")) { | 612 | if (obj->inherits("QMenu")) { | ||
Show All 23 Lines | 634 | case Qt::MidButton: | |||
609 | break; | 636 | break; | ||
610 | default: | 637 | default: | ||
611 | break; | 638 | break; | ||
612 | } | 639 | } | ||
613 | } | 640 | } | ||
614 | return QObject::eventFilter(obj, ev); | 641 | return QObject::eventFilter(obj, ev); | ||
615 | } | 642 | } | ||
616 | 643 | | |||
617 | void KrBookmarkHandler::resetShortcuts() | 644 | void KrBookmarkHandler::_resetActionTextAndHighlighting() | ||
618 | { | 645 | { | ||
619 | QHash<QAction *, QString>::const_iterator i = _msNamesWithAccelerators.begin(); | 646 | for (QHash<QAction *, QString>::const_iterator i = _quickSearchOriginalActionTitles.begin(); | ||
620 | for (; i != _msNamesWithAccelerators.end(); ++i) { | 647 | i != _quickSearchOriginalActionTitles.end(); ++i) { | ||
621 | if (i.key()) { | 648 | QAction *action = i.key(); | ||
622 | i.key()->setText(i.value()); | 649 | action->setText(i.value()); | ||
623 | } | 650 | _highlightAction(action, false); | ||
624 | } | | |||
625 | _msNamesWithAccelerators.clear(); | | |||
626 | } | 651 | } | ||
627 | 652 | | |||
628 | QString KrBookmarkHandler::createShortcutUnderline(const QString &text, int underlineEnd) | 653 | _quickSearchOriginalActionTitles.clear(); | ||
629 | { | | |||
630 | if (underlineEnd <= 0) { | | |||
631 | return text; | | |||
632 | } | | |||
633 | if (underlineEnd > text.length()) { | | |||
634 | underlineEnd = text.length(); | | |||
635 | } | | |||
636 | | ||||
637 | QString underlinedtext = text; | | |||
638 | for (int i = 0; i < underlineEnd; i++) { | | |||
639 | if (underlinedtext[2 * i] != '&') { | | |||
640 | underlinedtext.insert(2 * i, '&'); | | |||
641 | } | | |||
642 | } | | |||
643 | return underlinedtext; | | |||
644 | } | 654 | } | ||
645 | 655 | | |||
646 | #define POPULAR_URLS_ID 100100 | 656 | #define POPULAR_URLS_ID 100100 | ||
647 | #define TRASH_ID 100101 | 657 | #define TRASH_ID 100101 | ||
648 | #define LAN_ID 100103 | 658 | #define LAN_ID 100103 | ||
649 | #define VIRTUAL_FS_ID 100102 | 659 | #define VIRTUAL_FS_ID 100102 | ||
650 | #define JUMP_BACK_ID 100104 | 660 | #define JUMP_BACK_ID 100104 | ||
651 | 661 | | |||
▲ Show 20 Lines • Show All 130 Lines • Show Last 20 Lines |
Should use curly braces too match the rest of the code.