From 7f4fce35f97f262c36e4c00dad55c1b078cf3758 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 30 Nov 2019 05:23:22 -0500 Subject: fixed separators option being used even without filters changed filter list to use tristate items without selection --- src/filterlist.cpp | 232 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 141 insertions(+), 91 deletions(-) (limited to 'src/filterlist.cpp') diff --git a/src/filterlist.cpp b/src/filterlist.cpp index 81f8b670..0dee8544 100644 --- a/src/filterlist.cpp +++ b/src/filterlist.cpp @@ -11,28 +11,23 @@ using Criteria = ModListSortProxy::Criteria; class FilterList::CriteriaItem : public QTreeWidgetItem { public: - CriteriaItem(FilterList* list, QString name, CriteriaType type, int id) - : QTreeWidgetItem({name}), m_list(list), m_widget(nullptr), m_checkbox(nullptr) + enum States : int { - setData(0, Qt::ToolTipRole, name); - setData(0, TypeRole, type); - setData(0, IDRole, id); - - m_widget = new QWidget; - m_widget->setStyleSheet("background-color: rgba(0,0,0,0)"); + FirstState = 0, - auto* ly = new QVBoxLayout(m_widget); - ly->setAlignment(Qt::AlignCenter); - ly->setContentsMargins(0, 0, 0, 0); + Inactive = FirstState, + Active, + Inverted, - m_checkbox = new QCheckBox; - QObject::connect(m_checkbox, &QCheckBox::toggled, [&]{ m_list->onSelection(); }); - ly->addWidget(m_checkbox); - } + LastState = Inverted + }; - QWidget* widget() + CriteriaItem(FilterList* list, QString name, CriteriaType type, int id) + : QTreeWidgetItem({"", name}), m_list(list), m_state(Inactive) { - return m_widget; + setData(0, Qt::ToolTipRole, name); + setData(0, TypeRole, type); + setData(0, IDRole, id); } CriteriaType type() const @@ -45,14 +40,37 @@ public: return data(0, IDRole).toInt(); } - bool inverse() const + States state() const + { + return m_state; + } + + void setState(States s) { - return m_checkbox->isChecked(); + if (m_state != s) { + m_state = s; + updateState(); + } } - void setInverted(bool b) + void nextState() { - m_checkbox->setChecked(b); + m_state = static_cast(m_state + 1); + if (m_state > LastState) { + m_state = FirstState; + } + + updateState(); + } + + void previousState() + { + m_state = static_cast(m_state - 1); + if (m_state < FirstState) { + m_state = LastState; + } + + updateState(); } private: @@ -60,40 +78,91 @@ private: const int TypeRole = Qt::UserRole + 1; FilterList* m_list; - QWidget* m_widget; - QCheckBox* m_checkbox; + States m_state; + + void updateState() + { + QString s; + + switch (m_state) + { + case Inactive: + { + break; + } + + case Active: + { + // U+2713 CHECK MARK + s = QString::fromUtf8("\xe2\x9c\x93"); + break; + } + + case Inverted: + { + s = tr("Not"); + break; + } + } + + setText(0, s); + } +}; + + +class ClickFilter : public QObject +{ +public: + ClickFilter(std::function f) + : 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(e)); + } + } + + return QObject::eventFilter(o, e);; + } + +private: + std::function m_f; }; FilterList::FilterList(Ui::MainWindow* ui, CategoryFactory& factory) : ui(ui), m_factory(factory) { - connect( - ui->filters, &QTreeWidget::customContextMenuRequested, - [&](auto&& pos){ onContextMenu(pos); }); + ui->filters->viewport()->installEventFilter( + new ClickFilter([&](auto* e){ return onClick(e); })); connect( - ui->filters, &QTreeWidget::itemSelectionChanged, - [&]{ onSelection(); }); + ui->filtersClear, &QPushButton::clicked, + [&]{ clearSelection(); }); connect( - ui->filtersClear, &QPushButton::clicked, - [&]{ clear(); }); + ui->filtersEdit, &QPushButton::clicked, + [&]{ editCategories(); }); connect( ui->filtersAnd, &QCheckBox::toggled, - [&]{ onCriteriaChanged(); }); + [&]{ onOptionsChanged(); }); connect( ui->filtersOr, &QCheckBox::toggled, - [&]{ onCriteriaChanged(); }); + [&]{ onOptionsChanged(); }); connect( ui->filtersSeparators, &QCheckBox::toggled, - [&]{ onCriteriaChanged(); }); + [&]{ onOptionsChanged(); }); - ui->filters->header()->setSectionResizeMode(0, QHeaderView::Stretch); - ui->filters->header()->resizeSection(1, 50); + ui->filters->header()->setMinimumSectionSize(0); + ui->filters->header()->setSectionResizeMode(0, QHeaderView::Fixed); + ui->filters->header()->resizeSection(0, 30); ui->categoriesSplitter->setCollapsible(0, false); ui->categoriesSplitter->setCollapsible(1, false); } @@ -110,7 +179,7 @@ QTreeWidgetItem* FilterList::addCriteriaItem( ui->filters->addTopLevelItem(item); } - ui->filters->setItemWidget(item, 1, item->widget()); + item->setTextAlignment(0, Qt::AlignCenter); return item; } @@ -224,91 +293,72 @@ void FilterList::setSelection(const std::vector& criteria) void FilterList::clearSelection() { - ui->filters->clearSelection(); -} - -void FilterList::onSelection() -{ - const QModelIndexList indices = ui->filters->selectionModel()->selectedRows(); - std::vector criteria; - - for (auto* item : ui->filters->selectedItems()) { - const auto* ci = dynamic_cast(item); + for (int i=0; ifilters->topLevelItemCount(); ++i) { + auto* ci = dynamic_cast(ui->filters->topLevelItem(i)); if (!ci) { continue; } - criteria.push_back({ - ci->type(), ci->id(), ci->inverse() - }); + ci->setState(CriteriaItem::Inactive); } - emit criteriaChanged(criteria); + checkCriteria(); } -void FilterList::onContextMenu(const QPoint &pos) +bool FilterList::onClick(QMouseEvent* e) { - QMenu menu; + auto* item = ui->filters->itemAt(e->pos()); + if (!item) { + return false; + } - QAction* set = menu.addAction(tr("Set inverted"), [&]{ toggleInverted(true); }); - QAction* unset = menu.addAction(tr("Unset inverted"), [&]{ toggleInverted(false); }); - menu.addSeparator(); - menu.addAction(tr("Edit Categories..."), [&]{ editCategories(); }); + auto* ci = dynamic_cast(item); + if (!ci) { + return false; + } - if (ui->filters->selectedItems().empty()) { - set->setEnabled(false); - unset->setEnabled(false); + if (e->button() == Qt::LeftButton) { + ci->nextState(); + } else if (e->button() == Qt::RightButton) { + ci->previousState(); + } else { + return false; } - menu.exec(ui->filters->viewport()->mapToGlobal(pos)); + checkCriteria(); + return true; } -void FilterList::editCategories() +void FilterList::checkCriteria() { - CategoriesDialog dialog(qApp->activeWindow()); - - if (dialog.exec() == QDialog::Accepted) { - dialog.commitChanges(); - } -} + std::vector criteria; -void FilterList::clear() -{ - const auto count = ui->filters->topLevelItemCount(); - for (int i=0; i(ui->filters->topLevelItem(i)); + for (int i=0; ifilters->topLevelItemCount(); ++i) { + const auto* ci = dynamic_cast(ui->filters->topLevelItem(i)); if (!ci) { continue; } - ci->setInverted(false); + if (ci->state() != CriteriaItem::Inactive) { + criteria.push_back({ + ci->type(), ci->id(), (ci->state() == CriteriaItem::Inverted) + }); + } } - clearSelection(); + emit criteriaChanged(criteria); } -void FilterList::toggleInverted(bool b) +void FilterList::editCategories() { - bool changed = false; - - for (auto* item : ui->filters->selectedItems()) { - auto* ci = dynamic_cast(item); - if (!ci) { - continue; - } - - if (ci->inverse() != b) { - ci->setInverted(b); - changed = true; - } - } + CategoriesDialog dialog(qApp->activeWindow()); - if (changed) { - onSelection(); + if (dialog.exec() == QDialog::Accepted) { + dialog.commitChanges(); } } -void FilterList::onCriteriaChanged() +void FilterList::onOptionsChanged() { const auto mode = ui->filtersAnd->isChecked() ? ModListSortProxy::FILTER_AND : ModListSortProxy::FILTER_OR; -- cgit v1.3.1