diff options
| author | isanae <14251494+isanae@users.noreply.github.com> | 2019-11-30 05:23:22 -0500 |
|---|---|---|
| committer | isanae <14251494+isanae@users.noreply.github.com> | 2019-11-30 05:23:22 -0500 |
| commit | 7f4fce35f97f262c36e4c00dad55c1b078cf3758 (patch) | |
| tree | 5f737852d30176fc31bf64b0028d13350112d2ea | |
| parent | 38d56ef8310674bc5a2f8b304ee17a6b7e1c5798 (diff) | |
fixed separators option being used even without filters
changed filter list to use tristate items without selection
| -rw-r--r-- | src/filterlist.cpp | 232 | ||||
| -rw-r--r-- | src/filterlist.h | 8 | ||||
| -rw-r--r-- | src/mainwindow.ui | 64 | ||||
| -rw-r--r-- | src/modlistsortproxy.cpp | 26 | ||||
| -rw-r--r-- | src/modlistsortproxy.h | 3 |
5 files changed, 204 insertions, 129 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; diff --git a/src/filterlist.h b/src/filterlist.h index 52b90ea7..fac1d683 100644 --- a/src/filterlist.h +++ b/src/filterlist.h @@ -28,13 +28,11 @@ private: Ui::MainWindow* ui; CategoryFactory& m_factory; - void onContextMenu(const QPoint &pos); - void onSelection(); - void onCriteriaChanged(); + bool onClick(QMouseEvent* e); + void onOptionsChanged(); - void clear(); - void toggleInverted(bool b); void editCategories(); + void checkCriteria(); QTreeWidgetItem* addCriteriaItem( QTreeWidgetItem *root, const QString &name, int categoryID, diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 5206d797..1a64dfdd 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -76,59 +76,69 @@ <height>0</height> </size> </property> - <property name="contextMenuPolicy"> - <enum>Qt::CustomContextMenu</enum> - </property> <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> + <enum>QAbstractItemView::NoSelection</enum> </property> <property name="indentation"> <number>0</number> </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> <property name="uniformRowHeights"> <bool>true</bool> </property> <property name="headerHidden"> - <bool>false</bool> + <bool>true</bool> </property> <attribute name="headerVisible"> - <bool>true</bool> + <bool>false</bool> </attribute> <attribute name="headerCascadingSectionResizes"> - <bool>true</bool> - </attribute> - <attribute name="headerStretchLastSection"> <bool>false</bool> </attribute> <column> <property name="text"> - <string notr="true">Category</string> + <string/> </property> </column> <column> <property name="text"> - <string>Invert</string> + <string notr="true">Category</string> </property> </column> </widget> </item> <item> - <widget class="QPushButton" name="filtersClear"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>25</height> - </size> - </property> - <property name="text"> - <string>Clear</string> - </property> + <widget class="QWidget" name="widget_2" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_8"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>2</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="filtersClear"> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="filtersEdit"> + <property name="text"> + <string>Edit...</string> + </property> + </widget> + </item> + </layout> </widget> </item> <item> diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 36dcae59..e6bed49c 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -269,12 +269,12 @@ bool ModListSortProxy::hasConflictFlag(const std::vector<ModInfo::EFlag> &flags) bool ModListSortProxy::filterMatchesModAnd(ModInfo::Ptr info, bool enabled) const
{
- if (info->hasFlag(ModInfo::FLAG_SEPARATOR) && !m_FilterSeparators) {
+ if (!optionsMatchMod(info, enabled)) {
return false;
}
for (auto&& c : m_Criteria) {
- if (!criteriaMatchesMod(info, enabled, c)) {
+ if (!criteriaMatchMod(info, enabled, c)) {
return false;
}
}
@@ -284,12 +284,12 @@ bool ModListSortProxy::filterMatchesModAnd(ModInfo::Ptr info, bool enabled) cons bool ModListSortProxy::filterMatchesModOr(ModInfo::Ptr info, bool enabled) const
{
- if (info->hasFlag(ModInfo::FLAG_SEPARATOR) && !m_FilterSeparators) {
+ if (!optionsMatchMod(info, enabled)) {
return false;
}
for (auto&& c : m_Criteria) {
- if (criteriaMatchesMod(info, enabled, c)) {
+ if (criteriaMatchMod(info, enabled, c)) {
return true;
}
}
@@ -302,7 +302,23 @@ bool ModListSortProxy::filterMatchesModOr(ModInfo::Ptr info, bool enabled) const return true;
}
-bool ModListSortProxy::criteriaMatchesMod(
+bool ModListSortProxy::optionsMatchMod(ModInfo::Ptr info, bool) const
+{
+ // don't check options if there are no filters selected
+ if (!m_FilterActive) {
+ return true;
+ }
+
+ if (!m_FilterSeparators) {
+ if (info->hasFlag(ModInfo::FLAG_SEPARATOR)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ModListSortProxy::criteriaMatchMod(
ModInfo::Ptr info, bool enabled, const Criteria& c) const
{
bool b = false;
diff --git a/src/modlistsortproxy.h b/src/modlistsortproxy.h index 5aeaccce..9b533492 100644 --- a/src/modlistsortproxy.h +++ b/src/modlistsortproxy.h @@ -157,7 +157,8 @@ private: std::vector<Criteria> m_PreChangeCriteria;
- bool criteriaMatchesMod(ModInfo::Ptr info, bool enabled, const Criteria& c) const;
+ bool optionsMatchMod(ModInfo::Ptr info, bool enabled) const;
+ bool criteriaMatchMod(ModInfo::Ptr info, bool enabled, const Criteria& c) const;
bool categoryMatchesMod(ModInfo::Ptr info, bool enabled, int category) const;
bool contentMatchesMod(ModInfo::Ptr info, bool enabled, int content) const;
};
|
