summaryrefslogtreecommitdiffstats
path: root/qt-models
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2018-08-27 11:49:16 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2018-08-28 05:03:59 -0700
commitec586d0e0a19cb7af62506fc2a3cb2f53198bcb8 (patch)
tree90d2b7db6913c1af19b6fe11c6c85d438ce9124a /qt-models
parent80fe8fb331edd494ba53efb0879eb9d53031216e (diff)
downloadsubsurface-ec586d0e0a19cb7af62506fc2a3cb2f53198bcb8.tar.gz
Filter: replace checked-state by struct
In the future, we might be smarter about the dive-counts and calculate them only once and incrementally (if e.g. new dives are added). Prepare for more complex caching by turning the checked boolean into a struct, which can then be extended by a count and other things (e.g. the name). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'qt-models')
-rw-r--r--qt-models/filtermodels.cpp77
-rw-r--r--qt-models/filtermodels.h6
2 files changed, 50 insertions, 33 deletions
diff --git a/qt-models/filtermodels.cpp b/qt-models/filtermodels.cpp
index 1943056f7..4abdaf1d0 100644
--- a/qt-models/filtermodels.cpp
+++ b/qt-models/filtermodels.cpp
@@ -32,30 +32,41 @@ FilterModelBase::FilterModelBase(QObject *parent) : QStringListModel(parent),
{
}
-// Update the stringList and the checkState array.
+// Update the stringList and the items array.
// The last item is supposed to be the "Show Empty Tags" entry.
void FilterModelBase::updateList(const QStringList &newList)
{
- // Keep copy of old checkState array to reimport them later.
- std::vector<char> oldCheckState = checkState;
- checkState.resize(newList.count());
- std::fill(checkState.begin(), checkState.end(), false);
+ // Keep copy of the old items array to reimport the checked state later.
+ // Note that by using std::move(), this is an essentially free operation:
+ // The data is moved from the old array to the new one and the old array
+ // is reset to zero size.
+ std::vector<Item> oldItems = std::move(items);
+
+ // Resize the cleared array to the new size. This leaves the checked
+ // flag in an undefined state (since we didn't define a default constructor).
+ items.resize(newList.count());
+
+ // First, reset all checked states to false
anyChecked = false;
+ for (Item &item: items)
+ item.checked = false;
- // Ignore last item, since this is the "Show Empty Tags" entry.
- for (int i = 0; i < rowCount() - 1; i++) {
- if (oldCheckState[i]) {
+ // Then, restore the checked state. Ignore the last item, since
+ // this is the "Show Empty Tags" entry.
+ for (int i = 0; i < (int)oldItems.size() - 1; i++) {
+ if (oldItems[i].checked) {
int ind = newList.indexOf(stringList()[i]);
if (ind >= 0 && ind < newList.count() - 1) {
- checkState[ind] = true;
+ items[ind].checked = true;
anyChecked = true;
}
}
}
- // On program startup, the old list is empty.
- if (rowCount() > 0 && oldCheckState.back()) {
- checkState.back() = true;
+ // Reset the state of the "Show Empty Tags" entry. But be careful:
+ // on program startup, the old list is empty.
+ if (!oldItems.empty() && !items.empty() && oldItems.back().checked) {
+ items.back().checked = true;
anyChecked = true;
}
setStringList(newList);
@@ -69,10 +80,10 @@ Qt::ItemFlags FilterModelBase::flags(const QModelIndex &index) const
bool FilterModelBase::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (role == Qt::CheckStateRole) {
- checkState[index.row()] = value.toBool();
+ items[index.row()].checked = value.toBool();
anyChecked = false;
- for (int i = 0; i < rowCount(); i++) {
- if (checkState[i] == true) {
+ for (const Item &item: items) {
+ if (item.checked) {
anyChecked = true;
break;
}
@@ -86,7 +97,7 @@ bool FilterModelBase::setData(const QModelIndex &index, const QVariant &value, i
QVariant FilterModelBase::data(const QModelIndex &index, int role) const
{
if (role == Qt::CheckStateRole) {
- return checkState[index.row()] ? Qt::Checked : Qt::Unchecked;
+ return items[index.row()].checked ? Qt::Checked : Qt::Unchecked;
} else if (role == Qt::DisplayRole) {
QString value = stringList()[index.row()];
int count = countDives((index.row() == rowCount() - 1) ? "" : qPrintable(value));
@@ -97,23 +108,25 @@ QVariant FilterModelBase::data(const QModelIndex &index, int role) const
void FilterModelBase::clearFilter()
{
- std::fill(checkState.begin(), checkState.end(), false);
+ for (Item &item: items)
+ item.checked = false;
anyChecked = false;
emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0));
}
void FilterModelBase::selectAll()
{
- std::fill(checkState.begin(), checkState.end(), true);
+ for (Item &item: items)
+ item.checked = true;
anyChecked = true;
emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0));
}
void FilterModelBase::invertSelection()
{
- for (char &b : checkState)
- b = !b;
- anyChecked = std::any_of(checkState.begin(), checkState.end(), [](char b) { return !!b; });
+ for (Item &item : items)
+ item.checked = !item.checked;
+ anyChecked = std::any_of(items.begin(), items.end(), [](Item &item) { return !!item.checked; });
emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0));
}
@@ -143,13 +156,13 @@ bool SuitsFilterModel::doFilter(const dive *d) const
QString suit(d->suit);
// only show empty suit dives if the user checked that.
if (suit.isEmpty())
- return checkState[rowCount() - 1] != negate;
+ return items[rowCount() - 1].checked != 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])
+ if (items[i].checked && suit == suitList[i])
return !negate;
}
return negate;
@@ -208,7 +221,7 @@ bool TagFilterModel::doFilter(const dive *d) const
struct tag_entry *head = d->tag_list;
if (!head) // last tag means "Show empty tags";
- return checkState[rowCount() - 1] != negate;
+ return items[rowCount() - 1].checked != negate;
// have at least one tag.
QStringList tagList = stringList();
@@ -217,7 +230,7 @@ bool TagFilterModel::doFilter(const dive *d) const
while (head) {
QString tagName(head->tag->name);
int index = tagList.indexOf(tagName);
- if (index >= 0 && checkState[index])
+ if (index >= 0 && items[index].checked)
return !negate;
head = head->next;
}
@@ -249,13 +262,13 @@ bool BuddyFilterModel::doFilter(const dive *d) const
s = s.trimmed();
// only show empty buddie dives if the user checked that.
if (personsList.isEmpty())
- return checkState[rowCount() - 1] != negate;
+ return items[rowCount() - 1].checked != 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))
+ if (items[i].checked && personsList.contains(buddyList[i], Qt::CaseInsensitive))
return !negate;
}
return negate;
@@ -300,13 +313,13 @@ bool LocationFilterModel::doFilter(const dive *d) const
QString location(get_dive_location(d));
// only show empty location dives if the user checked that.
if (location.isEmpty())
- return checkState[rowCount() - 1] != negate;
+ return items[rowCount() - 1].checked != 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])
+ if (items[i].checked && location == locationList[i])
return !negate;
}
return negate;
@@ -341,8 +354,8 @@ void LocationFilterModel::changeName(const QString &oldName, const QString &newN
// If there was already an entry with the new name, we are merging entries.
// Thus, if the old entry was selected, also select the new entry.
- if (newIndex >= 0 && checkState[oldIndex])
- checkState[newIndex] = true;
+ if (newIndex >= 0 && items[oldIndex].checked)
+ items[newIndex].checked = true;
setStringList(list);
}
@@ -356,7 +369,7 @@ void LocationFilterModel::addName(const QString &newName)
if (!anyChecked || newName.isEmpty() || list.indexOf(newName) >= 0)
return;
list.prepend(newName);
- checkState.insert(checkState.begin(), true);
+ items.insert(items.begin(), { true });
setStringList(list);
}
diff --git a/qt-models/filtermodels.h b/qt-models/filtermodels.h
index bcbbf000a..8bac44680 100644
--- a/qt-models/filtermodels.h
+++ b/qt-models/filtermodels.h
@@ -11,12 +11,16 @@ struct dive;
class FilterModelBase : public QStringListModel {
Q_OBJECT
+protected:
+ struct Item {
+ bool checked;
+ };
+ std::vector<Item> items;
public:
virtual bool doFilter(const dive *d) const = 0;
void clearFilter();
void selectAll();
void invertSelection();
- std::vector<char> checkState;
bool anyChecked;
bool negate;
public