diff options
Diffstat (limited to 'src/gui/itemmodels/qstandarditemmodel.cpp')
-rw-r--r-- | src/gui/itemmodels/qstandarditemmodel.cpp | 173 |
1 files changed, 89 insertions, 84 deletions
diff --git a/src/gui/itemmodels/qstandarditemmodel.cpp b/src/gui/itemmodels/qstandarditemmodel.cpp index a972b7b106..8b3e381431 100644 --- a/src/gui/itemmodels/qstandarditemmodel.cpp +++ b/src/gui/itemmodels/qstandarditemmodel.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qstandarditemmodel.h" @@ -55,6 +19,11 @@ QT_BEGIN_NAMESPACE +// Used internally to store the flags +namespace { +constexpr auto DataFlagsRole = Qt::ItemDataRole(Qt::UserRole - 1); +} + static inline QString qStandardItemModelDataListMimeType() { return QStringLiteral("application/x-qstandarditemmodeldatalist"); @@ -311,14 +280,12 @@ void QStandardItemPrivate::setItemData(const QMap<int, QVariant> &roles) /*! \internal */ -const QMap<int, QVariant> QStandardItemPrivate::itemData() const +QMap<int, QVariant> QStandardItemPrivate::itemData() const { QMap<int, QVariant> result; - QList<QStandardItemData>::const_iterator it; - for (it = values.cbegin(); it != values.cend(); ++it){ - // Qt::UserRole - 1 is used internally to store the flags - if (it->role != Qt::UserRole - 1) - result.insert(it->role, it->value); + for (const auto &data : values) { + if (data.role != DataFlagsRole) + result.insert(data.role, data.value); } return result; } @@ -355,11 +322,11 @@ void QStandardItemPrivate::sortChildren(int column, Qt::SortOrder order) } QModelIndexList changedPersistentIndexesFrom, changedPersistentIndexesTo; - QList<QStandardItem*> sorted_children(children.count()); + QList<QStandardItem*> sorted_children(children.size()); for (int i = 0; i < rowCount(); ++i) { - int r = (i < sortable.count() + int r = (i < sortable.size() ? sortable.at(i).second - : unsortable.at(i - sortable.count())); + : unsortable.at(i - sortable.size())); for (int c = 0; c < columnCount(); ++c) { QStandardItem *itm = q->child(r, c); sorted_children[childIndex(i, c)] = itm; @@ -407,7 +374,7 @@ void QStandardItemPrivate::setModel(QStandardItemModel *mod) } itm->d_func()->model = mod; const QList<QStandardItem*> &childList = itm->d_func()->children; - for (int i = 0; i < childList.count(); ++i) { + for (int i = 0; i < childList.size(); ++i) { QStandardItem *chi = childList.at(i); if (chi) stack.push(chi); @@ -468,7 +435,7 @@ bool QStandardItemPrivate::insertRows(int row, const QList<QStandardItem*> &item Q_Q(QStandardItem); if ((row < 0) || (row > rowCount()) || items.isEmpty()) return false; - int count = items.count(); + int count = items.size(); if (model) model->d_func()->rowsAboutToBeInserted(q, row, row + count - 1); if (rowCount() == 0) { @@ -482,7 +449,7 @@ bool QStandardItemPrivate::insertRows(int row, const QList<QStandardItem*> &item if (index != -1) children.insert(index, columnCount() * count, nullptr); } - for (int i = 0; i < items.count(); ++i) { + for (int i = 0; i < items.size(); ++i) { QStandardItem *item = items.at(i); item->d_func()->model = model; item->d_func()->parent = q; @@ -514,7 +481,7 @@ bool QStandardItemPrivate::insertRows(int row, int count, const QList<QStandardI } if (!items.isEmpty()) { int index = childIndex(row, 0); - int limit = qMin(items.count(), columnCount() * count); + int limit = qMin(items.size(), columnCount() * count); for (int i = 0; i < limit; ++i) { QStandardItem *item = items.at(i); if (item) { @@ -559,7 +526,7 @@ bool QStandardItemPrivate::insertColumns(int column, int count, const QList<QSta } } if (!items.isEmpty()) { - int limit = qMin(items.count(), rowCount() * count); + int limit = qMin(items.size(), rowCount() * count); for (int i = 0; i < limit; ++i) { QStandardItem *item = items.at(i); if (item) { @@ -876,7 +843,7 @@ QStandardItem &QStandardItem::operator=(const QStandardItem &other) QStandardItem::~QStandardItem() { Q_D(QStandardItem); - for (QStandardItem *child : qAsConst(d->children)) { + for (QStandardItem *child : std::as_const(d->children)) { if (child) child->d_func()->setModel(nullptr); delete child; @@ -905,9 +872,15 @@ QStandardItem *QStandardItem::parent() const Sets the item's data for the given \a role to the specified \a value. If you subclass QStandardItem and reimplement this function, your - reimplementation should call emitDataChanged() if you do not call - the base implementation of setData(). This will ensure that e.g. - views using the model are notified of the changes. + reimplementation should: + \list + \li call emitDataChanged() if you do not call the base implementation of + setData(). This will ensure that e.g. views using the model are notified + of the changes + \li call the base implementation for roles you don't handle, otherwise + setting flags, e.g. by calling setFlags(), setCheckable(), setEditable() + etc., will not work. + \endlist \note The default implementation treats Qt::EditRole and Qt::DisplayRole as referring to the same data. @@ -961,6 +934,11 @@ void QStandardItem::clearData() Returns the item's data for the given \a role, or an invalid QVariant if there is no data for the role. + If you reimplement this function, your reimplementation should call + the base implementation for roles you don't handle, otherwise getting + flags, e.g. by calling flags(), isCheckable(), isEditable() etc., + will not work. + \note The default implementation treats Qt::EditRole and Qt::DisplayRole as referring to the same data. */ @@ -1020,7 +998,7 @@ void QStandardItem::emitDataChanged() */ void QStandardItem::setFlags(Qt::ItemFlags flags) { - setData((int)flags, Qt::UserRole - 1); + setData((int)flags, DataFlagsRole); } /*! @@ -1035,7 +1013,7 @@ void QStandardItem::setFlags(Qt::ItemFlags flags) */ Qt::ItemFlags QStandardItem::flags() const { - QVariant v = data(Qt::UserRole - 1); + QVariant v = data(DataFlagsRole); if (!v.isValid()) return (Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable |Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled); @@ -1624,8 +1602,8 @@ void QStandardItem::insertRow(int row, const QList<QStandardItem*> &items) Q_D(QStandardItem); if (row < 0) return; - if (columnCount() < items.count()) - setColumnCount(items.count()); + if (columnCount() < items.size()) + setColumnCount(items.size()); d->insertRows(row, 1, items); } @@ -1653,8 +1631,8 @@ void QStandardItem::insertColumn(int column, const QList<QStandardItem*> &items) Q_D(QStandardItem); if (column < 0) return; - if (rowCount() < items.count()) - setRowCount(items.count()); + if (rowCount() < items.size()) + setRowCount(items.size()); d->insertColumns(column, 1, items); } @@ -1893,10 +1871,37 @@ QStandardItem *QStandardItem::takeChild(int row, int column) QStandardItem *item = nullptr; int index = d->childIndex(row, column); if (index != -1) { + QModelIndex changedIdx; item = d->children.at(index); - if (item) - item->d_func()->setParentAndModel(nullptr, nullptr); + if (item) { + QStandardItemPrivate *const item_d = item->d_func(); + if (d->model) { + QStandardItemModelPrivate *const model_d = d->model->d_func(); + const int savedRows = item_d->rows; + const int savedCols = item_d->columns; + const QVector<QStandardItem*> savedChildren = item_d->children; + if (savedRows > 0) { + model_d->rowsAboutToBeRemoved(item, 0, savedRows - 1); + item_d->rows = 0; + item_d->children = QVector<QStandardItem*>(); //slightly faster than clear + model_d->rowsRemoved(item, 0, savedRows); + } + if (savedCols > 0) { + model_d->columnsAboutToBeRemoved(item, 0, savedCols - 1); + item_d->columns = 0; + item_d->children = QVector<QStandardItem*>(); //slightly faster than clear + model_d->columnsRemoved(item, 0, savedCols); + } + item_d->rows = savedRows; + item_d->columns = savedCols; + item_d->children = savedChildren; + changedIdx = d->model->indexFromItem(item); + } + item_d->setParentAndModel(nullptr, nullptr); + } d->children.replace(index, nullptr); + if (changedIdx.isValid()) + d->model->dataChanged(changedIdx, changedIdx); } return item; } @@ -2540,9 +2545,9 @@ QStandardItem *QStandardItemModel::verticalHeaderItem(int row) const void QStandardItemModel::setHorizontalHeaderLabels(const QStringList &labels) { Q_D(QStandardItemModel); - if (columnCount() < labels.count()) - setColumnCount(labels.count()); - for (int i = 0; i < labels.count(); ++i) { + if (columnCount() < labels.size()) + setColumnCount(labels.size()); + for (int i = 0; i < labels.size(); ++i) { QStandardItem *item = horizontalHeaderItem(i); if (!item) { item = d->createItem(); @@ -2563,9 +2568,9 @@ void QStandardItemModel::setHorizontalHeaderLabels(const QStringList &labels) void QStandardItemModel::setVerticalHeaderLabels(const QStringList &labels) { Q_D(QStandardItemModel); - if (rowCount() < labels.count()) - setRowCount(labels.count()); - for (int i = 0; i < labels.count(); ++i) { + if (rowCount() < labels.size()) + setRowCount(labels.size()); + for (int i = 0; i < labels.size(); ++i) { QStandardItem *item = verticalHeaderItem(i); if (!item) { item = d->createItem(); @@ -3111,21 +3116,21 @@ QStringList QStandardItemModel::mimeTypes() const */ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const { - QMimeData *data = QAbstractItemModel::mimeData(indexes); + std::unique_ptr<QMimeData> data(QAbstractItemModel::mimeData(indexes)); if (!data) return nullptr; const QString format = qStandardItemModelDataListMimeType(); if (!mimeTypes().contains(format)) - return data; + return data.release(); QByteArray encoded; QDataStream stream(&encoded, QIODevice::WriteOnly); QSet<QStandardItem*> itemsSet; QStack<QStandardItem*> stack; - itemsSet.reserve(indexes.count()); - stack.reserve(indexes.count()); - for (int i = 0; i < indexes.count(); ++i) { + itemsSet.reserve(indexes.size()); + stack.reserve(indexes.size()); + for (int i = 0; i < indexes.size(); ++i) { if (QStandardItem *item = itemFromIndex(indexes.at(i))) { itemsSet << item; stack.push(item); @@ -3135,7 +3140,7 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const } } - //remove duplicates childrens + //remove duplicates children { QDuplicateTracker<QStandardItem *> seen; while (!stack.isEmpty()) { @@ -3144,7 +3149,7 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const continue; const QList<QStandardItem*> &childList = itm->d_func()->children; - for (int i = 0; i < childList.count(); ++i) { + for (int i = 0; i < childList.size(); ++i) { QStandardItem *chi = childList.at(i); if (chi) { itemsSet.remove(chi); @@ -3154,8 +3159,8 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const } } - stack.reserve(itemsSet.count()); - for (QStandardItem *item : qAsConst(itemsSet)) + stack.reserve(itemsSet.size()); + for (QStandardItem *item : std::as_const(itemsSet)) stack.push(item); //stream everything recursively @@ -3164,12 +3169,12 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const if (itemsSet.contains(item)) //if the item is selection 'top-level', stream its position stream << item->row() << item->column(); - stream << *item << item->columnCount() << int(item->d_ptr->children.count()); + stream << *item << item->columnCount() << int(item->d_ptr->children.size()); stack += item->d_ptr->children; } data->setData(format, encoded); - return data; + return data.release(); } @@ -3253,15 +3258,15 @@ bool QStandardItemModel::dropMimeData(const QMimeData *data, Qt::DropAction acti // Compute the number of continuous rows upon insertion and modify the rows to match QList<int> rowsToInsert(bottom + 1); - for (int i = 0; i < rows.count(); ++i) + for (int i = 0; i < rows.size(); ++i) rowsToInsert[rows.at(i)] = 1; - for (int i = 0; i < rowsToInsert.count(); ++i) { + for (int i = 0; i < rowsToInsert.size(); ++i) { if (rowsToInsert.at(i) == 1){ rowsToInsert[i] = dragRowCount; ++dragRowCount; } } - for (int i = 0; i < rows.count(); ++i) + for (int i = 0; i < rows.size(); ++i) rows[i] = top + rowsToInsert.at(rows.at(i)); QBitArray isWrittenTo(dragRowCount * dragColumnCount); |