summaryrefslogtreecommitdiff
path: root/src/filterlist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/filterlist.cpp')
-rw-r--r--src/filterlist.cpp232
1 files changed, 141 insertions, 91 deletions
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<States>(m_state + 1);
+ if (m_state > LastState) {
+ m_state = FirstState;
+ }
+
+ updateState();
+ }
+
+ void previousState()
+ {
+ m_state = static_cast<States>(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<bool (QMouseEvent*)> 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<QMouseEvent*>(e));
+ }
+ }
+
+ return QObject::eventFilter(o, e);;
+ }
+
+private:
+ std::function<bool (QMouseEvent*)> 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>& criteria)
void FilterList::clearSelection()
{
- ui->filters->clearSelection();
-}
-
-void FilterList::onSelection()
-{
- const QModelIndexList indices = ui->filters->selectionModel()->selectedRows();
- std::vector<Criteria> criteria;
-
- for (auto* item : ui->filters->selectedItems()) {
- const auto* ci = dynamic_cast<CriteriaItem*>(item);
+ for (int i=0; i<ui->filters->topLevelItemCount(); ++i) {
+ auto* ci = dynamic_cast<CriteriaItem*>(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<CriteriaItem*>(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> criteria;
-void FilterList::clear()
-{
- const auto count = ui->filters->topLevelItemCount();
- for (int i=0; i<count; ++i) {
- auto* ci = dynamic_cast<CriteriaItem*>(ui->filters->topLevelItem(i));
+ for (int i=0; i<ui->filters->topLevelItemCount(); ++i) {
+ const auto* ci = dynamic_cast<CriteriaItem*>(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<CriteriaItem*>(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;