76void QStandardItemPrivate::setChild(
int row,
int column, QStandardItem *item,
81 qWarning(
"QStandardItem::setChild: Can't make an item a child of itself %p",
85 if ((row < 0) || (column < 0))
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);
97 if (model && emitChanged) {
98 emit model->layoutAboutToBeChanged();
102 if (item->d_func()->parent ==
nullptr) {
103 item->d_func()->setParentAndModel(q, model);
105 qWarning(
"QStandardItem::setChild: Ignoring duplicate insertion of item %p",
112 if (!item && oldItem)
113 oldItem->d_func()->setModel(
nullptr);
115 children.replace(index, item);
120 oldItem->d_func()->setModel(
nullptr);
124 item->d_func()->lastKnownIndex = index;
126 if (model && emitChanged)
127 emit model->layoutChanged();
129 if (emitChanged && model) {
131 model->d_func()->itemChanged(item);
133 const QModelIndex idx = model->index(row, column, q->index());
134 emit model->dataChanged(idx, idx);
890void QStandardItem::setData(
const QVariant &value,
int role)
893 role = (role == Qt::EditRole) ? Qt::DisplayRole : role;
894 const QList<
int> roles((role == Qt::DisplayRole) ?
895 QList<
int>({Qt::DisplayRole, Qt::EditRole}) :
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)
909 d->model->d_func()->itemChanged(
this, roles);
913 d->values.append(QStandardItemData(role, value));
915 d->model->d_func()->itemChanged(
this, roles);
1762void QStandardItem::removeRows(
int row,
int count)
1765 if ((count < 1) || (row < 0) || ((row + count) > rowCount()))
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);
1774 oldItem->d_func()->setModel(
nullptr);
1777 d->children.remove(qMax(i, 0), n);
1780 d->model->d_func()->rowsRemoved(
this, row, count);
1789void QStandardItem::removeColumns(
int column,
int count)
1792 if ((count < 1) || (column < 0) || ((column + count) > columnCount()))
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);
1801 oldItem->d_func()->setModel(
nullptr);
1804 d->children.remove(i, count);
1806 d->columns -= count;
1808 d->model->d_func()->columnsRemoved(
this, column, count);
1868QStandardItem *QStandardItem::takeChild(
int row,
int column)
1871 QStandardItem *item =
nullptr;
1872 int index = d->childIndex(row, column);
1874 QModelIndex changedIdx;
1875 item = d->children.at(index);
1877 QStandardItemPrivate *
const item_d = item->d_func();
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);
1886 item_d->children = QVector<QStandardItem*>();
1887 model_d->rowsRemoved(item, 0, savedRows);
1889 if (savedCols > 0) {
1890 model_d->columnsAboutToBeRemoved(item, 0, savedCols - 1);
1891 item_d->columns = 0;
1892 item_d->children = QVector<QStandardItem*>();
1893 model_d->columnsRemoved(item, 0, savedCols);
1895 item_d->rows = savedRows;
1896 item_d->columns = savedCols;
1897 item_d->children = savedChildren;
1898 changedIdx = d->model->indexFromItem(item);
1900 item_d->setParentAndModel(
nullptr,
nullptr);
1902 d->children.replace(index,
nullptr);
1903 if (changedIdx.isValid())
1904 d->model->dataChanged(changedIdx, changedIdx);
1916QList<QStandardItem*> QStandardItem::takeRow(
int row)
1919 QList<QStandardItem*> items;
1920 if ((row < 0) || (row >= rowCount()))
1923 d->model->d_func()->rowsAboutToBeRemoved(
this, row, row);
1925 int index = d->childIndex(row, 0);
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);
1932 ch->d_func()->setParentAndModel(
nullptr,
nullptr);
1935 d->children.remove(index, col_count);
1939 d->model->d_func()->rowsRemoved(
this, row, 1);
1950QList<QStandardItem*> QStandardItem::takeColumn(
int column)
1953 QList<QStandardItem*> items;
1954 if ((column < 0) || (column >= columnCount()))
1957 d->model->d_func()->columnsAboutToBeRemoved(
this, column, column);
1959 const int rowCount = d->rowCount();
1960 items.reserve(rowCount);
1961 for (
int row = rowCount - 1; row >= 0; --row) {
1962 int index = d->childIndex(row, column);
1963 QStandardItem *ch = d->children.at(index);
1965 ch->d_func()->setParentAndModel(
nullptr,
nullptr);
1966 d->children.remove(index);
1971 d->model->d_func()->columnsRemoved(
this, column, 1);
2003void QStandardItem::sortChildren(
int column, Qt::SortOrder order)
2006 if ((column < 0) || (rowCount() == 0))
2009 QList<QPersistentModelIndex> parents;
2012 emit d->model->layoutAboutToBeChanged(parents, QAbstractItemModel::VerticalSortHint);
2014 d->sortChildren(column, order);
2016 emit d->model->layoutChanged(parents, QAbstractItemModel::VerticalSortHint);
2212QStandardItemModel::QStandardItemModel(
int rows,
int columns, QObject *parent)
2213 : QAbstractItemModel(*
new QStandardItemModelPrivate, parent)
2215 Q_D(QStandardItemModel);
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);
2435void QStandardItemModel::setHorizontalHeaderItem(
int column, QStandardItem *item)
2437 Q_D(QStandardItemModel);
2440 if (columnCount() <= column)
2441 setColumnCount(column + 1);
2443 QStandardItem *oldItem = d->columnHeaderItems.at(column);
2444 if (item == oldItem)
2448 if (item->model() ==
nullptr) {
2449 item->d_func()->setModel(
this);
2451 qWarning(
"QStandardItem::setHorizontalHeaderItem: Ignoring duplicate insertion of item %p",
2458 oldItem->d_func()->setModel(
nullptr);
2461 d->columnHeaderItems.replace(column, item);
2462 emit headerDataChanged(Qt::Horizontal, column, column);
2491void QStandardItemModel::setVerticalHeaderItem(
int row, QStandardItem *item)
2493 Q_D(QStandardItemModel);
2496 if (rowCount() <= row)
2497 setRowCount(row + 1);
2499 QStandardItem *oldItem = d->rowHeaderItems.at(row);
2500 if (item == oldItem)
2504 if (item->model() ==
nullptr) {
2505 item->d_func()->setModel(
this);
2507 qWarning(
"QStandardItem::setVerticalHeaderItem: Ignoring duplicate insertion of item %p",
2514 oldItem->d_func()->setModel(
nullptr);
2517 d->rowHeaderItems.replace(row, item);
2518 emit headerDataChanged(Qt::Vertical, row, row);
2628QList<QStandardItem*> QStandardItemModel::findItems(
const QString &text,
2629 Qt::MatchFlags flags,
int column)
const
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)));
2894QVariant QStandardItemModel::headerData(
int section, Qt::Orientation orientation,
int role)
const
2896 Q_D(
const QStandardItemModel);
2898 || ((orientation == Qt::Horizontal) && (section >= columnCount()))
2899 || ((orientation == Qt::Vertical) && (section >= rowCount()))) {
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);
3054bool QStandardItemModel::setHeaderData(
int section, Qt::Orientation orientation,
const QVariant &value,
int role)
3056 Q_D(QStandardItemModel);
3058 || ((orientation == Qt::Horizontal) && (section >= columnCount()))
3059 || ((orientation == Qt::Vertical) && (section >= rowCount()))) {
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);
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);
3079 headerItem->setData(value, role);
3117QMimeData *QStandardItemModel::mimeData(
const QModelIndexList &indexes)
const
3119 std::unique_ptr<QMimeData> data(QAbstractItemModel::mimeData(indexes));
3123 const QString format = qStandardItemModelDataListMimeType();
3124 if (!mimeTypes().contains(format))
3125 return data.release();
3127 QDataStream stream(&encoded, QIODevice::WriteOnly);
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))) {
3138 qWarning(
"QStandardItemModel::mimeData: No item associated with invalid index");
3145 QDuplicateTracker<QStandardItem *> seen;
3146 while (!stack.isEmpty()) {
3147 QStandardItem *itm = stack.pop();
3148 if (seen.hasSeen(itm))
3151 const QList<QStandardItem*> &childList = itm->d_func()->children;
3152 for (
int i = 0; i < childList.size(); ++i) {
3153 QStandardItem *chi = childList.at(i);
3155 itemsSet.remove(chi);
3162 stack.reserve(itemsSet.size());
3163 for (QStandardItem *item : std::as_const(itemsSet))
3167 while (!stack.isEmpty()) {
3168 QStandardItem *item = stack.pop();
3169 if (itemsSet.contains(item))
3170 stream << item->row() << item->column();
3172 stream << *item << item->columnCount() <<
int(item->d_ptr->children.size());
3173 stack += item->d_ptr->children;
3176 data->setData(format, encoded);
3177 return data.release();
3206bool QStandardItemModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
3207 int row,
int column,
const QModelIndex &parent)
3209 Q_D(QStandardItemModel);
3211 if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
3214 const QString format = qStandardItemModelDataListMimeType();
3215 if (!data->hasFormat(format))
3216 return QAbstractItemModel::dropMimeData(data, action, row, column, parent);
3218 if (row > rowCount(parent))
3219 row = rowCount(parent);
3221 row = rowCount(parent);
3226 QByteArray encoded = data->data(format);
3227 QDataStream stream(&encoded, QIODevice::ReadOnly);
3236 QList<
int> rows, columns;
3237 QList<QStandardItem *> items;
3239 while (!stream.atEnd()) {
3241 QStandardItem *item = d->createItem();
3243 d->decodeDataRecursive(stream, item);
3249 left = qMin(c, left);
3250 bottom = qMax(r, bottom);
3251 right = qMax(c, right);
3256 int dragRowCount = 0;
3257 int dragColumnCount = right - left + 1;
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;
3269 for (
int i = 0; i < rows.size(); ++i)
3270 rows[i] = top + rowsToInsert.at(rows.at(i));
3272 QBitArray isWrittenTo(dragRowCount * dragColumnCount);
3275 int colCount = columnCount(parent);
3276 if (colCount < dragColumnCount + column) {
3277 insertColumns(colCount, dragColumnCount + column - colCount, parent);
3278 colCount = columnCount(parent);
3280 insertRows(row, dragRowCount, parent);
3283 column = qMax(0, column);
3285 QStandardItem *parentItem = itemFromIndex (parent);
3287 parentItem = invisibleRootItem();
3289 QList<QPersistentModelIndex> newIndexes(items.size());
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;
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);
3305 if (!isWrittenTo.testBit(flat)) {
3306 newIndexes[j] = index(destinationRow, destinationColumn, parentItem->index());
3307 isWrittenTo.setBit(flat);
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));