📄 qstandarditemmodel.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qstandarditemmodel.h"#ifndef QT_NO_STANDARDITEMMODEL#include <QtCore/qdatetime.h>#include <QtCore/qlist.h>#include <QtCore/qmap.h>#include <QtCore/qpair.h>#include <QtCore/qvariant.h>#include <QtCore/qvector.h>#include <QtCore/qstringlist.h>#include <private/qstandarditemmodel_p.h>#include <qdebug.h>class QStandardItemModelLessThan{public: inline QStandardItemModelLessThan() { } inline bool operator()(const QPair<QStandardItem*, int> &l, const QPair<QStandardItem*, int> &r) const { return *(l.first) < *(r.first); }};class QStandardItemModelGreaterThan{public: inline QStandardItemModelGreaterThan() { } inline bool operator()(const QPair<QStandardItem*, int> &l, const QPair<QStandardItem*, int> &r) const { return *(r.first) < *(l.first); }};/*! \internal*/QStandardItemPrivate::~QStandardItemPrivate(){ QVector<QStandardItem*>::const_iterator it; for (it = children.constBegin(); it != children.constEnd(); ++it) { QStandardItem *child = *it; if (child) child->d_func()->setModel(0); delete child; } children.clear(); if (parent && model) parent->d_func()->childDeleted(q_func());}/*! \internal*/QPair<int, int> QStandardItemPrivate::position() const{ if (QStandardItem *par = parent) { int idx = par->d_func()->childIndex(q_func()); if (idx == -1) return QPair<int, int>(-1, -1); return QPair<int, int>(idx / par->columnCount(), idx % par->columnCount()); } // ### support header items? return QPair<int, int>(-1, -1);}/*! \internal*/void QStandardItemPrivate::setChild(int row, int column, QStandardItem *item, bool emitChanged){ Q_Q(QStandardItem); if (item == q) { qWarning("QStandardItem::setChild: Can't make an item a child of itself %p", item); return; } if ((row < 0) || (column < 0)) return; if (rows <= row) q->setRowCount(row + 1); if (columns <= column) q->setColumnCount(column + 1); int index = childIndex(row, column); Q_ASSERT(index != -1); QStandardItem *oldItem = children.at(index); if (item == oldItem) return; if (item) { if (item->d_func()->parent == 0) { item->d_func()->setParentAndModel(q, model); } else { qWarning("QStandardItem::setChild: Ignoring duplicate insertion of item %p", item); return; } } if (oldItem) oldItem->d_func()->setModel(0); delete oldItem; children.replace(index, item); if (emitChanged && model) model->d_func()->itemChanged(item);}/*! \internal*/void QStandardItemPrivate::changeFlags(bool enable, Qt::ItemFlags f){ Q_Q(QStandardItem); Qt::ItemFlags flags = q->flags(); if (enable) flags |= f; else flags &= ~f; q->setFlags(flags);}/*! \internal*/void QStandardItemPrivate::childDeleted(QStandardItem *child){ int index = childIndex(child); Q_ASSERT(index != -1); children.replace(index, 0);}/*! \internal*/void QStandardItemPrivate::setItemData(const QMap<int, QVariant> &roles){ Q_Q(QStandardItem); //let's build the vector of new values QVector<QWidgetItemData> newValues; QMap<int, QVariant>::const_iterator it; for (it = roles.begin(); it != roles.end(); ++it) { QVariant value = it.value(); if (value.isValid()) { int role = it.key(); role = (role == Qt::EditRole) ? Qt::DisplayRole : role; QWidgetItemData wid(role,it.value()); newValues.append(wid); } } if (values!=newValues) { values=newValues; if (model) model->d_func()->itemChanged(q); }}/*! \internal*/const QMap<int, QVariant> QStandardItemPrivate::itemData() const{ QMap<int, QVariant> result; QVector<QWidgetItemData>::const_iterator it; for (it = values.begin(); it != values.end(); ++it) result.insert((*it).role, (*it).value); return result;}/*! \internal*/void QStandardItemPrivate::sortChildren(int column, Qt::SortOrder order){ Q_Q(QStandardItem); if (column >= columnCount()) return; QVector<QPair<QStandardItem*, int> > sortable; QVector<int> unsortable; sortable.reserve(rowCount()); unsortable.reserve(rowCount()); for (int row = 0; row < rowCount(); ++row) { QStandardItem *itm = q->child(row, column); if (itm) sortable.append(QPair<QStandardItem*,int>(itm, row)); else unsortable.append(row); } if (order == Qt::AscendingOrder) { QStandardItemModelLessThan lt; qStableSort(sortable.begin(), sortable.end(), lt); } else { QStandardItemModelGreaterThan gt; qStableSort(sortable.begin(), sortable.end(), gt); } QModelIndexList oldPersistentIndexes; if (model) oldPersistentIndexes = model->persistentIndexList(); QVector<QPair<QModelIndex, QModelIndex> > changedPersistentIndexes; QVector<QStandardItem*> sorted_children(children.count()); for (int i = 0; i < rowCount(); ++i) { int r = (i < sortable.count() ? sortable.at(i).second : unsortable.at(i - sortable.count())); for (int c = 0; c < columnCount(); ++c) { QStandardItem *itm = q->child(r, c); sorted_children[childIndex(i, c)] = itm; if (model) { QModelIndex from = model->createIndex(r, c, q); if (oldPersistentIndexes.contains(from)) { QModelIndex to = model->createIndex(i, c, q); changedPersistentIndexes.append( QPair<QModelIndex, QModelIndex>(from, to)); } } } } children = sorted_children; if (model) { QPair<QModelIndex, QModelIndex> indexPair; foreach (indexPair, changedPersistentIndexes) model->changePersistentIndex(indexPair.first, indexPair.second); } QVector<QStandardItem*>::iterator it; for (it = children.begin(); it != children.end(); ++it) { if (*it) (*it)->d_func()->sortChildren(column, order); }}/*! \internal*/QStandardItemModelPrivate::QStandardItemModelPrivate() : root(new QStandardItem), itemPrototype(0), sortRole(Qt::DisplayRole){}/*! \internal*/QStandardItemModelPrivate::~QStandardItemModelPrivate(){ delete root; delete itemPrototype; qDeleteAll(columnHeaderItems); qDeleteAll(rowHeaderItems);}/*! \internal*/void QStandardItemModelPrivate::init(){ Q_Q(QStandardItemModel); QObject::connect(q, SIGNAL(dataChanged(QModelIndex,QModelIndex)), q, SLOT(_q_emitItemChanged(QModelIndex,QModelIndex)));}/*! \internal*/void QStandardItemModelPrivate::_q_emitItemChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight){ Q_Q(QStandardItemModel); QModelIndex parent = topLeft.parent(); for (int row = topLeft.row(); row <= bottomRight.row(); ++row) { for (int column = topLeft.column(); column <= bottomRight.column(); ++column) { QModelIndex index = q->index(row, column, parent); if (QStandardItem *item = itemFromIndex(index)) emit q->itemChanged(item); } }}/*! \internal*/bool QStandardItemPrivate::insertRows(int row, const QList<QStandardItem*> &items){ Q_Q(QStandardItem); if ((row < 0) || (row > rowCount())) return false; int count = items.count(); if (model) model->d_func()->rowsAboutToBeInserted(q, row, row + count - 1); if (rowCount() == 0) { if (columnCount() == 0) q->setColumnCount(1); children.resize(columnCount() * count); rows = count; } else { rows += count; int index = childIndex(row, 0); if (index != -1) children.insert(index, columnCount() * count, 0); } for (int i = 0; i < items.count(); ++i) { int index = childIndex(i + row, 0); children.replace(index, items.at(i)); } if (model) model->d_func()->rowsInserted(q, row, count); return true;}bool QStandardItemPrivate::insertRows(int row, int count, const QList<QStandardItem*> &items){ Q_Q(QStandardItem); if ((count < 1) || (row < 0) || (row > rowCount())) return false; if (model) model->d_func()->rowsAboutToBeInserted(q, row, row + count - 1); if (rowCount() == 0) { children.resize(columnCount() * count); rows = count; } else { rows += count; int index = childIndex(row, 0); if (index != -1) children.insert(index, columnCount() * count, 0); } if (!items.isEmpty()) { int index = childIndex(row, 0); int limit = qMin(items.count(), columnCount() * count); for (int i = 0; i < limit; ++i) { QStandardItem *item = items.at(i); if (item) { if (item->d_func()->parent == 0) { item->d_func()->setParentAndModel(q, model); } else { qWarning("QStandardItem::insertRows: Ignoring duplicate insertion of item %p", item); item = 0; } } children.replace(index, item); ++index; } } if (model) model->d_func()->rowsInserted(q, row, count); return true;}/*! \internal*/bool QStandardItemPrivate::insertColumns(int column, int count, const QList<QStandardItem*> &items){ Q_Q(QStandardItem); if ((count < 1) || (column < 0) || (column > columnCount())) return false; if (model) model->d_func()->columnsAboutToBeInserted(q, column, column + count - 1); if (columnCount() == 0) { children.resize(rowCount() * count); columns = count; } else { columns += count; int index = childIndex(0, column); for (int row = 0; row < rowCount(); ++row) { children.insert(index, count, 0); index += columnCount(); } } if (!items.isEmpty()) { int limit = qMin(items.count(), rowCount() * count); for (int i = 0; i < limit; ++i) { QStandardItem *item = items.at(i); if (item) { if (item->d_func()->parent == 0) { item->d_func()->setParentAndModel(q, model); } else { qWarning("QStandardItem::insertColumns: Ignoring duplicate insertion of item %p", item); item = 0; } } int r = i / count; int c = column + (i % count); int index = childIndex(r, c); children.replace(index, item); } } if (model) model->d_func()->columnsInserted(q, column, count); return true;}/*! \internal*/void QStandardItemModelPrivate::itemChanged(QStandardItem *item){ Q_Q(QStandardItemModel); if (item->d_func()->parent == 0) { // Header item int idx = columnHeaderItems.indexOf(item); if (idx != -1) { emit q->headerDataChanged(Qt::Horizontal, idx, idx); } else { idx = rowHeaderItems.indexOf(item); if (idx != -1) emit q->headerDataChanged(Qt::Vertical, idx, idx); } } else { // Normal item QModelIndex index = q->indexFromItem(item); emit q->dataChanged(index, index); }}/*! \internal*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -