QmlMaterial 0.1.0
Loading...
Searching...
No Matches
selection_set.hpp
1#pragma once
2
3#include <QList>
4#include <QPointer>
5
6namespace qml_material::utils
7{
8// Non-owning selection state shared by action and button groups.
9template<class T>
10class SelectionSet {
11public:
12 QList<T*> members;
13 bool exclusive = true;
14 T* selected = nullptr;
15 quint64 revision = 0;
16
17 QList<QPointer<T>> snapshot() const {
18 QList<QPointer<T>> result;
19 for (auto* member : members) result.append(member);
20 return result;
21 }
22
23 template<class UpdateChecked>
24 void normalize(QObject* owner, T* preferred, UpdateChecked updateChecked) {
25 const auto serial = ++revision;
26 if (! exclusive) {
27 selected = nullptr;
28 return;
29 }
30 if (! members.contains(selected) || ! selected->isChecked()) selected = nullptr;
31 if (preferred && members.contains(preferred) && preferred->isChecked())
32 selected = preferred;
33 if (! selected) {
34 for (auto* member : members)
35 if (member->isChecked()) {
36 selected = member;
37 break;
38 }
39 }
40 QPointer<QObject> guard(owner);
41 const auto items = snapshot();
42 for (const auto& member : items) {
43 if (member && members.contains(member) && member != selected && member->isChecked())
44 updateChecked(member, false);
45 if (! guard || revision != serial) return;
46 }
47 }
48
49 Qt::CheckState checkState() const {
50 qsizetype checked = 0;
51 for (auto* member : members) checked += member->isChecked();
52 return ! checked ? Qt::Unchecked
53 : checked == members.size() ? Qt::Checked
54 : Qt::PartiallyChecked;
55 }
56};
57} // namespace qml_material::utils