Qt Utilities  5.13.0
Common Qt related C++ classes and routines used by my applications such as dialogs, widgets and models
checklistmodel.cpp
Go to the documentation of this file.
1 #include "./checklistmodel.h"
2 
3 #include <QSettings>
4 
10 namespace Models {
11 
28  : QAbstractListModel(parent)
29 {
30 }
31 
32 int ChecklistModel::rowCount(const QModelIndex &parent) const
33 {
34  if (!parent.isValid()) {
35  return m_items.size();
36  }
37  return 0;
38 }
39 
40 Qt::ItemFlags ChecklistModel::flags(const QModelIndex &index) const
41 {
42  if (!index.isValid() || index.row() >= m_items.count() || index.model() != this) {
43  return Qt::ItemIsDropEnabled; // allows drops outside the items
44  }
45  return QAbstractListModel::flags(index) | Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled;
46 }
47 
48 QVariant ChecklistModel::data(const QModelIndex &index, int role) const
49 {
50  if (index.isValid() && index.row() < m_items.size()) {
51  switch (role) {
52  case Qt::DisplayRole:
53  return m_items.at(index.row()).label();
54  case Qt::CheckStateRole:
55  return m_items.at(index.row()).checkState();
56  case idRole():
57  return m_items.at(index.row()).id();
58  default:;
59  }
60  }
61  return QVariant();
62 }
63 
64 QMap<int, QVariant> ChecklistModel::itemData(const QModelIndex &index) const
65 {
66  QMap<int, QVariant> roles;
67  roles.insert(Qt::DisplayRole, data(index, Qt::DisplayRole));
68  roles.insert(Qt::CheckStateRole, data(index, Qt::CheckStateRole));
69  roles.insert(idRole(), data(index, idRole()));
70  return roles;
71 }
72 
73 bool ChecklistModel::setData(const QModelIndex &index, const QVariant &value, int role)
74 {
75  bool success = false;
76  QVector<int> roles{ role };
77  if (index.isValid() && index.row() < m_items.size()) {
78  switch (role) {
79  case Qt::DisplayRole:
80  m_items[index.row()].m_label = value.toString();
81  success = true;
82  break;
83  case Qt::CheckStateRole:
84  if (value.canConvert(QMetaType::Int)) {
85  m_items[index.row()].m_checkState = static_cast<Qt::CheckState>(value.toInt());
86  success = true;
87  }
88  break;
89  case idRole(): {
90  m_items[index.row()].m_id = value;
91  success = true;
92  auto label = labelForId(value);
93  if (!label.isEmpty()) {
94  m_items[index.row()].m_label = std::move(label);
95  roles << Qt::DisplayRole;
96  }
97  break;
98  }
99  default:;
100  }
101  }
102  if (success) {
103  dataChanged(index, index, roles);
104  }
105  return success;
106 }
107 
108 bool ChecklistModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
109 {
110  for (QMap<int, QVariant>::ConstIterator it = roles.constBegin(); it != roles.constEnd(); ++it) {
111  setData(index, it.value(), it.key());
112  }
113  return true;
114 }
115 
119 bool ChecklistModel::setChecked(int row, Qt::CheckState checked)
120 {
121  if (row < 0 || row >= m_items.size()) {
122  return false;
123  }
124  m_items[row].m_checkState = checked ? Qt::Checked : Qt::Unchecked;
125  const auto index(this->index(row));
126  dataChanged(index, index, QVector<int>{ Qt::CheckStateRole });
127  return true;
128 }
129 
143 QString ChecklistModel::labelForId(const QVariant &) const
144 {
145  return QString();
146 }
147 
149 {
150  return Qt::MoveAction;
151 }
152 
153 bool ChecklistModel::insertRows(int row, int count, const QModelIndex &parent)
154 {
155  if (count < 1 || row < 0 || row > rowCount() || parent.isValid()) {
156  return false;
157  }
158  beginInsertRows(QModelIndex(), row, row + count - 1);
159  for (int index = row, end = row + count; index < end; ++index) {
160  m_items.insert(index, ChecklistItem());
161  }
162  endInsertRows();
163  return true;
164 }
165 
166 bool ChecklistModel::removeRows(int row, int count, const QModelIndex &parent)
167 {
168  if (count < 1 || row < 0 || (row + count) > rowCount() || parent.isValid()) {
169  return false;
170  }
171  beginRemoveRows(QModelIndex(), row, row + count - 1);
172  for (int index = row, end = row + count; index < end; ++index) {
173  m_items.removeAt(index);
174  }
175  endRemoveRows();
176  return true;
177 }
178 
182 void ChecklistModel::setItems(const QList<ChecklistItem> &items)
183 {
184  beginResetModel();
185  m_items = items;
186  for (auto &item : m_items) {
187  if (item.m_label.isEmpty()) {
188  item.m_label = labelForId(item.id());
189  }
190  }
191  endResetModel();
192 }
193 
204 void ChecklistModel::restore(QSettings &settings, const QString &name)
205 {
206  beginResetModel();
207  auto currentItems = m_items;
208  QList<QVariant> restoredIds;
209  m_items.clear();
210  int rows = settings.beginReadArray(name);
211  m_items.reserve(rows);
212  for (int i = 0; i < rows; ++i) {
213  settings.setArrayIndex(i);
214  QVariant id = settings.value(QStringLiteral("id"));
215  QVariant selected = settings.value(QStringLiteral("selected"));
216  if (!id.isNull() && !selected.isNull() && selected.canConvert(QMetaType::Bool) && !restoredIds.contains(id)) {
217  m_items << ChecklistItem(id, labelForId(id), selected.toBool() ? Qt::Checked : Qt::Unchecked);
218  restoredIds << id;
219  }
220  }
221  settings.endArray();
222  for (const ChecklistItem &item : currentItems) {
223  if (!restoredIds.contains(item.id())) {
224  m_items << item;
225  }
226  }
227  endResetModel();
228 }
229 
237 void ChecklistModel::save(QSettings &settings, const QString &name) const
238 {
239  settings.beginWriteArray(name, m_items.size());
240  int index = 0;
241  for (const ChecklistItem &item : m_items) {
242  settings.setArrayIndex(index);
243  settings.setValue(QStringLiteral("id"), item.id());
244  settings.setValue(QStringLiteral("selected"), item.isChecked());
245  ++index;
246  }
247  settings.endArray();
248 }
249 
253 QVariantList ChecklistModel::toVariantList() const
254 {
255  QVariantList checkedIds;
256  checkedIds.reserve(m_items.size());
257  for (const auto &item : m_items) {
258  if (item.isChecked()) {
259  checkedIds << item.id();
260  }
261  }
262  return checkedIds;
263 }
264 
268 void ChecklistModel::applyVariantList(const QVariantList &checkedIds)
269 {
270  for (auto &item : m_items) {
271  item.m_checkState = checkedIds.contains(item.id()) ? Qt::Checked : Qt::Unchecked;
272  }
273  emit dataChanged(index(0), index(m_items.size()), { Qt::CheckStateRole });
274 }
275 
276 } // namespace Models
ChecklistModel(QObject *parent=nullptr)
Constructs a new checklist model.
void save(QSettings &settings, const QString &name) const
Saves the IDs and checkstates to the specified settings object.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::DisplayRole) override
virtual QString labelForId(const QVariant &id) const
Returns the label for the specified id.
void setItems(const QList< ChecklistItem > &items)
Sets the items.
bool insertRows(int row, int count, const QModelIndex &parent) override
bool setItemData(const QModelIndex &index, const QMap< int, QVariant > &roles) override
bool removeRows(int row, int count, const QModelIndex &parent) override
Qt::ItemFlags flags(const QModelIndex &index) const override
static constexpr int idRole()
Returns the role used to get or set the item ID.
The ChecklistItem class provides an item for use with the ChecklistModel class.
QVariantList toVariantList() const
Returns the checked IDs.
QMap< int, QVariant > itemData(const QModelIndex &index) const override
void applyVariantList(const QVariantList &checkedIds)
Checks all items contained by checkedIds and unchecks other items.
void restore(QSettings &settings, const QString &name)
Restores the IDs and checkstates read from the specified settings object.
Qt::DropActions supportedDropActions() const override
Provides common models.
const QList< ChecklistItem > & items() const
Returns the items.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
bool setChecked(int row, bool checked)
Sets the checked state of the specified item.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override