Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qstandarditemmodel.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtCore/qdatetime.h>
7#include <QtCore/qlist.h>
8#include <QtCore/qmap.h>
9#include <QtCore/qpair.h>
10#include <QtCore/qvariant.h>
11#include <QtCore/qstringlist.h>
12#include <QtCore/qbitarray.h>
13#include <QtCore/qmimedata.h>
14#include <QtCore/qiodevice.h>
15#include <private/qduplicatetracker_p.h>
16#include <private/qstandarditemmodel_p.h>
17#include <qdebug.h>
18#include <algorithm>
19
21
22// Used internally to store the flags
23namespace {
25}
29 return QStringLiteral("application/x-qstandarditemmodeldatalist");
30}
31
33{
34public:
37
38 inline bool operator()(const QPair<QStandardItem*, int> &l,
39 const QPair<QStandardItem*, int> &r) const
40 {
41 return *(l.first) < *(r.first);
42 }
43};
44
46{
47public:
50
51 inline bool operator()(const QPair<QStandardItem*, int> &l,
52 const QPair<QStandardItem*, int> &r) const
53 {
54 return *(r.first) < *(l.first);
55 }
56};
57
61QPair<int, int> QStandardItemPrivate::position() const
62{
63 if (QStandardItem *par = parent) {
64 int idx = par->d_func()->childIndex(q_func());
65 if (idx == -1)
66 return QPair<int, int>(-1, -1);
67 return QPair<int, int>(idx / par->columnCount(), idx % par->columnCount());
68 }
69 // ### support header items?
70 return QPair<int, int>(-1, -1);
71}
72
77 bool emitChanged)
78{
79 Q_Q(QStandardItem);
80 if (item == q) {
81 qWarning("QStandardItem::setChild: Can't make an item a child of itself %p",
82 item);
83 return;
84 }
85 if ((row < 0) || (column < 0))
86 return;
87 if (rows <= row)
88 q->setRowCount(row + 1);
89 if (columns <= column)
90 q->setColumnCount(column + 1);
91 int index = childIndex(row, column);
92 Q_ASSERT(index != -1);
93 QStandardItem *oldItem = children.at(index);
94 if (item == oldItem)
95 return;
96
97 if (model && emitChanged) {
99 }
100
101 if (item) {
102 if (item->d_func()->parent == nullptr) {
103 item->d_func()->setParentAndModel(q, model);
104 } else {
105 qWarning("QStandardItem::setChild: Ignoring duplicate insertion of item %p",
106 item);
107 return;
108 }
109 }
110
111 // setting the model to nullptr invalidates the persistent index which we want to avoid
112 if (!item && oldItem)
113 oldItem->d_func()->setModel(nullptr);
114
116
117 // since now indexFromItem() does no longer return a valid index, the persistent index
118 // will not be invalidated anymore
119 if (oldItem)
120 oldItem->d_func()->setModel(nullptr);
121 delete oldItem;
122
123 if (item)
124 item->d_func()->lastKnownIndex = index;
125
126 if (model && emitChanged)
128
129 if (emitChanged && model) {
130 if (item) {
131 model->d_func()->itemChanged(item);
132 } else {
133 const QModelIndex idx = model->index(row, column, q->index());
134 emit model->dataChanged(idx, idx);
135 }
136 }
137}
138
139
144{
145 Q_Q(QStandardItem);
146 Qt::ItemFlags flags = q->flags();
147 if (enable)
148 flags |= f;
149 else
150 flags &= ~f;
151 q->setFlags(flags);
152}
153
158{
159 int index = childIndex(child);
160 Q_ASSERT(index != -1);
161 const auto modelIndex = child->index();
162 children.replace(index, nullptr);
163 emit model->dataChanged(modelIndex, modelIndex);
164}
165
166namespace {
167
168 struct ByNormalizedRole
169 {
170 static int normalizedRole(int role)
171 {
172 return role == Qt::EditRole ? Qt::DisplayRole : role;
173 }
174
175 bool operator()(const QStandardItemData& standardItemData, const std::pair<const int &, const QVariant&>& roleMapIt) const
176 {
177 return standardItemData.role < normalizedRole(roleMapIt.first);
178 }
179 bool operator()(const std::pair<const int&, const QVariant &>& roleMapIt, const QStandardItemData& standardItemData) const
180 {
181 return normalizedRole(roleMapIt.first) < standardItemData.role;
182 }
183
184 };
185
186 /*
187 Based on std::transform with a twist. The inputs are iterators of <int, QVariant> pair.
188 The variant is checked for validity and if not valid, that element is not taken into account
189 which means that the resulting output might be shorter than the input.
190 */
191 template<class Input, class OutputIt>
192 OutputIt roleMapStandardItemDataTransform(Input first1, Input last1, OutputIt d_first)
193 {
194 while (first1 != last1) {
195 if ((*first1).second.isValid())
196 *d_first++ = QStandardItemData(*first1);
197 ++first1;
198 }
199 return d_first;
200 }
201
203 /*
204 Based on std::set_union with a twist. The idea is to create a union of both inputs
205 with an additional constraint: if an input contains an invalid variant, it means
206 that this one should not be taken into account for generating the output.
207 */
208 template<class Input1, class Input2,
209 class OutputIt, class Compare>
210 OutputIt roleMapStandardItemDataUnion(Input1 first1, Input1 last1,
211 Input2 first2, Input2 last2,
212 OutputIt d_first, Compare comp)
213 {
214 for (; first1 != last1; ++d_first) {
215 if (first2 == last2) {
216 return roleMapStandardItemDataTransform(first1, last1, d_first);
217 }
218 if (comp(*first2, *first1)) {
219 *d_first = *first2++;
220 } else {
221 if ((*first1).second.isValid())
222 *d_first = QStandardItemData(*first1);
223 if (!comp(*first1, *first2))
224 ++first2;
225 ++first1;
226 }
227 }
228 return std::copy(first2, last2, d_first);
229 }
230}
231
235void QStandardItemPrivate::setItemData(const QMap<int, QVariant> &roles)
236{
237 Q_Q(QStandardItem);
238
239 auto byRole = [](const QStandardItemData& item1, const QStandardItemData& item2) {
240 return item1.role < item2.role;
241 };
242
243 std::sort(values.begin(), values.end(), byRole);
244
245 /*
246 Create a list of QStandardItemData that will contain the original values
247 if the matching role is not contained in roles, the new value if it is and
248 if the new value is an invalid QVariant, it will be removed.
249 */
250 QList<QStandardItemData> newValues;
251 newValues.reserve(values.size());
252 roleMapStandardItemDataUnion(roles.keyValueBegin(),
253 roles.keyValueEnd(),
254 values.cbegin(), values.cend(),
255 std::back_inserter(newValues), ByNormalizedRole());
256
257 if (newValues != values) {
258 values.swap(newValues);
259 if (model) {
260 QList<int> roleKeys;
261 roleKeys.reserve(roles.size() + 1);
262 bool hasEditRole = false;
263 bool hasDisplayRole = false;
264 for (auto it = roles.keyBegin(); it != roles.keyEnd(); ++it) {
265 roleKeys.push_back(*it);
266 if (*it == Qt::EditRole)
267 hasEditRole = true;
268 else if (*it == Qt::DisplayRole)
269 hasDisplayRole = true;
270 }
271 if (hasEditRole && !hasDisplayRole)
272 roleKeys.push_back(Qt::DisplayRole);
273 else if (!hasEditRole && hasDisplayRole)
274 roleKeys.push_back(Qt::EditRole);
275 model->d_func()->itemChanged(q, roleKeys);
276 }
277 }
278}
279
283QMap<int, QVariant> QStandardItemPrivate::itemData() const
284{
285 QMap<int, QVariant> result;
286 for (const auto &data : values) {
287 if (data.role != DataFlagsRole)
288 result.insert(data.role, data.value);
289 }
290 return result;
291}
292
297{
298 Q_Q(QStandardItem);
299 if (column >= columnCount())
300 return;
301
302 QList<QPair<QStandardItem*, int> > sortable;
303 QList<int> unsortable;
304
305 sortable.reserve(rowCount());
306 unsortable.reserve(rowCount());
307
308 for (int row = 0; row < rowCount(); ++row) {
309 QStandardItem *itm = q->child(row, column);
310 if (itm)
311 sortable.append(QPair<QStandardItem*,int>(itm, row));
312 else
313 unsortable.append(row);
314 }
315
316 if (order == Qt::AscendingOrder) {
318 std::stable_sort(sortable.begin(), sortable.end(), lt);
319 } else {
321 std::stable_sort(sortable.begin(), sortable.end(), gt);
322 }
323
324 QModelIndexList changedPersistentIndexesFrom, changedPersistentIndexesTo;
325 QList<QStandardItem*> sorted_children(children.size());
326 for (int i = 0; i < rowCount(); ++i) {
327 int r = (i < sortable.size()
328 ? sortable.at(i).second
329 : unsortable.at(i - sortable.size()));
330 for (int c = 0; c < columnCount(); ++c) {
331 QStandardItem *itm = q->child(r, c);
332 sorted_children[childIndex(i, c)] = itm;
333 if (model) {
334 QModelIndex from = model->createIndex(r, c, q);
335 if (model->d_func()->persistent.indexes.contains(from)) {
336 QModelIndex to = model->createIndex(i, c, q);
337 changedPersistentIndexesFrom.append(from);
338 changedPersistentIndexesTo.append(to);
339 }
340 }
341 }
342 }
343
344 children = sorted_children;
345
346 if (model) {
347 model->changePersistentIndexList(changedPersistentIndexesFrom, changedPersistentIndexesTo);
348 }
349
351 for (it = children.begin(); it != children.end(); ++it) {
352 if (*it)
353 (*it)->d_func()->sortChildren(column, order);
354 }
355}
356
362{
363 if (children.isEmpty()) {
364 if (model)
365 model->d_func()->invalidatePersistentIndex(model->indexFromItem(q_ptr));
366 model = mod;
367 } else {
368 QStack<QStandardItem*> stack;
369 stack.push(q_ptr);
370 while (!stack.isEmpty()) {
371 QStandardItem *itm = stack.pop();
372 if (itm->d_func()->model) {
373 itm->d_func()->model->d_func()->invalidatePersistentIndex(itm->d_func()->model->indexFromItem(itm));
374 }
375 itm->d_func()->model = mod;
376 const QList<QStandardItem*> &childList = itm->d_func()->children;
377 for (int i = 0; i < childList.size(); ++i) {
378 QStandardItem *chi = childList.at(i);
379 if (chi)
380 stack.push(chi);
381 }
382 }
383 }
384}
385
394
401
412
417 const QModelIndex &bottomRight)
418{
420 QModelIndex parent = topLeft.parent();
421 for (int row = topLeft.row(); row <= bottomRight.row(); ++row) {
422 for (int column = topLeft.column(); column <= bottomRight.column(); ++column) {
423 QModelIndex index = q->index(row, column, parent);
425 emit q->itemChanged(item);
426 }
427 }
428}
429
433bool QStandardItemPrivate::insertRows(int row, const QList<QStandardItem*> &items)
434{
435 Q_Q(QStandardItem);
436 if ((row < 0) || (row > rowCount()) || items.isEmpty())
437 return false;
438 int count = items.size();
439 if (model)
440 model->d_func()->rowsAboutToBeInserted(q, row, row + count - 1);
441 if (rowCount() == 0) {
442 if (columnCount() == 0)
443 q->setColumnCount(1);
445 rows = count;
446 } else {
447 rows += count;
448 int index = childIndex(row, 0);
449 if (index != -1)
450 children.insert(index, columnCount() * count, nullptr);
451 }
452 for (int i = 0; i < items.size(); ++i) {
454 item->d_func()->model = model;
455 item->d_func()->parent = q;
456 int index = childIndex(i + row, 0);
458 if (item)
459 item->d_func()->lastKnownIndex = index;
460 }
461 if (model)
462 model->d_func()->rowsInserted(q, row, count);
463 return true;
464}
465
466bool QStandardItemPrivate::insertRows(int row, int count, const QList<QStandardItem*> &items)
467{
468 Q_Q(QStandardItem);
469 if ((count < 1) || (row < 0) || (row > rowCount()) || count == 0)
470 return false;
471 if (model)
472 model->d_func()->rowsAboutToBeInserted(q, row, row + count - 1);
473 if (rowCount() == 0) {
475 rows = count;
476 } else {
477 rows += count;
478 int index = childIndex(row, 0);
479 if (index != -1)
480 children.insert(index, columnCount() * count, nullptr);
481 }
482 if (!items.isEmpty()) {
483 int index = childIndex(row, 0);
484 int limit = qMin(items.size(), columnCount() * count);
485 for (int i = 0; i < limit; ++i) {
487 if (item) {
488 if (item->d_func()->parent == nullptr) {
489 item->d_func()->setParentAndModel(q, model);
490 } else {
491 qWarning("QStandardItem::insertRows: Ignoring duplicate insertion of item %p",
492 item);
493 item = nullptr;
494 }
495 }
497 if (item)
498 item->d_func()->lastKnownIndex = index;
499 ++index;
500 }
501 }
502 if (model)
503 model->d_func()->rowsInserted(q, row, count);
504 return true;
505}
506
510bool QStandardItemPrivate::insertColumns(int column, int count, const QList<QStandardItem*> &items)
511{
512 Q_Q(QStandardItem);
513 if ((count < 1) || (column < 0) || (column > columnCount()) || count == 0)
514 return false;
515 if (model)
517 if (columnCount() == 0) {
519 columns = count;
520 } else {
521 columns += count;
522 int index = childIndex(0, column);
523 for (int row = 0; row < rowCount(); ++row) {
524 children.insert(index, count, nullptr);
525 index += columnCount();
526 }
527 }
528 if (!items.isEmpty()) {
529 int limit = qMin(items.size(), rowCount() * count);
530 for (int i = 0; i < limit; ++i) {
532 if (item) {
533 if (item->d_func()->parent == nullptr) {
534 item->d_func()->setParentAndModel(q, model);
535 } else {
536 qWarning("QStandardItem::insertColumns: Ignoring duplicate insertion of item %p",
537 item);
538 item = nullptr;
539 }
540 }
541 int r = i / count;
542 int c = column + (i % count);
543 int index = childIndex(r, c);
545 if (item)
546 item->d_func()->lastKnownIndex = index;
547 }
548 }
549 if (model)
550 model->d_func()->columnsInserted(q, column, count);
551 return true;
552}
553
558{
560 Q_ASSERT(item);
561 if (item->d_func()->parent == nullptr) {
562 // Header item
563 int idx = columnHeaderItems.indexOf(item);
564 if (idx != -1) {
565 emit q->headerDataChanged(Qt::Horizontal, idx, idx);
566 } else {
568 if (idx != -1)
569 emit q->headerDataChanged(Qt::Vertical, idx, idx);
570 }
571 } else {
572 // Normal item
573 const QModelIndex index = q->indexFromItem(item);
574 emit q->dataChanged(index, index, roles);
575 }
576}
577
582 int start, int end)
583{
585 QModelIndex index = q->indexFromItem(parent);
586 q->beginInsertRows(index, start, end);
587}
588
593 int start, int end)
594{
596 QModelIndex index = q->indexFromItem(parent);
597 q->beginInsertColumns(index, start, end);
598}
599
604 int start, int end)
605{
607 QModelIndex index = q->indexFromItem(parent);
608 q->beginRemoveRows(index, start, end);
609}
610
615 int start, int end)
616{
618 QModelIndex index = q->indexFromItem(parent);
619 q->beginRemoveColumns(index, start, end);
620}
621
626 int row, int count)
627{
629 if (parent == root.data())
630 rowHeaderItems.insert(row, count, nullptr);
631 q->endInsertRows();
632}
633
638 int column, int count)
639{
641 if (parent == root.data())
643 q->endInsertColumns();
644}
645
650 int row, int count)
651{
653 if (parent == root.data()) {
654 for (int i = row; i < row + count; ++i) {
655 QStandardItem *oldItem = rowHeaderItems.at(i);
656 if (oldItem)
657 oldItem->d_func()->setModel(nullptr);
658 delete oldItem;
659 }
661 }
662 q->endRemoveRows();
663}
664
669 int column, int count)
670{
672 if (parent == root.data()) {
673 for (int i = column; i < column + count; ++i) {
675 if (oldItem)
676 oldItem->d_func()->setModel(nullptr);
677 delete oldItem;
678 }
680 }
681 q->endRemoveColumns();
682}
683
773
782
791
795QStandardItem::QStandardItem(int rows, int columns)
797{
798 setRowCount(rows);
799 setColumnCount(columns);
800}
801
806 : d_ptr(&dd)
807{
808 Q_D(QStandardItem);
809 d->q_ptr = this;
810}
811
819 : d_ptr(new QStandardItemPrivate)
820{
821 Q_D(QStandardItem);
822 d->q_ptr = this;
824}
825
833{
834 Q_D(QStandardItem);
835 d->values = other.d_func()->values;
836 return *this;
837}
838
844{
845 Q_D(QStandardItem);
846 for (QStandardItem *child : std::as_const(d->children)) {
847 if (child)
848 child->d_func()->setModel(nullptr);
849 delete child;
850 }
851 d->children.clear();
852 if (d->parent && d->model)
853 d->parent->d_func()->childDeleted(this);
854}
855
864{
865 Q_D(const QStandardItem);
866 if (!d->model || (d->model->d_func()->root.data() != d->parent))
867 return d->parent;
868 return nullptr;
869}
870
891{
892 Q_D(QStandardItem);
893 role = (role == Qt::EditRole) ? Qt::DisplayRole : role;
894 const QList<int> roles((role == Qt::DisplayRole) ?
895 QList<int>({Qt::DisplayRole, Qt::EditRole}) :
896 QList<int>({role}));
897 for (auto it = d->values.begin(); it != d->values.end(); ++it) {
898 if ((*it).role == role) {
899 if (value.isValid()) {
900 if ((*it).value.userType() == value.userType() && (*it).value == value)
901 return;
902 (*it).value = value;
903 } else {
904 // Don't need to assign proper it after erase() since we
905 // return unconditionally in this code path.
906 d->values.erase(it);
907 }
908 if (d->model)
909 d->model->d_func()->itemChanged(this, roles);
910 return;
911 }
912 }
913 d->values.append(QStandardItemData(role, value));
914 if (d->model)
915 d->model->d_func()->itemChanged(this, roles);
916}
917
924{
925 Q_D(QStandardItem);
926 if (d->values.isEmpty())
927 return;
928 d->values.clear();
929 if (d->model)
930 d->model->d_func()->itemChanged(this, QList<int>{});
931}
932
946{
947 Q_D(const QStandardItem);
948 const int r = (role == Qt::EditRole) ? Qt::DisplayRole : role;
949 for (const auto &value : d->values) {
950 if (value.role == r)
951 return value.value;
952 }
953 return QVariant();
954}
955
967{
968 for (auto &roleData : roleDataSpan)
969 roleData.setData(data(roleData.role()));
970}
971
985{
986 Q_D(QStandardItem);
987 if (d->model)
988 d->model->d_func()->itemChanged(this);
989}
990
1000{
1001 setData((int)flags, DataFlagsRole);
1002}
1003
1014Qt::ItemFlags QStandardItem::flags() const
1015{
1016 QVariant v = data(DataFlagsRole);
1017 if (!v.isValid())
1020 return Qt::ItemFlags(v.toInt());
1021}
1022
1261{
1262 Q_D(QStandardItem);
1263 d->changeFlags(enabled, Qt::ItemIsEnabled);
1264}
1265
1290{
1291 Q_D(QStandardItem);
1292 d->changeFlags(editable, Qt::ItemIsEditable);
1293}
1294
1319void QStandardItem::setSelectable(bool selectable)
1320{
1321 Q_D(QStandardItem);
1322 d->changeFlags(selectable, Qt::ItemIsSelectable);
1323}
1324
1346{
1347 Q_D(QStandardItem);
1348 if (checkable && !isCheckable()) {
1349 // make sure there's data for the checkstate role
1350 if (!data(Qt::CheckStateRole).isValid())
1352 }
1353 d->changeFlags(checkable, Qt::ItemIsUserCheckable);
1354}
1355
1377{
1378 Q_D(QStandardItem);
1379 d->changeFlags(tristate, Qt::ItemIsAutoTristate);
1380}
1381
1403{
1404 Q_D(QStandardItem);
1405 d->changeFlags(tristate, Qt::ItemIsUserTristate);
1406}
1407
1420#if QT_CONFIG(draganddrop)
1421
1431void QStandardItem::setDragEnabled(bool dragEnabled)
1432{
1433 Q_D(QStandardItem);
1434 d->changeFlags(dragEnabled, Qt::ItemIsDragEnabled);
1435}
1436
1461void QStandardItem::setDropEnabled(bool dropEnabled)
1462{
1463 Q_D(QStandardItem);
1464 d->changeFlags(dropEnabled, Qt::ItemIsDropEnabled);
1465}
1466
1478#endif // QT_CONFIG(draganddrop)
1479
1487{
1488 Q_D(const QStandardItem);
1489 QPair<int, int> pos = d->position();
1490 return pos.first;
1491}
1492
1500{
1501 Q_D(const QStandardItem);
1502 QPair<int, int> pos = d->position();
1503 return pos.second;
1504}
1505
1519{
1520 Q_D(const QStandardItem);
1521 return d->model ? d->model->indexFromItem(this) : QModelIndex();
1522}
1523
1533{
1534 Q_D(const QStandardItem);
1535 return d->model;
1536}
1537
1545{
1546 int rc = rowCount();
1547 if (rc == rows)
1548 return;
1549 if (rc < rows)
1550 insertRows(qMax(rc, 0), rows - rc);
1551 else
1552 removeRows(qMax(rows, 0), rc - rows);
1553}
1554
1561{
1562 Q_D(const QStandardItem);
1563 return d->rowCount();
1564}
1565
1573{
1574 int cc = columnCount();
1575 if (cc == columns)
1576 return;
1577 if (cc < columns)
1578 insertColumns(qMax(cc, 0), columns - cc);
1579 else
1580 removeColumns(qMax(columns, 0), cc - columns);
1581}
1582
1589{
1590 Q_D(const QStandardItem);
1591 return d->columnCount();
1592}
1593
1600void QStandardItem::insertRow(int row, const QList<QStandardItem*> &items)
1601{
1602 Q_D(QStandardItem);
1603 if (row < 0)
1604 return;
1605 if (columnCount() < items.size())
1607 d->insertRows(row, 1, items);
1608}
1609
1615void QStandardItem::insertRows(int row, const QList<QStandardItem*> &items)
1616{
1617 Q_D(QStandardItem);
1618 if (row < 0)
1619 return;
1620 d->insertRows(row, items);
1621}
1622
1629void QStandardItem::insertColumn(int column, const QList<QStandardItem*> &items)
1630{
1631 Q_D(QStandardItem);
1632 if (column < 0)
1633 return;
1634 if (rowCount() < items.size())
1636 d->insertColumns(column, 1, items);
1637}
1638
1645{
1646 Q_D(QStandardItem);
1647 if (rowCount() < row) {
1648 count += row - rowCount();
1649 row = rowCount();
1650 }
1651 d->insertRows(row, count, QList<QStandardItem*>());
1652}
1653
1660{
1661 Q_D(QStandardItem);
1662 if (columnCount() < column) {
1663 count += column - columnCount();
1664 column = columnCount();
1665 }
1666 d->insertColumns(column, count, QList<QStandardItem*>());
1667}
1668
1741{
1742 removeRows(row, 1);
1743}
1744
1755
1763{
1764 Q_D(QStandardItem);
1765 if ((count < 1) || (row < 0) || ((row + count) > rowCount()))
1766 return;
1767 if (d->model)
1768 d->model->d_func()->rowsAboutToBeRemoved(this, row, row + count - 1);
1769 int i = d->childIndex(row, 0);
1770 int n = count * d->columnCount();
1771 for (int j = i; j < n+i; ++j) {
1772 QStandardItem *oldItem = d->children.at(j);
1773 if (oldItem)
1774 oldItem->d_func()->setModel(nullptr);
1775 delete oldItem;
1776 }
1777 d->children.remove(qMax(i, 0), n);
1778 d->rows -= count;
1779 if (d->model)
1780 d->model->d_func()->rowsRemoved(this, row, count);
1781}
1782
1790{
1791 Q_D(QStandardItem);
1792 if ((count < 1) || (column < 0) || ((column + count) > columnCount()))
1793 return;
1794 if (d->model)
1795 d->model->d_func()->columnsAboutToBeRemoved(this, column, column + count - 1);
1796 for (int row = d->rowCount() - 1; row >= 0; --row) {
1797 int i = d->childIndex(row, column);
1798 for (int j=i; j<i+count; ++j) {
1799 QStandardItem *oldItem = d->children.at(j);
1800 if (oldItem)
1801 oldItem->d_func()->setModel(nullptr);
1802 delete oldItem;
1803 }
1804 d->children.remove(i, count);
1805 }
1806 d->columns -= count;
1807 if (d->model)
1808 d->model->d_func()->columnsRemoved(this, column, count);
1809}
1810
1817{
1818 return (rowCount() > 0) && (columnCount() > 0);
1819}
1820
1831{
1832 Q_D(QStandardItem);
1833 d->setChild(row, column, item, true);
1834}
1835
1850{
1851 Q_D(const QStandardItem);
1852 int index = d->childIndex(row, column);
1853 if (index == -1)
1854 return nullptr;
1855 return d->children.at(index);
1856}
1857
1869{
1870 Q_D(QStandardItem);
1871 QStandardItem *item = nullptr;
1872 int index = d->childIndex(row, column);
1873 if (index != -1) {
1874 QModelIndex changedIdx;
1875 item = d->children.at(index);
1876 if (item) {
1877 QStandardItemPrivate *const item_d = item->d_func();
1878 if (d->model) {
1879 QStandardItemModelPrivate *const model_d = d->model->d_func();
1880 const int savedRows = item_d->rows;
1881 const int savedCols = item_d->columns;
1882 const QVector<QStandardItem*> savedChildren = item_d->children;
1883 if (savedRows > 0) {
1884 model_d->rowsAboutToBeRemoved(item, 0, savedRows - 1);
1885 item_d->rows = 0;
1886 item_d->children = QVector<QStandardItem*>(); //slightly faster than clear
1887 model_d->rowsRemoved(item, 0, savedRows);
1888 }
1889 if (savedCols > 0) {
1890 model_d->columnsAboutToBeRemoved(item, 0, savedCols - 1);
1891 item_d->columns = 0;
1892 item_d->children = QVector<QStandardItem*>(); //slightly faster than clear
1893 model_d->columnsRemoved(item, 0, savedCols);
1894 }
1895 item_d->rows = savedRows;
1896 item_d->columns = savedCols;
1897 item_d->children = savedChildren;
1898 changedIdx = d->model->indexFromItem(item);
1899 }
1900 item_d->setParentAndModel(nullptr, nullptr);
1901 }
1902 d->children.replace(index, nullptr);
1903 if (changedIdx.isValid())
1904 d->model->dataChanged(changedIdx, changedIdx);
1905 }
1906 return item;
1907}
1908
1916QList<QStandardItem*> QStandardItem::takeRow(int row)
1917{
1918 Q_D(QStandardItem);
1919 QList<QStandardItem*> items;
1920 if ((row < 0) || (row >= rowCount()))
1921 return items;
1922 if (d->model)
1923 d->model->d_func()->rowsAboutToBeRemoved(this, row, row);
1924
1925 int index = d->childIndex(row, 0); // Will return -1 if there are no columns
1926 if (index != -1) {
1927 int col_count = d->columnCount();
1928 items.reserve(col_count);
1929 for (int column = 0; column < col_count; ++column) {
1930 QStandardItem *ch = d->children.at(index + column);
1931 if (ch)
1932 ch->d_func()->setParentAndModel(nullptr, nullptr);
1933 items.append(ch);
1934 }
1935 d->children.remove(index, col_count);
1936 }
1937 d->rows--;
1938 if (d->model)
1939 d->model->d_func()->rowsRemoved(this, row, 1);
1940 return items;
1941}
1942
1950QList<QStandardItem*> QStandardItem::takeColumn(int column)
1951{
1952 Q_D(QStandardItem);
1953 QList<QStandardItem*> items;
1954 if ((column < 0) || (column >= columnCount()))
1955 return items;
1956 if (d->model)
1957 d->model->d_func()->columnsAboutToBeRemoved(this, column, column);
1958
1959 const int rowCount = d->rowCount();
1961 for (int row = rowCount - 1; row >= 0; --row) {
1962 int index = d->childIndex(row, column);
1963 QStandardItem *ch = d->children.at(index);
1964 if (ch)
1965 ch->d_func()->setParentAndModel(nullptr, nullptr);
1966 d->children.remove(index);
1967 items.prepend(ch);
1968 }
1969 d->columns--;
1970 if (d->model)
1971 d->model->d_func()->columnsRemoved(this, column, 1);
1972 return items;
1973}
1974
1988{
1989 const int role = model() ? model()->sortRole() : Qt::DisplayRole;
1990 const QVariant l = data(role), r = other.data(role);
1992}
1993
2004{
2005 Q_D(QStandardItem);
2006 if ((column < 0) || (rowCount() == 0))
2007 return;
2008
2009 QList<QPersistentModelIndex> parents;
2010 if (d->model) {
2011 parents << index();
2012 emit d->model->layoutAboutToBeChanged(parents, QAbstractItemModel::VerticalSortHint);
2013 }
2014 d->sortChildren(column, order);
2015 if (d->model)
2016 emit d->model->layoutChanged(parents, QAbstractItemModel::VerticalSortHint);
2017}
2018
2029{
2030 return new QStandardItem(*this);
2031}
2032
2042{
2043 return Type;
2044}
2045
2046#ifndef QT_NO_DATASTREAM
2047
2055{
2056 Q_D(QStandardItem);
2057 in >> d->values;
2058 qint32 flags;
2059 in >> flags;
2060 setFlags(Qt::ItemFlags(flags));
2061}
2062
2070{
2071 Q_D(const QStandardItem);
2072 out << d->values;
2073 out << flags();
2074}
2075
2087{
2088 item.read(in);
2089 return in;
2090}
2091
2103{
2104 item.write(out);
2105 return out;
2106}
2107
2108#endif // QT_NO_DATASTREAM
2109
2202{
2203 Q_D(QStandardItemModel);
2204 d->init();
2205 d->root->d_func()->setModel(this);
2206}
2207
2214{
2215 Q_D(QStandardItemModel);
2216 d->init();
2217 d->root->insertColumns(0, columns);
2218 d->columnHeaderItems.insert(0, columns, nullptr);
2219 d->root->insertRows(0, rows);
2220 d->rowHeaderItems.insert(0, rows, nullptr);
2221 d->root->d_func()->setModel(this);
2222}
2223
2228 : QAbstractItemModel(dd, parent)
2229{
2230 Q_D(QStandardItemModel);
2231 d->init();
2232}
2233
2238{
2239 Q_D(QStandardItemModel);
2240 delete d->itemPrototype;
2241 qDeleteAll(d->columnHeaderItems);
2242 qDeleteAll(d->rowHeaderItems);
2243 d->root.reset();
2244}
2245
2249void QStandardItemModel::setItemRoleNames(const QHash<int,QByteArray> &roleNames)
2250{
2251 Q_D(QStandardItemModel);
2252 d->roleNames = roleNames;
2253}
2254
2258QHash<int, QByteArray> QStandardItemModel::roleNames() const
2259{
2260 Q_D(const QStandardItemModel);
2261 return d->roleNames;
2262}
2263
2271{
2272 Q_D(QStandardItemModel);
2274 d->root.reset(new QStandardItem);
2275 d->root->setFlags(Qt::ItemIsDropEnabled);
2276 d->root->d_func()->setModel(this);
2277 qDeleteAll(d->columnHeaderItems);
2278 d->columnHeaderItems.clear();
2279 qDeleteAll(d->rowHeaderItems);
2280 d->rowHeaderItems.clear();
2281 endResetModel();
2282}
2283
2304{
2305 Q_D(const QStandardItemModel);
2306 if ((index.row() < 0) || (index.column() < 0) || (index.model() != this))
2307 return nullptr;
2308 QStandardItem *parent = static_cast<QStandardItem*>(index.internalPointer());
2309 if (parent == nullptr)
2310 return nullptr;
2311 QStandardItem *item = parent->child(index.row(), index.column());
2312 // lazy part
2313 if (item == nullptr) {
2314 item = d->createItem();
2315 parent->d_func()->setChild(index.row(), index.column(), item);
2316 }
2317 return item;
2318}
2319
2333{
2334 if (item && item->d_func()->parent) {
2335 QPair<int, int> pos = item->d_func()->position();
2336 return createIndex(pos.first, pos.second, item->d_func()->parent);
2337 }
2338 return QModelIndex();
2339}
2340
2351{
2352 Q_D(QStandardItemModel);
2353 d->root->setRowCount(rows);
2354}
2355
2366{
2367 Q_D(QStandardItemModel);
2368 d->root->setColumnCount(columns);
2369}
2370
2382{
2383 Q_D(QStandardItemModel);
2384 d->root->d_func()->setChild(row, column, item, true);
2385}
2386
2401{
2402 Q_D(const QStandardItemModel);
2403 return d->root->child(row, column);
2404}
2405
2420{
2421 Q_D(const QStandardItemModel);
2422 return d->root.data();
2423}
2424
2436{
2437 Q_D(QStandardItemModel);
2438 if (column < 0)
2439 return;
2440 if (columnCount() <= column)
2442
2443 QStandardItem *oldItem = d->columnHeaderItems.at(column);
2444 if (item == oldItem)
2445 return;
2446
2447 if (item) {
2448 if (item->model() == nullptr) {
2449 item->d_func()->setModel(this);
2450 } else {
2451 qWarning("QStandardItem::setHorizontalHeaderItem: Ignoring duplicate insertion of item %p",
2452 item);
2453 return;
2454 }
2455 }
2456
2457 if (oldItem)
2458 oldItem->d_func()->setModel(nullptr);
2459 delete oldItem;
2460
2461 d->columnHeaderItems.replace(column, item);
2463}
2464
2474{
2475 Q_D(const QStandardItemModel);
2476 if ((column < 0) || (column >= columnCount()))
2477 return nullptr;
2478 return d->columnHeaderItems.at(column);
2479}
2480
2492{
2493 Q_D(QStandardItemModel);
2494 if (row < 0)
2495 return;
2496 if (rowCount() <= row)
2497 setRowCount(row + 1);
2498
2499 QStandardItem *oldItem = d->rowHeaderItems.at(row);
2500 if (item == oldItem)
2501 return;
2502
2503 if (item) {
2504 if (item->model() == nullptr) {
2505 item->d_func()->setModel(this);
2506 } else {
2507 qWarning("QStandardItem::setVerticalHeaderItem: Ignoring duplicate insertion of item %p",
2508 item);
2509 return;
2510 }
2511 }
2512
2513 if (oldItem)
2514 oldItem->d_func()->setModel(nullptr);
2515 delete oldItem;
2516
2517 d->rowHeaderItems.replace(row, item);
2519}
2520
2530{
2531 Q_D(const QStandardItemModel);
2532 if ((row < 0) || (row >= rowCount()))
2533 return nullptr;
2534 return d->rowHeaderItems.at(row);
2535}
2536
2546{
2547 Q_D(QStandardItemModel);
2548 if (columnCount() < labels.size())
2549 setColumnCount(labels.size());
2550 for (int i = 0; i < labels.size(); ++i) {
2552 if (!item) {
2553 item = d->createItem();
2555 }
2556 item->setText(labels.at(i));
2557 }
2558}
2559
2569{
2570 Q_D(QStandardItemModel);
2571 if (rowCount() < labels.size())
2572 setRowCount(labels.size());
2573 for (int i = 0; i < labels.size(); ++i) {
2575 if (!item) {
2576 item = d->createItem();
2578 }
2579 item->setText(labels.at(i));
2580 }
2581}
2582
2599{
2600 Q_D(QStandardItemModel);
2601 if (d->itemPrototype != item) {
2602 delete d->itemPrototype;
2603 d->itemPrototype = item;
2604 }
2605}
2606
2617{
2618 Q_D(const QStandardItemModel);
2619 return d->itemPrototype;
2620}
2621
2628QList<QStandardItem*> QStandardItemModel::findItems(const QString &text,
2629 Qt::MatchFlags flags, int column) const
2630{
2631 QModelIndexList indexes = match(index(0, column, QModelIndex()),
2632 Qt::DisplayRole, text, -1, flags);
2633 QList<QStandardItem*> items;
2634 const int numIndexes = indexes.size();
2635 items.reserve(numIndexes);
2636 for (int i = 0; i < numIndexes; ++i)
2637 items.append(itemFromIndex(indexes.at(i)));
2638 return items;
2639}
2640
2649void QStandardItemModel::appendRow(const QList<QStandardItem*> &items)
2650{
2652}
2653
2662void QStandardItemModel::appendColumn(const QList<QStandardItem*> &items)
2663{
2665}
2666
2684void QStandardItemModel::insertRow(int row, const QList<QStandardItem*> &items)
2685{
2687}
2688
2709void QStandardItemModel::insertColumn(int column, const QList<QStandardItem*> &items)
2710{
2712}
2713
2723{
2724 Q_D(QStandardItemModel);
2725 return d->root->takeChild(row, column);
2726}
2727
2738QList<QStandardItem*> QStandardItemModel::takeRow(int row)
2739{
2740 Q_D(QStandardItemModel);
2741 return d->root->takeRow(row);
2742}
2743
2754QList<QStandardItem*> QStandardItemModel::takeColumn(int column)
2755{
2756 Q_D(QStandardItemModel);
2757 return d->root->takeColumn(column);
2758}
2759
2770{
2771 Q_D(QStandardItemModel);
2772 if ((column < 0) || (column >= columnCount()))
2773 return nullptr;
2774 QStandardItem *headerItem = d->columnHeaderItems.at(column);
2775 if (headerItem) {
2776 headerItem->d_func()->setParentAndModel(nullptr, nullptr);
2777 d->columnHeaderItems.replace(column, nullptr);
2778 }
2779 return headerItem;
2780}
2781
2792{
2793 Q_D(QStandardItemModel);
2794 if ((row < 0) || (row >= rowCount()))
2795 return nullptr;
2796 QStandardItem *headerItem = d->rowHeaderItems.at(row);
2797 if (headerItem) {
2798 headerItem->d_func()->setParentAndModel(nullptr, nullptr);
2799 d->rowHeaderItems.replace(row, nullptr);
2800 }
2801 return headerItem;
2802}
2803
2814{
2815 Q_D(const QStandardItemModel);
2816 return d->sortRole;
2817}
2818
2820{
2821 Q_D(QStandardItemModel);
2822 d->sortRole = role;
2823}
2824
2826{
2827 Q_D(QStandardItemModel);
2828 return &d->sortRole;
2829}
2830
2835{
2836 Q_D(const QStandardItemModel);
2837 QStandardItem *item = d->itemFromIndex(parent);
2838 return item ? item->columnCount() : 0;
2839}
2840
2845{
2846 Q_D(const QStandardItemModel);
2847 QStandardItem *item = d->itemFromIndex(index);
2848 return item ? item->data(role) : QVariant();
2849}
2850
2855{
2856 // Cannot offer a better implementation; users may be overriding
2857 // data(), and thus multiData() may fall out of sync for them.
2858 // The base class' implementation will simply call data() in a loop,
2859 // so it's fine.
2860 QAbstractItemModel::multiData(index, roleDataSpan);
2861}
2862
2867{
2868 Q_D(const QStandardItemModel);
2869 if (!d->indexValid(index))
2870 return d->root->flags();
2871 QStandardItem *item = d->itemFromIndex(index);
2872 if (item)
2873 return item->flags();
2879}
2880
2885{
2886 Q_D(const QStandardItemModel);
2887 QStandardItem *item = d->itemFromIndex(parent);
2888 return item ? item->hasChildren() : false;
2889}
2890
2894QVariant QStandardItemModel::headerData(int section, Qt::Orientation orientation, int role) const
2895{
2896 Q_D(const QStandardItemModel);
2897 if ((section < 0)
2898 || ((orientation == Qt::Horizontal) && (section >= columnCount()))
2899 || ((orientation == Qt::Vertical) && (section >= rowCount()))) {
2900 return QVariant();
2901 }
2902 QStandardItem *headerItem = nullptr;
2903 if (orientation == Qt::Horizontal)
2904 headerItem = d->columnHeaderItems.at(section);
2905 else if (orientation == Qt::Vertical)
2906 headerItem = d->rowHeaderItems.at(section);
2907 return headerItem ? headerItem->data(role)
2908 : QAbstractItemModel::headerData(section, orientation, role);
2909}
2910
2917{
2919}
2920
2925{
2926 Q_D(const QStandardItemModel);
2927 QStandardItem *parentItem = d->itemFromIndex(parent);
2928 if ((parentItem == nullptr)
2929 || (row < 0)
2930 || (column < 0)
2931 || (row >= parentItem->rowCount())
2932 || (column >= parentItem->columnCount())) {
2933 return QModelIndex();
2934 }
2935 return createIndex(row, column, parentItem);
2936}
2937
2942{
2943 Q_D(QStandardItemModel);
2944 QStandardItem *item = parent.isValid() ? itemFromIndex(parent) : d->root.data();
2945 if (item == nullptr)
2946 return false;
2947 return item->d_func()->insertColumns(column, count, QList<QStandardItem*>());
2948}
2949
2954{
2955 Q_D(QStandardItemModel);
2956 QStandardItem *item = parent.isValid() ? itemFromIndex(parent) : d->root.data();
2957 if (item == nullptr)
2958 return false;
2959 return item->d_func()->insertRows(row, count, QList<QStandardItem*>());
2960}
2961
2965QMap<int, QVariant> QStandardItemModel::itemData(const QModelIndex &index) const
2966{
2967 Q_D(const QStandardItemModel);
2968 const QStandardItem *const item = d->itemFromIndex(index);
2969 if (!item || item == d->root.data())
2970 return QMap<int, QVariant>();
2971 return item->d_func()->itemData();
2972}
2973
2978{
2979 Q_D(const QStandardItemModel);
2980 if (!d->indexValid(child))
2981 return QModelIndex();
2982 QStandardItem *parentItem = static_cast<QStandardItem*>(child.internalPointer());
2983 return indexFromItem(parentItem);
2984}
2985
2990{
2991 Q_D(QStandardItemModel);
2992 QStandardItem *item = d->itemFromIndex(parent);
2993 if ((item == nullptr) || (count < 1) || (column < 0) || ((column + count) > item->columnCount()))
2994 return false;
2995 item->removeColumns(column, count);
2996 return true;
2997}
2998
3003{
3004 Q_D(QStandardItemModel);
3005 QStandardItem *item = d->itemFromIndex(parent);
3006 if ((item == nullptr) || (count < 1) || (row < 0) || ((row + count) > item->rowCount()))
3007 return false;
3008 item->removeRows(row, count);
3009 return true;
3010}
3011
3016{
3017 Q_D(const QStandardItemModel);
3018 QStandardItem *item = d->itemFromIndex(parent);
3019 return item ? item->rowCount() : 0;
3020}
3021
3026{
3027 if (!index.isValid())
3028 return false;
3030 if (item == nullptr)
3031 return false;
3032 item->setData(value, role);
3033 return true;
3034}
3035
3040{
3042 return false;
3043 Q_D(QStandardItemModel);
3044 QStandardItem *item = d->itemFromIndex(index);
3045 if (!item)
3046 return false;
3047 item->clearData();
3048 return true;
3049}
3050
3054bool QStandardItemModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
3055{
3056 Q_D(QStandardItemModel);
3057 if ((section < 0)
3058 || ((orientation == Qt::Horizontal) && (section >= columnCount()))
3059 || ((orientation == Qt::Vertical) && (section >= rowCount()))) {
3060 return false;
3061 }
3062 QStandardItem *headerItem = nullptr;
3063 if (orientation == Qt::Horizontal) {
3064 headerItem = d->columnHeaderItems.at(section);
3065 if (headerItem == nullptr) {
3066 headerItem = d->createItem();
3067 headerItem->d_func()->setModel(this);
3068 d->columnHeaderItems.replace(section, headerItem);
3069 }
3070 } else if (orientation == Qt::Vertical) {
3071 headerItem = d->rowHeaderItems.at(section);
3072 if (headerItem == nullptr) {
3073 headerItem = d->createItem();
3074 headerItem->d_func()->setModel(this);
3075 d->rowHeaderItems.replace(section, headerItem);
3076 }
3077 }
3078 if (headerItem) {
3079 headerItem->setData(value, role);
3080 return true;
3081 }
3082 return false;
3083}
3084
3088bool QStandardItemModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
3089{
3091 if (item == nullptr)
3092 return false;
3093 item->d_func()->setItemData(roles);
3094 return true;
3095}
3096
3101{
3102 Q_D(QStandardItemModel);
3103 d->root->sortChildren(column, order);
3104}
3105
3113
3118{
3119 std::unique_ptr<QMimeData> data(QAbstractItemModel::mimeData(indexes));
3120 if (!data)
3121 return nullptr;
3122
3124 if (!mimeTypes().contains(format))
3125 return data.release();
3128
3129 QSet<QStandardItem*> itemsSet;
3130 QStack<QStandardItem*> stack;
3131 itemsSet.reserve(indexes.size());
3132 stack.reserve(indexes.size());
3133 for (int i = 0; i < indexes.size(); ++i) {
3134 if (QStandardItem *item = itemFromIndex(indexes.at(i))) {
3135 itemsSet << item;
3136 stack.push(item);
3137 } else {
3138 qWarning("QStandardItemModel::mimeData: No item associated with invalid index");
3139 return nullptr;
3140 }
3141 }
3142
3143 //remove duplicates children
3144 {
3145 QDuplicateTracker<QStandardItem *> seen;
3146 while (!stack.isEmpty()) {
3147 QStandardItem *itm = stack.pop();
3148 if (seen.hasSeen(itm))
3149 continue;
3150
3151 const QList<QStandardItem*> &childList = itm->d_func()->children;
3152 for (int i = 0; i < childList.size(); ++i) {
3153 QStandardItem *chi = childList.at(i);
3154 if (chi) {
3155 itemsSet.remove(chi);
3156 stack.push(chi);
3157 }
3158 }
3159 }
3160 }
3161
3162 stack.reserve(itemsSet.size());
3163 for (QStandardItem *item : std::as_const(itemsSet))
3164 stack.push(item);
3165
3166 //stream everything recursively
3167 while (!stack.isEmpty()) {
3168 QStandardItem *item = stack.pop();
3169 if (itemsSet.contains(item)) //if the item is selection 'top-level', stream its position
3170 stream << item->row() << item->column();
3171
3172 stream << *item << item->columnCount() << int(item->d_ptr->children.size());
3173 stack += item->d_ptr->children;
3174 }
3175
3176 data->setData(format, encoded);
3177 return data.release();
3178}
3179
3180
3181/* \internal
3182 Used by QStandardItemModel::dropMimeData
3183 stream out an item and his children
3184 */
3186{
3187 int colCount, childCount;
3188 stream >> *item;
3189 stream >> colCount >> childCount;
3190 item->setColumnCount(colCount);
3191
3192 int childPos = childCount;
3193
3194 while(childPos > 0) {
3195 childPos--;
3198 item->setChild( childPos / colCount, childPos % colCount, child);
3199 }
3200}
3201
3202
3207 int row, int column, const QModelIndex &parent)
3208{
3209 Q_D(QStandardItemModel);
3210 // check if the action is supported
3211 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
3212 return false;
3213 // check if the format is supported
3215 if (!data->hasFormat(format))
3217
3218 if (row > rowCount(parent))
3219 row = rowCount(parent);
3220 if (row == -1)
3221 row = rowCount(parent);
3222 if (column == -1)
3223 column = 0;
3224
3225 // decode and insert
3228
3229
3230 //code based on QAbstractItemModel::decodeData
3231 // adapted to work with QStandardItem
3232 int top = INT_MAX;
3233 int left = INT_MAX;
3234 int bottom = 0;
3235 int right = 0;
3236 QList<int> rows, columns;
3237 QList<QStandardItem *> items;
3238
3239 while (!stream.atEnd()) {
3240 int r, c;
3241 QStandardItem *item = d->createItem();
3242 stream >> r >> c;
3243 d->decodeDataRecursive(stream, item);
3244
3245 rows.append(r);
3246 columns.append(c);
3247 items.append(item);
3248 top = qMin(r, top);
3249 left = qMin(c, left);
3250 bottom = qMax(r, bottom);
3251 right = qMax(c, right);
3252 }
3253
3254 // insert the dragged items into the table, use a bit array to avoid overwriting items,
3255 // since items from different tables can have the same row and column
3256 int dragRowCount = 0;
3257 int dragColumnCount = right - left + 1;
3258
3259 // Compute the number of continuous rows upon insertion and modify the rows to match
3260 QList<int> rowsToInsert(bottom + 1);
3261 for (int i = 0; i < rows.size(); ++i)
3262 rowsToInsert[rows.at(i)] = 1;
3263 for (int i = 0; i < rowsToInsert.size(); ++i) {
3264 if (rowsToInsert.at(i) == 1){
3265 rowsToInsert[i] = dragRowCount;
3266 ++dragRowCount;
3267 }
3268 }
3269 for (int i = 0; i < rows.size(); ++i)
3270 rows[i] = top + rowsToInsert.at(rows.at(i));
3271
3272 QBitArray isWrittenTo(dragRowCount * dragColumnCount);
3273
3274 // make space in the table for the dropped data
3275 int colCount = columnCount(parent);
3276 if (colCount < dragColumnCount + column) {
3277 insertColumns(colCount, dragColumnCount + column - colCount, parent);
3278 colCount = columnCount(parent);
3279 }
3280 insertRows(row, dragRowCount, parent);
3281
3282 row = qMax(0, row);
3283 column = qMax(0, column);
3284
3285 QStandardItem *parentItem = itemFromIndex (parent);
3286 if (!parentItem)
3287 parentItem = invisibleRootItem();
3288
3289 QList<QPersistentModelIndex> newIndexes(items.size());
3290 // set the data in the table
3291 for (int j = 0; j < items.size(); ++j) {
3292 int relativeRow = rows.at(j) - top;
3293 int relativeColumn = columns.at(j) - left;
3294 int destinationRow = relativeRow + row;
3295 int destinationColumn = relativeColumn + column;
3296 int flat = (relativeRow * dragColumnCount) + relativeColumn;
3297 // if the item was already written to, or we just can't fit it in the table, create a new row
3298 if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
3299 destinationColumn = qBound(column, destinationColumn, colCount - 1);
3300 destinationRow = row + dragRowCount;
3301 insertRows(row + dragRowCount, 1, parent);
3302 flat = (dragRowCount * dragColumnCount) + relativeColumn;
3303 isWrittenTo.resize(++dragRowCount * dragColumnCount);
3304 }
3305 if (!isWrittenTo.testBit(flat)) {
3306 newIndexes[j] = index(destinationRow, destinationColumn, parentItem->index());
3307 isWrittenTo.setBit(flat);
3308 }
3309 }
3310
3311 for(int k = 0; k < newIndexes.size(); k++) {
3312 if (newIndexes.at(k).isValid()) {
3313 parentItem->setChild(newIndexes.at(k).row(), newIndexes.at(k).column(), items.at(k));
3314 } else {
3315 delete items.at(k);
3316 }
3317 }
3318
3319 return true;
3320}
3321
3323
3324#include "moc_qstandarditemmodel.cpp"
static const QHash< int, QByteArray > & defaultRoleNames()
static bool isVariantLessThan(const QVariant &left, const QVariant &right, Qt::CaseSensitivity cs=Qt::CaseSensitive, bool isLocaleAware=false)
void endResetModel()
Completes a model reset operation.
virtual Q_INVOKABLE QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits=1, Qt::MatchFlags flags=Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const
Returns a list of indexes for the items in the column of the start index where data stored under the ...
void columnsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after columns have been removed from the model.
void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted just before rows are inserted into the model.
virtual Q_INVOKABLE QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
Returns the data for the given role and section in the header with the specified orientation.
void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted just before columns are inserted into the model.
void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to)
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
Handles the data supplied by a drag and drop operation that ended with the given action.
void layoutAboutToBeChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles=QList< int >())
This signal is emitted whenever the data in an existing item changes.
virtual QMimeData * mimeData(const QModelIndexList &indexes) const
Returns an object that contains serialized items of data corresponding to the list of indexes specifi...
void layoutChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
bool checkIndex(const QModelIndex &index, CheckIndexOptions options=CheckIndexOption::NoOption) const
void headerDataChanged(Qt::Orientation orientation, int first, int last)
This signal is emitted whenever a header is changed.
void beginResetModel()
Begins a model reset operation.
void rowsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after rows have been inserted into the model.
virtual QStringList mimeTypes() const
Returns the list of allowed MIME types.
QModelIndex createIndex(int row, int column, const void *data=nullptr) const
Creates a model index for the given row and column with the internal pointer ptr.
void columnsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after columns have been inserted into the model.
virtual void multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
void rowsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after rows have been removed from the model.
\inmodule QtCore
Definition qbitarray.h:13
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:611
\inmodule QtCore\reentrant
Definition qdatastream.h:46
QList< QGraphicsItem * > children
void setData(int key, const QVariant &value)
Sets this item's custom data for the key key to value.
QScopedPointer< QGraphicsItemPrivate > d_ptr
QVariant data(int key) const
Returns this item's custom data for the key key as a QVariant.
GraphicsItemFlags flags() const
Returns this item's flags.
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:488
iterator end()
Definition qlist.h:626
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:794
void prepend(rvalue_ref t)
Definition qlist.h:473
iterator begin()
Definition qlist.h:625
void reserve(qsizetype size)
Definition qlist.h:753
void replace(qsizetype i, parameter_type t)
Definition qlist.h:543
void resize(qsizetype size)
Definition qlist.h:403
void append(parameter_type t)
Definition qlist.h:458
\inmodule QtCore
Definition qmimedata.h:16
\inmodule QtCore
constexpr int row() const noexcept
Returns the row this model index refers to.
QModelIndex parent() const
Returns the parent of the model index, or QModelIndex() if it has no parent.
constexpr int column() const noexcept
Returns the column this model index refers to.
QObjectList children
Definition qobject.h:74
QObject * parent
Definition qobject.h:73
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
T * data() const noexcept
Returns the value of the pointer referenced by this object.
QList< T > values() const
Definition qset.h:304
bool operator()(const QPair< QStandardItem *, int > &l, const QPair< QStandardItem *, int > &r) const
bool operator()(const QPair< QStandardItem *, int > &l, const QPair< QStandardItem *, int > &r) const
QList< QStandardItem * > rowHeaderItems
void rowsAboutToBeRemoved(QStandardItem *parent, int start, int end)
QStandardItem * createItem() const
void columnsAboutToBeRemoved(QStandardItem *parent, int start, int end)
void columnsRemoved(QStandardItem *parent, int column, int count)
QStandardItem * itemFromIndex(const QModelIndex &index) const
void columnsInserted(QStandardItem *parent, int column, int count)
void columnsAboutToBeInserted(QStandardItem *parent, int start, int end)
void itemChanged(QStandardItem *item, const QList< int > &roles=QList< int >())
void decodeDataRecursive(QDataStream &stream, QStandardItem *item)
QHash< int, QByteArray > roleNames
void rowsAboutToBeInserted(QStandardItem *parent, int start, int end)
void _q_emitItemChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
void rowsRemoved(QStandardItem *parent, int row, int count)
QScopedPointer< QStandardItem > root
QList< QStandardItem * > columnHeaderItems
void rowsInserted(QStandardItem *parent, int row, int count)
The QStandardItemModel class provides a generic model for storing custom data.
bool removeColumns(int column, int count, const QModelIndex &parent=QModelIndex()) override
\reimp
QList< QStandardItem * > takeRow(int row)
~QStandardItemModel()
Destructs the model.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
\reimp
bool clearItemData(const QModelIndex &index) override
\reimp
void clear()
Removes all items (including header items) from the model and sets the number of rows and columns to ...
QList< QStandardItem * > takeColumn(int column)
void multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const override
\reimp
void insertRow(int row, const QList< QStandardItem * > &items)
int columnCount(const QModelIndex &parent=QModelIndex()) const override
\reimp
QStringList mimeTypes() const override
\reimp
QMap< int, QVariant > itemData(const QModelIndex &index) const override
\reimp
QStandardItem * takeVerticalHeaderItem(int row)
bool hasChildren(const QModelIndex &parent=QModelIndex()) const override
\reimp
void setHorizontalHeaderLabels(const QStringList &labels)
void itemChanged(QStandardItem *item)
void insertColumn(int column, const QList< QStandardItem * > &items)
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
QMimeData * mimeData(const QModelIndexList &indexes) const override
\reimp
QBindable< int > bindableSortRole()
const QStandardItem * itemPrototype() const
QStandardItem * item(int row, int column=0) const
int sortRole
the item role that is used to query the model's data when sorting items
bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
\reimp
QList< QStandardItem * > findItems(const QString &text, Qt::MatchFlags flags=Qt::MatchExactly, int column=0) const
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
\reimp
void appendRow(const QList< QStandardItem * > &items)
bool setItemData(const QModelIndex &index, const QMap< int, QVariant > &roles) override
\reimp
void setItemRoleNames(const QHash< int, QByteArray > &roleNames)
Sets the item role names to roleNames.
void setItem(int row, int column, QStandardItem *item)
void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
\reimp
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
\reimp
QStandardItem * takeHorizontalHeaderItem(int column)
QHash< int, QByteArray > roleNames() const override
reimp
bool insertColumns(int column, int count, const QModelIndex &parent=QModelIndex()) override
\reimp
Qt::ItemFlags flags(const QModelIndex &index) const override
\reimp
QStandardItemModel(QObject *parent=nullptr)
Constructs a new item model with the given parent.
QModelIndex indexFromItem(const QStandardItem *item) const
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
\reimp
int rowCount(const QModelIndex &parent=QModelIndex()) const override
\reimp
QStandardItem * verticalHeaderItem(int row) const
QStandardItem * takeItem(int row, int column=0)
void setVerticalHeaderItem(int row, QStandardItem *item)
void setColumnCount(int columns)
Qt::DropActions supportedDropActions() const override
\reimp
void appendColumn(const QList< QStandardItem * > &items)
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
\reimp
QStandardItem * invisibleRootItem() const
QStandardItem * itemFromIndex(const QModelIndex &index) const
void setItemPrototype(const QStandardItem *item)
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role=Qt::EditRole) override
\reimp
void setHorizontalHeaderItem(int column, QStandardItem *item)
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
\reimp
QStandardItem * horizontalHeaderItem(int column) const
void setVerticalHeaderLabels(const QStringList &labels)
void setModel(QStandardItemModel *mod)
bool insertColumns(int column, int count, const QList< QStandardItem * > &items)
QList< QStandardItemData > values
QPair< int, int > position() const
void setItemData(const QMap< int, QVariant > &roles)
int childIndex(int row, int column) const
void setChild(int row, int column, QStandardItem *item, bool emitChanged=false)
QMap< int, QVariant > itemData() const
void childDeleted(QStandardItem *child)
bool insertRows(int row, int count, const QList< QStandardItem * > &items)
QStandardItemModel * model
void sortChildren(int column, Qt::SortOrder order)
QList< QStandardItem * > children
void changeFlags(bool enable, Qt::ItemFlags f)
The QStandardItem class provides an item for use with the QStandardItemModel class.
QStandardItem * child(int row, int column=0) const
Returns the child item at (row, column) if one has been set; otherwise returns \nullptr.
Qt::ItemFlags flags() const
Returns the item flags for the item.
void setText(const QString &text)
Sets the item's text to the text specified.
void insertColumns(int column, int count)
Inserts count columns of child items at column column.
void insertRows(int row, const QList< QStandardItem * > &items)
Inserts items at row.
void setEnabled(bool enabled)
Sets whether the item is enabled.
QDataStream & operator<<(QDataStream &out, const QStandardItem &item)
virtual void setData(const QVariant &value, int role=Qt::UserRole+1)
Sets the item's data for the given role to the specified value.
bool isCheckable() const
Returns whether the item is user-checkable.
int rowCount() const
Returns the number of child item rows that the item has.
void setUserTristate(bool tristate)
Sets whether the item is tristate and controlled by the user.
void setIcon(const QIcon &icon)
Sets the item's icon to the icon specified.
virtual QVariant data(int role=Qt::UserRole+1) const
Returns the item's data for the given role, or an invalid QVariant if there is no data for the role.
void sortChildren(int column, Qt::SortOrder order=Qt::AscendingOrder)
Sorts the children of the item using the given order, by the values in the given column.
int column() const
Returns the column where the item is located in its parent's child table, or -1 if the item has no pa...
QIcon icon() const
Returns the item's icon.
void setColumnCount(int columns)
Sets the number of child item columns to columns.
void removeColumns(int column, int count)
Removes count columns at column column.
QStandardItem * parent() const
Returns the item's parent item, or \nullptr if the item has no parent.
void setRowCount(int rows)
Sets the number of child item rows to rows.
virtual void multiData(QModelRoleDataSpan roleDataSpan) const
void setEditable(bool editable)
Sets whether the item is editable.
void insertColumn(int column, const QList< QStandardItem * > &items)
Inserts a column at column containing items.
void removeColumn(int column)
Removes the given column.
virtual bool operator<(const QStandardItem &other) const
Returns true if this item is less than other; otherwise returns false.
void setChild(int row, int column, QStandardItem *item)
Sets the child item at (row, column) to item.
QStandardItem()
Constructs an item.
QList< QStandardItem * > takeRow(int row)
Removes row without deleting the row items, and returns a list of pointers to the removed items.
QString text() const
Returns the item's text.
void setCheckable(bool checkable)
Sets whether the item is user-checkable.
virtual void read(QDataStream &in)
Reads the item from stream in.
QDataStream & operator>>(QDataStream &in, QStandardItem &item)
QStandardItem & operator=(const QStandardItem &other)
Assigns other's data and flags to this item.
int row() const
Returns the row where the item is located in its parent's child table, or -1 if the item has no paren...
int columnCount() const
Returns the number of child item columns that the item has.
QStandardItem * takeChild(int row, int column=0)
Removes the child item at (row, column) without deleting it, and returns a pointer to the item.
void removeRows(int row, int count)
Removes count rows at row row.
QList< QStandardItem * > takeColumn(int column)
Removes column without deleting the column items, and returns a list of pointers to the removed items...
virtual ~QStandardItem()
Destructs the item.
void setFlags(Qt::ItemFlags flags)
Sets the item flags for the item to flags.
void appendColumn(const QList< QStandardItem * > &items)
Appends a column containing items.
virtual void write(QDataStream &out) const
Writes the item to stream out.
void removeRow(int row)
Removes the given row.
void setSelectable(bool selectable)
Sets whether the item is selectable.
void appendRow(const QList< QStandardItem * > &items)
Appends a row containing items.
virtual int type() const
Returns the type of this item.
QModelIndex index() const
Returns the QModelIndex associated with this item.
virtual QStandardItem * clone() const
Returns a copy of this item.
QStandardItemModel * model() const
Returns the QStandardItemModel that this item belongs to.
bool hasChildren() const
Returns true if this item has any children; otherwise returns false.
void setAutoTristate(bool tristate)
Determines that the item is tristate and controlled by QTreeWidget if tristate is true.
void insertRow(int row, const QList< QStandardItem * > &items)
Inserts a row at row containing items.
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtCore
Definition qvariant.h:65
QString text
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
Combined button and popup list for selecting options.
constexpr auto DataFlagsRole
@ Unchecked
Orientation
Definition qnamespace.h:98
@ Horizontal
Definition qnamespace.h:99
@ Vertical
Definition qnamespace.h:100
ItemDataRole
@ UserRole
@ EditRole
@ CheckStateRole
@ DisplayRole
SortOrder
Definition qnamespace.h:121
@ AscendingOrder
Definition qnamespace.h:122
DropAction
@ CopyAction
@ MoveAction
@ ItemIsEditable
@ ItemIsDragEnabled
@ ItemIsUserTristate
@ ItemIsUserCheckable
@ ItemIsSelectable
@ ItemIsEnabled
@ ItemIsDropEnabled
@ ItemIsAutoTristate
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:166
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLenum GLsizei GLsizei GLint * values
[15]
GLsizei const GLfloat * v
[13]
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLdouble GLdouble right
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLfloat GLfloat f
GLint left
GLint GLint bottom
GLbitfield flags
GLboolean enable
GLuint start
GLfloat n
GLint GLsizei GLsizei GLenum format
GLenum GLenum GLsizei void GLsizei void * column
const GLubyte * c
GLint limit
GLuint in
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLenum GLenum GLsizei void * row
GLuint64EXT * result
[6]
GLfixed GLfixed GLint GLint order
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static QString qStandardItemModelDataListMimeType()
#define QStringLiteral(str)
#define emit
int qint32
Definition qtypes.h:49
QTextStream out(stdout)
[7]
std::array< QModelRoleData, 3 > roleData
[13]
QObject::connect nullptr
QSharedPointer< T > other(t)
[5]
QGraphicsItem * item
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:962