71void QStandardItemPrivate::setChild(
int row,
int column, QStandardItem *item,
76 qWarning(
"QStandardItem::setChild: Can't make an item a child of itself %p",
80 if ((row < 0) || (column < 0))
83 q->setRowCount(row + 1);
84 if (columns <= column)
85 q->setColumnCount(column + 1);
86 int index = childIndex(row, column);
87 Q_ASSERT(index != -1);
88 QStandardItem *oldItem = children.at(index);
92 if (model && emitChanged) {
93 emit model->layoutAboutToBeChanged();
97 if (item->d_func()->parent ==
nullptr) {
98 item->d_func()->setParentAndModel(q, model);
100 qWarning(
"QStandardItem::setChild: Ignoring duplicate insertion of item %p",
107 if (!item && oldItem)
108 oldItem->d_func()->setModel(
nullptr);
110 children.replace(index, item);
115 oldItem->d_func()->setModel(
nullptr);
119 item->d_func()->lastKnownIndex = index;
121 if (model && emitChanged)
122 emit model->layoutChanged();
124 if (emitChanged && model) {
126 model->d_func()->itemChanged(item);
128 const QModelIndex idx = model->index(row, column, q->index());
129 emit model->dataChanged(idx, idx);
230void QStandardItemPrivate::setItemData(
const QMap<
int, QVariant> &roles)
234 auto byRole = [](
const QStandardItemData& item1,
const QStandardItemData& item2) {
235 return item1.role < item2.role;
238 std::sort(values.begin(), values.end(), byRole);
241
242
243
244
245 QList<QStandardItemData> newValues;
246 newValues.reserve(values.size());
247 roleMapStandardItemDataUnion(roles.keyValueBegin(),
249 values.cbegin(), values.cend(),
250 std::back_inserter(newValues), ByNormalizedRole());
252 if (newValues != values) {
253 values.swap(newValues);
256 roleKeys.reserve(roles.size() + 1);
257 bool hasEditRole =
false;
258 bool hasDisplayRole =
false;
259 for (
auto it = roles.keyBegin(); it != roles.keyEnd(); ++it) {
260 roleKeys.push_back(*it);
261 if (*it == Qt::EditRole)
263 else if (*it == Qt::DisplayRole)
264 hasDisplayRole =
true;
266 if (hasEditRole && !hasDisplayRole)
267 roleKeys.push_back(Qt::DisplayRole);
268 else if (!hasEditRole && hasDisplayRole)
269 roleKeys.push_back(Qt::EditRole);
270 model->d_func()->itemChanged(q, roleKeys);
291void QStandardItemPrivate::sortChildren(
int column, Qt::SortOrder order)
294 if (column >= columnCount())
297 QList<std::pair<QStandardItem*,
int> > sortable;
298 QList<
int> unsortable;
300 sortable.reserve(rowCount());
301 unsortable.reserve(rowCount());
303 for (
int row = 0; row < rowCount(); ++row) {
304 QStandardItem *itm = q->child(row, column);
306 sortable.emplace_back(itm, row);
308 unsortable.append(row);
311 if (order == Qt::AscendingOrder) {
312 QStandardItemModelLessThan lt;
313 std::stable_sort(sortable.begin(), sortable.end(), lt);
315 QStandardItemModelGreaterThan gt;
316 std::stable_sort(sortable.begin(), sortable.end(), gt);
319 QModelIndexList changedPersistentIndexesFrom, changedPersistentIndexesTo;
320 QList<QStandardItem*> sorted_children(children.size());
321 for (
int i = 0; i < rowCount(); ++i) {
322 int r = (i < sortable.size()
323 ? sortable.at(i).second
324 : unsortable.at(i - sortable.size()));
325 for (
int c = 0; c < columnCount(); ++c) {
326 QStandardItem *itm = q->child(r, c);
327 sorted_children[childIndex(i, c)] = itm;
329 QModelIndex from = model->createIndex(r, c, q);
330 if (model->d_func()->persistent.indexes.contains(from)) {
331 QModelIndex to = model->createIndex(i, c, q);
332 changedPersistentIndexesFrom.append(from);
333 changedPersistentIndexesTo.append(to);
339 children = sorted_children;
342 model->changePersistentIndexList(changedPersistentIndexesFrom, changedPersistentIndexesTo);
345 QList<QStandardItem*>::iterator it;
346 for (it = children.begin(); it != children.end(); ++it) {
348 (*it)->d_func()->sortChildren(column, order);
356void QStandardItemPrivate::setModel(QStandardItemModel *mod)
358 if (children.isEmpty()) {
360 model->d_func()->invalidatePersistentIndex(model->indexFromItem(q_ptr));
363 QStack<QStandardItem*> stack;
365 while (!stack.isEmpty()) {
366 QStandardItem *itm = stack.pop();
367 if (itm->d_func()->model) {
368 itm->d_func()->model->d_func()->invalidatePersistentIndex(itm->d_func()->model->indexFromItem(itm));
370 itm->d_func()->model = mod;
371 const QList<QStandardItem*> &childList = itm->d_func()->children;
372 for (
int i = 0; i < childList.size(); ++i) {
373 QStandardItem *chi = childList.at(i);
411void QStandardItemModelPrivate::_q_emitItemChanged(
const QModelIndex &topLeft,
412 const QModelIndex &bottomRight)
414 Q_Q(QStandardItemModel);
415 QModelIndex parent = topLeft.parent();
416 for (
int row = topLeft.row(); row <= bottomRight.row(); ++row) {
417 for (
int column = topLeft.column(); column <= bottomRight.column(); ++column) {
418 QModelIndex index = q->index(row, column, parent);
419 if (QStandardItem *item = itemFromIndex(index))
420 emit q->itemChanged(item);
428bool QStandardItemPrivate::insertRows(
int row,
const QList<QStandardItem*> &items)
431 if ((row < 0) || (row > rowCount()) || items.isEmpty())
433 int count = items.size();
435 model->d_func()->rowsAboutToBeInserted(q, row, row + count - 1);
436 if (rowCount() == 0) {
437 if (columnCount() == 0)
438 q->setColumnCount(1);
439 children.resize(columnCount() * count);
443 int index = childIndex(row, 0);
445 children.insert(index, columnCount() * count,
nullptr);
447 for (
int i = 0; i < items.size(); ++i) {
448 QStandardItem *item = items.at(i);
449 item->d_func()->setParentAndModel(q, model);
450 int index = childIndex(i + row, 0);
451 children.replace(index, item);
453 item->d_func()->lastKnownIndex = index;
456 model->d_func()->rowsInserted(q, row, count);
460bool QStandardItemPrivate::insertRows(
int row,
int count,
const QList<QStandardItem*> &items)
463 if ((count < 1) || (row < 0) || (row > rowCount()) || count == 0)
466 model->d_func()->rowsAboutToBeInserted(q, row, row + count - 1);
467 if (rowCount() == 0) {
468 children.resize(columnCount() * count);
472 int index = childIndex(row, 0);
474 children.insert(index, columnCount() * count,
nullptr);
476 if (!items.isEmpty()) {
477 int index = childIndex(row, 0);
478 int limit = qMin(items.size(), columnCount() * count);
479 for (
int i = 0; i < limit; ++i) {
480 QStandardItem *item = items.at(i);
482 if (item->d_func()->parent ==
nullptr) {
483 item->d_func()->setParentAndModel(q, model);
485 qWarning(
"QStandardItem::insertRows: Ignoring duplicate insertion of item %p",
490 children.replace(index, item);
492 item->d_func()->lastKnownIndex = index;
497 model->d_func()->rowsInserted(q, row, count);
504bool QStandardItemPrivate::insertColumns(
int column,
int count,
const QList<QStandardItem*> &items)
507 if ((count < 1) || (column < 0) || (column > columnCount()) || count == 0)
510 model->d_func()->columnsAboutToBeInserted(q, column, column + count - 1);
511 if (columnCount() == 0) {
512 children.resize(rowCount() * count);
516 int index = childIndex(0, column);
517 for (
int row = 0; row < rowCount(); ++row) {
518 children.insert(index, count,
nullptr);
519 index += columnCount();
522 if (!items.isEmpty()) {
523 int limit = qMin(items.size(), rowCount() * count);
524 for (
int i = 0; i < limit; ++i) {
525 QStandardItem *item = items.at(i);
527 if (item->d_func()->parent ==
nullptr) {
528 item->d_func()->setParentAndModel(q, model);
530 qWarning(
"QStandardItem::insertColumns: Ignoring duplicate insertion of item %p",
536 int c = column + (i % count);
537 int index = childIndex(r, c);
538 children.replace(index, item);
540 item->d_func()->lastKnownIndex = index;
544 model->d_func()->columnsInserted(q, column, count);
551void QStandardItemModelPrivate::itemChanged(QStandardItem *item,
const QList<
int> &roles)
553 Q_Q(QStandardItemModel);
555 if (item->d_func()->parent ==
nullptr) {
557 int idx = columnHeaderItems.indexOf(item);
559 emit q->headerDataChanged(Qt::Horizontal, idx, idx);
561 idx = rowHeaderItems.indexOf(item);
563 emit q->headerDataChanged(Qt::Vertical, idx, idx);
567 const QModelIndex index = q->indexFromItem(item);
568 emit q->dataChanged(index, index, roles);
884void QStandardItem::setData(
const QVariant &value,
int role)
887 role = (role == Qt::EditRole) ? Qt::DisplayRole : role;
888 const QList<
int> roles((role == Qt::DisplayRole) ?
889 QList<
int>({Qt::DisplayRole, Qt::EditRole}) :
891 for (
auto it = d->values.begin(); it != d->values.end(); ++it) {
892 if ((*it).role == role) {
893 if (value.isValid()) {
894 if ((*it).value.userType() == value.userType() && (*it).value == value)
903 d->model->d_func()->itemChanged(
this, roles);
907 d->values.append(QStandardItemData(role, value));
909 d->model->d_func()->itemChanged(
this, roles);
1756void QStandardItem::removeRows(
int row,
int count)
1759 if ((count < 1) || (row < 0) || ((row + count) > rowCount()))
1762 d->model->d_func()->rowsAboutToBeRemoved(
this, row, row + count - 1);
1763 int i = d->childIndex(row, 0);
1764 int n = count * d->columnCount();
1765 for (
int j = i; j < n+i; ++j) {
1766 QStandardItem *oldItem = d->children.at(j);
1768 oldItem->d_func()->setModel(
nullptr);
1771 d->children.remove(qMax(i, 0), n);
1774 d->model->d_func()->rowsRemoved(
this, row, count);
1783void QStandardItem::removeColumns(
int column,
int count)
1786 if ((count < 1) || (column < 0) || ((column + count) > columnCount()))
1789 d->model->d_func()->columnsAboutToBeRemoved(
this, column, column + count - 1);
1790 for (
int row = d->rowCount() - 1; row >= 0; --row) {
1791 int i = d->childIndex(row, column);
1792 for (
int j=i; j<i+count; ++j) {
1793 QStandardItem *oldItem = d->children.at(j);
1795 oldItem->d_func()->setModel(
nullptr);
1798 d->children.remove(i, count);
1800 d->columns -= count;
1802 d->model->d_func()->columnsRemoved(
this, column, count);
1862QStandardItem *QStandardItem::takeChild(
int row,
int column)
1865 QStandardItem *item =
nullptr;
1866 int index = d->childIndex(row, column);
1868 QModelIndex changedIdx;
1869 item = d->children.at(index);
1871 QStandardItemPrivate *
const item_d = item->d_func();
1873 QStandardItemModelPrivate *
const model_d = d->model->d_func();
1874 const int savedRows = item_d->rows;
1875 const int savedCols = item_d->columns;
1876 const QVector<QStandardItem*> savedChildren = item_d->children;
1877 if (savedRows > 0) {
1878 model_d->rowsAboutToBeRemoved(item, 0, savedRows - 1);
1880 item_d->children = QVector<QStandardItem*>();
1881 model_d->rowsRemoved(item, 0, savedRows);
1883 if (savedCols > 0) {
1884 model_d->columnsAboutToBeRemoved(item, 0, savedCols - 1);
1885 item_d->columns = 0;
1886 item_d->children = QVector<QStandardItem*>();
1887 model_d->columnsRemoved(item, 0, savedCols);
1889 item_d->rows = savedRows;
1890 item_d->columns = savedCols;
1891 item_d->children = savedChildren;
1892 changedIdx = d->model->indexFromItem(item);
1894 item_d->setParentAndModel(
nullptr,
nullptr);
1896 d->children.replace(index,
nullptr);
1897 if (changedIdx.isValid())
1898 d->model->dataChanged(changedIdx, changedIdx);
1910QList<QStandardItem*> QStandardItem::takeRow(
int row)
1913 QList<QStandardItem*> items;
1914 if ((row < 0) || (row >= rowCount()))
1917 d->model->d_func()->rowsAboutToBeRemoved(
this, row, row);
1919 int index = d->childIndex(row, 0);
1921 int col_count = d->columnCount();
1922 items.reserve(col_count);
1923 for (
int column = 0; column < col_count; ++column) {
1924 QStandardItem *ch = d->children.at(index + column);
1926 ch->d_func()->setParentAndModel(
nullptr,
nullptr);
1929 d->children.remove(index, col_count);
1933 d->model->d_func()->rowsRemoved(
this, row, 1);
1944QList<QStandardItem*> QStandardItem::takeColumn(
int column)
1947 QList<QStandardItem*> items;
1948 if ((column < 0) || (column >= columnCount()))
1951 d->model->d_func()->columnsAboutToBeRemoved(
this, column, column);
1953 const int rowCount = d->rowCount();
1954 items.reserve(rowCount);
1955 for (
int row = rowCount - 1; row >= 0; --row) {
1956 int index = d->childIndex(row, column);
1957 QStandardItem *ch = d->children.at(index);
1959 ch->d_func()->setParentAndModel(
nullptr,
nullptr);
1960 d->children.remove(index);
1965 d->model->d_func()->columnsRemoved(
this, column, 1);
1997void QStandardItem::sortChildren(
int column, Qt::SortOrder order)
2000 if ((column < 0) || (rowCount() == 0))
2003 QList<QPersistentModelIndex> parents;
2006 emit d->model->layoutAboutToBeChanged(parents, QAbstractItemModel::VerticalSortHint);
2008 d->sortChildren(column, order);
2010 emit d->model->layoutChanged(parents, QAbstractItemModel::VerticalSortHint);
2206QStandardItemModel::QStandardItemModel(
int rows,
int columns, QObject *parent)
2207 : QAbstractItemModel(*
new QStandardItemModelPrivate, parent)
2209 Q_D(QStandardItemModel);
2211 d->root->insertColumns(0, columns);
2212 d->columnHeaderItems.insert(0, columns,
nullptr);
2213 d->root->insertRows(0, rows);
2214 d->rowHeaderItems.insert(0, rows,
nullptr);
2215 d->root->d_func()->setModel(
this);
2429void QStandardItemModel::setHorizontalHeaderItem(
int column, QStandardItem *item)
2431 Q_D(QStandardItemModel);
2434 if (columnCount() <= column)
2435 setColumnCount(column + 1);
2437 QStandardItem *oldItem = d->columnHeaderItems.at(column);
2438 if (item == oldItem)
2442 if (item->model() ==
nullptr) {
2443 item->d_func()->setModel(
this);
2445 qWarning(
"QStandardItem::setHorizontalHeaderItem: Ignoring duplicate insertion of item %p",
2452 oldItem->d_func()->setModel(
nullptr);
2455 d->columnHeaderItems.replace(column, item);
2456 emit headerDataChanged(Qt::Horizontal, column, column);
2485void QStandardItemModel::setVerticalHeaderItem(
int row, QStandardItem *item)
2487 Q_D(QStandardItemModel);
2490 if (rowCount() <= row)
2491 setRowCount(row + 1);
2493 QStandardItem *oldItem = d->rowHeaderItems.at(row);
2494 if (item == oldItem)
2498 if (item->model() ==
nullptr) {
2499 item->d_func()->setModel(
this);
2501 qWarning(
"QStandardItem::setVerticalHeaderItem: Ignoring duplicate insertion of item %p",
2508 oldItem->d_func()->setModel(
nullptr);
2511 d->rowHeaderItems.replace(row, item);
2512 emit headerDataChanged(Qt::Vertical, row, row);
2622QList<QStandardItem*> QStandardItemModel::findItems(
const QString &text,
2623 Qt::MatchFlags flags,
int column)
const
2625 QModelIndexList indexes = match(index(0, column, QModelIndex()),
2626 Qt::DisplayRole, text, -1, flags);
2627 QList<QStandardItem*> items;
2628 const int numIndexes = indexes.size();
2629 items.reserve(numIndexes);
2630 for (
int i = 0; i < numIndexes; ++i)
2631 items.append(itemFromIndex(indexes.at(i)));
2888QVariant QStandardItemModel::headerData(
int section, Qt::Orientation orientation,
int role)
const
2890 Q_D(
const QStandardItemModel);
2892 || ((orientation == Qt::Horizontal) && (section >= columnCount()))
2893 || ((orientation == Qt::Vertical) && (section >= rowCount()))) {
2896 QStandardItem *headerItem =
nullptr;
2897 if (orientation == Qt::Horizontal)
2898 headerItem = d->columnHeaderItems.at(section);
2899 else if (orientation == Qt::Vertical)
2900 headerItem = d->rowHeaderItems.at(section);
2901 return headerItem ? headerItem->data(role)
2902 : QAbstractItemModel::headerData(section, orientation, role);
3048bool QStandardItemModel::setHeaderData(
int section, Qt::Orientation orientation,
const QVariant &value,
int role)
3050 Q_D(QStandardItemModel);
3052 || ((orientation == Qt::Horizontal) && (section >= columnCount()))
3053 || ((orientation == Qt::Vertical) && (section >= rowCount()))) {
3056 QStandardItem *headerItem =
nullptr;
3057 if (orientation == Qt::Horizontal) {
3058 headerItem = d->columnHeaderItems.at(section);
3059 if (headerItem ==
nullptr) {
3060 headerItem = d->createItem();
3061 headerItem->d_func()->setModel(
this);
3062 d->columnHeaderItems.replace(section, headerItem);
3064 }
else if (orientation == Qt::Vertical) {
3065 headerItem = d->rowHeaderItems.at(section);
3066 if (headerItem ==
nullptr) {
3067 headerItem = d->createItem();
3068 headerItem->d_func()->setModel(
this);
3069 d->rowHeaderItems.replace(section, headerItem);
3073 headerItem->setData(value, role);
3111QMimeData *QStandardItemModel::mimeData(
const QModelIndexList &indexes)
const
3113 std::unique_ptr<QMimeData> data(QAbstractItemModel::mimeData(indexes));
3117 const QString format = qStandardItemModelDataListMimeType();
3118 if (!mimeTypes().contains(format))
3119 return data.release();
3121 QDataStream stream(&encoded, QIODevice::WriteOnly);
3123 QSet<QStandardItem*> itemsSet;
3124 QStack<QStandardItem*> stack;
3125 itemsSet.reserve(indexes.size());
3126 stack.reserve(indexes.size());
3127 for (
int i = 0; i < indexes.size(); ++i) {
3128 if (QStandardItem *item = itemFromIndex(indexes.at(i))) {
3132 qWarning(
"QStandardItemModel::mimeData: No item associated with invalid index");
3139 QDuplicateTracker<QStandardItem *> seen;
3140 while (!stack.isEmpty()) {
3141 QStandardItem *itm = stack.pop();
3142 if (seen.hasSeen(itm))
3145 const QList<QStandardItem*> &childList = itm->d_func()->children;
3146 for (
int i = 0; i < childList.size(); ++i) {
3147 QStandardItem *chi = childList.at(i);
3149 itemsSet.remove(chi);
3156 stack.reserve(itemsSet.size());
3157 for (QStandardItem *item : std::as_const(itemsSet))
3161 while (!stack.isEmpty()) {
3162 QStandardItem *item = stack.pop();
3163 if (itemsSet.contains(item))
3164 stream << item->row() << item->column();
3166 stream << *item << item->columnCount() <<
int(item->d_ptr->children.size());
3167 stack += item->d_ptr->children;
3170 data->setData(format, encoded);
3171 return data.release();
3200bool QStandardItemModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
3201 int row,
int column,
const QModelIndex &parent)
3203 Q_D(QStandardItemModel);
3205 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
3208 const QString format = qStandardItemModelDataListMimeType();
3209 if (!data->hasFormat(format))
3210 return QAbstractItemModel::dropMimeData(data, action, row, column, parent);
3212 if (row > rowCount(parent))
3213 row = rowCount(parent);
3215 row = rowCount(parent);
3220 QByteArray encoded = data->data(format);
3221 QDataStream stream(&encoded, QIODevice::ReadOnly);
3230 QList<
int> rows, columns;
3231 QList<QStandardItem *> items;
3233 while (!stream.atEnd()) {
3235 QStandardItem *item = d->createItem();
3237 d->decodeDataRecursive(stream, item);
3243 left = qMin(c, left);
3244 bottom = qMax(r, bottom);
3245 right = qMax(c, right);
3250 int dragRowCount = 0;
3251 int dragColumnCount = right - left + 1;
3254 QList<
int> rowsToInsert(bottom + 1);
3255 for (
int i = 0; i < rows.size(); ++i)
3256 rowsToInsert[rows.at(i)] = 1;
3257 for (
int i = 0; i < rowsToInsert.size(); ++i) {
3258 if (rowsToInsert.at(i) == 1){
3259 rowsToInsert[i] = dragRowCount;
3263 for (
int i = 0; i < rows.size(); ++i)
3264 rows[i] = top + rowsToInsert.at(rows.at(i));
3266 QBitArray isWrittenTo(dragRowCount * dragColumnCount);
3269 int colCount = columnCount(parent);
3270 if (colCount < dragColumnCount + column) {
3271 insertColumns(colCount, dragColumnCount + column - colCount, parent);
3272 colCount = columnCount(parent);
3274 insertRows(row, dragRowCount, parent);
3277 column = qMax(0, column);
3279 QStandardItem *parentItem = itemFromIndex (parent);
3281 parentItem = invisibleRootItem();
3283 QList<QPersistentModelIndex> newIndexes(items.size());
3285 for (
int j = 0; j < items.size(); ++j) {
3286 int relativeRow = rows.at(j) - top;
3287 int relativeColumn = columns.at(j) - left;
3288 int destinationRow = relativeRow + row;
3289 int destinationColumn = relativeColumn + column;
3290 int flat = (relativeRow * dragColumnCount) + relativeColumn;
3292 if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
3293 destinationColumn = qBound(column, destinationColumn, colCount - 1);
3294 destinationRow = row + dragRowCount;
3295 insertRows(row + dragRowCount, 1, parent);
3296 flat = (dragRowCount * dragColumnCount) + relativeColumn;
3297 isWrittenTo.resize(++dragRowCount * dragColumnCount);
3299 if (!isWrittenTo.testBit(flat)) {
3300 newIndexes[j] = index(destinationRow, destinationColumn, parentItem->index());
3301 isWrittenTo.setBit(flat);
3305 for(
int k = 0; k < newIndexes.size(); k++) {
3306 if (newIndexes.at(k).isValid()) {
3307 parentItem->setChild(newIndexes.at(k).row(), newIndexes.at(k).column(), items.at(k));