From ca66940ec39047eada21f7900bf0e49d61cb45fb Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Sat, 14 Apr 2018 14:12:36 +0300 Subject: [PATCH] Popup improvements - ESC closes the popup. - Up/Down arrows for navigation. - BackTab for backwards navigation. fixes #301 fixes #302 --- include/SuggestionsPopup.hpp | 16 ++++++++-- include/TextInputWidget.h | 3 +- src/SuggestionsPopup.cpp | 59 ++++++++++++++++++++++++++---------- src/TextInputWidget.cc | 20 +++++++----- 4 files changed, 72 insertions(+), 26 deletions(-) diff --git a/include/SuggestionsPopup.hpp b/include/SuggestionsPopup.hpp index 80f28466..dcbe52fa 100644 --- a/include/SuggestionsPopup.hpp +++ b/include/SuggestionsPopup.hpp @@ -62,15 +62,27 @@ public: public slots: void addUsers(const QVector &users); - void cycleThroughSuggestions(); void selectHoveredSuggestion(); + //! Move to the next available suggestion item. + void selectNextSuggestion(); + //! Move to the previous available suggestion item. + void selectPreviousSuggestion(); + //! Remove hovering from all items. + void resetHovering(); + //! Set hovering to the item in the given layout position. + void setHovering(int pos); signals: void itemSelected(const QString &user); private: + void hoverSelection(); + void resetSelection() { selectedItem_ = -1; } + void selectFirstItem() { selectedItem_ = 0; } + void selectLastItem() { selectedItem_ = layout_->count() - 1; } + QVBoxLayout *layout_; //! Counter for tab completion (cycling). - int tab_clicks_; + int selectedItem_ = -1; }; diff --git a/include/TextInputWidget.h b/include/TextInputWidget.h index 89eb5947..7a52ea77 100644 --- a/include/TextInputWidget.h +++ b/include/TextInputWidget.h @@ -73,7 +73,8 @@ signals: //! Trigger the suggestion popup. void showSuggestions(const QString &query); void resultsRetrieved(const QVector &results); - void cycleSuggestions(); + void selectNextSuggestion(); + void selectPreviousSuggestion(); void selectHoveredSuggestion(); public slots: diff --git a/src/SuggestionsPopup.cpp b/src/SuggestionsPopup.cpp index 174076f9..51229806 100644 --- a/src/SuggestionsPopup.cpp +++ b/src/SuggestionsPopup.cpp @@ -1,8 +1,8 @@ -#include "SuggestionsPopup.hpp" #include "Avatar.h" #include "AvatarProvider.h" #include "Config.h" #include "DropShadow.h" +#include "SuggestionsPopup.hpp" #include "Utils.h" #include "timeline/TimelineViewManager.h" @@ -72,7 +72,6 @@ PopupItem::mousePressEvent(QMouseEvent *event) SuggestionsPopup::SuggestionsPopup(QWidget *parent) : QWidget(parent) - , tab_clicks_(0) { setAttribute(Qt::WA_ShowWithoutActivating, true); setWindowFlags(Qt::ToolTip | Qt::NoDropShadowWindowHint); @@ -103,41 +102,69 @@ SuggestionsPopup::addUsers(const QVector &users) connect(user, &PopupItem::clicked, this, &SuggestionsPopup::itemSelected); } - tab_clicks_ = 0; // Reset to start from the beginning of pop-up window on next invocation. + resetSelection(); resize(geometry().width(), 40 * users.size()); } void -SuggestionsPopup::cycleThroughSuggestions() +SuggestionsPopup::hoverSelection() { - tab_clicks_ %= layout_->count(); // Stay within the number of items in layout. + resetHovering(); + setHovering(selectedItem_); + update(); +} - // Reset flag for hovering effect first. +void +SuggestionsPopup::selectNextSuggestion() +{ + selectedItem_++; + if (selectedItem_ >= layout_->count()) + selectFirstItem(); + + hoverSelection(); +} + +void +SuggestionsPopup::selectPreviousSuggestion() +{ + selectedItem_--; + if (selectedItem_ < 0) + selectLastItem(); + + hoverSelection(); +} + +void +SuggestionsPopup::resetHovering() +{ for (int i = 0; i < layout_->count(); ++i) { - const auto &p = qobject_cast(layout_->itemAt(i)->widget()); - p->setHovering(false); + const auto item = qobject_cast(layout_->itemAt(i)->widget()); + + if (item) + item->setHovering(false); } +} - const auto &item = layout_->itemAt(tab_clicks_); +void +SuggestionsPopup::setHovering(int pos) +{ + const auto &item = layout_->itemAt(pos); const auto &widget = qobject_cast(item->widget()); - widget->setHovering(true); - ++tab_clicks_; - - update(); // Request to update the paint event. + if (widget) + widget->setHovering(true); } void SuggestionsPopup::selectHoveredSuggestion() { - // Each tab press increments the counter by one, so the element desired is one off. - const auto item = layout_->itemAt(tab_clicks_ - 1); + const auto item = layout_->itemAt(selectedItem_); if (!item) return; const auto &widget = qobject_cast(item->widget()); emit itemSelected(TimelineViewManager::displayName(widget->user())); - tab_clicks_ = 0; // Reset to start from the beginning of pop-up window on next invocation. + resetSelection(); } diff --git a/src/TextInputWidget.cc b/src/TextInputWidget.cc index 459fcd51..4c6c8704 100644 --- a/src/TextInputWidget.cc +++ b/src/TextInputWidget.cc @@ -88,9 +88,13 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent) // For cycling through the suggestions by hitting tab. connect(this, - &FilteredTextEdit::cycleSuggestions, + &FilteredTextEdit::selectNextSuggestion, &popup_, - &SuggestionsPopup::cycleThroughSuggestions); + &SuggestionsPopup::selectNextSuggestion); + connect(this, + &FilteredTextEdit::selectPreviousSuggestion, + &popup_, + &SuggestionsPopup::selectPreviousSuggestion); connect(this, &FilteredTextEdit::selectHoveredSuggestion, &popup_, @@ -138,19 +142,21 @@ FilteredTextEdit::keyPressEvent(QKeyEvent *event) if (popup_.isVisible()) { switch (event->key()) { + case Qt::Key_Down: case Qt::Key_Tab: - emit cycleSuggestions(); + emit selectNextSuggestion(); return; case Qt::Key_Enter: case Qt::Key_Return: emit selectHoveredSuggestion(); return; case Qt::Key_Escape: - break; - case Qt::Key_Space: - case Qt::Key_Backtab: { closeSuggestions(); - break; + return; + case Qt::Key_Up: + case Qt::Key_Backtab: { + emit selectPreviousSuggestion(); + return; } default: break;