⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qsortfilterproxymodel.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************** Copyright (C) 1992-2006 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://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** 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 <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;    };    mutable QMap<QModelIndex, Mapping*> source_index_mapping;    int sort_column;    Qt::SortOrder sort_order;    int filter_column;    QRegExp filter_regexp;    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 =            reinterpret_cast<QMap<QModelIndex, Mapping *>::const_iterator & >(p);        Q_ASSERT(it != source_index_mapping.end());        Q_ASSERT(it.value());        return it;    }    inline QModelIndex create_index(int row, int column,                                    QMap<QModelIndex, Mapping*>::const_iterator it) const    {        const void *p = static_cast<const void *>(it);        return q_func()->createIndex(row, column, const_cast<void *>(p));    }    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_sourceLayoutAboutToBeChanged(const QModelIndex &source_parent);    void _q_sourceLayoutChanged();    void _q_sourceReset();    void clear_mapping();};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;    int persistent_count = persistent.indexes.count();    for (int i = 0; i < persistent_count; ++i) {        QModelIndex proxy_index = persistent.indexes.at(i)->index;        QModelIndex source_index = proxy_to_source(proxy_index);        source_indexes.append(source_index);    }    qDeleteAll(source_index_mapping);    source_index_mapping.clear();    // update the persistent indexes    for (int i = 0; i < persistent_count; ++i) {        QModelIndex source_index = source_indexes.at(i);        create_mapping(source_index.parent());        QModelIndex proxy_index = source_to_proxy(source_index);        persistent.indexes[i]->index = proxy_index;    }}IndexMap::const_iterator QSortFilterProxyModelPrivate::create_mapping(    const QModelIndex &source_parent) const{    Q_Q(const QSortFilterProxyModel);    IndexMap::const_iterator it = source_index_mapping.find(source_parent);    if (it != source_index_mapping.end()) // 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);    }    if (sort_column >= 0) { // only sorts rows        if (sort_order == Qt::AscendingOrder) {            QSortFilterProxyModelLessThan lt(sort_column, source_parent, model, q);            qStableSort(m->source_rows.begin(), m->source_rows.end(), lt);        } else {            QSortFilterProxyModelGreaterThan gt(sort_column, source_parent, model, q);            qStableSort(m->source_rows.begin(), m->source_rows.end(), gt);        }    }    m->proxy_rows.fill(-1, source_rows);    for (int i = 0; i < m->source_rows.size(); ++i)        m->proxy_rows[m->source_rows.at(i)] = i;    m->proxy_columns.fill(-1, source_cols);    for (int i = 0; i < m->source_columns.size(); ++i)        m->proxy_columns[m->source_columns.at(i)] = i;    it = source_index_mapping.insert(source_parent, m);    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.end());        it2.value()->mapped_children.append(source_parent);    }    Q_ASSERT(it != source_index_mapping.end());    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());    return create_index(proxy_row, proxy_column, it);}void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &source_top_left,                                                     const QModelIndex &source_bottom_right){    Q_Q(QSortFilterProxyModel);    QModelIndex proxy_top_left = source_to_proxy(source_top_left);    QModelIndex proxy_bottom_right = source_to_proxy(source_bottom_right);    emit q->dataChanged(proxy_top_left, proxy_bottom_right);}void QSortFilterProxyModelPrivate::_q_sourceHeaderDataChanged(Qt::Orientation orientation,                                                           int start, int end){    Q_Q(QSortFilterProxyModel);    Mapping *m = create_mapping(QModelIndex()).value();    int proxy_start = (orientation == Qt::Vertical                       ? m->proxy_rows.at(start)                       : m->proxy_columns.at(start));    int proxy_end = (orientation == Qt::Vertical                     ? m->proxy_rows.at(end)                     : m->proxy_columns.at(end));    emit q->headerDataChanged(orientation, proxy_start, proxy_end);}void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QModelIndex &source_parent){    Q_Q(QSortFilterProxyModel);    const QModelIndex proxy_parent = source_to_proxy(source_parent);;    int first = 0;    int last = q->rowCount(proxy_parent) - 1;    changes.push(QAbstractItemModelPrivate::Change(proxy_parent, first, last));    if (last >= first)        rowsAboutToBeRemoved(proxy_parent, first, last);    remove_from_mapping(source_parent);}void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged(){    Q_Q(QSortFilterProxyModel);    QAbstractItemModelPrivate::Change change = changes.pop();    if (change.last >= change.first)        rowsRemoved(change.parent, change.first, change.last);    emit q->layoutChanged();}void QSortFilterProxyModelPrivate::_q_sourceReset(){    Q_Q(QSortFilterProxyModel);    // All internal structures are deleted in clear()    q->reset();}/*!    \since 4.1    \class QSortFilterProxyModel    \brief The QSortFilterProxyModel class provides support for sorting and filtering data passed    between another model and a view.    \ingroup model-view    QSortFilterProxyModel can be used for sorting items, filtering    out items, or both. The model transforms the structure of a    source model by mapping the model indexes it supplies to new    indexes, corresponding to different locations, for views to use.    This approach allows a given source model to be restructured as    far as views are concerned without requiring any transformations    on the underlying data, and without duplicating the data in    memory.    Let's assume that we want to sort and filter the items provided    by a custom model. The code to set up the model and the view, \e    without sorting and filtering, would look like this:    \code        QTreeView *treeView = new QTreeView;        MyItemModel *model = new MyItemModel(this);        treeView->setModel(model);    \endcode    To add sorting and filtering support to \c MyItemModel, we need    to create a QSortFilterProxyModel, call setSourceModel() with the    \c MyItemModel as argument, and install the QSortFilterProxyModel    on the view:    \code        QTreeView *treeView = new QTreeView;        MyItemModel *sourceModel = new MyItemModel(this);        QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);        proxyModel->setSourceModel(sourceModel);        treeView->setModel(proxyModel);    \endcode    At this point, neither sorting nor filtering is enabled; the    original data is displayed in the view. Any changes made through    the QSortFilterProxyModel are applied to the original model.    The QSortFilterProxyModel acts as a wrapper for the original    model. If you need to convert source \l{QModelIndex}es to    sorted/filtered model indexes or vice versa, use mapToSource(),    mapFromSource(), mapSelectionToSource(), and    mapSelectionFromSource().    By default, sorting and filtering isn't dynamically reapplied    whenever the data of the original model changes, as an    optimization. To enable dynamic sorting and filtering, call    setDynamicSortFilter(true). At any time, you can call clear() to    resort/refilter the data.    \section1 Sorting    QHeaderView has a \l    {QHeaderVIew::showSortIndicator()}{showSortIndicator()} property    and a \l {QHeaderView::setClickable()}{setClickable()} function    that together control whether the user can sort the view by    clicking the view's horizontal header. For example:    \code        treeView->header()->setClickable(true);        treeView->header()->setSortIndicatorShown(true);    \endcode    When this feature is on, clicking on a header section sorts the    items according to that column. By clicking repeatedly, the user    can alternate between ascending and descending order.    \image qsortfilterproxymodel-sorting.png A sorted QTreeView    Behind the scene, the view calls the sort() virtual function on

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -