📄 qsortfilterproxymodel.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 "qsortfilterproxymodel.h"#ifndef QT_NO_SORTFILTERPROXYMODEL#include "qitemselectionmodel.h"#include <qsize.h>#include <qdebug.h>#include <qdatetime.h>#include <qpair.h>#include <qstringlist.h>#include <private/qabstractitemmodel_p.h>#include <private/qabstractproxymodel_p.h>class QSortFilterProxyModelLessThan{public: inline QSortFilterProxyModelLessThan(int column, const QModelIndex &parent, const QAbstractItemModel *source, const QSortFilterProxyModel *proxy) : sort_column(column), source_parent(parent), source_model(source), proxy_model(proxy) {} inline bool operator()(int r1, int r2) const { QModelIndex i1 = source_model->index(r1, sort_column, source_parent); QModelIndex i2 = source_model->index(r2, sort_column, source_parent); return proxy_model->lessThan(i1, i2); }private: int sort_column; QModelIndex source_parent; const QAbstractItemModel *source_model; const QSortFilterProxyModel *proxy_model;};class QSortFilterProxyModelGreaterThan{public: inline QSortFilterProxyModelGreaterThan(int column, const QModelIndex &parent, const QAbstractItemModel *source, const QSortFilterProxyModel *proxy) : sort_column(column), source_parent(parent), source_model(source), proxy_model(proxy) {} inline bool operator()(int r1, int r2) const { QModelIndex i1 = source_model->index(r1, sort_column, source_parent); QModelIndex i2 = source_model->index(r2, sort_column, source_parent); return proxy_model->lessThan(i2, i1); }private: int sort_column; QModelIndex source_parent; const QAbstractItemModel *source_model; const QSortFilterProxyModel *proxy_model;};class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate{ Q_DECLARE_PUBLIC(QSortFilterProxyModel)public: struct Mapping { QVector<int> source_rows; QVector<int> source_columns; QVector<int> proxy_rows; QVector<int> proxy_columns; QVector<QModelIndex> mapped_children; QMap<QModelIndex, Mapping *>::const_iterator map_iter; }; mutable QMap<QModelIndex, Mapping*> source_index_mapping; int sort_column; Qt::SortOrder sort_order; Qt::CaseSensitivity sort_casesensitivity; int sort_role; bool sort_localeaware; int filter_column; QRegExp filter_regexp; int filter_role; bool dynamic_sortfilter; QList<QPersistentModelIndex> saved_persistent_indexes; QMap<QModelIndex, Mapping *>::const_iterator create_mapping( const QModelIndex &source_parent) const; QModelIndex proxy_to_source(const QModelIndex &proxyIndex) const; QModelIndex source_to_proxy(const QModelIndex &sourceIndex) const; void remove_from_mapping(const QModelIndex &source_parent); inline QMap<QModelIndex, Mapping *>::const_iterator index_to_iterator( const QModelIndex &proxy_index) const { Q_ASSERT(proxy_index.isValid()); const void *p = proxy_index.internalPointer(); Q_ASSERT(p); QMap<QModelIndex, Mapping *>::const_iterator it = static_cast<const Mapping*>(p)->map_iter; Q_ASSERT(it != source_index_mapping.constEnd()); Q_ASSERT(it.value()); return it; } inline QModelIndex create_index(int row, int column, QMap<QModelIndex, Mapping*>::const_iterator it) const { return q_func()->createIndex(row, column, *it); } void _q_sourceDataChanged(const QModelIndex &source_top_left, const QModelIndex &source_bottom_right); void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int start, int end); void _q_sourceReset(); void _q_sourceLayoutAboutToBeChanged(); void _q_sourceLayoutChanged(); void _q_sourceRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end); void _q_sourceRowsInserted(const QModelIndex &source_parent, int start, int end); void _q_sourceRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end); void _q_sourceRowsRemoved(const QModelIndex &source_parent, int start, int end); void _q_sourceColumnsAboutToBeInserted(const QModelIndex &source_parent, int start, int end); void _q_sourceColumnsInserted(const QModelIndex &source_parent, int start, int end); void _q_sourceColumnsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end); void _q_sourceColumnsRemoved(const QModelIndex &source_parent, int start, int end); void clear_mapping(); void sort(); void sort_source_rows(QVector<int> &source_rows, const QModelIndex &source_parent) const; QVector<QPair<int, QVector<int > > > proxy_intervals_for_source_items_to_add( const QVector<int> &proxy_to_source, const QVector<int> &source_items, const QModelIndex &source_parent, Qt::Orientation orient) const; QVector<QPair<int, int > > proxy_intervals_for_source_items( const QVector<int> &source_to_proxy, const QVector<int> &source_items) const; void insert_source_items( QVector<int> &source_to_proxy, QVector<int> &proxy_to_source, const QVector<int> &source_items, const QModelIndex &source_parent, Qt::Orientation orient, bool emit_signal = true); void remove_source_items( QVector<int> &source_to_proxy, QVector<int> &proxy_to_source, const QVector<int> &source_items, const QModelIndex &source_parent, Qt::Orientation orient, bool emit_signal = true); void remove_proxy_interval( QVector<int> &source_to_proxy, QVector<int> &proxy_to_source, int proxy_start, int proxy_end, const QModelIndex &proxy_parent, Qt::Orientation orient, bool emit_signal = true); void build_source_to_proxy_mapping( const QVector<int> &proxy_to_source, QVector<int> &source_to_proxy) const; void source_items_inserted(const QModelIndex &source_parent, int start, int end, Qt::Orientation orient); void source_items_about_to_be_removed(const QModelIndex &source_parent, int start, int end, Qt::Orientation orient); void source_items_removed(const QModelIndex &source_parent, int start, int end, Qt::Orientation orient); void proxy_item_range( const QVector<int> &source_to_proxy, const QVector<int> &source_items, int &proxy_low, int &proxy_high) const; QModelIndexList store_persistent_indexes(); void update_persistent_indexes(const QModelIndexList &source_indexes); void filter_changed(); void handle_filter_changed( QVector<int> &source_to_proxy, QVector<int> &proxy_to_source, const QModelIndex &source_parent, Qt::Orientation orient); void updateChildrenMapping(const QModelIndex &source_parent, Mapping *parent_mapping, Qt::Orientation orient, int start, int end, int delta_item_count, bool remove);};typedef QMap<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap;void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source_parent){ if (Mapping *m = source_index_mapping.take(source_parent)) { for (int i = 0; i < m->mapped_children.size(); ++i) remove_from_mapping(m->mapped_children.at(i)); delete m; }}void QSortFilterProxyModelPrivate::clear_mapping(){ // store the persistent indexes QModelIndexList source_indexes = store_persistent_indexes(); qDeleteAll(source_index_mapping); source_index_mapping.clear(); // update the persistent indexes update_persistent_indexes(source_indexes);}IndexMap::const_iterator QSortFilterProxyModelPrivate::create_mapping( const QModelIndex &source_parent) const{ Q_Q(const QSortFilterProxyModel); IndexMap::const_iterator it = source_index_mapping.constFind(source_parent); if (it != source_index_mapping.constEnd()) // was mapped already return it; Mapping *m = new Mapping; int source_rows = model->rowCount(source_parent); for (int i = 0; i < source_rows; ++i) { if (q->filterAcceptsRow(i, source_parent)) m->source_rows.append(i); } int source_cols = model->columnCount(source_parent); for (int i = 0; i < source_cols; ++i) { if (q->filterAcceptsColumn(i, source_parent)) m->source_columns.append(i); } sort_source_rows(m->source_rows, source_parent); m->proxy_rows.resize(source_rows); build_source_to_proxy_mapping(m->source_rows, m->proxy_rows); m->proxy_columns.resize(source_cols); build_source_to_proxy_mapping(m->source_columns, m->proxy_columns); it = IndexMap::const_iterator(source_index_mapping.insert(source_parent, m)); m->map_iter = it; if (source_parent.isValid()) { QModelIndex source_grand_parent = source_parent.parent(); IndexMap::const_iterator it2 = create_mapping(source_grand_parent); Q_ASSERT(it2 != source_index_mapping.constEnd()); it2.value()->mapped_children.append(source_parent); } Q_ASSERT(it != source_index_mapping.constEnd()); Q_ASSERT(it.value()); return it;}QModelIndex QSortFilterProxyModelPrivate::proxy_to_source(const QModelIndex &proxy_index) const{ if (!proxy_index.isValid()) return QModelIndex(); // for now; we may want to be able to set a root index later IndexMap::const_iterator it = index_to_iterator(proxy_index); Mapping *m = it.value(); if ((proxy_index.row() >= m->source_rows.size()) || (proxy_index.column() >= m->source_columns.size())) return QModelIndex(); int source_row = m->source_rows.at(proxy_index.row()); int source_col = m->source_columns.at(proxy_index.column()); return model->index(source_row, source_col, it.key());}QModelIndex QSortFilterProxyModelPrivate::source_to_proxy(const QModelIndex &source_index) const{ if (!source_index.isValid()) return QModelIndex(); // for now; we may want to be able to set a root index later QModelIndex source_parent = source_index.parent(); IndexMap::const_iterator it = create_mapping(source_parent); Mapping *m = it.value(); if ((source_index.row() >= m->proxy_rows.size()) || (source_index.column() >= m->proxy_columns.size())) return QModelIndex(); int proxy_row = m->proxy_rows.at(source_index.row()); int proxy_column = m->proxy_columns.at(source_index.column()); if (proxy_row == -1 || proxy_column == -1) return QModelIndex(); return create_index(proxy_row, proxy_column, it);}/*! \internal Sorts the existing mappings.*/void QSortFilterProxyModelPrivate::sort(){ Q_Q(QSortFilterProxyModel); emit q->layoutAboutToBeChanged(); QModelIndexList source_indexes = store_persistent_indexes(); IndexMap::const_iterator it = source_index_mapping.constBegin(); for (; it != source_index_mapping.constEnd(); ++it) { QModelIndex source_parent = it.key(); Mapping *m = it.value(); sort_source_rows(m->source_rows, source_parent); build_source_to_proxy_mapping(m->source_rows, m->proxy_rows); } update_persistent_indexes(source_indexes); emit q->layoutChanged();}/*! \internal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -