diff options
-rw-r--r-- | desktop-widgets/listfilter.ui | 10 | ||||
-rw-r--r-- | desktop-widgets/simplewidgets.cpp | 1 | ||||
-rw-r--r-- | qt-models/filtermodels.cpp | 80 | ||||
-rw-r--r-- | qt-models/filtermodels.h | 5 |
4 files changed, 55 insertions, 41 deletions
diff --git a/desktop-widgets/listfilter.ui b/desktop-widgets/listfilter.ui index 48d813d21..b1d717bf0 100644 --- a/desktop-widgets/listfilter.ui +++ b/desktop-widgets/listfilter.ui @@ -51,6 +51,16 @@ </property> </widget> </item> + <item> + <widget class="QToolButton" name="notButton"> + <property name="text"> + <string>¬</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </item> </layout> </item> <item> diff --git a/desktop-widgets/simplewidgets.cpp b/desktop-widgets/simplewidgets.cpp index b63349819..f8cd96943 100644 --- a/desktop-widgets/simplewidgets.cpp +++ b/desktop-widgets/simplewidgets.cpp @@ -516,6 +516,7 @@ FilterBase::FilterBase(FilterModelBase *model_, QWidget *parent) : QWidget(paren filter->setSourceModel(model); filter->setFilterCaseSensitivity(Qt::CaseInsensitive); connect(ui.filterInternalList, SIGNAL(textChanged(QString)), filter, SLOT(setFilterFixedString(QString))); + connect(ui.notButton, &QToolButton::toggled, model, &FilterModelBase::setNegate); ui.filterList->setModel(filter); addContextMenuEntry(tr("Select All"), &FilterModelBase::selectAll); diff --git a/qt-models/filtermodels.cpp b/qt-models/filtermodels.cpp index 004ff8493..48a2fd9b9 100644 --- a/qt-models/filtermodels.cpp +++ b/qt-models/filtermodels.cpp @@ -26,7 +26,8 @@ CREATE_INSTANCE_METHOD(SuitsFilterModel) CREATE_INSTANCE_METHOD(MultiFilterSortModel) FilterModelBase::FilterModelBase(QObject *parent) : QStringListModel(parent), - anyChecked(false) + anyChecked(false), + negate(false) { } @@ -115,6 +116,12 @@ void FilterModelBase::invertSelection() emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0)); } +void FilterModelBase::setNegate(bool negateParam) +{ + negate = negateParam; + emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0)); +} + SuitsFilterModel::SuitsFilterModel(QObject *parent) : FilterModelBase(parent) { } @@ -129,28 +136,25 @@ bool SuitsFilterModel::doFilter(dive *d, QModelIndex &index0, QAbstractItemModel Q_UNUSED(index0); Q_UNUSED(sourceModel); - if (!anyChecked) { + // rowCount() == 0 should never happen, because we have the "no suits" row + // let's handle it gracefully anyway. + if (!anyChecked || rowCount() == 0) return true; - } // Checked means 'Show', Unchecked means 'Hide'. QString suit(d->suit); // only show empty suit dives if the user checked that. - if (suit.isEmpty()) { - if (rowCount() > 0) - return checkState[rowCount() - 1]; - else - return true; - } + if (suit.isEmpty()) + return checkState[rowCount() - 1] != negate; // there is a suit selected QStringList suitList = stringList(); // Ignore last item, since this is the "Show Empty Tags" entry for (int i = 0; i < rowCount() - 1; i++) { if (checkState[i] && suit == suitList[i]) - return true; + return !negate; } - return false; + return negate; } void SuitsFilterModel::repopulate() @@ -200,18 +204,16 @@ bool TagFilterModel::doFilter(dive *d, QModelIndex &index0, QAbstractItemModel * Q_UNUSED(sourceModel); // If there's nothing checked, this should show everything - if (!anyChecked) { + // rowCount() == 0 should never happen, because we have the "no tags" row + // let's handle it gracefully anyway. + if (!anyChecked || rowCount() == 0) return true; - } + // Checked means 'Show', Unchecked means 'Hide'. struct tag_entry *head = d->tag_list; - if (!head) { // last tag means "Show empty tags"; - if (rowCount() > 0) - return checkState[rowCount() - 1]; - else - return true; - } + if (!head) // last tag means "Show empty tags"; + return checkState[rowCount() - 1] != negate; // have at least one tag. QStringList tagList = stringList(); @@ -221,11 +223,11 @@ bool TagFilterModel::doFilter(dive *d, QModelIndex &index0, QAbstractItemModel * QString tagName(head->tag->name); int index = tagList.indexOf(tagName); if (checkState[index]) - return true; + return !negate; head = head->next; } } - return false; + return negate; } BuddyFilterModel::BuddyFilterModel(QObject *parent) : FilterModelBase(parent) @@ -243,30 +245,28 @@ bool BuddyFilterModel::doFilter(dive *d, QModelIndex &index0, QAbstractItemModel Q_UNUSED(sourceModel); // If there's nothing checked, this should show everything - if (!anyChecked) { + // rowCount() == 0 should never happen, because we have the "no tags" row + // let's handle it gracefully anyway. + if (!anyChecked || rowCount() == 0) return true; - } + // Checked means 'Show', Unchecked means 'Hide'. QString persons = QString(d->buddy) + "," + QString(d->divemaster); QStringList personsList = persons.split(',', QString::SkipEmptyParts); for (QString &s : personsList) s = s.trimmed(); // only show empty buddie dives if the user checked that. - if (personsList.isEmpty()) { - if (rowCount() > 0) - return checkState[rowCount() - 1]; - else - return true; - } + if (personsList.isEmpty()) + return checkState[rowCount() - 1] != negate; // have at least one buddy QStringList buddyList = stringList(); // Ignore last item, since this is the "Show Empty Tags" entry for (int i = 0; i < rowCount() - 1; i++) { if (checkState[i] && personsList.contains(buddyList[i], Qt::CaseInsensitive)) - return true; + return !negate; } - return false; + return negate; } void BuddyFilterModel::repopulate() @@ -302,27 +302,25 @@ bool LocationFilterModel::doFilter(struct dive *d, QModelIndex &index0, QAbstrac Q_UNUSED(index0); Q_UNUSED(sourceModel); - if (!anyChecked) { + // rowCount() == 0 should never happen, because we have the "no location" row + // let's handle it gracefully anyway. + if (!anyChecked || rowCount() == 0) return true; - } + // Checked means 'Show', Unchecked means 'Hide'. QString location(get_dive_location(d)); // only show empty location dives if the user checked that. - if (location.isEmpty()) { - if (rowCount() > 0) - return checkState[rowCount() - 1]; - else - return true; - } + if (location.isEmpty()) + return checkState[rowCount() - 1] != negate; // There is a location selected QStringList locationList = stringList(); // Ignore last item, since this is the "Show Empty Tags" entry for (int i = 0; i < rowCount() - 1; i++) { if (checkState[i] && location == locationList[i]) - return true; + return !negate; } - return false; + return negate; } void LocationFilterModel::repopulate() diff --git a/qt-models/filtermodels.h b/qt-models/filtermodels.h index 9db5e5a97..b866b68b2 100644 --- a/qt-models/filtermodels.h +++ b/qt-models/filtermodels.h @@ -8,6 +8,7 @@ #include <vector> class FilterModelBase : public QStringListModel { + Q_OBJECT public: virtual bool doFilter(struct dive *d, QModelIndex &index0, QAbstractItemModel *sourceModel) const = 0; void clearFilter(); @@ -15,6 +16,10 @@ public: void invertSelection(); std::vector<char> checkState; bool anyChecked; + bool negate; +public +slots: + void setNegate(bool negate); protected: explicit FilterModelBase(QObject *parent = 0); void updateList(const QStringList &new_list); |