Qx v0.5.8
Qt Extensions Library
Loading...
Searching...
No Matches
qx-table.h
1#ifndef QX_TABLE_H
2#define QX_TABLE_H
3
4// Qt Includes
5#include <QList>
6#include <QSize>
7
8namespace Qx
9{
10
11template<typename T>
12class Table
13{
14//-Iterators------------------------------------------------------------------------------------------------
15public:
16 typedef typename QList<QList<T>>::const_iterator row_iterator;
17 /* TODO: Add more iterators, expects ones, as well as one that traversers each element
18 * from top left to bottom right
19 */
20
21//-Instance Variables---------------------------------------------------------------------------------------
22protected:
24
25//-Constructor----------------------------------------------------------------------------------------------
26public:
27 Table() {}
28
30 {
32 for(QList<T>& row : mTable)
33 row.resize(size.width());
34 }
35
36 Table(QSize size, const T& value)
37 {
38 QList<T> row(size.width(), value);
40 }
41
42 Table(std::initializer_list<std::initializer_list<T>> table)
43 {
44 if(table.size() == 0)
45 return;
46
47 qsizetype headerWidth = table.begin()->size();
48
49 for(auto itr = table.begin(); itr != table.end(); itr++)
50 {
51 if(itr->size() != headerWidth)
52 {
53 mTable.clear();
54 break;
55 }
56
57 mTable.append(*itr);
58 }
59 }
60
61//-Instance Functions----------------------------------------------------------------------------------------------
62public:
63 T& at(qsizetype r, qsizetype c)
64 {
65 Q_ASSERT_X(size_t(r) < size_t(rowCount()) && size_t(c) < size_t(columnCount()), Q_FUNC_INFO, "index out of range");
66
67 return mTable[r][c];
68 }
69
70 const T& at(qsizetype r, qsizetype c) const
71 {
72 Q_ASSERT_X(size_t(r) < size_t(rowCount()) && size_t(c) < size_t(columnCount()), Q_FUNC_INFO, "index out of range");
73
74 return mTable.at(r).at(c);
75 }
76
78 {
79 qsizetype rowCap = mTable.capacity();
80 qsizetype colCap = !mTable.isEmpty() ? mTable.first().capacity() : 0;
81
82 return QSize(rowCap, colCap);
83 }
84
85 QList<T> columnAt(qsizetype i) const
86 {
87 Q_ASSERT_X(size_t(i) < size_t(columnCount()), Q_FUNC_INFO, "index out of range");
88
89 // Build column list
90 QList<T> col;
91
92 for(const QList<T>& row : mTable)
93 col << row[i];
94
95 return col;
96 }
97
98 qsizetype columnCount() const { return mTable.isEmpty() ? 0 : mTable.first().size(); }
99
101 {
102 Q_ASSERT(columnCount() > 0);
103 return columnAt(0);
104 }
105
106 const QList<T>& firstRow() const
107 {
108 Q_ASSERT(rowCount() > 0);
109 return rowAt(0);
110 }
111
112 qsizetype height() const { return rowCount(); }
113
114 bool isEmpty() const { return mTable.isEmpty(); }
115
117 {
118 qsizetype height = columnCount();
119 Q_ASSERT(height > 0);
120 return rowAt(height - 1);
121 }
122
123 const QList<T>& lastRow() const
124 {
125 qsizetype width = rowCount();
126 Q_ASSERT(width > 0);
127 return rowAt(width - 1);
128 }
129
130 const QList<T>& rowAt(qsizetype i) const
131 {
132 Q_ASSERT_X(i < rowCount(), Q_FUNC_INFO, "index out of range");
133
134 return mTable[i];
135 }
136
138
139 qsizetype rowCount() const { return mTable.size(); }
140
141 row_iterator rowEnd() const { return mTable.constEnd(); }
142
143 Table section(qsizetype r, qsizetype c, qsizetype height, qsizetype width) const
144 {
145 // Empty shortcut: If table is already empty, or start pos would make it empty
146 if(mTable.isEmpty() || size_t(r) > size_t(mTable.size() - 1) || size_t(c) > size_t(mTable.first().size() - 1))
147 return Table();
148
149 // Cap width/height to max
150 qsizetype wDelta = r + width - mTable.size();
151 qsizetype hDelta = c + height - mTable.first().size();
152 width = wDelta > 0 ? width - wDelta : width;
153 height = hDelta > 0 ? height - hDelta : height;
154
155 Table sec;
156 sec.mTable = mTable.sliced(r, width);
157 for(QList<T>& row : sec.mTable)
158 row = row.sliced(c, height);
159
160 return sec;
161 }
162
163 QSize size() const { return QSize(columnCount(), rowCount()); }
164
165 T value(qsizetype r, qsizetype c) const { return value(r, c, T()); }
166
167 T value(qsizetype r, qsizetype c, const T& defaultValue) const
168 {
169 return r < rowCount() && c < columnCount() ? at(r,c) : defaultValue;
170 }
171
172 void addColumns(qsizetype c) { resizeColumns(columnCount() + c); }
173
174 void addRows(qsizetype r) { resizeRows(rowCount() + r); }
175
176 void appendColumn(const QList<T>& c)
177 {
178 // If column is larger than current table height, expand it
179 if(c.size() > columnCount())
180 resizeColumns(c.size());
181
182 // Add values from column, or default values if column is smaller than height
183 for(qsizetype i = 0; i < mTable.size(); i++)
184 mTable[i].append(i > c.size() - 1 ? T() : c[i]);
185 }
186
187 void appendRow(const QList<T>& r)
188 {
189 // If row is larger than current table width, expand it
190 if(r.size() > rowCount())
191 resizeRows(r.size());
192
193 // Add row
194 mTable.append(r);
195
196 // Expand row if it's smaller than the table's width
197 qsizetype width = rowCount();
198 if(r.size() < width)
199 mTable.back().resize(width);
200 }
201
202 void fill(const T& value, QSize size)
203 {
204 if(!size.isNull())
205 resize(size);
206
207 for(QList<T>& row : mTable)
208 row.fill(value);
209 }
210
211 void insertColumn(qsizetype i, const QList<T>& c)
212 {
213 Q_ASSERT_X(i >= 0 && i <= columnCount(), "QTable<T>::insertColumn", "index out of range");
214
215 // Expand height if c is larger than current height
216 qsizetype rows = rowCount();
217 if(c.size() > rows)
218 {
219 resizeRows(c.size());
220 rows = c.size();
221 }
222
223 // Insert values from column, or default values if column is smaller than height
224 for(qsizetype r = 0; r < rows; r++)
225 mTable[r].insert(i, r > c.size() - 1 ? T() : c[r]);
226 }
227
228 void insertRow(qsizetype i, const QList<T>& r)
229 {
230 Q_ASSERT_X(i >= 0 && i <= rowCount(), "QTable<T>::insertRow", "index out of range");
231
232 // Expand width if r is larger than current width
233 qsizetype columns = columnCount();
234 if(r.size() > columns)
235 {
236 resizeColumns(r.size());
237 columns = r.size();
238 }
239
240 // Insert row, then expand it if it's smaller than the current width
241 mTable.insert(i, r);
242 if(r.size() < columns)
243 mTable[i].resize(columns);
244 }
245
246 void removeColumnAt(qsizetype i) { removeColumns(i); }
247
248 void removeColumns(qsizetype i, qsizetype n = 1)
249 {
250 Q_ASSERT_X(size_t(i) + size_t(n) <= size_t(columnCount()), Q_FUNC_INFO, "index out of range");
251 Q_ASSERT_X(n >= 0, Q_FUNC_INFO, "invalid count");
252
253 if (n == 0)
254 return;
255
256 for(QList<T>& row : mTable)
257 row.remove(i, n);
258 }
259
260 void removeRowAt(qsizetype i) { removeRows(i); }
261
262 void removeRows(qsizetype i, qsizetype n = 1)
263 {
264 Q_ASSERT_X(size_t(i) + size_t(n) <= size_t(rowCount()), Q_FUNC_INFO, "index out of range");
265 Q_ASSERT_X(n >= 0, Q_FUNC_INFO, "invalid count");
266
267 if (n == 0)
268 return;
269
270 mTable.remove(i, n);
271 }
272
274 {
275 Q_ASSERT(columnCount() > 0);
277 }
278
280 {
281 Q_ASSERT(rowCount() > 0);
282 removeRowAt(0);
283 }
284
286 {
287 qsizetype height = columnCount();
288 Q_ASSERT(height > 0);
290 }
291
293 {
294 qsizetype width = rowCount();
295 Q_ASSERT(width > 0);
297 }
298
299 void replaceColumn(qsizetype i, const QList<T>& c)
300 {
301 // Expand height if c is larger than current height
302 qsizetype rows = rowCount();
303 qsizetype rowGrowth = rows - c.size();
304 if(rowGrowth > 0)
305 resizeRows(c.size());
306
307 // Replace with values from column, or default values if column is smaller than height
308 for(qsizetype r = 0; r < rows; r++)
309 mTable[r].replace(i, r > c.size() - 1 ? T() : c[r]);
310 }
311
312 void replaceRow(qsizetype i, const QList<T>& r)
313 {
314 // Expand width if r is larger than current width
315 qsizetype columns = columnCount();
316 qsizetype columnGrowth = columns - r.size();
317 if(columnGrowth > 0)
318 resizeColumns(r.size());
319
320 // Replace row, then expand it if it's smaller than the current width
321 mTable.replace(i, r);
322 if(columnGrowth < 0)
323 mTable[i].resize(columns);
324 }
325
327 {
328 /* TODO: This class could be modified so that it somehow tracks which rows are
329 * actually part of the table, so that empty rows could be added without messing up the actual row
330 * count/size of the table. This would avoid the limitation mentioned in this methods doc, as empty
331 * rows could be added, which then have reserve called on them in order to reserve the full
332 * size specified by the user, though it would add a small amount of overhead elsewhere.
333 */
334
335 if(size == Table::size())
336 return;
337
339 for(QList<T>& row : mTable)
340 row.reserve(size.width());
341 }
342
344 {
345 if(size == Table::size())
346 return;
347
350 }
351
352 void resizeColumns(qsizetype size)
353 {
354 if(size == columnCount())
355 return;
356
357 for(QList<T>& row : mTable)
358 row.resize(size);
359 }
360
361 void resizeRows(qsizetype size)
362 {
363 if(size == rowCount())
364 return;
365
366 qsizetype currentSize = rowCount();
367 qsizetype growth = size - currentSize;
368 qsizetype columns = columnCount();
369
371
372 if(growth > 0 && columns > 0)
373 {
374
375 for(qsizetype r = currentSize; r < rowCount(); r++)
376 mTable[r].resize(columns);
377 }
378 }
379
380 void squeeze()
381 {
382 mTable.squeeze();
383 for(QList<T>& row : mTable)
384 row.squeeze();
385 }
386
388 {
389 Q_ASSERT_X(size_t(i) < size_t(columnCount()), Q_FUNC_INFO, "index out of range");
390
391 QList<T> col = columnAt(i);
393 return col;
394 }
395
397 {
398 Q_ASSERT(columnCount() > 0);
399 return takeColumnAt(0);
400 }
401
403 {
404 Q_ASSERT(rowCount() > 0);
405 return takeRowAt(0);
406 }
407
409 {
410 qsizetype height = columnCount();
411 Q_ASSERT(height > 0);
412 return takeColumnAt(height - 1);
413 }
414
416 {
417 qsizetype width = rowCount();
418 Q_ASSERT(width > 0);
419 return takeRowAt(width - 1);
420 }
421
422 QList<T> takeRowAt(qsizetype i)
423 {
424 Q_ASSERT_X(size_t(i) < size_t(rowCount()), Q_FUNC_INFO, "index out of range");
425
426 return mTable.takeAt(i);
427 }
428
429 qsizetype width() const { return columnCount(); }
430
431 bool operator==(const Table& other) const { return mTable == other.mTable; }
432 bool operator!=(const Table& other) const { return !(mTable == other.mTable); }
433};
434
435}
436
437#endif // QX_TABLE_H
The Table class is a template class that provides a dynamic two-dimensional array.
Definition qx-table.h:13
void removeColumnAt(qsizetype i)
Definition qx-table.h:246
qsizetype height() const
Definition qx-table.h:112
void insertColumn(qsizetype i, const QList< T > &c)
Definition qx-table.h:211
void removeColumns(qsizetype i, qsizetype n=1)
Definition qx-table.h:248
Table(QSize size)
Definition qx-table.h:29
Table(QSize size, const T &value)
Definition qx-table.h:36
void fill(const T &value, QSize size)
Definition qx-table.h:202
T value(qsizetype r, qsizetype c) const
Definition qx-table.h:165
row_iterator rowBegin() const
Definition qx-table.h:137
Table(std::initializer_list< std::initializer_list< T > > table)
Definition qx-table.h:42
void resize(QSize size)
Definition qx-table.h:343
T value(qsizetype r, qsizetype c, const T &defaultValue) const
Definition qx-table.h:167
QList< QList< T > > mTable
Definition qx-table.h:23
QList< QList< T > >::const_iterator row_iterator
Definition qx-table.h:16
Table section(qsizetype r, qsizetype c, qsizetype height, qsizetype width) const
Definition qx-table.h:143
bool operator!=(const Table &other) const
Definition qx-table.h:432
QList< T > takeLastColumn()
Definition qx-table.h:408
Table()
Definition qx-table.h:27
qsizetype rowCount() const
Definition qx-table.h:139
bool isEmpty() const
Definition qx-table.h:114
row_iterator rowEnd() const
Definition qx-table.h:141
void appendRow(const QList< T > &r)
Definition qx-table.h:187
QList< T > takeFirstRow()
Definition qx-table.h:402
void removeLastColumn()
Definition qx-table.h:285
const QList< T > & rowAt(qsizetype i) const
Definition qx-table.h:130
void removeFirstColumn()
Definition qx-table.h:273
QList< T > takeColumnAt(qsizetype i)
Definition qx-table.h:387
qsizetype width() const
Definition qx-table.h:429
qsizetype columnCount() const
Definition qx-table.h:98
const T & at(qsizetype r, qsizetype c) const
Definition qx-table.h:70
bool operator==(const Table &other) const
Definition qx-table.h:431
void removeRows(qsizetype i, qsizetype n=1)
Definition qx-table.h:262
QList< T > firstColumn() const
Definition qx-table.h:100
QList< T > columnAt(qsizetype i) const
Definition qx-table.h:85
QList< T > takeRowAt(qsizetype i)
Definition qx-table.h:422
const QList< T > & firstRow() const
Definition qx-table.h:106
QSize size() const
Definition qx-table.h:163
void appendColumn(const QList< T > &c)
Definition qx-table.h:176
T & at(qsizetype r, qsizetype c)
Definition qx-table.h:63
void addRows(qsizetype r)
Definition qx-table.h:174
void addColumns(qsizetype c)
Definition qx-table.h:172
const QList< T > & lastRow() const
Definition qx-table.h:123
void removeFirstRow()
Definition qx-table.h:279
QList< T > takeFirstColumn()
Definition qx-table.h:396
void replaceColumn(qsizetype i, const QList< T > &c)
Definition qx-table.h:299
void resizeColumns(qsizetype size)
Definition qx-table.h:352
void removeRowAt(qsizetype i)
Definition qx-table.h:260
void removeLastRow()
Definition qx-table.h:292
QList< T > lastColumn() const
Definition qx-table.h:116
void replaceRow(qsizetype i, const QList< T > &r)
Definition qx-table.h:312
void resizeRows(qsizetype size)
Definition qx-table.h:361
void squeeze()
Definition qx-table.h:380
void reserve(QSize size)
Definition qx-table.h:326
void insertRow(qsizetype i, const QList< T > &r)
Definition qx-table.h:228
QList< T > takeLastRow()
Definition qx-table.h:415
QSize capacity() const
Definition qx-table.h:77
The Qx namespace is the main namespace through which all non-global functionality of the Qx library i...
Definition qx-processwaiter.cpp:5
void append(QList< T > &&value)
QList< T >::const_reference at(qsizetype i) const const
QList< T >::reference back()
qsizetype capacity() const const
void clear()
QList< T >::const_iterator constBegin() const const
QList< T >::const_iterator constEnd() const const
T & first()
QList< T >::iterator insert(QList< T >::const_iterator before, QList< T >::parameter_type value)
bool isEmpty() const const
void remove(qsizetype i, qsizetype n)
void replace(qsizetype i, QList< T >::parameter_type value)
void reserve(qsizetype size)
void resize(qsizetype size)
qsizetype size() const const
QList< T > sliced(qsizetype pos) const const
void squeeze()
T takeAt(qsizetype i)
int height() const const
bool isNull() const const
int width() const const