diff options
| -rw-r--r-- | src/filterlist.cpp | 96 | ||||
| -rw-r--r-- | src/filterlist.h | 3 | ||||
| -rw-r--r-- | src/mainwindow.ui | 6 |
3 files changed, 72 insertions, 33 deletions
diff --git a/src/filterlist.cpp b/src/filterlist.cpp index 0a5d0414..b345d21d 100644 --- a/src/filterlist.cpp +++ b/src/filterlist.cpp @@ -111,51 +111,88 @@ private: }; -class ClickFilter : public QObject +class CriteriaItemFilter : public QObject { public: - ClickFilter(std::function<bool (QMouseEvent*)> f) - : m_f(std::move(f)) + using Callback = std::function<bool (QTreeWidgetItem*, int)>; + + CriteriaItemFilter(QTreeWidget* tree, Callback f) + : QObject(tree), m_tree(tree), m_f(std::move(f)) { } bool eventFilter(QObject* o, QEvent* e) override { - if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonDblClick) { - if (m_f) { - return m_f(static_cast<QMouseEvent*>(e)); + // careful: this filter is installed on both the tree and the viewport + // + // no check is currently necessary because mouse events originate from the + // viewport only and keyboard events from the tree only + + if (m_f) { + if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonDblClick) { + if (handleMouse(static_cast<QMouseEvent*>(e))) { + return true; + } + } else if (e->type() == QEvent::KeyPress) { + if (handleKeyboard(static_cast<QKeyEvent*>(e))) { + return true; + } } } - return QObject::eventFilter(o, e);; + return QObject::eventFilter(o, e); } private: - std::function<bool (QMouseEvent*)> m_f; + QTreeWidget* m_tree; + Callback m_f; + + bool handleMouse(QMouseEvent* e) + { + auto* item = m_tree->itemAt(e->pos()); + if (!item) { + return false; + } + + m_tree->setCurrentItem(item); + + const auto dir = (e->button() == Qt::LeftButton ? 1 : - 1); + + return m_f(item, dir); + } + + bool handleKeyboard(QKeyEvent* e) + { + if (e->key() == Qt::Key_Space) { + auto* item = m_tree->currentItem(); + if (!item) { + return false; + } + + const auto shiftPressed = (e->modifiers() & Qt::ShiftModifier); + const auto dir = (shiftPressed ? -1 : 1); + + return m_f(item, dir); + } + + return false; + } }; FilterList::FilterList(Ui::MainWindow* ui, CategoryFactory& factory) : ui(ui), m_factory(factory) { - ui->filters->viewport()->installEventFilter( - new ClickFilter([&](auto* e){ return onClick(e); })); - - connect( - ui->filtersClear, &QPushButton::clicked, - [&]{ clearSelection(); }); - - connect( - ui->filtersEdit, &QPushButton::clicked, - [&]{ editCategories(); }); + auto* eventFilter = new CriteriaItemFilter( + ui->filters, [&](auto* item, int dir){ return cycleItem(item, dir); }); - connect( - ui->filtersAnd, &QCheckBox::toggled, - [&]{ onOptionsChanged(); }); + ui->filters->installEventFilter(eventFilter); + ui->filters->viewport()->installEventFilter(eventFilter); - connect( - ui->filtersOr, &QCheckBox::toggled, - [&]{ onOptionsChanged(); }); + connect(ui->filtersClear, &QPushButton::clicked, [&]{ clearSelection(); }); + connect(ui->filtersEdit, &QPushButton::clicked, [&]{ editCategories(); }); + connect(ui->filtersAnd, &QCheckBox::toggled, [&]{ onOptionsChanged(); }); + connect(ui->filtersOr, &QCheckBox::toggled, [&]{ onOptionsChanged(); }); connect( ui->filtersSeparators, qOverload<int>(&QComboBox::currentIndexChanged), @@ -321,21 +358,16 @@ void FilterList::clearSelection() checkCriteria(); } -bool FilterList::onClick(QMouseEvent* e) +bool FilterList::cycleItem(QTreeWidgetItem* item, int direction) { - auto* item = ui->filters->itemAt(e->pos()); - if (!item) { - return false; - } - auto* ci = dynamic_cast<CriteriaItem*>(item); if (!ci) { return false; } - if (e->button() == Qt::LeftButton) { + if (direction > 0) { ci->nextState(); - } else if (e->button() == Qt::RightButton) { + } else if (direction < 0) { ci->previousState(); } else { return false; diff --git a/src/filterlist.h b/src/filterlist.h index 671462d4..72cbe8bf 100644 --- a/src/filterlist.h +++ b/src/filterlist.h @@ -34,10 +34,12 @@ private: CategoryFactory& m_factory; bool onClick(QMouseEvent* e); + void onItemActivated(QTreeWidgetItem* item); void onOptionsChanged(); void editCategories(); void checkCriteria(); + bool cycleItem(QTreeWidgetItem* item, int direction); QTreeWidgetItem* addCriteriaItem( QTreeWidgetItem *root, const QString &name, int categoryID, @@ -47,7 +49,6 @@ private: void addCategoryCriteria( QTreeWidgetItem *root, const std::set<int> &categoriesUsed, int targetID); void addSpecialCriteria(int type); - }; #endif // MODORGANIZER_CATEGORIESLIST_INCLUDED diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 0520db84..309e9f62 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -79,6 +79,9 @@ <property name="contextMenuPolicy"> <enum>Qt::NoContextMenu</enum> </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> <property name="selectionMode"> <enum>QAbstractItemView::NoSelection</enum> </property> @@ -91,6 +94,9 @@ <property name="uniformRowHeights"> <bool>true</bool> </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> <property name="headerHidden"> <bool>true</bool> </property> |
