EHM DAL 0.2.3
Data abstraction layer for Eastside Hockey Manager
Loading...
Searching...
No Matches
game_child_tree_table.h
1#pragma once
2
3// Application headers
4#include "include/column_data/column_data.h"
5#include "include/tables/game_child_table.h"
6
7// Qt headers
8#include <QDataStream>
9
10namespace ehm_dal::tables {
11template<class T_ChildAbstractTableItem,
12 class T_ParentAbstractTableItem,
13 class T_ColumnData = ehm_dal::column_data::ColumnData>
20 : public GameChildTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>
21{
22public:
23 GameChildTreeTable(const QString &table_name,
24 const ehm_dal::tables::TableIndex table_id,
25 const TableType table_type);
26
27 // Child data
28 // NOTE the sibling() function fails QAbstractItemModelTester but does work
29 bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
30 QModelIndex sibling(int row, int column, const QModelIndex &idx) const override;
31
32 // Get data
33 QVariant data(const QModelIndex &index, qint32 role = Qt::DisplayRole) const override;
34
35 // Get data - counts
36 qint32 columnCount(const QModelIndex &parent = QModelIndex()) const override;
37 qint32 rowCount(const QModelIndex &parent = QModelIndex()) const override;
38
39 // Indexes
40 bool hasIndex(int row, int column, const QModelIndex &parent = QModelIndex()) const;
41 QModelIndex index(qint32 row,
42 qint32 column,
43 const QModelIndex &parent = QModelIndex()) const override;
44 QModelIndex parent(const QModelIndex &index) const override;
45
46 // Set data
47 bool setData(const QModelIndex &index,
48 const QVariant &value,
49 qint32 role = Qt::EditRole) override;
50
51 // Table model type
52 inline QString modelName() const override { return QStringLiteral("Game child tree table"); }
53 inline constexpr AbstractBaseModel::AbstractTableModelType modelType() const override
54 {
55 return AbstractBaseModel::AbstractTableModelType::GameChildTreeTable;
56 }
57
58private:
59 static constexpr qint32 parent_row_column_count_{1}; // Column count for parent rows
60};
61
62/* ============================== */
63/* Game Child Tree Table */
64/* ============================== */
65
66template<class T_ChildAbstractTableItem, class T_ParentAbstractTableItem, class T_ColumnData>
68 GameChildTreeTable(const QString &table_name,
69 const TableIndex table_id,
70 const TableType table_type)
71 : GameChildTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>(table_name,
72 table_id,
73 table_type)
74{}
75
76/* ================= */
77/* Children */
78/* ================= */
79
80template<class T_ChildAbstractTableItem, class T_ParentAbstractTableItem, class T_ColumnData>
81bool GameChildTreeTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>::hasChildren(
82 const QModelIndex &parent) const
83{
84 if (!parent.isValid())
85 return true; // The root has children: the parent rows
86
87 if (parent.column() != 0)
88 return false; // Only parent column 0 should have children
89
90 if (parent.internalId() == static_cast<quintptr>(GameChildTreeTable::NO_PARENT))
91 return this->rowCount(parent) > 0; // True if the parent row has any children
92
93 return false; // Parent row has no children
94}
95
96template<class T_ChildAbstractTableItem, class T_ParentAbstractTableItem, class T_ColumnData>
97QModelIndex
98GameChildTreeTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>::sibling(
99 int row, int column, const QModelIndex &idx) const
100{
101 if (!idx.isValid())
102 return QModelIndex();
103
104 // For top-level items (i.e. parent)
105 if (!idx.parent().isValid()) {
106 // Top-level items only have one column.
107 // If column != 0 or the row is out of bounds, return an invalid index.
108 if (column != 0 || row < 0 || row >= rowCount())
109 return QModelIndex();
110
111 return index(row, 0); // Return the top-level index for the specified row
112 }
113
114 // For child items
115 if (row < 0 || row >= rowCount(idx.parent()) || column < 0
116 || column >= columnCount(idx.parent()))
117 return QModelIndex();
118
119 return index(row, column, idx.parent());
120}
121
122/* ================= */
123/* Get Data */
124/* ================= */
125
126template<class T_ChildAbstractTableItem, class T_ParentAbstractTableItem, class T_ColumnData>
127QVariant GameChildTreeTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>::data(
128 const QModelIndex &index, qint32 role) const
129{
130 // Child data
131 if (index.internalId() != static_cast<quintptr>(GameChildTreeTable::NO_PARENT))
132 return GameChildTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>::
133 data(index, role);
134
135 // Parent data
136 if (role == Qt::DisplayRole) {
137 switch (index.column()) {
138 case 0:
139 return this->parent_table_->text(index.row());
140 default:
141 break;
142 }
143 }
144
145 return QVariant();
146}
147
148/* ========================== */
149/* Get Data - Counts */
150/* ========================== */
151
152template<class T_ChildAbstractTableItem, class T_ParentAbstractTableItem, class T_ColumnData>
153qint32
154GameChildTreeTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>::columnCount(
155 const QModelIndex &parent) const
156{
157 if (!parent.isValid())
158 return this->constColumnData()->columnCount(); // Parent level
159
160 if (parent.internalId() == static_cast<quintptr>(GameChildTreeTable::NO_PARENT)
161 && parent.column() == 0)
162 return this->constColumnData()->columnCount(); // Child level
163
164 return 0; // Return 0 by default, although this shouldn't typically be reached
165
166 // NOTE previous (working code) was as follows.
167 // This however fails QAbstractItemModelTester with the following error
168 // FAIL! childIndex != childIndex1 () returned FALSE
169 /* Q_UNUSED(parent)
170 return this->constColumnData()->columnCount();*/
171}
172
173template<class T_ChildAbstractTableItem, class T_ParentAbstractTableItem, class T_ColumnData>
174qint32 GameChildTreeTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>::rowCount(
175 const QModelIndex &parent) const
176{
177 // Return number of parent rows
178 if (!parent.isValid())
179 return this->parent_table_->rowCount();
180
181 // Return number of child rows for a parent
182 if (parent.internalId() == static_cast<quintptr>(GameChildTreeTable::NO_PARENT)
183 && parent.column() == 0)
184 return this->parent_table_->childRowCount(parent.row(), this->attributes()->id());
185
186 return 0; // Child rows do not have their own children
187}
188
189/* ================ */
190/* Indexes */
191/* ================ */
192
193template<class T_ChildAbstractTableItem, class T_ParentAbstractTableItem, class T_ColumnData>
194bool GameChildTreeTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>::hasIndex(
195 int row, int column, const QModelIndex &parent) const
196{
197 if (parent.isValid() && parent.column() != 0) // Only parent column 0 should have children
198 return false;
199
200 if (column < 0 || column >= this->columnCount(parent)) {
201 return false;
202 }
203
204 return row >= 0 && row < this->rowCount(parent);
205}
206
207template<class T_ChildAbstractTableItem, class T_ParentAbstractTableItem, class T_ColumnData>
208QModelIndex
209GameChildTreeTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>::index(
210 qint32 row, qint32 column, const QModelIndex &parent) const
211{
212 if (!this->hasIndex(row, column, parent))
213 return QModelIndex();
214
215 if (!parent.isValid())
216 return this->createIndex(row, column, static_cast<quintptr>(GameChildTreeTable::NO_PARENT));
217
218 return this->createIndex(row,
219 column,
220 parent.row() + GameChildTreeTable::CHILD_INDEX_PARENT_ROW_MODIFIER);
221}
222
223template<class T_ChildAbstractTableItem, class T_ParentAbstractTableItem, class T_ColumnData>
224QModelIndex
225GameChildTreeTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>::parent(
226 const QModelIndex &index) const
227{
228 if (!index.isValid()
229 || index.internalId() == static_cast<quintptr>(GameChildTreeTable::NO_PARENT))
230 return QModelIndex();
231
232 return this->createIndex(index.internalId()
233 - GameChildTreeTable::CHILD_INDEX_PARENT_ROW_MODIFIER,
234 0);
235}
236
237/* ================= */
238/* Set Data */
239/* ================= */
240
241template<class T_ChildAbstractTableItem, class T_ParentAbstractTableItem, class T_ColumnData>
242bool GameChildTreeTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>::setData(
243 const QModelIndex &index, const QVariant &value, qint32 role)
244{
245 if (index.internalId() == static_cast<quintptr>(GameChildTreeTable::NO_PARENT))
246 return false;
247
248 return GameChildTable<T_ChildAbstractTableItem, T_ParentAbstractTableItem, T_ColumnData>::setData(
249 index, value, role);
250}
251
252} // namespace ehm_dal::tables
The ColumnData class represents a container of ehm_dal::column_data::Column and attributes relating t...
Definition: column_data.h:18
The GameChildTable class is a model for child data of a parent table. Each parent item has a single c...
Definition: game_child_table.h:20
The GameChildTreeTable class is a model for child data of a parent table. Each parent item can have m...
Definition: game_child_tree_table.h:21
namespace ehm_dal::tables
Definition: column.h:4
TableType
The TableType enum denotes different types of database table.
Definition: table_type.h:12
TableIndex
The TableIndex enum represents the id number of each table within the database.
Definition: table_index.h:14