From 211e434a05c666e172b2f1e2f72c7695adac52a1 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 10 Dec 2011 19:13:51 +0100 Subject: Move proxy and selection models to QtCore. Change-Id: I71097855cb9e28105238e496778f29f99f7fc84e Reviewed-by: Thiago Macieira Reviewed-by: Lars Knoll --- src/widgets/itemviews/itemviews.pri | 12 - src/widgets/itemviews/qabstractitemview.h | 2 +- src/widgets/itemviews/qabstractproxymodel.cpp | 388 ---- src/widgets/itemviews/qabstractproxymodel.h | 113 - src/widgets/itemviews/qabstractproxymodel_p.h | 76 - src/widgets/itemviews/qidentityproxymodel.cpp | 578 ----- src/widgets/itemviews/qidentityproxymodel.h | 120 - src/widgets/itemviews/qitemselectionmodel.cpp | 1641 -------------- src/widgets/itemviews/qitemselectionmodel.h | 256 --- src/widgets/itemviews/qitemselectionmodel_p.h | 113 - src/widgets/itemviews/qlistwidget.h | 2 +- src/widgets/itemviews/qsortfilterproxymodel.cpp | 2703 ----------------------- src/widgets/itemviews/qsortfilterproxymodel.h | 205 -- src/widgets/itemviews/qstringlistmodel.cpp | 310 --- src/widgets/itemviews/qstringlistmodel.h | 91 - src/widgets/util/qcompleter.cpp | 2 +- src/widgets/util/qcompleter_p.h | 2 +- 17 files changed, 4 insertions(+), 6610 deletions(-) delete mode 100644 src/widgets/itemviews/qabstractproxymodel.cpp delete mode 100644 src/widgets/itemviews/qabstractproxymodel.h delete mode 100644 src/widgets/itemviews/qabstractproxymodel_p.h delete mode 100644 src/widgets/itemviews/qidentityproxymodel.cpp delete mode 100644 src/widgets/itemviews/qidentityproxymodel.h delete mode 100644 src/widgets/itemviews/qitemselectionmodel.cpp delete mode 100644 src/widgets/itemviews/qitemselectionmodel.h delete mode 100644 src/widgets/itemviews/qitemselectionmodel_p.h delete mode 100644 src/widgets/itemviews/qsortfilterproxymodel.cpp delete mode 100644 src/widgets/itemviews/qsortfilterproxymodel.h delete mode 100644 src/widgets/itemviews/qstringlistmodel.cpp delete mode 100644 src/widgets/itemviews/qstringlistmodel.h (limited to 'src/widgets') diff --git a/src/widgets/itemviews/itemviews.pri b/src/widgets/itemviews/itemviews.pri index 7ef704546e..d5a5012f83 100644 --- a/src/widgets/itemviews/itemviews.pri +++ b/src/widgets/itemviews/itemviews.pri @@ -4,7 +4,6 @@ HEADERS += \ itemviews/qabstractitemview.h \ itemviews/qabstractitemview_p.h \ itemviews/qheaderview.h \ - itemviews/qidentityproxymodel.h \ itemviews/qlistview.h \ itemviews/qlistview_p.h \ itemviews/qbsptree_p.h \ @@ -14,8 +13,6 @@ HEADERS += \ itemviews/qtreeview_p.h \ itemviews/qabstractitemdelegate.h \ itemviews/qitemdelegate.h \ - itemviews/qitemselectionmodel.h \ - itemviews/qitemselectionmodel_p.h \ itemviews/qdirmodel.h \ itemviews/qlistwidget.h \ itemviews/qlistwidget_p.h \ @@ -26,14 +23,10 @@ HEADERS += \ itemviews/qwidgetitemdata_p.h \ itemviews/qproxymodel.h \ itemviews/qproxymodel_p.h \ - itemviews/qabstractproxymodel.h \ - itemviews/qabstractproxymodel_p.h \ - itemviews/qsortfilterproxymodel.h \ itemviews/qitemeditorfactory.h \ itemviews/qitemeditorfactory_p.h \ itemviews/qstandarditemmodel.h \ itemviews/qstandarditemmodel_p.h \ - itemviews/qstringlistmodel.h \ itemviews/qtreewidgetitemiterator.h \ itemviews/qdatawidgetmapper.h \ itemviews/qfileiconprovider.h \ @@ -45,24 +38,19 @@ HEADERS += \ SOURCES += \ itemviews/qabstractitemview.cpp \ itemviews/qheaderview.cpp \ - itemviews/qidentityproxymodel.cpp \ itemviews/qlistview.cpp \ itemviews/qbsptree.cpp \ itemviews/qtableview.cpp \ itemviews/qtreeview.cpp \ itemviews/qabstractitemdelegate.cpp \ itemviews/qitemdelegate.cpp \ - itemviews/qitemselectionmodel.cpp \ itemviews/qdirmodel.cpp \ itemviews/qlistwidget.cpp \ itemviews/qtablewidget.cpp \ itemviews/qtreewidget.cpp \ itemviews/qproxymodel.cpp \ - itemviews/qabstractproxymodel.cpp \ - itemviews/qsortfilterproxymodel.cpp \ itemviews/qitemeditorfactory.cpp \ itemviews/qstandarditemmodel.cpp \ - itemviews/qstringlistmodel.cpp \ itemviews/qtreewidgetitemiterator.cpp \ itemviews/qdatawidgetmapper.cpp \ itemviews/qfileiconprovider.cpp \ diff --git a/src/widgets/itemviews/qabstractitemview.h b/src/widgets/itemviews/qabstractitemview.h index 25501e67c5..00b19cf0d1 100644 --- a/src/widgets/itemviews/qabstractitemview.h +++ b/src/widgets/itemviews/qabstractitemview.h @@ -44,7 +44,7 @@ #include #include -#include +#include #include QT_BEGIN_HEADER diff --git a/src/widgets/itemviews/qabstractproxymodel.cpp b/src/widgets/itemviews/qabstractproxymodel.cpp deleted file mode 100644 index 47810d6cc7..0000000000 --- a/src/widgets/itemviews/qabstractproxymodel.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qabstractproxymodel.h" - -#ifndef QT_NO_PROXYMODEL - -#include "qitemselectionmodel.h" -#include -#include -#include - - -QT_BEGIN_NAMESPACE - -/*! - \since 4.1 - \class QAbstractProxyModel - \brief The QAbstractProxyModel class provides a base class for proxy item - models that can do sorting, filtering or other data processing tasks. - \ingroup model-view - \inmodule QtWidgets - - This class defines the standard interface that proxy models must use to be - able to interoperate correctly with other model/view components. It is not - supposed to be instantiated directly. - - All standard proxy models are derived from the QAbstractProxyModel class. - If you need to create a new proxy model class, it is usually better to - subclass an existing class that provides the closest behavior to the one - you want to provide. - - Proxy models that filter or sort items of data from a source model should - be created by using or subclassing QSortFilterProxyModel. - - To subclass QAbstractProxyModel, you need to implement mapFromSource() and - mapToSource(). The mapSelectionFromSource() and mapSelectionToSource() - functions only need to be reimplemented if you need a behavior different - from the default behavior. - - \note If the source model is deleted or no source model is specified, the - proxy model operates on a empty placeholder model. - - \sa QSortFilterProxyModel, QAbstractItemModel, {Model/View Programming} -*/ - -//detects the deletion of the source model -void QAbstractProxyModelPrivate::_q_sourceModelDestroyed() -{ - model = QAbstractItemModelPrivate::staticEmptyModel(); -} - -/*! - Constructs a proxy model with the given \a parent. -*/ - -QAbstractProxyModel::QAbstractProxyModel(QObject *parent) - :QAbstractItemModel(*new QAbstractProxyModelPrivate, parent) -{ - setSourceModel(QAbstractItemModelPrivate::staticEmptyModel()); -} - -/*! - \internal -*/ - -QAbstractProxyModel::QAbstractProxyModel(QAbstractProxyModelPrivate &dd, QObject *parent) - : QAbstractItemModel(dd, parent) -{ - setSourceModel(QAbstractItemModelPrivate::staticEmptyModel()); -} - -/*! - Destroys the proxy model. -*/ -QAbstractProxyModel::~QAbstractProxyModel() -{ - -} - -/*! - Sets the given \a sourceModel to be processed by the proxy model. -*/ -void QAbstractProxyModel::setSourceModel(QAbstractItemModel *sourceModel) -{ - Q_D(QAbstractProxyModel); - if (d->model) - disconnect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed())); - - if (sourceModel) { - d->model = sourceModel; - connect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed())); - } else { - d->model = QAbstractItemModelPrivate::staticEmptyModel(); - } - d->roleNames = d->model->roleNames(); -} - -/*! - Returns the model that contains the data that is available through the proxy model. -*/ -QAbstractItemModel *QAbstractProxyModel::sourceModel() const -{ - Q_D(const QAbstractProxyModel); - if (d->model == QAbstractItemModelPrivate::staticEmptyModel()) - return 0; - return d->model; -} - -/*! - \reimp - */ -bool QAbstractProxyModel::submit() -{ - Q_D(QAbstractProxyModel); - return d->model->submit(); -} - -/*! - \reimp - */ -void QAbstractProxyModel::revert() -{ - Q_D(QAbstractProxyModel); - d->model->revert(); -} - - -/*! - \fn QModelIndex QAbstractProxyModel::mapToSource(const QModelIndex &proxyIndex) const - - Reimplement this function to return the model index in the source model that - corresponds to the \a proxyIndex in the proxy model. - - \sa mapFromSource() -*/ - -/*! - \fn QModelIndex QAbstractProxyModel::mapFromSource(const QModelIndex &sourceIndex) const - - Reimplement this function to return the model index in the proxy model that - corresponds to the \a sourceIndex from the source model. - - \sa mapToSource() -*/ - -/*! - Returns a source selection mapped from the specified \a proxySelection. - - Reimplement this method to map proxy selections to source selections. - */ -QItemSelection QAbstractProxyModel::mapSelectionToSource(const QItemSelection &proxySelection) const -{ - QModelIndexList proxyIndexes = proxySelection.indexes(); - QItemSelection sourceSelection; - for (int i = 0; i < proxyIndexes.size(); ++i) { - const QModelIndex proxyIdx = mapToSource(proxyIndexes.at(i)); - if (!proxyIdx.isValid()) - continue; - sourceSelection << QItemSelectionRange(proxyIdx); - } - return sourceSelection; -} - -/*! - Returns a proxy selection mapped from the specified \a sourceSelection. - - Reimplement this method to map source selections to proxy selections. -*/ -QItemSelection QAbstractProxyModel::mapSelectionFromSource(const QItemSelection &sourceSelection) const -{ - QModelIndexList sourceIndexes = sourceSelection.indexes(); - QItemSelection proxySelection; - for (int i = 0; i < sourceIndexes.size(); ++i) { - const QModelIndex srcIdx = mapFromSource(sourceIndexes.at(i)); - if (!srcIdx.isValid()) - continue; - proxySelection << QItemSelectionRange(srcIdx); - } - return proxySelection; -} - -/*! - \reimp - */ -QVariant QAbstractProxyModel::data(const QModelIndex &proxyIndex, int role) const -{ - Q_D(const QAbstractProxyModel); - return d->model->data(mapToSource(proxyIndex), role); -} - -/*! - \reimp - */ -QVariant QAbstractProxyModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - Q_D(const QAbstractProxyModel); - int sourceSection; - if (orientation == Qt::Horizontal) { - const QModelIndex proxyIndex = index(0, section); - sourceSection = mapToSource(proxyIndex).column(); - } else { - const QModelIndex proxyIndex = index(section, 0); - sourceSection = mapToSource(proxyIndex).row(); - } - return d->model->headerData(sourceSection, orientation, role); -} - -/*! - \reimp - */ -QMap QAbstractProxyModel::itemData(const QModelIndex &proxyIndex) const -{ - Q_D(const QAbstractProxyModel); - return d->model->itemData(mapToSource(proxyIndex)); -} - -/*! - \reimp - */ -Qt::ItemFlags QAbstractProxyModel::flags(const QModelIndex &index) const -{ - Q_D(const QAbstractProxyModel); - return d->model->flags(mapToSource(index)); -} - -/*! - \reimp - */ -bool QAbstractProxyModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - Q_D(QAbstractProxyModel); - return d->model->setData(mapToSource(index), value, role); -} - -/*! - \reimp - */ -bool QAbstractProxyModel::setItemData(const QModelIndex &index, const QMap< int, QVariant >& roles) -{ - Q_D(QAbstractProxyModel); - return d->model->setItemData(mapToSource(index), roles); -} - -/*! - \reimp - */ -bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) -{ - Q_D(QAbstractProxyModel); - int sourceSection; - if (orientation == Qt::Horizontal) { - const QModelIndex proxyIndex = index(0, section); - sourceSection = mapToSource(proxyIndex).column(); - } else { - const QModelIndex proxyIndex = index(section, 0); - sourceSection = mapToSource(proxyIndex).row(); - } - return d->model->setHeaderData(sourceSection, orientation, value, role); -} - -/*! - \reimp - */ -QModelIndex QAbstractProxyModel::buddy(const QModelIndex &index) const -{ - Q_D(const QAbstractProxyModel); - return mapFromSource(d->model->buddy(mapToSource(index))); -} - -/*! - \reimp - */ -bool QAbstractProxyModel::canFetchMore(const QModelIndex &parent) const -{ - Q_D(const QAbstractProxyModel); - return d->model->canFetchMore(mapToSource(parent)); -} - -/*! - \reimp - */ -void QAbstractProxyModel::fetchMore(const QModelIndex &parent) -{ - Q_D(QAbstractProxyModel); - d->model->fetchMore(mapToSource(parent)); -} - -/*! - \reimp - */ -void QAbstractProxyModel::sort(int column, Qt::SortOrder order) -{ - Q_D(QAbstractProxyModel); - d->model->sort(column, order); -} - -/*! - \reimp - */ -QSize QAbstractProxyModel::span(const QModelIndex &index) const -{ - Q_D(const QAbstractProxyModel); - return d->model->span(mapToSource(index)); -} - -/*! - \reimp - */ -bool QAbstractProxyModel::hasChildren(const QModelIndex &parent) const -{ - Q_D(const QAbstractProxyModel); - return d->model->hasChildren(mapToSource(parent)); -} - -/*! - \reimp - */ -QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const -{ - Q_D(const QAbstractProxyModel); - QModelIndexList list; - foreach(const QModelIndex &index, indexes) - list << mapToSource(index); - return d->model->mimeData(list); -} - -/*! - \reimp - */ -QStringList QAbstractProxyModel::mimeTypes() const -{ - Q_D(const QAbstractProxyModel); - return d->model->mimeTypes(); -} - -/*! - \reimp - */ -Qt::DropActions QAbstractProxyModel::supportedDropActions() const -{ - Q_D(const QAbstractProxyModel); - return d->model->supportedDropActions(); -} - -QT_END_NAMESPACE - -#include "moc_qabstractproxymodel.cpp" - -#endif // QT_NO_PROXYMODEL diff --git a/src/widgets/itemviews/qabstractproxymodel.h b/src/widgets/itemviews/qabstractproxymodel.h deleted file mode 100644 index a24755b556..0000000000 --- a/src/widgets/itemviews/qabstractproxymodel.h +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QABSTRACTPROXYMODEL_H -#define QABSTRACTPROXYMODEL_H - -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#ifndef QT_NO_PROXYMODEL - -class QAbstractProxyModelPrivate; -class QItemSelection; - -class Q_WIDGETS_EXPORT QAbstractProxyModel : public QAbstractItemModel -{ - Q_OBJECT - -public: - QAbstractProxyModel(QObject *parent = 0); - ~QAbstractProxyModel(); - - virtual void setSourceModel(QAbstractItemModel *sourceModel); - QAbstractItemModel *sourceModel() const; - - virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const = 0; - virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const = 0; - - virtual QItemSelection mapSelectionToSource(const QItemSelection &selection) const; - virtual QItemSelection mapSelectionFromSource(const QItemSelection &selection) const; - - bool submit(); - void revert(); - - QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const; - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - QMap itemData(const QModelIndex &index) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - - bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - bool setItemData(const QModelIndex& index, const QMap &roles); - bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole); - - QModelIndex buddy(const QModelIndex &index) const; - bool canFetchMore(const QModelIndex &parent) const; - void fetchMore(const QModelIndex &parent); - void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); - QSize span(const QModelIndex &index) const; - bool hasChildren(const QModelIndex &parent = QModelIndex()) const; - - QMimeData* mimeData(const QModelIndexList &indexes) const; - QStringList mimeTypes() const; - Qt::DropActions supportedDropActions() const; - -protected: - QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent); - -private: - Q_DECLARE_PRIVATE(QAbstractProxyModel) - Q_DISABLE_COPY(QAbstractProxyModel) - Q_PRIVATE_SLOT(d_func(), void _q_sourceModelDestroyed()) -}; - -#endif // QT_NO_PROXYMODEL - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QABSTRACTPROXYMODEL_H diff --git a/src/widgets/itemviews/qabstractproxymodel_p.h b/src/widgets/itemviews/qabstractproxymodel_p.h deleted file mode 100644 index 9bd38d1cdc..0000000000 --- a/src/widgets/itemviews/qabstractproxymodel_p.h +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QABSTRACTPROXYMODEL_P_H -#define QABSTRACTPROXYMODEL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of QAbstractItemModel*. This header file may change from version -// to version without notice, or even be removed. -// -// We mean it. -// -// - -#include "private/qabstractitemmodel_p.h" - -#ifndef QT_NO_PROXYMODEL - -QT_BEGIN_NAMESPACE - -class QAbstractProxyModelPrivate : public QAbstractItemModelPrivate -{ - Q_DECLARE_PUBLIC(QAbstractProxyModel) -public: - QAbstractProxyModelPrivate() : QAbstractItemModelPrivate(), model(0) {} - QAbstractItemModel *model; - virtual void _q_sourceModelDestroyed(); -}; - -QT_END_NAMESPACE - -#endif // QT_NO_PROXYMODEL - -#endif // QABSTRACTPROXYMODEL_P_H diff --git a/src/widgets/itemviews/qidentityproxymodel.cpp b/src/widgets/itemviews/qidentityproxymodel.cpp deleted file mode 100644 index c891565794..0000000000 --- a/src/widgets/itemviews/qidentityproxymodel.cpp +++ /dev/null @@ -1,578 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qidentityproxymodel.h" - -#ifndef QT_NO_IDENTITYPROXYMODEL - -#include "qitemselectionmodel.h" -#include - -QT_BEGIN_NAMESPACE - -class QIdentityProxyModelPrivate : public QAbstractProxyModelPrivate -{ - QIdentityProxyModelPrivate() - { - - } - - Q_DECLARE_PUBLIC(QIdentityProxyModel) - - QList layoutChangePersistentIndexes; - QModelIndexList proxyIndexes; - - void _q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end); - void _q_sourceRowsInserted(const QModelIndex &parent, int start, int end); - void _q_sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - void _q_sourceRowsRemoved(const QModelIndex &parent, int start, int end); - void _q_sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest); - void _q_sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest); - - void _q_sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end); - void _q_sourceColumnsInserted(const QModelIndex &parent, int start, int end); - void _q_sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - void _q_sourceColumnsRemoved(const QModelIndex &parent, int start, int end); - void _q_sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest); - void _q_sourceColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest); - - void _q_sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last); - - void _q_sourceLayoutAboutToBeChanged(); - void _q_sourceLayoutChanged(); - void _q_sourceModelAboutToBeReset(); - void _q_sourceModelReset(); - -}; - -/*! - \since 4.8 - \class QIdentityProxyModel - \brief The QIdentityProxyModel class proxies its source model unmodified - - \ingroup model-view - \inmodule QtWidgets - - QIdentityProxyModel can be used to forward the structure of a source model exactly, with no sorting, filtering or other transformation. - This is similar in concept to an identity matrix where A.I = A. - - Because it does no sorting or filtering, this class is most suitable to proxy models which transform the data() of the source model. - For example, a proxy model could be created to define the font used, or the background colour, or the tooltip etc. This removes the - need to implement all data handling in the same class that creates the structure of the model, and can also be used to create - re-usable components. - - This also provides a way to change the data in the case where a source model is supplied by a third party which can not be modified. - - \snippet doc/src/snippets/code/src_gui_itemviews_qidentityproxymodel.cpp 0 - - \sa QAbstractProxyModel, {Model/View Programming}, QAbstractItemModel - -*/ - -/*! - Constructs an identity model with the given \a parent. -*/ -QIdentityProxyModel::QIdentityProxyModel(QObject* parent) - : QAbstractProxyModel(*new QIdentityProxyModelPrivate, parent) -{ - -} - -/*! \internal - */ -QIdentityProxyModel::QIdentityProxyModel(QIdentityProxyModelPrivate &dd, QObject* parent) - : QAbstractProxyModel(dd, parent) -{ - -} - -/*! - Destroys this identity model. -*/ -QIdentityProxyModel::~QIdentityProxyModel() -{ -} - -/*! - \reimp - */ -int QIdentityProxyModel::columnCount(const QModelIndex& parent) const -{ - Q_ASSERT(parent.isValid() ? parent.model() == this : true); - Q_D(const QIdentityProxyModel); - return d->model->columnCount(mapToSource(parent)); -} - -/*! - \reimp - */ -bool QIdentityProxyModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) -{ - Q_ASSERT(parent.isValid() ? parent.model() == this : true); - Q_D(QIdentityProxyModel); - return d->model->dropMimeData(data, action, row, column, mapToSource(parent)); -} - -/*! - \reimp - */ -QModelIndex QIdentityProxyModel::index(int row, int column, const QModelIndex& parent) const -{ - Q_ASSERT(parent.isValid() ? parent.model() == this : true); - Q_D(const QIdentityProxyModel); - if (!hasIndex(row, column, parent)) - return QModelIndex(); - const QModelIndex sourceParent = mapToSource(parent); - const QModelIndex sourceIndex = d->model->index(row, column, sourceParent); - Q_ASSERT(sourceIndex.isValid()); - return mapFromSource(sourceIndex); -} - -/*! - \reimp - */ -bool QIdentityProxyModel::insertColumns(int column, int count, const QModelIndex& parent) -{ - Q_ASSERT(parent.isValid() ? parent.model() == this : true); - Q_D(QIdentityProxyModel); - return d->model->insertColumns(column, count, mapToSource(parent)); -} - -/*! - \reimp - */ -bool QIdentityProxyModel::insertRows(int row, int count, const QModelIndex& parent) -{ - Q_ASSERT(parent.isValid() ? parent.model() == this : true); - Q_D(QIdentityProxyModel); - return d->model->insertRows(row, count, mapToSource(parent)); -} - -/*! - \reimp - */ -QModelIndex QIdentityProxyModel::mapFromSource(const QModelIndex& sourceIndex) const -{ - Q_D(const QIdentityProxyModel); - if (!d->model || !sourceIndex.isValid()) - return QModelIndex(); - - Q_ASSERT(sourceIndex.model() == d->model); - return createIndex(sourceIndex.row(), sourceIndex.column(), sourceIndex.internalPointer()); -} - -/*! - \reimp - */ -QItemSelection QIdentityProxyModel::mapSelectionFromSource(const QItemSelection& selection) const -{ - Q_D(const QIdentityProxyModel); - QItemSelection proxySelection; - - if (!d->model) - return proxySelection; - - QItemSelection::const_iterator it = selection.constBegin(); - const QItemSelection::const_iterator end = selection.constEnd(); - for ( ; it != end; ++it) { - Q_ASSERT(it->model() == d->model); - const QItemSelectionRange range(mapFromSource(it->topLeft()), mapFromSource(it->bottomRight())); - proxySelection.append(range); - } - - return proxySelection; -} - -/*! - \reimp - */ -QItemSelection QIdentityProxyModel::mapSelectionToSource(const QItemSelection& selection) const -{ - Q_D(const QIdentityProxyModel); - QItemSelection sourceSelection; - - if (!d->model) - return sourceSelection; - - QItemSelection::const_iterator it = selection.constBegin(); - const QItemSelection::const_iterator end = selection.constEnd(); - for ( ; it != end; ++it) { - Q_ASSERT(it->model() == this); - const QItemSelectionRange range(mapToSource(it->topLeft()), mapToSource(it->bottomRight())); - sourceSelection.append(range); - } - - return sourceSelection; -} - -/*! - \reimp - */ -QModelIndex QIdentityProxyModel::mapToSource(const QModelIndex& proxyIndex) const -{ - Q_D(const QIdentityProxyModel); - if (!d->model || !proxyIndex.isValid()) - return QModelIndex(); - Q_ASSERT(proxyIndex.model() == this); - return d->model->createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer()); -} - -/*! - \reimp - */ -QModelIndexList QIdentityProxyModel::match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const -{ - Q_D(const QIdentityProxyModel); - Q_ASSERT(start.isValid() ? start.model() == this : true); - if (!d->model) - return QModelIndexList(); - - const QModelIndexList sourceList = d->model->match(mapToSource(start), role, value, hits, flags); - QModelIndexList::const_iterator it = sourceList.constBegin(); - const QModelIndexList::const_iterator end = sourceList.constEnd(); - QModelIndexList proxyList; - for ( ; it != end; ++it) - proxyList.append(mapFromSource(*it)); - return proxyList; -} - -/*! - \reimp - */ -QModelIndex QIdentityProxyModel::parent(const QModelIndex& child) const -{ - Q_ASSERT(child.isValid() ? child.model() == this : true); - const QModelIndex sourceIndex = mapToSource(child); - const QModelIndex sourceParent = sourceIndex.parent(); - return mapFromSource(sourceParent); -} - -/*! - \reimp - */ -bool QIdentityProxyModel::removeColumns(int column, int count, const QModelIndex& parent) -{ - Q_ASSERT(parent.isValid() ? parent.model() == this : true); - Q_D(QIdentityProxyModel); - return d->model->removeColumns(column, count, mapToSource(parent)); -} - -/*! - \reimp - */ -bool QIdentityProxyModel::removeRows(int row, int count, const QModelIndex& parent) -{ - Q_ASSERT(parent.isValid() ? parent.model() == this : true); - Q_D(QIdentityProxyModel); - return d->model->removeRows(row, count, mapToSource(parent)); -} - -/*! - \reimp - */ -int QIdentityProxyModel::rowCount(const QModelIndex& parent) const -{ - Q_ASSERT(parent.isValid() ? parent.model() == this : true); - Q_D(const QIdentityProxyModel); - return d->model->rowCount(mapToSource(parent)); -} - -/*! - \reimp - */ -void QIdentityProxyModel::setSourceModel(QAbstractItemModel* sourceModel) -{ - beginResetModel(); - - if (sourceModel) { - disconnect(sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)), - this, SLOT(_q_sourceRowsAboutToBeInserted(const QModelIndex &, int, int))); - disconnect(sourceModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(_q_sourceRowsInserted(const QModelIndex &, int, int))); - disconnect(sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), - this, SLOT(_q_sourceRowsAboutToBeRemoved(const QModelIndex &, int, int))); - disconnect(sourceModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - this, SLOT(_q_sourceRowsRemoved(const QModelIndex &, int, int))); - disconnect(sourceModel, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)), - this, SLOT(_q_sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); - disconnect(sourceModel, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), - this, SLOT(_q_sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); - disconnect(sourceModel, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)), - this, SLOT(_q_sourceColumnsAboutToBeInserted(const QModelIndex &, int, int))); - disconnect(sourceModel, SIGNAL(columnsInserted(const QModelIndex &, int, int)), - this, SLOT(_q_sourceColumnsInserted(const QModelIndex &, int, int))); - disconnect(sourceModel, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)), - this, SLOT(_q_sourceColumnsAboutToBeRemoved(const QModelIndex &, int, int))); - disconnect(sourceModel, SIGNAL(columnsRemoved(const QModelIndex &, int, int)), - this, SLOT(_q_sourceColumnsRemoved(const QModelIndex &, int, int))); - disconnect(sourceModel, SIGNAL(columnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)), - this, SLOT(_q_sourceColumnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); - disconnect(sourceModel, SIGNAL(columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), - this, SLOT(_q_sourceColumnsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); - disconnect(sourceModel, SIGNAL(modelAboutToBeReset()), - this, SLOT(_q_sourceModelAboutToBeReset())); - disconnect(sourceModel, SIGNAL(modelReset()), - this, SLOT(_q_sourceModelReset())); - disconnect(sourceModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), - this, SLOT(_q_sourceDataChanged(const QModelIndex &, const QModelIndex &))); - disconnect(sourceModel, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int))); - disconnect(sourceModel, SIGNAL(layoutAboutToBeChanged()), - this, SLOT(_q_sourceLayoutAboutToBeChanged())); - disconnect(sourceModel, SIGNAL(layoutChanged()), - this, SLOT(_q_sourceLayoutChanged())); - } - - QAbstractProxyModel::setSourceModel(sourceModel); - - if (sourceModel) { - connect(sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)), - SLOT(_q_sourceRowsAboutToBeInserted(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - SLOT(_q_sourceRowsInserted(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), - SLOT(_q_sourceRowsAboutToBeRemoved(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - SLOT(_q_sourceRowsRemoved(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)), - SLOT(_q_sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); - connect(sourceModel, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), - SLOT(_q_sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); - connect(sourceModel, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)), - SLOT(_q_sourceColumnsAboutToBeInserted(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(columnsInserted(const QModelIndex &, int, int)), - SLOT(_q_sourceColumnsInserted(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)), - SLOT(_q_sourceColumnsAboutToBeRemoved(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(columnsRemoved(const QModelIndex &, int, int)), - SLOT(_q_sourceColumnsRemoved(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(columnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)), - SLOT(_q_sourceColumnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); - connect(sourceModel, SIGNAL(columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), - SLOT(_q_sourceColumnsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); - connect(sourceModel, SIGNAL(modelAboutToBeReset()), - SLOT(_q_sourceModelAboutToBeReset())); - connect(sourceModel, SIGNAL(modelReset()), - SLOT(_q_sourceModelReset())); - connect(sourceModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), - SLOT(_q_sourceDataChanged(const QModelIndex &, const QModelIndex &))); - connect(sourceModel, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int))); - connect(sourceModel, SIGNAL(layoutAboutToBeChanged()), - SLOT(_q_sourceLayoutAboutToBeChanged())); - connect(sourceModel, SIGNAL(layoutChanged()), - SLOT(_q_sourceLayoutChanged())); - } - - endResetModel(); -} - -void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end) -{ - Q_ASSERT(parent.isValid() ? parent.model() == model : true); - Q_Q(QIdentityProxyModel); - q->beginInsertColumns(q->mapFromSource(parent), start, end); -} - -void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest) -{ - Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true); - Q_ASSERT(destParent.isValid() ? destParent.model() == model : true); - Q_Q(QIdentityProxyModel); - q->beginMoveColumns(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destParent), dest); -} - -void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end) -{ - Q_ASSERT(parent.isValid() ? parent.model() == model : true); - Q_Q(QIdentityProxyModel); - q->beginRemoveColumns(q->mapFromSource(parent), start, end); -} - -void QIdentityProxyModelPrivate::_q_sourceColumnsInserted(const QModelIndex &parent, int start, int end) -{ - Q_ASSERT(parent.isValid() ? parent.model() == model : true); - Q_Q(QIdentityProxyModel); - Q_UNUSED(parent) - Q_UNUSED(start) - Q_UNUSED(end) - q->endInsertColumns(); -} - -void QIdentityProxyModelPrivate::_q_sourceColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest) -{ - Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true); - Q_ASSERT(destParent.isValid() ? destParent.model() == model : true); - Q_Q(QIdentityProxyModel); - Q_UNUSED(sourceParent) - Q_UNUSED(sourceStart) - Q_UNUSED(sourceEnd) - Q_UNUSED(destParent) - Q_UNUSED(dest) - q->endMoveColumns(); -} - -void QIdentityProxyModelPrivate::_q_sourceColumnsRemoved(const QModelIndex &parent, int start, int end) -{ - Q_ASSERT(parent.isValid() ? parent.model() == model : true); - Q_Q(QIdentityProxyModel); - Q_UNUSED(parent) - Q_UNUSED(start) - Q_UNUSED(end) - q->endRemoveColumns(); -} - -void QIdentityProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - Q_ASSERT(topLeft.isValid() ? topLeft.model() == model : true); - Q_ASSERT(bottomRight.isValid() ? bottomRight.model() == model : true); - Q_Q(QIdentityProxyModel); - q->dataChanged(q->mapFromSource(topLeft), q->mapFromSource(bottomRight)); -} - -void QIdentityProxyModelPrivate::_q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last) -{ - Q_Q(QIdentityProxyModel); - q->headerDataChanged(orientation, first, last); -} - -void QIdentityProxyModelPrivate::_q_sourceLayoutAboutToBeChanged() -{ - Q_Q(QIdentityProxyModel); - - foreach(const QPersistentModelIndex &proxyPersistentIndex, q->persistentIndexList()) { - proxyIndexes << proxyPersistentIndex; - Q_ASSERT(proxyPersistentIndex.isValid()); - const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex); - Q_ASSERT(srcPersistentIndex.isValid()); - layoutChangePersistentIndexes << srcPersistentIndex; - } - - q->layoutAboutToBeChanged(); -} - -void QIdentityProxyModelPrivate::_q_sourceLayoutChanged() -{ - Q_Q(QIdentityProxyModel); - - for (int i = 0; i < proxyIndexes.size(); ++i) { - q->changePersistentIndex(proxyIndexes.at(i), q->mapFromSource(layoutChangePersistentIndexes.at(i))); - } - - layoutChangePersistentIndexes.clear(); - proxyIndexes.clear(); - - q->layoutChanged(); -} - -void QIdentityProxyModelPrivate::_q_sourceModelAboutToBeReset() -{ - Q_Q(QIdentityProxyModel); - q->beginResetModel(); -} - -void QIdentityProxyModelPrivate::_q_sourceModelReset() -{ - Q_Q(QIdentityProxyModel); - q->endResetModel(); -} - -void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end) -{ - Q_ASSERT(parent.isValid() ? parent.model() == model : true); - Q_Q(QIdentityProxyModel); - q->beginInsertRows(q->mapFromSource(parent), start, end); -} - -void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest) -{ - Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true); - Q_ASSERT(destParent.isValid() ? destParent.model() == model : true); - Q_Q(QIdentityProxyModel); - q->beginMoveRows(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destParent), dest); -} - -void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) -{ - Q_ASSERT(parent.isValid() ? parent.model() == model : true); - Q_Q(QIdentityProxyModel); - q->beginRemoveRows(q->mapFromSource(parent), start, end); -} - -void QIdentityProxyModelPrivate::_q_sourceRowsInserted(const QModelIndex &parent, int start, int end) -{ - Q_ASSERT(parent.isValid() ? parent.model() == model : true); - Q_Q(QIdentityProxyModel); - Q_UNUSED(parent) - Q_UNUSED(start) - Q_UNUSED(end) - q->endInsertRows(); -} - -void QIdentityProxyModelPrivate::_q_sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest) -{ - Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true); - Q_ASSERT(destParent.isValid() ? destParent.model() == model : true); - Q_Q(QIdentityProxyModel); - Q_UNUSED(sourceParent) - Q_UNUSED(sourceStart) - Q_UNUSED(sourceEnd) - Q_UNUSED(destParent) - Q_UNUSED(dest) - q->endMoveRows(); -} - -void QIdentityProxyModelPrivate::_q_sourceRowsRemoved(const QModelIndex &parent, int start, int end) -{ - Q_ASSERT(parent.isValid() ? parent.model() == model : true); - Q_Q(QIdentityProxyModel); - Q_UNUSED(parent) - Q_UNUSED(start) - Q_UNUSED(end) - q->endRemoveRows(); -} - -QT_END_NAMESPACE - -#include "moc_qidentityproxymodel.cpp" - -#endif // QT_NO_IDENTITYPROXYMODEL diff --git a/src/widgets/itemviews/qidentityproxymodel.h b/src/widgets/itemviews/qidentityproxymodel.h deleted file mode 100644 index 8a8422244f..0000000000 --- a/src/widgets/itemviews/qidentityproxymodel.h +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QIDENTITYPROXYMODEL_H -#define QIDENTITYPROXYMODEL_H - -#include - -#ifndef QT_NO_IDENTITYPROXYMODEL - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QIdentityProxyModelPrivate; - -class Q_WIDGETS_EXPORT QIdentityProxyModel : public QAbstractProxyModel -{ - Q_OBJECT -public: - explicit QIdentityProxyModel(QObject* parent = 0); - ~QIdentityProxyModel(); - - int columnCount(const QModelIndex& parent = QModelIndex()) const; - QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; - QModelIndex mapFromSource(const QModelIndex& sourceIndex) const; - QModelIndex mapToSource(const QModelIndex& proxyIndex) const; - QModelIndex parent(const QModelIndex& child) const; - int rowCount(const QModelIndex& parent = QModelIndex()) const; - bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent); - - QItemSelection mapSelectionFromSource(const QItemSelection& selection) const; - QItemSelection mapSelectionToSource(const QItemSelection& selection) const; - QModelIndexList match(const QModelIndex& start, int role, const QVariant& value, int hits = 1, Qt::MatchFlags flags = Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const; - void setSourceModel(QAbstractItemModel* sourceModel); - - bool insertColumns(int column, int count, const QModelIndex& parent = QModelIndex()); - bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()); - bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()); - bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()); - -protected: - QIdentityProxyModel(QIdentityProxyModelPrivate &dd, QObject* parent); - -private: - Q_DECLARE_PRIVATE(QIdentityProxyModel) - Q_DISABLE_COPY(QIdentityProxyModel) - - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsInserted(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeRemoved(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsRemoved(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)) - - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeInserted(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsInserted(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsRemoved(QModelIndex,int,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int)) - - Q_PRIVATE_SLOT(d_func(), void _q_sourceDataChanged(QModelIndex,QModelIndex)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last)) - - Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutAboutToBeChanged()) - Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutChanged()) - Q_PRIVATE_SLOT(d_func(), void _q_sourceModelAboutToBeReset()) - Q_PRIVATE_SLOT(d_func(), void _q_sourceModelReset()) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QT_NO_IDENTITYPROXYMODEL - -#endif // QIDENTITYPROXYMODEL_H - diff --git a/src/widgets/itemviews/qitemselectionmodel.cpp b/src/widgets/itemviews/qitemselectionmodel.cpp deleted file mode 100644 index 08470a4300..0000000000 --- a/src/widgets/itemviews/qitemselectionmodel.cpp +++ /dev/null @@ -1,1641 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qitemselectionmodel.h" -#include -#include - -#ifndef QT_NO_ITEMVIEWS - -QT_BEGIN_NAMESPACE - -/*! - \class QItemSelectionRange - - \brief The QItemSelectionRange class manages information about a - range of selected items in a model. - - \ingroup model-view - \inmodule QtWidgets - - A QItemSelectionRange contains information about a range of - selected items in a model. A range of items is a contiguous array - of model items, extending to cover a number of adjacent rows and - columns with a common parent item; this can be visualized as a - two-dimensional block of cells in a table. A selection range has a - top(), left() a bottom(), right() and a parent(). - - The QItemSelectionRange class is one of the \l{Model/View Classes} - and is part of Qt's \l{Model/View Programming}{model/view framework}. - - The model items contained in the selection range can be obtained - using the indexes() function. Use QItemSelectionModel::selectedIndexes() - to get a list of all selected items for a view. - - You can determine whether a given model item lies within a - particular range by using the contains() function. Ranges can also - be compared using the overloaded operators for equality and - inequality, and the intersects() function allows you to determine - whether two ranges overlap. - - \sa {Model/View Programming}, QAbstractItemModel, QItemSelection, - QItemSelectionModel -*/ - -/*! - \fn QItemSelectionRange::QItemSelectionRange() - - Constructs an empty selection range. -*/ - -/*! - \fn QItemSelectionRange::QItemSelectionRange(const QItemSelectionRange &other) - - Copy constructor. Constructs a new selection range with the same contents - as the \a other range given. - -*/ - -/*! - \fn QItemSelectionRange::QItemSelectionRange(const QModelIndex &topLeft, const QModelIndex &bottomRight) - - Constructs a new selection range containing only the index specified - by the \a topLeft and the index \a bottomRight. - -*/ - -/*! - \fn QItemSelectionRange::QItemSelectionRange(const QModelIndex &index) - - Constructs a new selection range containing only the model item specified - by the model index \a index. -*/ - -/*! - \fn int QItemSelectionRange::top() const - - Returns the row index corresponding to the uppermost selected row in the - selection range. - -*/ - -/*! - \fn int QItemSelectionRange::left() const - - Returns the column index corresponding to the leftmost selected column in the - selection range. -*/ - -/*! - \fn int QItemSelectionRange::bottom() const - - Returns the row index corresponding to the lowermost selected row in the - selection range. - -*/ - -/*! - \fn int QItemSelectionRange::right() const - - Returns the column index corresponding to the rightmost selected column in - the selection range. - -*/ - -/*! - \fn int QItemSelectionRange::width() const - - Returns the number of selected columns in the selection range. - -*/ - -/*! - \fn int QItemSelectionRange::height() const - - Returns the number of selected rows in the selection range. - -*/ - -/*! - \fn const QAbstractItemModel *QItemSelectionRange::model() const - - Returns the model that the items in the selection range belong to. -*/ - -/*! - \fn QModelIndex QItemSelectionRange::topLeft() const - - Returns the index for the item located at the top-left corner of - the selection range. - - \sa top(), left(), bottomRight() -*/ - -/*! - \fn QModelIndex QItemSelectionRange::bottomRight() const - - Returns the index for the item located at the bottom-right corner - of the selection range. - - \sa bottom(), right(), topLeft() -*/ - -/*! - \fn QModelIndex QItemSelectionRange::parent() const - - Returns the parent model item index of the items in the selection range. - -*/ - -/*! - \fn bool QItemSelectionRange::contains(const QModelIndex &index) const - - Returns true if the model item specified by the \a index lies within the - range of selected items; otherwise returns false. -*/ - -/*! - \fn bool QItemSelectionRange::contains(int row, int column, - const QModelIndex &parentIndex) const - \overload - - Returns true if the model item specified by (\a row, \a column) - and with \a parentIndex as the parent item lies within the range - of selected items; otherwise returns false. -*/ - -/*! - \fn bool QItemSelectionRange::intersects(const QItemSelectionRange &other) const - - Returns true if this selection range intersects (overlaps with) the \a other - range given; otherwise returns false. - -*/ -bool QItemSelectionRange::intersects(const QItemSelectionRange &other) const -{ - return (isValid() && other.isValid() - && parent() == other.parent() - && model() == other.model() - && ((top() <= other.top() && bottom() >= other.top()) - || (top() >= other.top() && top() <= other.bottom())) - && ((left() <= other.left() && right() >= other.left()) - || (left() >= other.left() && left() <= other.right()))); -} - -/*! - \fn QItemSelectionRange QItemSelectionRange::intersect(const QItemSelectionRange &other) const - \obsolete - - Use intersected(\a other) instead. -*/ - -/*! - \fn QItemSelectionRange QItemSelectionRange::intersected(const QItemSelectionRange &other) const - \since 4.2 - - Returns a new selection range containing only the items that are found in - both the selection range and the \a other selection range. -*/ - -QItemSelectionRange QItemSelectionRange::intersect(const QItemSelectionRange &other) const -{ - if (model() == other.model() && parent() == other.parent()) { - QModelIndex topLeft = model()->index(qMax(top(), other.top()), - qMax(left(), other.left()), - other.parent()); - QModelIndex bottomRight = model()->index(qMin(bottom(), other.bottom()), - qMin(right(), other.right()), - other.parent()); - return QItemSelectionRange(topLeft, bottomRight); - } - return QItemSelectionRange(); -} - -/*! - \fn bool QItemSelectionRange::operator==(const QItemSelectionRange &other) const - - Returns true if the selection range is exactly the same as the \a other - range given; otherwise returns false. - -*/ - -/*! - \fn bool QItemSelectionRange::operator!=(const QItemSelectionRange &other) const - - Returns true if the selection range differs from the \a other range given; - otherwise returns false. - -*/ - -/*! - \fn bool QItemSelectionRange::isValid() const - - Returns true if the selection range is valid; otherwise returns false. - -*/ - -/* - \internal - - utility function for getting the indexes from a range - it avoid concatenating list and works on one - */ - -static void indexesFromRange(const QItemSelectionRange &range, QModelIndexList &result) -{ - if (range.isValid() && range.model()) { - for (int column = range.left(); column <= range.right(); ++column) { - for (int row = range.top(); row <= range.bottom(); ++row) { - QModelIndex index = range.model()->index(row, column, range.parent()); - Qt::ItemFlags flags = range.model()->flags(index); - if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled)) - result.append(index); - } - } - } -} - -/*! - Returns true if the selection range contains no selectable item - \since 4.7 -*/ - -bool QItemSelectionRange::isEmpty() const -{ - if (!isValid() || !model()) - return true; - - for (int column = left(); column <= right(); ++column) { - for (int row = top(); row <= bottom(); ++row) { - QModelIndex index = model()->index(row, column, parent()); - Qt::ItemFlags flags = model()->flags(index); - if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled)) - return false; - } - } - return true; -} - -/*! - Returns the list of model index items stored in the selection. -*/ - -QModelIndexList QItemSelectionRange::indexes() const -{ - QModelIndexList result; - indexesFromRange(*this, result); - return result; -} - -/*! - \class QItemSelection - - \brief The QItemSelection class manages information about selected items in a model. - - \ingroup model-view - \inmodule QtWidgets - - A QItemSelection describes the items in a model that have been - selected by the user. A QItemSelection is basically a list of - selection ranges, see QItemSelectionRange. It provides functions for - creating and manipulating selections, and selecting a range of items - from a model. - - The QItemSelection class is one of the \l{Model/View Classes} - and is part of Qt's \l{Model/View Programming}{model/view framework}. - - An item selection can be constructed and initialized to contain a - range of items from an existing model. The following example constructs - a selection that contains a range of items from the given \c model, - beginning at the \c topLeft, and ending at the \c bottomRight. - - \snippet doc/src/snippets/code/src_gui_itemviews_qitemselectionmodel.cpp 0 - - An empty item selection can be constructed, and later populated as - required. So, if the model is going to be unavailable when we construct - the item selection, we can rewrite the above code in the following way: - - \snippet doc/src/snippets/code/src_gui_itemviews_qitemselectionmodel.cpp 1 - - QItemSelection saves memory, and avoids unnecessary work, by working with - selection ranges rather than recording the model item index for each - item in the selection. Generally, an instance of this class will contain - a list of non-overlapping selection ranges. - - Use merge() to merge one item selection into another without making - overlapping ranges. Use split() to split one selection range into - smaller ranges based on a another selection range. - - \sa {Model/View Programming}, QItemSelectionModel -*/ - -/*! - \fn QItemSelection::QItemSelection() - - Constructs an empty selection. -*/ - -/*! - Constructs an item selection that extends from the top-left model item, - specified by the \a topLeft index, to the bottom-right item, specified - by \a bottomRight. -*/ -QItemSelection::QItemSelection(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - select(topLeft, bottomRight); -} - -/*! - Adds the items in the range that extends from the top-left model - item, specified by the \a topLeft index, to the bottom-right item, - specified by \a bottomRight to the list. - - \note \a topLeft and \a bottomRight must have the same parent. -*/ -void QItemSelection::select(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - if (!topLeft.isValid() || !bottomRight.isValid()) - return; - - if ((topLeft.model() != bottomRight.model()) - || topLeft.parent() != bottomRight.parent()) { - qWarning("Can't select indexes from different model or with different parents"); - return; - } - if (topLeft.row() > bottomRight.row() || topLeft.column() > bottomRight.column()) { - int top = qMin(topLeft.row(), bottomRight.row()); - int bottom = qMax(topLeft.row(), bottomRight.row()); - int left = qMin(topLeft.column(), bottomRight.column()); - int right = qMax(topLeft.column(), bottomRight.column()); - QModelIndex tl = topLeft.sibling(top, left); - QModelIndex br = bottomRight.sibling(bottom, right); - append(QItemSelectionRange(tl, br)); - return; - } - append(QItemSelectionRange(topLeft, bottomRight)); -} - -/*! - Returns true if the selection contains the given \a index; otherwise - returns false. -*/ - -bool QItemSelection::contains(const QModelIndex &index) const -{ - if (index.flags() & Qt::ItemIsSelectable) { - QList::const_iterator it = begin(); - for (; it != end(); ++it) - if ((*it).contains(index)) - return true; - } - return false; -} - -/*! - Returns a list of model indexes that correspond to the selected items. -*/ - -QModelIndexList QItemSelection::indexes() const -{ - QModelIndexList result; - QList::const_iterator it = begin(); - for (; it != end(); ++it) - indexesFromRange(*it, result); - return result; -} - -/*! - Merges the \a other selection with this QItemSelection using the - \a command given. This method guarantees that no ranges are overlapping. - - Note that only QItemSelectionModel::Select, - QItemSelectionModel::Deselect, and QItemSelectionModel::Toggle are - supported. - - \sa split() -*/ -void QItemSelection::merge(const QItemSelection &other, QItemSelectionModel::SelectionFlags command) -{ - if (other.isEmpty() || - !(command & QItemSelectionModel::Select || - command & QItemSelectionModel::Deselect || - command & QItemSelectionModel::Toggle)) - return; - - QItemSelection newSelection = other; - // Collect intersections - QItemSelection intersections; - QItemSelection::iterator it = newSelection.begin(); - while (it != newSelection.end()) { - if (!(*it).isValid()) { - it = newSelection.erase(it); - continue; - } - for (int t = 0; t < count(); ++t) { - if ((*it).intersects(at(t))) - intersections.append(at(t).intersected(*it)); - } - ++it; - } - - // Split the old (and new) ranges using the intersections - for (int i = 0; i < intersections.count(); ++i) { // for each intersection - for (int t = 0; t < count();) { // splitt each old range - if (at(t).intersects(intersections.at(i))) { - split(at(t), intersections.at(i), this); - removeAt(t); - } else { - ++t; - } - } - // only split newSelection if Toggle is specified - for (int n = 0; (command & QItemSelectionModel::Toggle) && n < newSelection.count();) { - if (newSelection.at(n).intersects(intersections.at(i))) { - split(newSelection.at(n), intersections.at(i), &newSelection); - newSelection.removeAt(n); - } else { - ++n; - } - } - } - // do not add newSelection for Deselect - if (!(command & QItemSelectionModel::Deselect)) - operator+=(newSelection); -} - -/*! - Splits the selection \a range using the selection \a other range. - Removes all items in \a other from \a range and puts the result in \a result. - This can be compared with the semantics of the \e subtract operation of a set. - \sa merge() -*/ - -void QItemSelection::split(const QItemSelectionRange &range, - const QItemSelectionRange &other, QItemSelection *result) -{ - if (range.parent() != other.parent() || range.model() != other.model()) - return; - - QModelIndex parent = other.parent(); - int top = range.top(); - int left = range.left(); - int bottom = range.bottom(); - int right = range.right(); - int other_top = other.top(); - int other_left = other.left(); - int other_bottom = other.bottom(); - int other_right = other.right(); - const QAbstractItemModel *model = range.model(); - Q_ASSERT(model); - if (other_top > top) { - QModelIndex tl = model->index(top, left, parent); - QModelIndex br = model->index(other_top - 1, right, parent); - result->append(QItemSelectionRange(tl, br)); - top = other_top; - } - if (other_bottom < bottom) { - QModelIndex tl = model->index(other_bottom + 1, left, parent); - QModelIndex br = model->index(bottom, right, parent); - result->append(QItemSelectionRange(tl, br)); - bottom = other_bottom; - } - if (other_left > left) { - QModelIndex tl = model->index(top, left, parent); - QModelIndex br = model->index(bottom, other_left - 1, parent); - result->append(QItemSelectionRange(tl, br)); - left = other_left; - } - if (other_right < right) { - QModelIndex tl = model->index(top, other_right + 1, parent); - QModelIndex br = model->index(bottom, right, parent); - result->append(QItemSelectionRange(tl, br)); - right = other_right; - } -} - - -void QItemSelectionModelPrivate::initModel(QAbstractItemModel *model) -{ - this->model = model; - if (model) { - Q_Q(QItemSelectionModel); - QObject::connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); - QObject::connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - q, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int))); - QObject::connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - q, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int))); - QObject::connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - q, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int))); - QObject::connect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - q, SLOT(_q_layoutAboutToBeChanged())); - QObject::connect(model, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - q, SLOT(_q_layoutAboutToBeChanged())); - QObject::connect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), - q, SLOT(_q_layoutChanged())); - QObject::connect(model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), - q, SLOT(_q_layoutChanged())); - QObject::connect(model, SIGNAL(layoutAboutToBeChanged()), - q, SLOT(_q_layoutAboutToBeChanged())); - QObject::connect(model, SIGNAL(layoutChanged()), - q, SLOT(_q_layoutChanged())); - } -} - -/*! - \internal - - returns a QItemSelection where all ranges have been expanded to: - Rows: left: 0 and right: columnCount()-1 - Columns: top: 0 and bottom: rowCount()-1 -*/ - -QItemSelection QItemSelectionModelPrivate::expandSelection(const QItemSelection &selection, - QItemSelectionModel::SelectionFlags command) const -{ - if (selection.isEmpty() && !((command & QItemSelectionModel::Rows) || - (command & QItemSelectionModel::Columns))) - return selection; - - QItemSelection expanded; - if (command & QItemSelectionModel::Rows) { - for (int i = 0; i < selection.count(); ++i) { - QModelIndex parent = selection.at(i).parent(); - int colCount = model->columnCount(parent); - QModelIndex tl = model->index(selection.at(i).top(), 0, parent); - QModelIndex br = model->index(selection.at(i).bottom(), colCount - 1, parent); - //we need to merge because the same row could have already been inserted - expanded.merge(QItemSelection(tl, br), QItemSelectionModel::Select); - } - } - if (command & QItemSelectionModel::Columns) { - for (int i = 0; i < selection.count(); ++i) { - QModelIndex parent = selection.at(i).parent(); - int rowCount = model->rowCount(parent); - QModelIndex tl = model->index(0, selection.at(i).left(), parent); - QModelIndex br = model->index(rowCount - 1, selection.at(i).right(), parent); - //we need to merge because the same column could have already been inserted - expanded.merge(QItemSelection(tl, br), QItemSelectionModel::Select); - } - } - return expanded; -} - -/*! - \internal -*/ -void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &parent, - int start, int end) -{ - Q_Q(QItemSelectionModel); - finalize(); - - // update current index - if (currentIndex.isValid() && parent == currentIndex.parent() - && currentIndex.row() >= start && currentIndex.row() <= end) { - QModelIndex old = currentIndex; - if (start > 0) // there are rows left above the change - currentIndex = model->index(start - 1, old.column(), parent); - else if (model && end < model->rowCount(parent) - 1) // there are rows left below the change - currentIndex = model->index(end + 1, old.column(), parent); - else // there are no rows left in the table - currentIndex = QModelIndex(); - emit q->currentChanged(currentIndex, old); - emit q->currentRowChanged(currentIndex, old); - if (currentIndex.column() != old.column()) - emit q->currentColumnChanged(currentIndex, old); - } - - QItemSelection deselected; - QItemSelection newParts; - QItemSelection::iterator it = ranges.begin(); - while (it != ranges.end()) { - if (it->topLeft().parent() != parent) { // Check parents until reaching root or contained in range - QModelIndex itParent = it->topLeft().parent(); - while (itParent.isValid() && itParent.parent() != parent) - itParent = itParent.parent(); - - if (itParent.isValid() && start <= itParent.row() && itParent.row() <= end) { - deselected.append(*it); - it = ranges.erase(it); - } else { - ++it; - } - } else if (start <= it->bottom() && it->bottom() <= end // Full inclusion - && start <= it->top() && it->top() <= end) { - deselected.append(*it); - it = ranges.erase(it); - } else if (start <= it->top() && it->top() <= end) { // Top intersection - deselected.append(QItemSelectionRange(it->topLeft(), model->index(end, it->left(), it->parent()))); - *it = QItemSelectionRange(model->index(end + 1, it->left(), it->parent()), it->bottomRight()); - ++it; - } else if (start <= it->bottom() && it->bottom() <= end) { // Bottom intersection - deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), it->bottomRight())); - *it = QItemSelectionRange(it->topLeft(), model->index(start - 1, it->right(), it->parent())); - ++it; - } else if (it->top() < start && end < it->bottom()) { // Middle intersection - // If the parent contains (1, 2, 3, 4, 5, 6, 7, 8) and [3, 4, 5, 6] is selected, - // and [4, 5] is removed, we need to split [3, 4, 5, 6] into [3], [4, 5] and [6]. - // [4, 5] is appended to deselected, and [3] and [6] remain part of the selection - // in ranges. - const QItemSelectionRange removedRange(model->index(start, it->right(), it->parent()), - model->index(end, it->left(), it->parent())); - deselected.append(removedRange); - QItemSelection::split(*it, removedRange, &newParts); - it = ranges.erase(it); - } else - ++it; - } - ranges.append(newParts); - - if (!deselected.isEmpty()) - emit q->selectionChanged(QItemSelection(), deselected); -} - -/*! - \internal -*/ -void QItemSelectionModelPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &parent, - int start, int end) -{ - Q_Q(QItemSelectionModel); - - // update current index - if (currentIndex.isValid() && parent == currentIndex.parent() - && currentIndex.column() >= start && currentIndex.column() <= end) { - QModelIndex old = currentIndex; - if (start > 0) // there are columns to the left of the change - currentIndex = model->index(old.row(), start - 1, parent); - else if (model && end < model->columnCount() - 1) // there are columns to the right of the change - currentIndex = model->index(old.row(), end + 1, parent); - else // there are no columns left in the table - currentIndex = QModelIndex(); - emit q->currentChanged(currentIndex, old); - if (currentIndex.row() != old.row()) - emit q->currentRowChanged(currentIndex, old); - emit q->currentColumnChanged(currentIndex, old); - } - - // update selections - QModelIndex tl = model->index(0, start, parent); - QModelIndex br = model->index(model->rowCount(parent) - 1, end, parent); - q->select(QItemSelection(tl, br), QItemSelectionModel::Deselect); - finalize(); -} - -/*! - \internal - - Split selection ranges if columns are about to be inserted in the middle. -*/ -void QItemSelectionModelPrivate::_q_columnsAboutToBeInserted(const QModelIndex &parent, - int start, int end) -{ - Q_UNUSED(end); - finalize(); - QList split; - QList::iterator it = ranges.begin(); - for (; it != ranges.end(); ) { - if ((*it).isValid() && (*it).parent() == parent - && (*it).left() < start && (*it).right() >= start) { - QModelIndex bottomMiddle = model->index((*it).bottom(), start - 1, (*it).parent()); - QItemSelectionRange left((*it).topLeft(), bottomMiddle); - QModelIndex topMiddle = model->index((*it).top(), start, (*it).parent()); - QItemSelectionRange right(topMiddle, (*it).bottomRight()); - it = ranges.erase(it); - split.append(left); - split.append(right); - } else { - ++it; - } - } - ranges += split; -} - -/*! - \internal - - Split selection ranges if rows are about to be inserted in the middle. -*/ -void QItemSelectionModelPrivate::_q_rowsAboutToBeInserted(const QModelIndex &parent, - int start, int end) -{ - Q_UNUSED(end); - finalize(); - QList split; - QList::iterator it = ranges.begin(); - for (; it != ranges.end(); ) { - if ((*it).isValid() && (*it).parent() == parent - && (*it).top() < start && (*it).bottom() >= start) { - QModelIndex middleRight = model->index(start - 1, (*it).right(), (*it).parent()); - QItemSelectionRange top((*it).topLeft(), middleRight); - QModelIndex middleLeft = model->index(start, (*it).left(), (*it).parent()); - QItemSelectionRange bottom(middleLeft, (*it).bottomRight()); - it = ranges.erase(it); - split.append(top); - split.append(bottom); - } else { - ++it; - } - } - ranges += split; -} - -/*! - \internal - - Split selection into individual (persistent) indexes. This is done in - preparation for the layoutChanged() signal, where the indexes can be - merged again. -*/ -void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged() -{ - savedPersistentIndexes.clear(); - savedPersistentCurrentIndexes.clear(); - - // optimization for when all indexes are selected - // (only if there is lots of items (1000) because this is not entirely correct) - if (ranges.isEmpty() && currentSelection.count() == 1) { - QItemSelectionRange range = currentSelection.first(); - QModelIndex parent = range.parent(); - tableRowCount = model->rowCount(parent); - tableColCount = model->columnCount(parent); - if (tableRowCount * tableColCount > 1000 - && range.top() == 0 - && range.left() == 0 - && range.bottom() == tableRowCount - 1 - && range.right() == tableColCount - 1) { - tableSelected = true; - tableParent = parent; - return; - } - } - tableSelected = false; - - QModelIndexList indexes = ranges.indexes(); - QModelIndexList::const_iterator it; - for (it = indexes.constBegin(); it != indexes.constEnd(); ++it) - savedPersistentIndexes.append(QPersistentModelIndex(*it)); - indexes = currentSelection.indexes(); - for (it = indexes.constBegin(); it != indexes.constEnd(); ++it) - savedPersistentCurrentIndexes.append(QPersistentModelIndex(*it)); -} - -/*! - \internal - - Merges \a indexes into an item selection made up of ranges. - Assumes that the indexes are sorted. -*/ -static QItemSelection mergeIndexes(const QList &indexes) -{ - QItemSelection colSpans; - // merge columns - int i = 0; - while (i < indexes.count()) { - QModelIndex tl = indexes.at(i); - QModelIndex br = tl; - while (++i < indexes.count()) { - QModelIndex next = indexes.at(i); - if ((next.parent() == br.parent()) - && (next.row() == br.row()) - && (next.column() == br.column() + 1)) - br = next; - else - break; - } - colSpans.append(QItemSelectionRange(tl, br)); - } - // merge rows - QItemSelection rowSpans; - i = 0; - while (i < colSpans.count()) { - QModelIndex tl = colSpans.at(i).topLeft(); - QModelIndex br = colSpans.at(i).bottomRight(); - QModelIndex prevTl = tl; - while (++i < colSpans.count()) { - QModelIndex nextTl = colSpans.at(i).topLeft(); - QModelIndex nextBr = colSpans.at(i).bottomRight(); - - if (nextTl.parent() != tl.parent()) - break; // we can't merge selection ranges from different parents - - if ((nextTl.column() == prevTl.column()) && (nextBr.column() == br.column()) - && (nextTl.row() == prevTl.row() + 1) && (nextBr.row() == br.row() + 1)) { - br = nextBr; - prevTl = nextTl; - } else { - break; - } - } - rowSpans.append(QItemSelectionRange(tl, br)); - } - return rowSpans; -} - -/*! - \internal - - Merge the selected indexes into selection ranges again. -*/ -void QItemSelectionModelPrivate::_q_layoutChanged() -{ - // special case for when all indexes are selected - if (tableSelected && tableColCount == model->columnCount(tableParent) - && tableRowCount == model->rowCount(tableParent)) { - ranges.clear(); - currentSelection.clear(); - int bottom = tableRowCount - 1; - int right = tableColCount - 1; - QModelIndex tl = model->index(0, 0, tableParent); - QModelIndex br = model->index(bottom, right, tableParent); - currentSelection << QItemSelectionRange(tl, br); - tableParent = QModelIndex(); - tableSelected = false; - return; - } - - if (savedPersistentCurrentIndexes.isEmpty() && savedPersistentIndexes.isEmpty()) { - // either the selection was actually empty, or we - // didn't get the layoutAboutToBeChanged() signal - return; - } - // clear the "old" selection - ranges.clear(); - currentSelection.clear(); - - // sort the "new" selection, as preparation for merging - qStableSort(savedPersistentIndexes.begin(), savedPersistentIndexes.end()); - qStableSort(savedPersistentCurrentIndexes.begin(), savedPersistentCurrentIndexes.end()); - - // update the selection by merging the individual indexes - ranges = mergeIndexes(savedPersistentIndexes); - currentSelection = mergeIndexes(savedPersistentCurrentIndexes); - - // release the persistent indexes - savedPersistentIndexes.clear(); - savedPersistentCurrentIndexes.clear(); -} - -/*! - \class QItemSelectionModel - - \brief The QItemSelectionModel class keeps track of a view's selected items. - - \ingroup model-view - \inmodule QtWidgets - - A QItemSelectionModel keeps track of the selected items in a view, or - in several views onto the same model. It also keeps track of the - currently selected item in a view. - - The QItemSelectionModel class is one of the \l{Model/View Classes} - and is part of Qt's \l{Model/View Programming}{model/view framework}. - - The selected items are stored using ranges. Whenever you want to - modify the selected items use select() and provide either a - QItemSelection, or a QModelIndex and a QItemSelectionModel::SelectionFlag. - - The QItemSelectionModel takes a two layer approach to selection - management, dealing with both selected items that have been committed - and items that are part of the current selection. The current - selected items are part of the current interactive selection (for - example with rubber-band selection or keyboard-shift selections). - - To update the currently selected items, use the bitwise OR of - QItemSelectionModel::Current and any of the other SelectionFlags. - If you omit the QItemSelectionModel::Current command, a new current - selection will be created, and the previous one added to the whole - selection. All functions operate on both layers; for example, - selectedItems() will return items from both layers. - - \sa {Model/View Programming}, QAbstractItemModel, {Chart Example} -*/ - -/*! - Constructs a selection model that operates on the specified item \a model. -*/ -QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model) - : QObject(*new QItemSelectionModelPrivate, model) -{ - d_func()->initModel(model); -} - -/*! - Constructs a selection model that operates on the specified item \a model with \a parent. -*/ -QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model, QObject *parent) - : QObject(*new QItemSelectionModelPrivate, parent) -{ - d_func()->initModel(model); -} - -/*! - \internal -*/ -QItemSelectionModel::QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstractItemModel *model) - : QObject(dd, model) -{ - dd.initModel(model); -} - -/*! - Destroys the selection model. -*/ -QItemSelectionModel::~QItemSelectionModel() -{ -} - -/*! - Selects the model item \a index using the specified \a command, and emits - selectionChanged(). - - \sa QItemSelectionModel::SelectionFlags -*/ -void QItemSelectionModel::select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command) -{ - QItemSelection selection(index, index); - select(selection, command); -} - -/*! - \fn void QItemSelectionModel::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) - - This signal is emitted whenever the current item changes. The \a previous - model item index is replaced by the \a current index as the selection's - current item. - - Note that this signal will not be emitted when the item model is reset. - - \sa currentIndex() setCurrentIndex() selectionChanged() -*/ - -/*! - \fn void QItemSelectionModel::currentColumnChanged(const QModelIndex ¤t, const QModelIndex &previous) - - This signal is emitted if the \a current item changes and its column is - different to the column of the \a previous current item. - - Note that this signal will not be emitted when the item model is reset. - - \sa currentChanged() currentRowChanged() currentIndex() setCurrentIndex() -*/ - -/*! - \fn void QItemSelectionModel::currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous) - - This signal is emitted if the \a current item changes and its row is - different to the row of the \a previous current item. - - Note that this signal will not be emitted when the item model is reset. - - \sa currentChanged() currentColumnChanged() currentIndex() setCurrentIndex() -*/ - -/*! - \fn void QItemSelectionModel::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) - - This signal is emitted whenever the selection changes. The change in the - selection is represented as an item selection of \a deselected items and - an item selection of \a selected items. - - Note the that the current index changes independently from the selection. - Also note that this signal will not be emitted when the item model is reset. - - \sa select() currentChanged() -*/ - -/*! - \enum QItemSelectionModel::SelectionFlag - - This enum describes the way the selection model will be updated. - - \value NoUpdate No selection will be made. - \value Clear The complete selection will be cleared. - \value Select All specified indexes will be selected. - \value Deselect All specified indexes will be deselected. - \value Toggle All specified indexes will be selected or - deselected depending on their current state. - \value Current The current selection will be updated. - \value Rows All indexes will be expanded to span rows. - \value Columns All indexes will be expanded to span columns. - \value SelectCurrent A combination of Select and Current, provided for - convenience. - \value ToggleCurrent A combination of Toggle and Current, provided for - convenience. - \value ClearAndSelect A combination of Clear and Select, provided for - convenience. -*/ - -/*! - Selects the item \a selection using the specified \a command, and emits - selectionChanged(). - - \sa QItemSelectionModel::SelectionFlag -*/ -void QItemSelectionModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) -{ - Q_D(QItemSelectionModel); - if (command == NoUpdate) - return; - - // store old selection - QItemSelection sel = selection; - // If d->ranges is non-empty when the source model is reset the persistent indexes - // it contains will be invalid. We can't clear them in a modelReset slot because that might already - // be too late if another model observer is connected to the same modelReset slot and is invoked first - // it might call select() on this selection model before any such QItemSelectionModelPrivate::_q_modelReset() slot - // is invoked, so it would not be cleared yet. We clear it invalid ranges in it here. - QItemSelection::iterator it = d->ranges.begin(); - while (it != d->ranges.end()) { - if (!it->isValid()) - it = d->ranges.erase(it); - else - ++it; - } - - QItemSelection old = d->ranges; - old.merge(d->currentSelection, d->currentCommand); - - // expand selection according to SelectionBehavior - if (command & Rows || command & Columns) - sel = d->expandSelection(sel, command); - - // clear ranges and currentSelection - if (command & Clear) { - d->ranges.clear(); - d->currentSelection.clear(); - } - - // merge and clear currentSelection if Current was not set (ie. start new currentSelection) - if (!(command & Current)) - d->finalize(); - - // update currentSelection - if (command & Toggle || command & Select || command & Deselect) { - d->currentCommand = command; - d->currentSelection = sel; - } - - // generate new selection, compare with old and emit selectionChanged() - QItemSelection newSelection = d->ranges; - newSelection.merge(d->currentSelection, d->currentCommand); - emitSelectionChanged(newSelection, old); -} - -/*! - Clears the selection model. Emits selectionChanged() and currentChanged(). -*/ -void QItemSelectionModel::clear() -{ - clearSelection(); - clearCurrentIndex(); -} - -/*! - Clears the current index. Emits currentChanged(). - */ -void QItemSelectionModel::clearCurrentIndex() -{ - Q_D(QItemSelectionModel); - QModelIndex previous = d->currentIndex; - d->currentIndex = QModelIndex(); - if (previous.isValid()) { - emit currentChanged(d->currentIndex, previous); - emit currentRowChanged(d->currentIndex, previous); - emit currentColumnChanged(d->currentIndex, previous); - } -} - -/*! - Clears the selection model. Does not emit any signals. -*/ -void QItemSelectionModel::reset() -{ - bool block = blockSignals(true); - clear(); - blockSignals(block); -} - -/*! - \since 4.2 - Clears the selection in the selection model. Emits selectionChanged(). -*/ -void QItemSelectionModel::clearSelection() -{ - Q_D(QItemSelectionModel); - if (d->ranges.count() == 0 && d->currentSelection.count() == 0) - return; - - select(QItemSelection(), Clear); -} - - -/*! - Sets the model item \a index to be the current item, and emits - currentChanged(). The current item is used for keyboard navigation and - focus indication; it is independent of any selected items, although a - selected item can also be the current item. - - Depending on the specified \a command, the \a index can also become part - of the current selection. - \sa select() -*/ -void QItemSelectionModel::setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command) -{ - Q_D(QItemSelectionModel); - if (index == d->currentIndex) { - if (command != NoUpdate) - select(index, command); // select item - return; - } - QPersistentModelIndex previous = d->currentIndex; - d->currentIndex = index; // set current before emitting selection changed below - if (command != NoUpdate) - select(d->currentIndex, command); // select item - emit currentChanged(d->currentIndex, previous); - if (d->currentIndex.row() != previous.row() || - d->currentIndex.parent() != previous.parent()) - emit currentRowChanged(d->currentIndex, previous); - if (d->currentIndex.column() != previous.column() || - d->currentIndex.parent() != previous.parent()) - emit currentColumnChanged(d->currentIndex, previous); -} - -/*! - Returns the model item index for the current item, or an invalid index - if there is no current item. -*/ -QModelIndex QItemSelectionModel::currentIndex() const -{ - return static_cast(d_func()->currentIndex); -} - -/*! - Returns true if the given model item \a index is selected. -*/ -bool QItemSelectionModel::isSelected(const QModelIndex &index) const -{ - Q_D(const QItemSelectionModel); - if (d->model != index.model() || !index.isValid()) - return false; - - bool selected = false; - // search model ranges - QList::const_iterator it = d->ranges.begin(); - for (; it != d->ranges.end(); ++it) { - if ((*it).isValid() && (*it).contains(index)) { - selected = true; - break; - } - } - - // check currentSelection - if (d->currentSelection.count()) { - if ((d->currentCommand & Deselect) && selected) - selected = !d->currentSelection.contains(index); - else if (d->currentCommand & Toggle) - selected ^= d->currentSelection.contains(index); - else if ((d->currentCommand & Select) && !selected) - selected = d->currentSelection.contains(index); - } - - if (selected) { - Qt::ItemFlags flags = d->model->flags(index); - return (flags & Qt::ItemIsSelectable); - } - - return false; -} - -/*! - Returns true if all items are selected in the \a row with the given - \a parent. - - Note that this function is usually faster than calling isSelected() - on all items in the same row and that unselectable items are - ignored. -*/ -bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) const -{ - Q_D(const QItemSelectionModel); - if (parent.isValid() && d->model != parent.model()) - return false; - - // return false if row exist in currentSelection (Deselect) - if (d->currentCommand & Deselect && d->currentSelection.count()) { - for (int i=0; icurrentSelection.count(); ++i) { - if (d->currentSelection.at(i).parent() == parent && - row >= d->currentSelection.at(i).top() && - row <= d->currentSelection.at(i).bottom()) - return false; - } - } - // return false if ranges in both currentSelection and ranges - // intersect and have the same row contained - if (d->currentCommand & Toggle && d->currentSelection.count()) { - for (int i=0; icurrentSelection.count(); ++i) - if (d->currentSelection.at(i).top() <= row && - d->currentSelection.at(i).bottom() >= row) - for (int j=0; jranges.count(); ++j) - if (d->ranges.at(j).top() <= row && d->ranges.at(j).bottom() >= row - && d->currentSelection.at(i).intersected(d->ranges.at(j)).isValid()) - return false; - } - // add ranges and currentSelection and check through them all - QList::const_iterator it; - QList joined = d->ranges; - if (d->currentSelection.count()) - joined += d->currentSelection; - int colCount = d->model->columnCount(parent); - for (int column = 0; column < colCount; ++column) { - for (it = joined.constBegin(); it != joined.constEnd(); ++it) { - if ((*it).contains(row, column, parent)) { - bool selectable = false; - for (int i = column; !selectable && i <= (*it).right(); ++i) { - Qt::ItemFlags flags = d->model->index(row, i, parent).flags(); - selectable = flags & Qt::ItemIsSelectable; - } - if (selectable){ - column = qMax(column, (*it).right()); - break; - } - } - } - if (it == joined.constEnd()) - return false; - } - return colCount > 0; // no columns means no selected items -} - -/*! - Returns true if all items are selected in the \a column with the given - \a parent. - - Note that this function is usually faster than calling isSelected() - on all items in the same column and that unselectable items are - ignored. -*/ -bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent) const -{ - Q_D(const QItemSelectionModel); - if (parent.isValid() && d->model != parent.model()) - return false; - - // return false if column exist in currentSelection (Deselect) - if (d->currentCommand & Deselect && d->currentSelection.count()) { - for (int i = 0; i < d->currentSelection.count(); ++i) { - if (d->currentSelection.at(i).parent() == parent && - column >= d->currentSelection.at(i).left() && - column <= d->currentSelection.at(i).right()) - return false; - } - } - // return false if ranges in both currentSelection and the selection model - // intersect and have the same column contained - if (d->currentCommand & Toggle && d->currentSelection.count()) { - for (int i = 0; i < d->currentSelection.count(); ++i) { - if (d->currentSelection.at(i).left() <= column && - d->currentSelection.at(i).right() >= column) { - for (int j = 0; j < d->ranges.count(); ++j) { - if (d->ranges.at(j).left() <= column && d->ranges.at(j).right() >= column - && d->currentSelection.at(i).intersected(d->ranges.at(j)).isValid()) { - return false; - } - } - } - } - } - // add ranges and currentSelection and check through them all - QList::const_iterator it; - QList joined = d->ranges; - if (d->currentSelection.count()) - joined += d->currentSelection; - int rowCount = d->model->rowCount(parent); - for (int row = 0; row < rowCount; ++row) { - for (it = joined.constBegin(); it != joined.constEnd(); ++it) { - if ((*it).contains(row, column, parent)) { - Qt::ItemFlags flags = d->model->index(row, column, parent).flags(); - if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled)) { - row = qMax(row, (*it).bottom()); - break; - } - } - } - if (it == joined.constEnd()) - return false; - } - return rowCount > 0; // no rows means no selected items -} - -/*! - Returns true if there are any items selected in the \a row with the given - \a parent. -*/ -bool QItemSelectionModel::rowIntersectsSelection(int row, const QModelIndex &parent) const -{ - Q_D(const QItemSelectionModel); - if (parent.isValid() && d->model != parent.model()) - return false; - - QItemSelection sel = d->ranges; - sel.merge(d->currentSelection, d->currentCommand); - for (int i = 0; i < sel.count(); ++i) { - int top = sel.at(i).top(); - int bottom = sel.at(i).bottom(); - int left = sel.at(i).left(); - int right = sel.at(i).right(); - if (top <= row && bottom >= row) { - for (int j = left; j <= right; j++) { - const Qt::ItemFlags flags = d->model->index(row, j, parent).flags(); - if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled)) - return true; - } - } - } - - return false; -} - -/*! - Returns true if there are any items selected in the \a column with the given - \a parent. -*/ -bool QItemSelectionModel::columnIntersectsSelection(int column, const QModelIndex &parent) const -{ - Q_D(const QItemSelectionModel); - if (parent.isValid() && d->model != parent.model()) - return false; - - QItemSelection sel = d->ranges; - sel.merge(d->currentSelection, d->currentCommand); - for (int i = 0; i < sel.count(); ++i) { - int left = sel.at(i).left(); - int right = sel.at(i).right(); - int top = sel.at(i).top(); - int bottom = sel.at(i).bottom(); - if (left <= column && right >= column) { - for (int j = top; j <= bottom; j++) { - const Qt::ItemFlags flags = d->model->index(j, column, parent).flags(); - if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled)) - return true; - } - } - } - - return false; -} - -/*! - \since 4.2 - - Returns true if the selection model contains any selection ranges; - otherwise returns false. -*/ -bool QItemSelectionModel::hasSelection() const -{ - Q_D(const QItemSelectionModel); - if (d->currentCommand & (Toggle | Deselect)) { - QItemSelection sel = d->ranges; - sel.merge(d->currentSelection, d->currentCommand); - return !sel.isEmpty(); - } else { - return !(d->ranges.isEmpty() && d->currentSelection.isEmpty()); - } -} - -/*! - Returns a list of all selected model item indexes. The list contains no - duplicates, and is not sorted. -*/ -QModelIndexList QItemSelectionModel::selectedIndexes() const -{ - Q_D(const QItemSelectionModel); - QItemSelection selected = d->ranges; - selected.merge(d->currentSelection, d->currentCommand); - return selected.indexes(); -} - -/*! - \since 4.2 - Returns the indexes in the given \a column for the rows where all columns are selected. - - \sa selectedIndexes(), selectedColumns() -*/ - -QModelIndexList QItemSelectionModel::selectedRows(int column) const -{ - QModelIndexList indexes; - //the QSet contains pairs of parent modelIndex - //and row number - QSet< QPair > rowsSeen; - - const QItemSelection ranges = selection(); - for (int i = 0; i < ranges.count(); ++i) { - const QItemSelectionRange &range = ranges.at(i); - QModelIndex parent = range.parent(); - for (int row = range.top(); row <= range.bottom(); row++) { - QPair rowDef = qMakePair(parent, row); - if (!rowsSeen.contains(rowDef)) { - rowsSeen << rowDef; - if (isRowSelected(row, parent)) { - indexes.append(model()->index(row, column, parent)); - } - } - } - } - - return indexes; -} - -/*! - \since 4.2 - Returns the indexes in the given \a row for columns where all rows are selected. - - \sa selectedIndexes(), selectedRows() -*/ - -QModelIndexList QItemSelectionModel::selectedColumns(int row) const -{ - QModelIndexList indexes; - //the QSet contains pairs of parent modelIndex - //and column number - QSet< QPair > columnsSeen; - - const QItemSelection ranges = selection(); - for (int i = 0; i < ranges.count(); ++i) { - const QItemSelectionRange &range = ranges.at(i); - QModelIndex parent = range.parent(); - for (int column = range.left(); column <= range.right(); column++) { - QPair columnDef = qMakePair(parent, column); - if (!columnsSeen.contains(columnDef)) { - columnsSeen << columnDef; - if (isColumnSelected(column, parent)) { - indexes.append(model()->index(row, column, parent)); - } - } - } - } - - return indexes; -} - -/*! - Returns the selection ranges stored in the selection model. -*/ -const QItemSelection QItemSelectionModel::selection() const -{ - Q_D(const QItemSelectionModel); - QItemSelection selected = d->ranges; - selected.merge(d->currentSelection, d->currentCommand); - int i = 0; - // make sure we have no invalid ranges - // ### should probably be handled more generic somewhere else - while (imodel; -} - -/*! - Compares the two selections \a newSelection and \a oldSelection - and emits selectionChanged() with the deselected and selected items. -*/ -void QItemSelectionModel::emitSelectionChanged(const QItemSelection &newSelection, - const QItemSelection &oldSelection) -{ - // if both selections are empty or equal we return - if ((oldSelection.isEmpty() && newSelection.isEmpty()) || - oldSelection == newSelection) - return; - - // if either selection is empty we do not need to compare - if (oldSelection.isEmpty() || newSelection.isEmpty()) { - emit selectionChanged(newSelection, oldSelection); - return; - } - - QItemSelection deselected = oldSelection; - QItemSelection selected = newSelection; - - // remove equal ranges - bool advance; - for (int o = 0; o < deselected.count(); ++o) { - advance = true; - for (int s = 0; s < selected.count() && o < deselected.count();) { - if (deselected.at(o) == selected.at(s)) { - deselected.removeAt(o); - selected.removeAt(s); - advance = false; - } else { - ++s; - } - } - if (advance) - ++o; - } - - // find intersections - QItemSelection intersections; - for (int o = 0; o < deselected.count(); ++o) { - for (int s = 0; s < selected.count(); ++s) { - if (deselected.at(o).intersects(selected.at(s))) - intersections.append(deselected.at(o).intersected(selected.at(s))); - } - } - - // compare remaining ranges with intersections and split them to find deselected and selected - for (int i = 0; i < intersections.count(); ++i) { - // split deselected - for (int o = 0; o < deselected.count();) { - if (deselected.at(o).intersects(intersections.at(i))) { - QItemSelection::split(deselected.at(o), intersections.at(i), &deselected); - deselected.removeAt(o); - } else { - ++o; - } - } - // split selected - for (int s = 0; s < selected.count();) { - if (selected.at(s).intersects(intersections.at(i))) { - QItemSelection::split(selected.at(s), intersections.at(i), &selected); - selected.removeAt(s); - } else { - ++s; - } - } - } - - if (!selected.isEmpty() || !deselected.isEmpty()) - emit selectionChanged(selected, deselected); -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug dbg, const QItemSelectionRange &range) -{ -#ifndef Q_BROKEN_DEBUG_STREAM - dbg.nospace() << "QItemSelectionRange(" << range.topLeft() - << ',' << range.bottomRight() << ')'; - return dbg.space(); -#else - qWarning("This compiler doesn't support streaming QItemSelectionRange to QDebug"); - return dbg; - Q_UNUSED(range); -#endif -} -#endif - -QT_END_NAMESPACE - -#include "moc_qitemselectionmodel.cpp" - -#endif // QT_NO_ITEMVIEWS diff --git a/src/widgets/itemviews/qitemselectionmodel.h b/src/widgets/itemviews/qitemselectionmodel.h deleted file mode 100644 index ea0528a590..0000000000 --- a/src/widgets/itemviews/qitemselectionmodel.h +++ /dev/null @@ -1,256 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QITEMSELECTIONMODEL_H -#define QITEMSELECTIONMODEL_H - -#include -#include -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#ifndef QT_NO_ITEMVIEWS - -class Q_WIDGETS_EXPORT QItemSelectionRange -{ - -public: - inline QItemSelectionRange() {} - inline QItemSelectionRange(const QItemSelectionRange &other) - : tl(other.tl), br(other.br) {} - inline QItemSelectionRange(const QModelIndex &topLeft, const QModelIndex &bottomRight); - explicit inline QItemSelectionRange(const QModelIndex &index) - { tl = index; br = tl; } - - inline int top() const { return tl.row(); } - inline int left() const { return tl.column(); } - inline int bottom() const { return br.row(); } - inline int right() const { return br.column(); } - inline int width() const { return br.column() - tl.column() + 1; } - inline int height() const { return br.row() - tl.row() + 1; } - - inline QModelIndex topLeft() const { return QModelIndex(tl); } - inline QModelIndex bottomRight() const { return QModelIndex(br); } - inline QModelIndex parent() const { return tl.parent(); } - inline const QAbstractItemModel *model() const { return tl.model(); } - - inline bool contains(const QModelIndex &index) const - { - return (parent() == index.parent() - && tl.row() <= index.row() && tl.column() <= index.column() - && br.row() >= index.row() && br.column() >= index.column()); - } - - inline bool contains(int row, int column, const QModelIndex &parentIndex) const - { - return (parent() == parentIndex - && tl.row() <= row && tl.column() <= column - && br.row() >= row && br.column() >= column); - } - - bool intersects(const QItemSelectionRange &other) const; - QItemSelectionRange intersect(const QItemSelectionRange &other) const; // ### Qt 5: make QT4_SUPPORT - inline QItemSelectionRange intersected(const QItemSelectionRange &other) const - { return intersect(other); } - - inline bool operator==(const QItemSelectionRange &other) const - { return (tl == other.tl && br == other.br); } - inline bool operator!=(const QItemSelectionRange &other) const - { return !operator==(other); } - inline bool operator<(const QItemSelectionRange &other) const - { - // Comparing parents will compare the models, but if two equivalent ranges - // in two different models have invalid parents, they would appear the same - if (other.tl.model() == tl.model()) { - // parent has to be calculated, so we only do so once. - const QModelIndex topLeftParent = tl.parent(); - const QModelIndex otherTopLeftParent = other.tl.parent(); - if (topLeftParent == otherTopLeftParent) { - if (other.tl.row() == tl.row()) { - if (other.tl.column() == tl.column()) { - if (other.br.row() == br.row()) { - return br.column() < other.br.column(); - } - return br.row() < other.br.row(); - } - return tl.column() < other.tl.column(); - } - return tl.row() < other.tl.row(); - } - return topLeftParent < otherTopLeftParent; - } - return tl.model() < other.tl.model(); - } - - inline bool isValid() const - { - return (tl.isValid() && br.isValid() && tl.parent() == br.parent() - && top() <= bottom() && left() <= right()); - } - - bool isEmpty() const; - - QModelIndexList indexes() const; - -private: - QPersistentModelIndex tl, br; -}; -Q_DECLARE_TYPEINFO(QItemSelectionRange, Q_MOVABLE_TYPE); - -inline QItemSelectionRange::QItemSelectionRange(const QModelIndex &atopLeft, - const QModelIndex &abottomRight) -{ tl = atopLeft; br = abottomRight; } - -class QItemSelection; -class QItemSelectionModelPrivate; - -class Q_WIDGETS_EXPORT QItemSelectionModel : public QObject -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QItemSelectionModel) - Q_FLAGS(SelectionFlags) - -public: - - enum SelectionFlag { - NoUpdate = 0x0000, - Clear = 0x0001, - Select = 0x0002, - Deselect = 0x0004, - Toggle = 0x0008, - Current = 0x0010, - Rows = 0x0020, - Columns = 0x0040, - SelectCurrent = Select | Current, - ToggleCurrent = Toggle | Current, - ClearAndSelect = Clear | Select - }; - - Q_DECLARE_FLAGS(SelectionFlags, SelectionFlag) - - explicit QItemSelectionModel(QAbstractItemModel *model); - explicit QItemSelectionModel(QAbstractItemModel *model, QObject *parent); - virtual ~QItemSelectionModel(); - - QModelIndex currentIndex() const; - - bool isSelected(const QModelIndex &index) const; - bool isRowSelected(int row, const QModelIndex &parent) const; - bool isColumnSelected(int column, const QModelIndex &parent) const; - - bool rowIntersectsSelection(int row, const QModelIndex &parent) const; - bool columnIntersectsSelection(int column, const QModelIndex &parent) const; - - bool hasSelection() const; - - QModelIndexList selectedIndexes() const; - QModelIndexList selectedRows(int column = 0) const; - QModelIndexList selectedColumns(int row = 0) const; - const QItemSelection selection() const; - - const QAbstractItemModel *model() const; - -public Q_SLOTS: - virtual void setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command); - virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command); - virtual void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command); - virtual void clear(); - virtual void reset(); - - void clearSelection(); - virtual void clearCurrentIndex(); - -Q_SIGNALS: - void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); - void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); - void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous); - void currentColumnChanged(const QModelIndex ¤t, const QModelIndex &previous); - -protected: - QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstractItemModel *model); - void emitSelectionChanged(const QItemSelection &newSelection, const QItemSelection &oldSelection); - -private: - Q_DISABLE_COPY(QItemSelectionModel) - Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeRemoved(const QModelIndex&, int, int)) - Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeRemoved(const QModelIndex&, int, int)) - Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeInserted(const QModelIndex&, int, int)) - Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeInserted(const QModelIndex&, int, int)) - Q_PRIVATE_SLOT(d_func(), void _q_layoutAboutToBeChanged()) - Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged()) -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QItemSelectionModel::SelectionFlags) - -// dummy implentation of qHash() necessary for instantiating QList::toSet() with MSVC -inline uint qHash(const QItemSelectionRange &) { return 0; } - -class Q_WIDGETS_EXPORT QItemSelection : public QList -{ -public: - QItemSelection() {} - QItemSelection(const QModelIndex &topLeft, const QModelIndex &bottomRight); - void select(const QModelIndex &topLeft, const QModelIndex &bottomRight); - bool contains(const QModelIndex &index) const; - QModelIndexList indexes() const; - void merge(const QItemSelection &other, QItemSelectionModel::SelectionFlags command); - static void split(const QItemSelectionRange &range, - const QItemSelectionRange &other, - QItemSelection *result); -}; - -#ifndef QT_NO_DEBUG_STREAM -Q_WIDGETS_EXPORT QDebug operator<<(QDebug, const QItemSelectionRange &); -#endif - -#endif // QT_NO_ITEMVIEWS - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QITEMSELECTIONMODEL_H diff --git a/src/widgets/itemviews/qitemselectionmodel_p.h b/src/widgets/itemviews/qitemselectionmodel_p.h deleted file mode 100644 index 5eb9ecccda..0000000000 --- a/src/widgets/itemviews/qitemselectionmodel_p.h +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QITEMSELECTIONMODEL_P_H -#define QITEMSELECTIONMODEL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "private/qobject_p.h" - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_ITEMVIEWS -class QItemSelectionModelPrivate: public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QItemSelectionModel) -public: - QItemSelectionModelPrivate() - : model(0), - currentCommand(QItemSelectionModel::NoUpdate), - tableSelected(false), tableColCount(0), tableRowCount(0) {} - - QItemSelection expandSelection(const QItemSelection &selection, - QItemSelectionModel::SelectionFlags command) const; - - void initModel(QAbstractItemModel *model); - - void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - void _q_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end); - void _q_columnsAboutToBeInserted(const QModelIndex &parent, int start, int end); - void _q_layoutAboutToBeChanged(); - void _q_layoutChanged(); - - inline void remove(QList &r) - { - QList::const_iterator it = r.constBegin(); - for (; it != r.constEnd(); ++it) - ranges.removeAll(*it); - } - - inline void finalize() - { - ranges.merge(currentSelection, currentCommand); - if (!currentSelection.isEmpty()) // ### perhaps this should be in QList - currentSelection.clear(); - } - - QPointer model; - QItemSelection ranges; - QItemSelection currentSelection; - QPersistentModelIndex currentIndex; - QItemSelectionModel::SelectionFlags currentCommand; - QList savedPersistentIndexes; - QList savedPersistentCurrentIndexes; - // optimization when all indexes are selected - bool tableSelected; - QPersistentModelIndex tableParent; - int tableColCount, tableRowCount; -}; - -#endif // QT_NO_ITEMVIEWS - -QT_END_NAMESPACE - -#endif // QITEMSELECTIONMODEL_P_H diff --git a/src/widgets/itemviews/qlistwidget.h b/src/widgets/itemviews/qlistwidget.h index 750b85b4c1..6eb2ab78fd 100644 --- a/src/widgets/itemviews/qlistwidget.h +++ b/src/widgets/itemviews/qlistwidget.h @@ -45,7 +45,7 @@ #include #include #include -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/itemviews/qsortfilterproxymodel.cpp b/src/widgets/itemviews/qsortfilterproxymodel.cpp deleted file mode 100644 index f29ad7bc57..0000000000 --- a/src/widgets/itemviews/qsortfilterproxymodel.cpp +++ /dev/null @@ -1,2703 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsortfilterproxymodel.h" - -#ifndef QT_NO_SORTFILTERPROXYMODEL - -#include "qitemselectionmodel.h" -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -typedef QList > QModelIndexPairList; - -static inline QSet qVectorToSet(const QVector &vector) -{ - QSet set; - set.reserve(vector.size()); - for(int i=0; i < vector.size(); ++i) - set << vector.at(i); - return set; -} - -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; -}; - - -//this struct is used to store what are the rows that are removed -//between a call to rowsAboutToBeRemoved and rowsRemoved -//it avoids readding rows to the mapping that are currently being removed -struct QRowsRemoval -{ - QRowsRemoval(const QModelIndex &parent_source, int start, int end) : parent_source(parent_source), start(start), end(end) - { - } - - QRowsRemoval() : start(-1), end(-1) - { - } - - bool contains(QModelIndex parent, int row) - { - do { - if (parent == parent_source) - return row >= start && row <= end; - row = parent.row(); - parent = parent.parent(); - } while (row >= 0); - return false; - } -private: - QModelIndex parent_source; - int start; - int end; -}; - -class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate -{ - Q_DECLARE_PUBLIC(QSortFilterProxyModel) - -public: - struct Mapping { - QVector source_rows; - QVector source_columns; - QVector proxy_rows; - QVector proxy_columns; - QVector mapped_children; - QHash::const_iterator map_iter; - }; - - mutable QHash source_index_mapping; - - int source_sort_column; - int proxy_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; - QRowsRemoval itemsBeingRemoved; - - QModelIndexPairList saved_persistent_indexes; - - QHash::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; - bool can_create_mapping(const QModelIndex &source_parent) const; - - void remove_from_mapping(const QModelIndex &source_parent); - - inline QHash::const_iterator index_to_iterator( - const QModelIndex &proxy_index) const - { - Q_ASSERT(proxy_index.isValid()); - Q_ASSERT(proxy_index.model() == q_func()); - const void *p = proxy_index.internalPointer(); - Q_ASSERT(p); - QHash::const_iterator it = - static_cast(p)->map_iter; - Q_ASSERT(it != source_index_mapping.constEnd()); - Q_ASSERT(it.value()); - return it; - } - - inline QModelIndex create_index(int row, int column, - QHash::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_sourceAboutToBeReset(); - void _q_sourceReset(); - - void _q_sourceLayoutAboutToBeChanged(const QList &sourceParents); - void _q_sourceLayoutChanged(const QList &sourceParents); - - 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_sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, - int sourceStart, int sourceEnd, - const QModelIndex &destParent, int dest); - void _q_sourceRowsMoved(const QModelIndex &sourceParent, - int sourceStart, int sourceEnd, - const QModelIndex &destParent, int dest); - 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 _q_sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, - int sourceStart, int sourceEnd, - const QModelIndex &destParent, int dest); - void _q_sourceColumnsMoved(const QModelIndex &sourceParent, - int sourceStart, int sourceEnd, - const QModelIndex &destParent, int dest); - - void _q_clearMapping(); - - void sort(); - bool update_source_sort_column(); - void sort_source_rows(QVector &source_rows, - const QModelIndex &source_parent) const; - QVector > > proxy_intervals_for_source_items_to_add( - const QVector &proxy_to_source, const QVector &source_items, - const QModelIndex &source_parent, Qt::Orientation orient) const; - QVector > proxy_intervals_for_source_items( - const QVector &source_to_proxy, const QVector &source_items) const; - void insert_source_items( - QVector &source_to_proxy, QVector &proxy_to_source, - const QVector &source_items, const QModelIndex &source_parent, - Qt::Orientation orient, bool emit_signal = true); - void remove_source_items( - QVector &source_to_proxy, QVector &proxy_to_source, - const QVector &source_items, const QModelIndex &source_parent, - Qt::Orientation orient, bool emit_signal = true); - void remove_proxy_interval( - QVector &source_to_proxy, QVector &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 &proxy_to_source, QVector &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 &source_to_proxy, const QVector &source_items, - int &proxy_low, int &proxy_high) const; - - QModelIndexPairList store_persistent_indexes(); - void update_persistent_indexes(const QModelIndexPairList &source_indexes); - - void filter_changed(const QModelIndex &source_parent = QModelIndex()); - QSet handle_filter_changed( - QVector &source_to_proxy, QVector &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); - - virtual void _q_sourceModelDestroyed(); -}; - -typedef QHash IndexMap; - -void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed() -{ - QAbstractProxyModelPrivate::_q_sourceModelDestroyed(); - _q_clearMapping(); -} - -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::_q_clearMapping() -{ - // store the persistent indexes - QModelIndexPairList source_indexes = store_persistent_indexes(); - - qDeleteAll(source_index_mapping); - source_index_mapping.clear(); - if (dynamic_sortfilter && update_source_sort_column()) { - //update_source_sort_column might have created wrong mapping so we have to clear it again - 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); - m->source_rows.reserve(source_rows); - 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); - m->source_columns.reserve(source_cols); - 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 - if (proxy_index.model() != q_func()) { - qWarning() << "QSortFilterProxyModel: index from wrong model passed to mapToSource"; - Q_ASSERT(!"QSortFilterProxyModel: index from wrong model passed to mapToSource"); - return QModelIndex(); - } - 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 - if (source_index.model() != model) { - qWarning() << "QSortFilterProxyModel: index from wrong model passed to mapFromSource"; - Q_ASSERT(!"QSortFilterProxyModel: index from wrong model passed to mapFromSource"); - return QModelIndex(); - } - 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); -} - -bool QSortFilterProxyModelPrivate::can_create_mapping(const QModelIndex &source_parent) const -{ - if (source_parent.isValid()) { - QModelIndex source_grand_parent = source_parent.parent(); - IndexMap::const_iterator it = source_index_mapping.constFind(source_grand_parent); - if (it == source_index_mapping.constEnd()) { - // Don't care, since we don't have mapping for the grand parent - return false; - } - Mapping *gm = it.value(); - if (gm->proxy_rows.at(source_parent.row()) == -1 || - gm->proxy_columns.at(source_parent.column()) == -1) { - // Don't care, since parent is filtered - return false; - } - } - return true; -} - -/*! - \internal - - Sorts the existing mappings. -*/ -void QSortFilterProxyModelPrivate::sort() -{ - Q_Q(QSortFilterProxyModel); - emit q->layoutAboutToBeChanged(); - QModelIndexPairList 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 - - update the source_sort_column according to the proxy_sort_column - return true if the column was changed -*/ -bool QSortFilterProxyModelPrivate::update_source_sort_column() -{ - Q_Q(QSortFilterProxyModel); - QModelIndex proxy_index = q->index(0, proxy_sort_column, QModelIndex()); - int old_source_sort_colum = source_sort_column; - source_sort_column = q->mapToSource(proxy_index).column(); - return old_source_sort_colum != source_sort_column; -} - - -/*! - \internal - - Sorts the given \a source_rows according to current sort column and order. -*/ -void QSortFilterProxyModelPrivate::sort_source_rows( - QVector &source_rows, const QModelIndex &source_parent) const -{ - Q_Q(const QSortFilterProxyModel); - if (source_sort_column >= 0) { - if (sort_order == Qt::AscendingOrder) { - QSortFilterProxyModelLessThan lt(source_sort_column, source_parent, model, q); - qStableSort(source_rows.begin(), source_rows.end(), lt); - } else { - QSortFilterProxyModelGreaterThan gt(source_sort_column, source_parent, model, q); - qStableSort(source_rows.begin(), source_rows.end(), gt); - } - } else { // restore the source model order - qStableSort(source_rows.begin(), source_rows.end()); - } -} - -/*! - \internal - - Given source-to-proxy mapping \a source_to_proxy and the set of - source items \a source_items (which are part of that mapping), - determines the corresponding proxy item intervals that should - be removed from the proxy model. - - The result is a vector of pairs, where each pair represents a - (start, end) tuple, sorted in ascending order. -*/ -QVector > QSortFilterProxyModelPrivate::proxy_intervals_for_source_items( - const QVector &source_to_proxy, const QVector &source_items) const -{ - QVector > proxy_intervals; - if (source_items.isEmpty()) - return proxy_intervals; - - int source_items_index = 0; - while (source_items_index < source_items.size()) { - int first_proxy_item = source_to_proxy.at(source_items.at(source_items_index)); - Q_ASSERT(first_proxy_item != -1); - int last_proxy_item = first_proxy_item; - ++source_items_index; - // Find end of interval - while ((source_items_index < source_items.size()) - && (source_to_proxy.at(source_items.at(source_items_index)) == last_proxy_item + 1)) { - ++last_proxy_item; - ++source_items_index; - } - // Add interval to result - proxy_intervals.append(QPair(first_proxy_item, last_proxy_item)); - } - qStableSort(proxy_intervals.begin(), proxy_intervals.end()); - return proxy_intervals; -} - -/*! - \internal - - Given source-to-proxy mapping \a src_to_proxy and proxy-to-source mapping - \a proxy_to_source, removes \a source_items from this proxy model. - The corresponding proxy items are removed in intervals, so that the proper - rows/columnsRemoved(start, end) signals will be generated. -*/ -void QSortFilterProxyModelPrivate::remove_source_items( - QVector &source_to_proxy, QVector &proxy_to_source, - const QVector &source_items, const QModelIndex &source_parent, - Qt::Orientation orient, bool emit_signal) -{ - Q_Q(QSortFilterProxyModel); - QModelIndex proxy_parent = q->mapFromSource(source_parent); - if (!proxy_parent.isValid() && source_parent.isValid()) - return; // nothing to do (already removed) - - QVector > proxy_intervals; - proxy_intervals = proxy_intervals_for_source_items(source_to_proxy, source_items); - - for (int i = proxy_intervals.size()-1; i >= 0; --i) { - QPair interval = proxy_intervals.at(i); - int proxy_start = interval.first; - int proxy_end = interval.second; - remove_proxy_interval(source_to_proxy, proxy_to_source, proxy_start, proxy_end, - proxy_parent, orient, emit_signal); - } -} - -/*! - \internal - - Given source-to-proxy mapping \a source_to_proxy and proxy-to-source mapping - \a proxy_to_source, removes items from \a proxy_start to \a proxy_end - (inclusive) from this proxy model. -*/ -void QSortFilterProxyModelPrivate::remove_proxy_interval( - QVector &source_to_proxy, QVector &proxy_to_source, int proxy_start, int proxy_end, - const QModelIndex &proxy_parent, Qt::Orientation orient, bool emit_signal) -{ - Q_Q(QSortFilterProxyModel); - if (emit_signal) { - if (orient == Qt::Vertical) - q->beginRemoveRows(proxy_parent, proxy_start, proxy_end); - else - q->beginRemoveColumns(proxy_parent, proxy_start, proxy_end); - } - - // Remove items from proxy-to-source mapping - proxy_to_source.remove(proxy_start, proxy_end - proxy_start + 1); - - build_source_to_proxy_mapping(proxy_to_source, source_to_proxy); - - if (emit_signal) { - if (orient == Qt::Vertical) - q->endRemoveRows(); - else - q->endRemoveColumns(); - } -} - -/*! - \internal - - Given proxy-to-source mapping \a proxy_to_source and a set of - unmapped source items \a source_items, determines the proxy item - intervals at which the subsets of source items should be inserted - (but does not actually add them to the mapping). - - The result is a vector of pairs, each pair representing a tuple (start, - items), where items is a vector containing the (sorted) source items that - should be inserted at that proxy model location. -*/ -QVector > > QSortFilterProxyModelPrivate::proxy_intervals_for_source_items_to_add( - const QVector &proxy_to_source, const QVector &source_items, - const QModelIndex &source_parent, Qt::Orientation orient) const -{ - Q_Q(const QSortFilterProxyModel); - QVector > > proxy_intervals; - if (source_items.isEmpty()) - return proxy_intervals; - - int proxy_low = 0; - int proxy_item = 0; - int source_items_index = 0; - QVector source_items_in_interval; - bool compare = (orient == Qt::Vertical && source_sort_column >= 0 && dynamic_sortfilter); - while (source_items_index < source_items.size()) { - source_items_in_interval.clear(); - int first_new_source_item = source_items.at(source_items_index); - source_items_in_interval.append(first_new_source_item); - ++source_items_index; - - // Find proxy item at which insertion should be started - int proxy_high = proxy_to_source.size() - 1; - QModelIndex i1 = compare ? model->index(first_new_source_item, source_sort_column, source_parent) : QModelIndex(); - while (proxy_low <= proxy_high) { - proxy_item = (proxy_low + proxy_high) / 2; - if (compare) { - QModelIndex i2 = model->index(proxy_to_source.at(proxy_item), source_sort_column, source_parent); - if ((sort_order == Qt::AscendingOrder) ? q->lessThan(i1, i2) : q->lessThan(i2, i1)) - proxy_high = proxy_item - 1; - else - proxy_low = proxy_item + 1; - } else { - if (first_new_source_item < proxy_to_source.at(proxy_item)) - proxy_high = proxy_item - 1; - else - proxy_low = proxy_item + 1; - } - } - proxy_item = proxy_low; - - // Find the sequence of new source items that should be inserted here - if (proxy_item >= proxy_to_source.size()) { - for ( ; source_items_index < source_items.size(); ++source_items_index) - source_items_in_interval.append(source_items.at(source_items_index)); - } else { - i1 = compare ? model->index(proxy_to_source.at(proxy_item), source_sort_column, source_parent) : QModelIndex(); - for ( ; source_items_index < source_items.size(); ++source_items_index) { - int new_source_item = source_items.at(source_items_index); - if (compare) { - QModelIndex i2 = model->index(new_source_item, source_sort_column, source_parent); - if ((sort_order == Qt::AscendingOrder) ? q->lessThan(i1, i2) : q->lessThan(i2, i1)) - break; - } else { - if (proxy_to_source.at(proxy_item) < new_source_item) - break; - } - source_items_in_interval.append(new_source_item); - } - } - - // Add interval to result - proxy_intervals.append(QPair >(proxy_item, source_items_in_interval)); - } - return proxy_intervals; -} - -/*! - \internal - - Given source-to-proxy mapping \a source_to_proxy and proxy-to-source mapping - \a proxy_to_source, inserts the given \a source_items into this proxy model. - The source items are inserted in intervals (based on some sorted order), so - that the proper rows/columnsInserted(start, end) signals will be generated. -*/ -void QSortFilterProxyModelPrivate::insert_source_items( - QVector &source_to_proxy, QVector &proxy_to_source, - const QVector &source_items, const QModelIndex &source_parent, - Qt::Orientation orient, bool emit_signal) -{ - Q_Q(QSortFilterProxyModel); - QModelIndex proxy_parent = q->mapFromSource(source_parent); - if (!proxy_parent.isValid() && source_parent.isValid()) - return; // nothing to do (source_parent is not mapped) - - QVector > > proxy_intervals; - proxy_intervals = proxy_intervals_for_source_items_to_add( - proxy_to_source, source_items, source_parent, orient); - - for (int i = proxy_intervals.size()-1; i >= 0; --i) { - QPair > interval = proxy_intervals.at(i); - int proxy_start = interval.first; - QVector source_items = interval.second; - int proxy_end = proxy_start + source_items.size() - 1; - - if (emit_signal) { - if (orient == Qt::Vertical) - q->beginInsertRows(proxy_parent, proxy_start, proxy_end); - else - q->beginInsertColumns(proxy_parent, proxy_start, proxy_end); - } - - for (int i = 0; i < source_items.size(); ++i) - proxy_to_source.insert(proxy_start + i, source_items.at(i)); - - build_source_to_proxy_mapping(proxy_to_source, source_to_proxy); - - if (emit_signal) { - if (orient == Qt::Vertical) - q->endInsertRows(); - else - q->endInsertColumns(); - } - } -} - -/*! - \internal - - Handles source model items insertion (columnsInserted(), rowsInserted()). - Determines - 1) which of the inserted items to also insert into proxy model (filtering), - 2) where to insert the items into the proxy model (sorting), - then inserts those items. - The items are inserted into the proxy model in intervals (based on - sorted order), so that the proper rows/columnsInserted(start, end) - signals will be generated. -*/ -void QSortFilterProxyModelPrivate::source_items_inserted( - const QModelIndex &source_parent, int start, int end, Qt::Orientation orient) -{ - Q_Q(QSortFilterProxyModel); - if ((start < 0) || (end < 0)) - return; - IndexMap::const_iterator it = source_index_mapping.constFind(source_parent); - if (it == source_index_mapping.constEnd()) { - if (!can_create_mapping(source_parent)) - return; - it = create_mapping(source_parent); - Mapping *m = it.value(); - QModelIndex proxy_parent = q->mapFromSource(source_parent); - if (m->source_rows.count() > 0) { - q->beginInsertRows(proxy_parent, 0, m->source_rows.count() - 1); - q->endInsertRows(); - } - if (m->source_columns.count() > 0) { - q->beginInsertColumns(proxy_parent, 0, m->source_columns.count() - 1); - q->endInsertColumns(); - } - return; - } - - Mapping *m = it.value(); - QVector &source_to_proxy = (orient == Qt::Vertical) ? m->proxy_rows : m->proxy_columns; - QVector &proxy_to_source = (orient == Qt::Vertical) ? m->source_rows : m->source_columns; - - int delta_item_count = end - start + 1; - int old_item_count = source_to_proxy.size(); - - updateChildrenMapping(source_parent, m, orient, start, end, delta_item_count, false); - - // Expand source-to-proxy mapping to account for new items - if (start < 0 || start > source_to_proxy.size()) { - qWarning("QSortFilterProxyModel: invalid inserted rows reported by source model"); - remove_from_mapping(source_parent); - return; - } - source_to_proxy.insert(start, delta_item_count, -1); - - if (start < old_item_count) { - // Adjust existing "stale" indexes in proxy-to-source mapping - int proxy_count = proxy_to_source.size(); - for (int proxy_item = 0; proxy_item < proxy_count; ++proxy_item) { - int source_item = proxy_to_source.at(proxy_item); - if (source_item >= start) - proxy_to_source.replace(proxy_item, source_item + delta_item_count); - } - build_source_to_proxy_mapping(proxy_to_source, source_to_proxy); - } - - // Figure out which items to add to mapping based on filter - QVector source_items; - for (int i = start; i <= end; ++i) { - if ((orient == Qt::Vertical) - ? q->filterAcceptsRow(i, source_parent) - : q->filterAcceptsColumn(i, source_parent)) { - source_items.append(i); - } - } - - if (model->rowCount(source_parent) == delta_item_count) { - // Items were inserted where there were none before. - // If it was new rows make sure to create mappings for columns so that a - // valid mapping can be retrieved later and vice-versa. - - QVector &orthogonal_proxy_to_source = (orient == Qt::Horizontal) ? m->source_rows : m->source_columns; - QVector &orthogonal_source_to_proxy = (orient == Qt::Horizontal) ? m->proxy_rows : m->proxy_columns; - - if (orthogonal_source_to_proxy.isEmpty()) { - const int ortho_end = (orient == Qt::Horizontal) ? model->rowCount(source_parent) : model->columnCount(source_parent); - - orthogonal_source_to_proxy.resize(ortho_end); - - for (int ortho_item = 0; ortho_item < ortho_end; ++ortho_item) { - if ((orient == Qt::Horizontal) ? q->filterAcceptsRow(ortho_item, source_parent) - : q->filterAcceptsColumn(ortho_item, source_parent)) { - orthogonal_proxy_to_source.append(ortho_item); - } - } - if (orient == Qt::Horizontal) { - // We're reacting to columnsInserted, but we've just inserted new rows. Sort them. - sort_source_rows(orthogonal_proxy_to_source, source_parent); - } - build_source_to_proxy_mapping(orthogonal_proxy_to_source, orthogonal_source_to_proxy); - } - } - - // Sort and insert the items - if (orient == Qt::Vertical) // Only sort rows - sort_source_rows(source_items, source_parent); - insert_source_items(source_to_proxy, proxy_to_source, source_items, source_parent, orient); -} - -/*! - \internal - - Handles source model items removal - (columnsAboutToBeRemoved(), rowsAboutToBeRemoved()). -*/ -void QSortFilterProxyModelPrivate::source_items_about_to_be_removed( - const QModelIndex &source_parent, int start, int end, Qt::Orientation orient) -{ - if ((start < 0) || (end < 0)) - return; - IndexMap::const_iterator it = source_index_mapping.constFind(source_parent); - if (it == source_index_mapping.constEnd()) { - // Don't care, since we don't have mapping for this index - return; - } - - Mapping *m = it.value(); - QVector &source_to_proxy = (orient == Qt::Vertical) ? m->proxy_rows : m->proxy_columns; - QVector &proxy_to_source = (orient == Qt::Vertical) ? m->source_rows : m->source_columns; - - // figure out which items to remove - QVector source_items_to_remove; - int proxy_count = proxy_to_source.size(); - for (int proxy_item = 0; proxy_item < proxy_count; ++proxy_item) { - int source_item = proxy_to_source.at(proxy_item); - if ((source_item >= start) && (source_item <= end)) - source_items_to_remove.append(source_item); - } - - remove_source_items(source_to_proxy, proxy_to_source, source_items_to_remove, - source_parent, orient); -} - -/*! - \internal - - Handles source model items removal (columnsRemoved(), rowsRemoved()). -*/ -void QSortFilterProxyModelPrivate::source_items_removed( - const QModelIndex &source_parent, int start, int end, Qt::Orientation orient) -{ - if ((start < 0) || (end < 0)) - return; - IndexMap::const_iterator it = source_index_mapping.constFind(source_parent); - if (it == source_index_mapping.constEnd()) { - // Don't care, since we don't have mapping for this index - return; - } - - Mapping *m = it.value(); - QVector &source_to_proxy = (orient == Qt::Vertical) ? m->proxy_rows : m->proxy_columns; - QVector &proxy_to_source = (orient == Qt::Vertical) ? m->source_rows : m->source_columns; - - if (end >= source_to_proxy.size()) - end = source_to_proxy.size() - 1; - - // Shrink the source-to-proxy mapping to reflect the new item count - int delta_item_count = end - start + 1; - source_to_proxy.remove(start, delta_item_count); - - int proxy_count = proxy_to_source.size(); - if (proxy_count > source_to_proxy.size()) { - // mapping is in an inconsistent state -- redo the whole mapping - qWarning("QSortFilterProxyModel: inconsistent changes reported by source model"); - remove_from_mapping(source_parent); - Q_Q(QSortFilterProxyModel); - q->reset(); - return; - } - - // Adjust "stale" indexes in proxy-to-source mapping - for (int proxy_item = 0; proxy_item < proxy_count; ++proxy_item) { - int source_item = proxy_to_source.at(proxy_item); - if (source_item >= start) { - Q_ASSERT(source_item - delta_item_count >= 0); - proxy_to_source.replace(proxy_item, source_item - delta_item_count); - } - } - build_source_to_proxy_mapping(proxy_to_source, source_to_proxy); - - updateChildrenMapping(source_parent, m, orient, start, end, delta_item_count, true); - -} - - -/*! - \internal - updates the mapping of the children when inserting or removing items -*/ -void QSortFilterProxyModelPrivate::updateChildrenMapping(const QModelIndex &source_parent, Mapping *parent_mapping, - Qt::Orientation orient, int start, int end, int delta_item_count, bool remove) -{ - // see if any mapped children should be (re)moved - QVector > moved_source_index_mappings; - QVector::iterator it2 = parent_mapping->mapped_children.begin(); - for ( ; it2 != parent_mapping->mapped_children.end();) { - const QModelIndex source_child_index = *it2; - const int pos = (orient == Qt::Vertical) - ? source_child_index.row() - : source_child_index.column(); - if (pos < start) { - // not affected - ++it2; - } else if (remove && pos <= end) { - // in the removed interval - it2 = parent_mapping->mapped_children.erase(it2); - remove_from_mapping(source_child_index); - } else { - // below the removed items -- recompute the index - QModelIndex new_index; - const int newpos = remove ? pos - delta_item_count : pos + delta_item_count; - if (orient == Qt::Vertical) { - new_index = model->index(newpos, - source_child_index.column(), - source_parent); - } else { - new_index = model->index(source_child_index.row(), - newpos, - source_parent); - } - *it2 = new_index; - ++it2; - - // update mapping - Mapping *cm = source_index_mapping.take(source_child_index); - Q_ASSERT(cm); - // we do not reinsert right away, because the new index might be identical with another, old index - moved_source_index_mappings.append(QPair(new_index, cm)); - } - } - - // reinsert moved, mapped indexes - QVector >::iterator it = moved_source_index_mappings.begin(); - for (; it != moved_source_index_mappings.end(); ++it) { -#ifdef QT_STRICT_ITERATORS - source_index_mapping.insert((*it).first, (*it).second); - (*it).second->map_iter = source_index_mapping.constFind((*it).first); -#else - (*it).second->map_iter = source_index_mapping.insert((*it).first, (*it).second); -#endif - } -} - -/*! - \internal -*/ -void QSortFilterProxyModelPrivate::proxy_item_range( - const QVector &source_to_proxy, const QVector &source_items, - int &proxy_low, int &proxy_high) const -{ - proxy_low = INT_MAX; - proxy_high = INT_MIN; - for (int i = 0; i < source_items.count(); ++i) { - int proxy_item = source_to_proxy.at(source_items.at(i)); - Q_ASSERT(proxy_item != -1); - if (proxy_item < proxy_low) - proxy_low = proxy_item; - if (proxy_item > proxy_high) - proxy_high = proxy_item; - } -} - -/*! - \internal -*/ -void QSortFilterProxyModelPrivate::build_source_to_proxy_mapping( - const QVector &proxy_to_source, QVector &source_to_proxy) const -{ - source_to_proxy.fill(-1); - int proxy_count = proxy_to_source.size(); - for (int i = 0; i < proxy_count; ++i) - source_to_proxy[proxy_to_source.at(i)] = i; -} - -/*! - \internal - - Maps the persistent proxy indexes to source indexes and - returns the list of source indexes. -*/ -QModelIndexPairList QSortFilterProxyModelPrivate::store_persistent_indexes() -{ - Q_Q(QSortFilterProxyModel); - QModelIndexPairList source_indexes; - foreach (QPersistentModelIndexData *data, persistent.indexes) { - QModelIndex proxy_index = data->index; - QModelIndex source_index = q->mapToSource(proxy_index); - source_indexes.append(qMakePair(proxy_index, QPersistentModelIndex(source_index))); - } - return source_indexes; -} - -/*! - \internal - - Maps \a source_indexes to proxy indexes and stores those - as persistent indexes. -*/ -void QSortFilterProxyModelPrivate::update_persistent_indexes( - const QModelIndexPairList &source_indexes) -{ - Q_Q(QSortFilterProxyModel); - QModelIndexList from, to; - for (int i = 0; i < source_indexes.count(); ++i) { - QModelIndex source_index = source_indexes.at(i).second; - QModelIndex old_proxy_index = source_indexes.at(i).first; - create_mapping(source_index.parent()); - QModelIndex proxy_index = q->mapFromSource(source_index); - from << old_proxy_index; - to << proxy_index; - } - q->changePersistentIndexList(from, to); -} - - -/*! - \internal - - Updates the proxy model (adds/removes rows) based on the - new filter. -*/ -void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_parent) -{ - IndexMap::const_iterator it = source_index_mapping.constFind(source_parent); - if (it == source_index_mapping.constEnd()) - return; - Mapping *m = it.value(); - QSet rows_removed = handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical); - QSet columns_removed = handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal); - QVector::iterator it2 = m->mapped_children.end(); - while (it2 != m->mapped_children.begin()) { - --it2; - const QModelIndex source_child_index = *it2; - if (rows_removed.contains(source_child_index.row()) || columns_removed.contains(source_child_index.column())) { - it2 = m->mapped_children.erase(it2); - remove_from_mapping(source_child_index); - } else { - filter_changed(source_child_index); - } - } -} - -/*! - \internal - returns the removed items indexes -*/ -QSet QSortFilterProxyModelPrivate::handle_filter_changed( - QVector &source_to_proxy, QVector &proxy_to_source, - const QModelIndex &source_parent, Qt::Orientation orient) -{ - Q_Q(QSortFilterProxyModel); - // Figure out which mapped items to remove - QVector source_items_remove; - for (int i = 0; i < proxy_to_source.count(); ++i) { - const int source_item = proxy_to_source.at(i); - if ((orient == Qt::Vertical) - ? !q->filterAcceptsRow(source_item, source_parent) - : !q->filterAcceptsColumn(source_item, source_parent)) { - // This source item does not satisfy the filter, so it must be removed - source_items_remove.append(source_item); - } - } - // Figure out which non-mapped items to insert - QVector source_items_insert; - int source_count = source_to_proxy.size(); - for (int source_item = 0; source_item < source_count; ++source_item) { - if (source_to_proxy.at(source_item) == -1) { - if ((orient == Qt::Vertical) - ? q->filterAcceptsRow(source_item, source_parent) - : q->filterAcceptsColumn(source_item, source_parent)) { - // This source item satisfies the filter, so it must be added - source_items_insert.append(source_item); - } - } - } - if (!source_items_remove.isEmpty() || !source_items_insert.isEmpty()) { - // Do item removal and insertion - remove_source_items(source_to_proxy, proxy_to_source, - source_items_remove, source_parent, orient); - if (orient == Qt::Vertical) - sort_source_rows(source_items_insert, source_parent); - insert_source_items(source_to_proxy, proxy_to_source, - source_items_insert, source_parent, orient); - } - return qVectorToSet(source_items_remove); -} - -void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &source_top_left, - const QModelIndex &source_bottom_right) -{ - Q_Q(QSortFilterProxyModel); - if (!source_top_left.isValid() || !source_bottom_right.isValid()) - return; - QModelIndex source_parent = source_top_left.parent(); - IndexMap::const_iterator it = source_index_mapping.find(source_parent); - if (it == source_index_mapping.constEnd()) { - // Don't care, since we don't have mapping for this index - return; - } - Mapping *m = it.value(); - - // Figure out how the source changes affect us - QVector source_rows_remove; - QVector source_rows_insert; - QVector source_rows_change; - QVector source_rows_resort; - int end = qMin(source_bottom_right.row(), m->proxy_rows.count() - 1); - for (int source_row = source_top_left.row(); source_row <= end; ++source_row) { - if (dynamic_sortfilter) { - if (m->proxy_rows.at(source_row) != -1) { - if (!q->filterAcceptsRow(source_row, source_parent)) { - // This source row no longer satisfies the filter, so it must be removed - source_rows_remove.append(source_row); - } else if (source_sort_column >= source_top_left.column() && source_sort_column <= source_bottom_right.column()) { - // This source row has changed in a way that may affect sorted order - source_rows_resort.append(source_row); - } else { - // This row has simply changed, without affecting filtering nor sorting - source_rows_change.append(source_row); - } - } else { - if (!itemsBeingRemoved.contains(source_parent, source_row) && q->filterAcceptsRow(source_row, source_parent)) { - // This source row now satisfies the filter, so it must be added - source_rows_insert.append(source_row); - } - } - } else { - if (m->proxy_rows.at(source_row) != -1) - source_rows_change.append(source_row); - } - } - - if (!source_rows_remove.isEmpty()) { - remove_source_items(m->proxy_rows, m->source_rows, - source_rows_remove, source_parent, Qt::Vertical); - QSet source_rows_remove_set = qVectorToSet(source_rows_remove); - QVector::iterator it = m->mapped_children.end(); - while (it != m->mapped_children.begin()) { - --it; - const QModelIndex source_child_index = *it; - if (source_rows_remove_set.contains(source_child_index.row())) { - it = m->mapped_children.erase(it); - remove_from_mapping(source_child_index); - } - } - } - - if (!source_rows_resort.isEmpty()) { - // Re-sort the rows of this level - QList parents; - parents << q->mapFromSource(source_parent); - emit q->layoutAboutToBeChanged(parents); - QModelIndexPairList source_indexes = store_persistent_indexes(); - remove_source_items(m->proxy_rows, m->source_rows, source_rows_resort, - source_parent, Qt::Vertical, false); - sort_source_rows(source_rows_resort, source_parent); - insert_source_items(m->proxy_rows, m->source_rows, source_rows_resort, - source_parent, Qt::Vertical, false); - update_persistent_indexes(source_indexes); - emit q->layoutChanged(parents); - // Make sure we also emit dataChanged for the rows - source_rows_change += source_rows_resort; - } - - if (!source_rows_change.isEmpty()) { - // Find the proxy row range - int proxy_start_row; - int proxy_end_row; - proxy_item_range(m->proxy_rows, source_rows_change, - proxy_start_row, proxy_end_row); - // ### Find the proxy column range also - if (proxy_end_row >= 0) { - // the row was accepted, but some columns might still be filtered out - int source_left_column = source_top_left.column(); - while (source_left_column < source_bottom_right.column() - && m->proxy_columns.at(source_left_column) == -1) - ++source_left_column; - const QModelIndex proxy_top_left = create_index( - proxy_start_row, m->proxy_columns.at(source_left_column), it); - int source_right_column = source_bottom_right.column(); - while (source_right_column > source_top_left.column() - && m->proxy_columns.at(source_right_column) == -1) - --source_right_column; - const QModelIndex proxy_bottom_right = create_index( - proxy_end_row, m->proxy_columns.at(source_right_column), it); - emit q->dataChanged(proxy_top_left, proxy_bottom_right); - } - } - - if (!source_rows_insert.isEmpty()) { - sort_source_rows(source_rows_insert, source_parent); - insert_source_items(m->proxy_rows, m->source_rows, - source_rows_insert, source_parent, Qt::Vertical); - } -} - -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_sourceAboutToBeReset() -{ - Q_Q(QSortFilterProxyModel); - q->beginResetModel(); -} - -void QSortFilterProxyModelPrivate::_q_sourceReset() -{ - Q_Q(QSortFilterProxyModel); - invalidatePersistentIndexes(); - _q_clearMapping(); - // All internal structures are deleted in clear() - q->endResetModel(); - update_source_sort_column(); - if (dynamic_sortfilter) - sort(); -} - -void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList &sourceParents) -{ - Q_Q(QSortFilterProxyModel); - saved_persistent_indexes.clear(); - - QList parents; - foreach (const QPersistentModelIndex &parent, sourceParents) { - if (!parent.isValid()) { - parents << QModelIndex(); - continue; - } - const QModelIndex mappedParent = q->mapFromSource(parent); - // Might be filtered out. - if (mappedParent.isValid()) - parents << mappedParent; - } - - // All parents filtered out. - if (!sourceParents.isEmpty() && parents.isEmpty()) - return; - - emit q->layoutAboutToBeChanged(parents); - if (persistent.indexes.isEmpty()) - return; - - saved_persistent_indexes = store_persistent_indexes(); -} - -void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged(const QList &sourceParents) -{ - Q_Q(QSortFilterProxyModel); - - // Optimize: We only actually have to clear the mapping related to the contents of - // sourceParents, not everything. - qDeleteAll(source_index_mapping); - source_index_mapping.clear(); - - update_persistent_indexes(saved_persistent_indexes); - saved_persistent_indexes.clear(); - - if (dynamic_sortfilter && update_source_sort_column()) { - //update_source_sort_column might have created wrong mapping so we have to clear it again - qDeleteAll(source_index_mapping); - source_index_mapping.clear(); - } - - QList parents; - foreach (const QPersistentModelIndex &parent, sourceParents) { - if (!parent.isValid()) { - parents << QModelIndex(); - continue; - } - const QModelIndex mappedParent = q->mapFromSource(parent); - if (mappedParent.isValid()) - parents << mappedParent; - } - - if (!sourceParents.isEmpty() && parents.isEmpty()) - return; - - emit q->layoutChanged(parents); -} - -void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeInserted( - const QModelIndex &source_parent, int start, int end) -{ - Q_UNUSED(start); - Q_UNUSED(end); - //Force the creation of a mapping now, even if its empty. - //We need it because the proxy can be acessed at the moment it emits rowsAboutToBeInserted in insert_source_items - if (can_create_mapping(source_parent)) - create_mapping(source_parent); -} - -void QSortFilterProxyModelPrivate::_q_sourceRowsInserted( - const QModelIndex &source_parent, int start, int end) -{ - source_items_inserted(source_parent, start, end, Qt::Vertical); - if (update_source_sort_column() && dynamic_sortfilter) //previous call to update_source_sort_column may fail if the model has no column. - sort(); // now it should succeed so we need to make sure to sort again -} - -void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeRemoved( - const QModelIndex &source_parent, int start, int end) -{ - itemsBeingRemoved = QRowsRemoval(source_parent, start, end); - source_items_about_to_be_removed(source_parent, start, end, - Qt::Vertical); -} - -void QSortFilterProxyModelPrivate::_q_sourceRowsRemoved( - const QModelIndex &source_parent, int start, int end) -{ - itemsBeingRemoved = QRowsRemoval(); - source_items_removed(source_parent, start, end, Qt::Vertical); -} - -void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeMoved( - const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest) -{ - Q_Q(QSortFilterProxyModel); - // Because rows which are contiguous in the source model might not be contiguous - // in the proxy due to sorting, the best thing we can do here is be specific about what - // parents are having their children changed. - // Optimize: Emit move signals if the proxy is not sorted. Will need to account for rows - // being filtered out though. - - saved_persistent_indexes.clear(); - - QList parents; - parents << q->mapFromSource(sourceParent); - if (sourceParent != destParent) - parents << q->mapFromSource(destParent); - emit q->layoutAboutToBeChanged(parents); - if (persistent.indexes.isEmpty()) - return; - saved_persistent_indexes = store_persistent_indexes(); -} - -void QSortFilterProxyModelPrivate::_q_sourceRowsMoved( - const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest) -{ - Q_Q(QSortFilterProxyModel); - - // Optimize: We only need to clear and update the persistent indexes which are children of - // sourceParent or destParent - qDeleteAll(source_index_mapping); - source_index_mapping.clear(); - - update_persistent_indexes(saved_persistent_indexes); - saved_persistent_indexes.clear(); - - if (dynamic_sortfilter && update_source_sort_column()) { - //update_source_sort_column might have created wrong mapping so we have to clear it again - qDeleteAll(source_index_mapping); - source_index_mapping.clear(); - } - - QList parents; - parents << q->mapFromSource(sourceParent); - if (sourceParent != destParent) - parents << q->mapFromSource(destParent); - emit q->layoutChanged(parents); -} - -void QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeInserted( - const QModelIndex &source_parent, int start, int end) -{ - Q_UNUSED(start); - Q_UNUSED(end); - //Force the creation of a mapping now, even if its empty. - //We need it because the proxy can be acessed at the moment it emits columnsAboutToBeInserted in insert_source_items - if (can_create_mapping(source_parent)) - create_mapping(source_parent); -} - -void QSortFilterProxyModelPrivate::_q_sourceColumnsInserted( - const QModelIndex &source_parent, int start, int end) -{ - Q_Q(const QSortFilterProxyModel); - source_items_inserted(source_parent, start, end, Qt::Horizontal); - - if (source_parent.isValid()) - return; //we sort according to the root column only - if (source_sort_column == -1) { - //we update the source_sort_column depending on the proxy_sort_column - if (update_source_sort_column() && dynamic_sortfilter) - sort(); - } else { - if (start <= source_sort_column) - source_sort_column += end - start + 1; - - proxy_sort_column = q->mapFromSource(model->index(0,source_sort_column, source_parent)).column(); - } -} - -void QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeRemoved( - const QModelIndex &source_parent, int start, int end) -{ - source_items_about_to_be_removed(source_parent, start, end, - Qt::Horizontal); -} - -void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved( - const QModelIndex &source_parent, int start, int end) -{ - Q_Q(const QSortFilterProxyModel); - source_items_removed(source_parent, start, end, Qt::Horizontal); - - if (source_parent.isValid()) - return; //we sort according to the root column only - if (start <= source_sort_column) { - if (end < source_sort_column) - source_sort_column -= end - start + 1; - else - source_sort_column = -1; - } - - proxy_sort_column = q->mapFromSource(model->index(0,source_sort_column, source_parent)).column(); -} - -void QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeMoved( - const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest) -{ - Q_Q(QSortFilterProxyModel); - - saved_persistent_indexes.clear(); - - QList parents; - parents << q->mapFromSource(sourceParent); - if (sourceParent != destParent) - parents << q->mapFromSource(destParent); - emit q->layoutAboutToBeChanged(parents); - - if (persistent.indexes.isEmpty()) - return; - saved_persistent_indexes = store_persistent_indexes(); -} - -void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved( - const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest) -{ - Q_Q(QSortFilterProxyModel); - - qDeleteAll(source_index_mapping); - source_index_mapping.clear(); - - update_persistent_indexes(saved_persistent_indexes); - saved_persistent_indexes.clear(); - - if (dynamic_sortfilter && update_source_sort_column()) { - qDeleteAll(source_index_mapping); - source_index_mapping.clear(); - } - - QList parents; - parents << q->mapFromSource(sourceParent); - if (sourceParent != destParent) - parents << q->mapFromSource(destParent); - emit q->layoutChanged(parents); -} - -/*! - \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 - \inmodule QtWidgets - - 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: - - \snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 1 - - 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: - - \snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 0 - \snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 2 - - 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(). - - \note By default, the model does not dynamically re-sort and re-filter data - whenever the original model changes. This behavior can be changed by - setting the \l{QSortFilterProxyModel::dynamicSortFilter}{dynamicSortFilter} - property. - - The \l{itemviews/basicsortfiltermodel}{Basic Sort/Filter Model} and - \l{itemviews/customsortfiltermodel}{Custom Sort/Filter Model} examples - illustrate how to use QSortFilterProxyModel to perform basic sorting and - filtering and how to subclass it to implement custom behavior. - - \section1 Sorting - - QTableView and QTreeView have a - \l{QTreeView::sortingEnabled}{sortingEnabled} property that controls - whether the user can sort the view by clicking the view's horizontal - header. For example: - - \snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 3 - - When this feature is on (the default is off), 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 the model - to reorder the data in the model. To make your data sortable, you can - either implement sort() in your model, or use a QSortFilterProxyModel to - wrap your model -- QSortFilterProxyModel provides a generic sort() - reimplementation that operates on the sortRole() (Qt::DisplayRole by - default) of the items and that understands several data types, including - \c int, QString, and QDateTime. For hierarchical models, sorting is applied - recursively to all child items. String comparisons are case sensitive by - default; this can be changed by setting the \l{QSortFilterProxyModel::} - {sortCaseSensitivity} property. - - Custom sorting behavior is achieved by subclassing - QSortFilterProxyModel and reimplementing lessThan(), which is - used to compare items. For example: - - \snippet examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 5 - - (This code snippet comes from the - \l{itemviews/customsortfiltermodel}{Custom Sort/Filter Model} - example.) - - An alternative approach to sorting is to disable sorting on the view and to - impose a certain order to the user. This is done by explicitly calling - sort() with the desired column and order as arguments on the - QSortFilterProxyModel (or on the original model if it implements sort()). - For example: - - \snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 4 - - QSortFilterProxyModel can be sorted by column -1, in which case it returns - to the sort order of the underlying source model. - - \section1 Filtering - - In addition to sorting, QSortFilterProxyModel can be used to hide items - that do not match a certain filter. The filter is specified using a QRegExp - object and is applied to the filterRole() (Qt::DisplayRole by default) of - each item, for a given column. The QRegExp object can be used to match a - regular expression, a wildcard pattern, or a fixed string. For example: - - \snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 5 - - For hierarchical models, the filter is applied recursively to all children. - If a parent item doesn't match the filter, none of its children will be - shown. - - A common use case is to let the user specify the filter regexp, wildcard - pattern, or fixed string in a QLineEdit and to connect the - \l{QLineEdit::textChanged()}{textChanged()} signal to setFilterRegExp(), - setFilterWildcard(), or setFilterFixedString() to reapply the filter. - - Custom filtering behavior can be achieved by reimplementing the - filterAcceptsRow() and filterAcceptsColumn() functions. For - example (from the \l{itemviews/customsortfiltermodel} - {Custom Sort/Filter Model} example), the following implementation ignores - the \l{QSortFilterProxyModel::filterKeyColumn}{filterKeyColumn} property - and performs filtering on columns 0, 1, and 2: - - \snippet examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 3 - - (This code snippet comes from the - \l{itemviews/customsortfiltermodel}{Custom Sort/Filter Model} - example.) - - If you are working with large amounts of filtering and have to invoke - invalidateFilter() repeatedly, using reset() may be more efficient, - depending on the implementation of your model. However, reset() returns the - proxy model to its original state, losing selection information, and will - cause the proxy model to be repopulated. - - \section1 Subclassing - - Since QAbstractProxyModel and its subclasses are derived from - QAbstractItemModel, much of the same advice about subclassing normal models - also applies to proxy models. In addition, it is worth noting that many of - the default implementations of functions in this class are written so that - they call the equivalent functions in the relevant source model. This - simple proxying mechanism may need to be overridden for source models with - more complex behavior; for example, if the source model provides a custom - hasChildren() implementation, you should also provide one in the proxy - model. - - \note Some general guidelines for subclassing models are available in the - \l{Model Subclassing Reference}. - - \sa QAbstractProxyModel, QAbstractItemModel, {Model/View Programming}, - {Basic Sort/Filter Model Example}, {Custom Sort/Filter Model Example}, QIdentityProxyModel -*/ - -/*! - Constructs a sorting filter model with the given \a parent. -*/ - -QSortFilterProxyModel::QSortFilterProxyModel(QObject *parent) - : QAbstractProxyModel(*new QSortFilterProxyModelPrivate, parent) -{ - Q_D(QSortFilterProxyModel); - d->proxy_sort_column = d->source_sort_column = -1; - d->sort_order = Qt::AscendingOrder; - d->sort_casesensitivity = Qt::CaseSensitive; - d->sort_role = Qt::DisplayRole; - d->sort_localeaware = false; - d->filter_column = 0; - d->filter_role = Qt::DisplayRole; - d->dynamic_sortfilter = false; - connect(this, SIGNAL(modelReset()), this, SLOT(_q_clearMapping())); -} - -/*! - Destroys this sorting filter model. -*/ -QSortFilterProxyModel::~QSortFilterProxyModel() -{ - Q_D(QSortFilterProxyModel); - qDeleteAll(d->source_index_mapping); - d->source_index_mapping.clear(); -} - -/*! - \reimp -*/ -void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel) -{ - Q_D(QSortFilterProxyModel); - - beginResetModel(); - - disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex))); - - disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int))); - - disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsInserted(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsAboutToBeInserted(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsInserted(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsRemoved(QModelIndex,int,int))); - - disconnect(d->model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - - disconnect(d->model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int))); - - disconnect(d->model, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - - disconnect(d->model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int))); - - disconnect(d->model, SIGNAL(layoutAboutToBeChanged(QList)), - this, SLOT(_q_sourceLayoutAboutToBeChanged(QList))); - - disconnect(d->model, SIGNAL(layoutChanged(QList)), - this, SLOT(_q_sourceLayoutChanged(QList))); - - disconnect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset())); - disconnect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset())); - - QAbstractProxyModel::setSourceModel(sourceModel); - - connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex))); - - connect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int))); - - connect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int))); - - connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsInserted(QModelIndex,int,int))); - - connect(d->model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsAboutToBeInserted(QModelIndex,int,int))); - - connect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsInserted(QModelIndex,int,int))); - - connect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int))); - - connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int))); - - connect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int))); - - connect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sourceColumnsRemoved(QModelIndex,int,int))); - - connect(d->model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - - connect(d->model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int))); - - connect(d->model, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - - connect(d->model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int))); - - connect(d->model, SIGNAL(layoutAboutToBeChanged(QList)), - this, SLOT(_q_sourceLayoutAboutToBeChanged(QList))); - - connect(d->model, SIGNAL(layoutChanged(QList)), - this, SLOT(_q_sourceLayoutChanged(QList))); - - connect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset())); - connect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset())); - - d->_q_clearMapping(); - endResetModel(); - if (d->update_source_sort_column() && d->dynamic_sortfilter) - d->sort(); -} - -/*! - \reimp -*/ -QModelIndex QSortFilterProxyModel::index(int row, int column, const QModelIndex &parent) const -{ - Q_D(const QSortFilterProxyModel); - if (row < 0 || column < 0) - return QModelIndex(); - - QModelIndex source_parent = mapToSource(parent); // parent is already mapped at this point - IndexMap::const_iterator it = d->create_mapping(source_parent); // but make sure that the children are mapped - if (it.value()->source_rows.count() <= row || it.value()->source_columns.count() <= column) - return QModelIndex(); - - return d->create_index(row, column, it); -} - -/*! - \reimp -*/ -QModelIndex QSortFilterProxyModel::parent(const QModelIndex &child) const -{ - Q_D(const QSortFilterProxyModel); - if (!d->indexValid(child)) - return QModelIndex(); - IndexMap::const_iterator it = d->index_to_iterator(child); - Q_ASSERT(it != d->source_index_mapping.constEnd()); - QModelIndex source_parent = it.key(); - QModelIndex proxy_parent = mapFromSource(source_parent); - return proxy_parent; -} - -/*! - \reimp -*/ -int QSortFilterProxyModel::rowCount(const QModelIndex &parent) const -{ - Q_D(const QSortFilterProxyModel); - QModelIndex source_parent = mapToSource(parent); - if (parent.isValid() && !source_parent.isValid()) - return 0; - IndexMap::const_iterator it = d->create_mapping(source_parent); - return it.value()->source_rows.count(); -} - -/*! - \reimp -*/ -int QSortFilterProxyModel::columnCount(const QModelIndex &parent) const -{ - Q_D(const QSortFilterProxyModel); - QModelIndex source_parent = mapToSource(parent); - if (parent.isValid() && !source_parent.isValid()) - return 0; - IndexMap::const_iterator it = d->create_mapping(source_parent); - return it.value()->source_columns.count(); -} - -/*! - \reimp -*/ -bool QSortFilterProxyModel::hasChildren(const QModelIndex &parent) const -{ - Q_D(const QSortFilterProxyModel); - QModelIndex source_parent = mapToSource(parent); - if (parent.isValid() && !source_parent.isValid()) - return false; - if (!d->model->hasChildren(source_parent)) - return false; - - if (d->model->canFetchMore(source_parent)) - return true; //we assume we might have children that can be fetched - - QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value(); - return m->source_rows.count() != 0 && m->source_columns.count() != 0; -} - -/*! - \reimp -*/ -QVariant QSortFilterProxyModel::data(const QModelIndex &index, int role) const -{ - Q_D(const QSortFilterProxyModel); - QModelIndex source_index = mapToSource(index); - if (index.isValid() && !source_index.isValid()) - return QVariant(); - return d->model->data(source_index, role); -} - -/*! - \reimp -*/ -bool QSortFilterProxyModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - Q_D(QSortFilterProxyModel); - QModelIndex source_index = mapToSource(index); - if (index.isValid() && !source_index.isValid()) - return false; - return d->model->setData(source_index, value, role); -} - -/*! - \reimp -*/ -QVariant QSortFilterProxyModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - Q_D(const QSortFilterProxyModel); - IndexMap::const_iterator it = d->create_mapping(QModelIndex()); - if (it.value()->source_rows.count() * it.value()->source_columns.count() > 0) - return QAbstractProxyModel::headerData(section, orientation, role); - int source_section; - if (orientation == Qt::Vertical) { - if (section < 0 || section >= it.value()->source_rows.count()) - return QVariant(); - source_section = it.value()->source_rows.at(section); - } else { - if (section < 0 || section >= it.value()->source_columns.count()) - return QVariant(); - source_section = it.value()->source_columns.at(section); - } - return d->model->headerData(source_section, orientation, role); -} - -/*! - \reimp -*/ -bool QSortFilterProxyModel::setHeaderData(int section, Qt::Orientation orientation, - const QVariant &value, int role) -{ - Q_D(QSortFilterProxyModel); - IndexMap::const_iterator it = d->create_mapping(QModelIndex()); - if (it.value()->source_rows.count() * it.value()->source_columns.count() > 0) - return QAbstractProxyModel::setHeaderData(section, orientation, value, role); - int source_section; - if (orientation == Qt::Vertical) { - if (section < 0 || section >= it.value()->source_rows.count()) - return false; - source_section = it.value()->source_rows.at(section); - } else { - if (section < 0 || section >= it.value()->source_columns.count()) - return false; - source_section = it.value()->source_columns.at(section); - } - return d->model->setHeaderData(source_section, orientation, value, role); -} - -/*! - \reimp -*/ -QMimeData *QSortFilterProxyModel::mimeData(const QModelIndexList &indexes) const -{ - Q_D(const QSortFilterProxyModel); - QModelIndexList source_indexes; - for (int i = 0; i < indexes.count(); ++i) - source_indexes << mapToSource(indexes.at(i)); - return d->model->mimeData(source_indexes); -} - -/*! - \reimp -*/ -QStringList QSortFilterProxyModel::mimeTypes() const -{ - Q_D(const QSortFilterProxyModel); - return d->model->mimeTypes(); -} - -/*! - \reimp -*/ -Qt::DropActions QSortFilterProxyModel::supportedDropActions() const -{ - Q_D(const QSortFilterProxyModel); - return d->model->supportedDropActions(); -} - -/*! - \reimp -*/ -bool QSortFilterProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action, - int row, int column, const QModelIndex &parent) -{ - Q_D(QSortFilterProxyModel); - if ((row == -1) && (column == -1)) - return d->model->dropMimeData(data, action, -1, -1, mapToSource(parent)); - int source_destination_row = -1; - int source_destination_column = -1; - QModelIndex source_parent; - if (row == rowCount(parent)) { - source_parent = mapToSource(parent); - source_destination_row = d->model->rowCount(source_parent); - } else { - QModelIndex proxy_index = index(row, column, parent); - QModelIndex source_index = mapToSource(proxy_index); - source_destination_row = source_index.row(); - source_destination_column = source_index.column(); - source_parent = source_index.parent(); - } - return d->model->dropMimeData(data, action, source_destination_row, - source_destination_column, source_parent); -} - -/*! - \reimp -*/ -bool QSortFilterProxyModel::insertRows(int row, int count, const QModelIndex &parent) -{ - Q_D(QSortFilterProxyModel); - if (row < 0 || count <= 0) - return false; - QModelIndex source_parent = mapToSource(parent); - if (parent.isValid() && !source_parent.isValid()) - return false; - QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value(); - if (row > m->source_rows.count()) - return false; - int source_row = (row >= m->source_rows.count() - ? m->source_rows.count() - : m->source_rows.at(row)); - return d->model->insertRows(source_row, count, source_parent); -} - -/*! - \reimp -*/ -bool QSortFilterProxyModel::insertColumns(int column, int count, const QModelIndex &parent) -{ - Q_D(QSortFilterProxyModel); - if (column < 0|| count <= 0) - return false; - QModelIndex source_parent = mapToSource(parent); - if (parent.isValid() && !source_parent.isValid()) - return false; - QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value(); - if (column > m->source_columns.count()) - return false; - int source_column = (column >= m->source_columns.count() - ? m->source_columns.count() - : m->source_columns.at(column)); - return d->model->insertColumns(source_column, count, source_parent); -} - -/*! - \reimp -*/ -bool QSortFilterProxyModel::removeRows(int row, int count, const QModelIndex &parent) -{ - Q_D(QSortFilterProxyModel); - if (row < 0 || count <= 0) - return false; - QModelIndex source_parent = mapToSource(parent); - if (parent.isValid() && !source_parent.isValid()) - return false; - QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value(); - if (row + count > m->source_rows.count()) - return false; - if ((count == 1) - || ((d->source_sort_column < 0) && (m->proxy_rows.count() == m->source_rows.count()))) { - int source_row = m->source_rows.at(row); - return d->model->removeRows(source_row, count, source_parent); - } - // remove corresponding source intervals - // ### if this proves to be slow, we can switch to single-row removal - QVector rows; - for (int i = row; i < row + count; ++i) - rows.append(m->source_rows.at(i)); - qSort(rows.begin(), rows.end()); - - int pos = rows.count() - 1; - bool ok = true; - while (pos >= 0) { - const int source_end = rows.at(pos--); - int source_start = source_end; - while ((pos >= 0) && (rows.at(pos) == (source_start - 1))) { - --source_start; - --pos; - } - ok = ok && d->model->removeRows(source_start, source_end - source_start + 1, - source_parent); - } - return ok; -} - -/*! - \reimp -*/ -bool QSortFilterProxyModel::removeColumns(int column, int count, const QModelIndex &parent) -{ - Q_D(QSortFilterProxyModel); - if (column < 0 || count <= 0) - return false; - QModelIndex source_parent = mapToSource(parent); - if (parent.isValid() && !source_parent.isValid()) - return false; - QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value(); - if (column + count > m->source_columns.count()) - return false; - if ((count == 1) || (m->proxy_columns.count() == m->source_columns.count())) { - int source_column = m->source_columns.at(column); - return d->model->removeColumns(source_column, count, source_parent); - } - // remove corresponding source intervals - QVector columns; - for (int i = column; i < column + count; ++i) - columns.append(m->source_columns.at(i)); - - int pos = columns.count() - 1; - bool ok = true; - while (pos >= 0) { - const int source_end = columns.at(pos--); - int source_start = source_end; - while ((pos >= 0) && (columns.at(pos) == (source_start - 1))) { - --source_start; - --pos; - } - ok = ok && d->model->removeColumns(source_start, source_end - source_start + 1, - source_parent); - } - return ok; -} - -/*! - \reimp -*/ -void QSortFilterProxyModel::fetchMore(const QModelIndex &parent) -{ - Q_D(QSortFilterProxyModel); - QModelIndex source_parent; - if (d->indexValid(parent)) - source_parent = mapToSource(parent); - d->model->fetchMore(source_parent); -} - -/*! - \reimp -*/ -bool QSortFilterProxyModel::canFetchMore(const QModelIndex &parent) const -{ - Q_D(const QSortFilterProxyModel); - QModelIndex source_parent; - if (d->indexValid(parent)) - source_parent = mapToSource(parent); - return d->model->canFetchMore(source_parent); -} - -/*! - \reimp -*/ -Qt::ItemFlags QSortFilterProxyModel::flags(const QModelIndex &index) const -{ - Q_D(const QSortFilterProxyModel); - QModelIndex source_index; - if (d->indexValid(index)) - source_index = mapToSource(index); - return d->model->flags(source_index); -} - -/*! - \reimp -*/ -QModelIndex QSortFilterProxyModel::buddy(const QModelIndex &index) const -{ - Q_D(const QSortFilterProxyModel); - if (!d->indexValid(index)) - return QModelIndex(); - QModelIndex source_index = mapToSource(index); - QModelIndex source_buddy = d->model->buddy(source_index); - if (source_index == source_buddy) - return index; - return mapFromSource(source_buddy); -} - -/*! - \reimp -*/ -QModelIndexList QSortFilterProxyModel::match(const QModelIndex &start, int role, - const QVariant &value, int hits, - Qt::MatchFlags flags) const -{ - return QAbstractProxyModel::match(start, role, value, hits, flags); -} - -/*! - \reimp -*/ -QSize QSortFilterProxyModel::span(const QModelIndex &index) const -{ - Q_D(const QSortFilterProxyModel); - QModelIndex source_index = mapToSource(index); - if (index.isValid() && !source_index.isValid()) - return QSize(); - return d->model->span(source_index); -} - -/*! - \reimp -*/ -void QSortFilterProxyModel::sort(int column, Qt::SortOrder order) -{ - Q_D(QSortFilterProxyModel); - if (d->dynamic_sortfilter && d->proxy_sort_column == column && d->sort_order == order) - return; - d->sort_order = order; - d->proxy_sort_column = column; - d->update_source_sort_column(); - d->sort(); -} - -/*! - \since 4.5 - \brief the column currently used for sorting - - This returns the most recently used sort column. -*/ -int QSortFilterProxyModel::sortColumn() const -{ - Q_D(const QSortFilterProxyModel); - return d->proxy_sort_column; -} - -/*! - \since 4.5 - \brief the order currently used for sorting - - This returns the most recently used sort order. -*/ -Qt::SortOrder QSortFilterProxyModel::sortOrder() const -{ - Q_D(const QSortFilterProxyModel); - return d->sort_order; -} - -/*! - \property QSortFilterProxyModel::filterRegExp - \brief the QRegExp used to filter the contents of the source model - - Setting this property overwrites the current - \l{QSortFilterProxyModel::filterCaseSensitivity}{filterCaseSensitivity}. - By default, the QRegExp is an empty string matching all contents. - - If no QRegExp or an empty string is set, everything in the source model - will be accepted. - - \sa filterCaseSensitivity, setFilterWildcard(), setFilterFixedString() -*/ -QRegExp QSortFilterProxyModel::filterRegExp() const -{ - Q_D(const QSortFilterProxyModel); - return d->filter_regexp; -} - -void QSortFilterProxyModel::setFilterRegExp(const QRegExp ®Exp) -{ - Q_D(QSortFilterProxyModel); - d->filter_regexp = regExp; - d->filter_changed(); -} - -/*! - \property QSortFilterProxyModel::filterKeyColumn - \brief the column where the key used to filter the contents of the - source model is read from. - - The default value is 0. If the value is -1, the keys will be read - from all columns. -*/ -int QSortFilterProxyModel::filterKeyColumn() const -{ - Q_D(const QSortFilterProxyModel); - return d->filter_column; -} - -void QSortFilterProxyModel::setFilterKeyColumn(int column) -{ - Q_D(QSortFilterProxyModel); - d->filter_column = column; - d->filter_changed(); -} - -/*! - \property QSortFilterProxyModel::filterCaseSensitivity - - \brief the case sensitivity of the QRegExp pattern used to filter the - contents of the source model - - By default, the filter is case sensitive. - - \sa filterRegExp, sortCaseSensitivity -*/ -Qt::CaseSensitivity QSortFilterProxyModel::filterCaseSensitivity() const -{ - Q_D(const QSortFilterProxyModel); - return d->filter_regexp.caseSensitivity(); -} - -void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs) -{ - Q_D(QSortFilterProxyModel); - if (cs == d->filter_regexp.caseSensitivity()) - return; - d->filter_regexp.setCaseSensitivity(cs); - d->filter_changed(); -} - -/*! - \since 4.2 - \property QSortFilterProxyModel::sortCaseSensitivity - \brief the case sensitivity setting used for comparing strings when sorting - - By default, sorting is case sensitive. - - \sa filterCaseSensitivity, lessThan() -*/ -Qt::CaseSensitivity QSortFilterProxyModel::sortCaseSensitivity() const -{ - Q_D(const QSortFilterProxyModel); - return d->sort_casesensitivity; -} - -void QSortFilterProxyModel::setSortCaseSensitivity(Qt::CaseSensitivity cs) -{ - Q_D(QSortFilterProxyModel); - if (d->sort_casesensitivity == cs) - return; - - d->sort_casesensitivity = cs; - d->sort(); -} - -/*! - \since 4.3 - \property QSortFilterProxyModel::isSortLocaleAware - \brief the local aware setting used for comparing strings when sorting - - By default, sorting is not local aware. - - \sa sortCaseSensitivity, lessThan() -*/ -bool QSortFilterProxyModel::isSortLocaleAware() const -{ - Q_D(const QSortFilterProxyModel); - return d->sort_localeaware; -} - -void QSortFilterProxyModel::setSortLocaleAware(bool on) -{ - Q_D(QSortFilterProxyModel); - if (d->sort_localeaware == on) - return; - - d->sort_localeaware = on; - d->sort(); -} - -/*! - \overload - - Sets the regular expression used to filter the contents - of the source model to \a pattern. - - \sa setFilterCaseSensitivity(), setFilterWildcard(), setFilterFixedString(), filterRegExp() -*/ -void QSortFilterProxyModel::setFilterRegExp(const QString &pattern) -{ - Q_D(QSortFilterProxyModel); - d->filter_regexp.setPatternSyntax(QRegExp::RegExp); - d->filter_regexp.setPattern(pattern); - d->filter_changed(); -} - -/*! - Sets the wildcard expression used to filter the contents - of the source model to the given \a pattern. - - \sa setFilterCaseSensitivity(), setFilterRegExp(), setFilterFixedString(), filterRegExp() -*/ -void QSortFilterProxyModel::setFilterWildcard(const QString &pattern) -{ - Q_D(QSortFilterProxyModel); - d->filter_regexp.setPatternSyntax(QRegExp::Wildcard); - d->filter_regexp.setPattern(pattern); - d->filter_changed(); -} - -/*! - Sets the fixed string used to filter the contents - of the source model to the given \a pattern. - - \sa setFilterCaseSensitivity(), setFilterRegExp(), setFilterWildcard(), filterRegExp() -*/ -void QSortFilterProxyModel::setFilterFixedString(const QString &pattern) -{ - Q_D(QSortFilterProxyModel); - d->filter_regexp.setPatternSyntax(QRegExp::FixedString); - d->filter_regexp.setPattern(pattern); - d->filter_changed(); -} - -/*! - \since 4.2 - \property QSortFilterProxyModel::dynamicSortFilter - \brief whether the proxy model is dynamically sorted and filtered - whenever the contents of the source model change - - Note that you should not update the source model through the proxy - model when dynamicSortFilter is true. For instance, if you set the - proxy model on a QComboBox, then using functions that update the - model, e.g., \l{QComboBox::}{addItem()}, will not work as - expected. An alternative is to set dynamicSortFilter to false and - call \l{QSortFilterProxyModel::}{sort()} after adding items to the - QComboBox. - - The default value is false. -*/ -bool QSortFilterProxyModel::dynamicSortFilter() const -{ - Q_D(const QSortFilterProxyModel); - return d->dynamic_sortfilter; -} - -void QSortFilterProxyModel::setDynamicSortFilter(bool enable) -{ - Q_D(QSortFilterProxyModel); - d->dynamic_sortfilter = enable; - if (enable) - d->sort(); -} - -/*! - \since 4.2 - \property QSortFilterProxyModel::sortRole - \brief the item role that is used to query the source model's data when sorting items - - The default value is Qt::DisplayRole. - - \sa lessThan() -*/ -int QSortFilterProxyModel::sortRole() const -{ - Q_D(const QSortFilterProxyModel); - return d->sort_role; -} - -void QSortFilterProxyModel::setSortRole(int role) -{ - Q_D(QSortFilterProxyModel); - if (d->sort_role == role) - return; - d->sort_role = role; - d->sort(); -} - -/*! - \since 4.2 - \property QSortFilterProxyModel::filterRole - \brief the item role that is used to query the source model's data when filtering items - - The default value is Qt::DisplayRole. - - \sa filterAcceptsRow() -*/ -int QSortFilterProxyModel::filterRole() const -{ - Q_D(const QSortFilterProxyModel); - return d->filter_role; -} - -void QSortFilterProxyModel::setFilterRole(int role) -{ - Q_D(QSortFilterProxyModel); - if (d->filter_role == role) - return; - d->filter_role = role; - d->filter_changed(); -} - -/*! - \obsolete - - This function is obsolete. Use invalidate() instead. -*/ -void QSortFilterProxyModel::clear() -{ - Q_D(QSortFilterProxyModel); - emit layoutAboutToBeChanged(); - d->_q_clearMapping(); - emit layoutChanged(); -} - -/*! - \since 4.3 - - Invalidates the current sorting and filtering. - - \sa invalidateFilter() -*/ -void QSortFilterProxyModel::invalidate() -{ - Q_D(QSortFilterProxyModel); - emit layoutAboutToBeChanged(); - d->_q_clearMapping(); - emit layoutChanged(); -} - -/*! - \obsolete - - This function is obsolete. Use invalidateFilter() instead. -*/ -void QSortFilterProxyModel::filterChanged() -{ - Q_D(QSortFilterProxyModel); - d->filter_changed(); -} - -/*! - \since 4.3 - - Invalidates the current filtering. - - This function should be called if you are implementing custom filtering - (e.g. filterAcceptsRow()), and your filter parameters have changed. - - \sa invalidate() -*/ -void QSortFilterProxyModel::invalidateFilter() -{ - Q_D(QSortFilterProxyModel); - d->filter_changed(); -} - -/*! - Returns true if the value of the item referred to by the given - index \a left is less than the value of the item referred to by - the given index \a right, otherwise returns false. - - This function is used as the < operator when sorting, and handles - the following QVariant types: - - \list - \o QVariant::Int - \o QVariant::UInt - \o QVariant::LongLong - \o QVariant::ULongLong - \o QVariant::Double - \o QVariant::Char - \o QVariant::Date - \o QVariant::Time - \o QVariant::DateTime - \o QVariant::String - \endlist - - Any other type will be converted to a QString using - QVariant::toString(). - - Comparison of \l{QString}s is case sensitive by default; this can - be changed using the \l {QSortFilterProxyModel::sortCaseSensitivity} - {sortCaseSensitivity} property. - - By default, the Qt::DisplayRole associated with the - \l{QModelIndex}es is used for comparisons. This can be changed by - setting the \l {QSortFilterProxyModel::sortRole} {sortRole} property. - - \note The indices passed in correspond to the source model. - - \sa sortRole, sortCaseSensitivity, dynamicSortFilter -*/ -bool QSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const -{ - Q_D(const QSortFilterProxyModel); - QVariant l = (left.model() ? left.model()->data(left, d->sort_role) : QVariant()); - QVariant r = (right.model() ? right.model()->data(right, d->sort_role) : QVariant()); - switch (l.userType()) { - case QVariant::Invalid: - return (r.type() != QVariant::Invalid); - case QVariant::Int: - return l.toInt() < r.toInt(); - case QVariant::UInt: - return l.toUInt() < r.toUInt(); - case QVariant::LongLong: - return l.toLongLong() < r.toLongLong(); - case QVariant::ULongLong: - return l.toULongLong() < r.toULongLong(); - case QMetaType::Float: - return l.toFloat() < r.toFloat(); - case QVariant::Double: - return l.toDouble() < r.toDouble(); - case QVariant::Char: - return l.toChar() < r.toChar(); - case QVariant::Date: - return l.toDate() < r.toDate(); - case QVariant::Time: - return l.toTime() < r.toTime(); - case QVariant::DateTime: - return l.toDateTime() < r.toDateTime(); - case QVariant::String: - default: - if (d->sort_localeaware) - return l.toString().localeAwareCompare(r.toString()) < 0; - else - return l.toString().compare(r.toString(), d->sort_casesensitivity) < 0; - } - return false; -} - -/*! - Returns true if the item in the row indicated by the given \a source_row - and \a source_parent should be included in the model; otherwise returns - false. - - The default implementation returns true if the value held by the relevant item - matches the filter string, wildcard string or regular expression. - - \note By default, the Qt::DisplayRole is used to determine if the row - should be accepted or not. This can be changed by setting the - \l{QSortFilterProxyModel::filterRole}{filterRole} property. - - \sa filterAcceptsColumn(), setFilterFixedString(), setFilterRegExp(), setFilterWildcard() -*/ -bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const -{ - Q_D(const QSortFilterProxyModel); - if (d->filter_regexp.isEmpty()) - return true; - if (d->filter_column == -1) { - int column_count = d->model->columnCount(source_parent); - for (int column = 0; column < column_count; ++column) { - QModelIndex source_index = d->model->index(source_row, column, source_parent); - QString key = d->model->data(source_index, d->filter_role).toString(); - if (key.contains(d->filter_regexp)) - return true; - } - return false; - } - QModelIndex source_index = d->model->index(source_row, d->filter_column, source_parent); - if (!source_index.isValid()) // the column may not exist - return true; - QString key = d->model->data(source_index, d->filter_role).toString(); - return key.contains(d->filter_regexp); -} - -/*! - Returns true if the item in the column indicated by the given \a source_column - and \a source_parent should be included in the model; otherwise returns false. - - The default implementation returns true if the value held by the relevant item - matches the filter string, wildcard string or regular expression. - - \note By default, the Qt::DisplayRole is used to determine if the row - should be accepted or not. This can be changed by setting the \l - filterRole property. - - \sa filterAcceptsRow(), setFilterFixedString(), setFilterRegExp(), setFilterWildcard() -*/ -bool QSortFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const -{ - Q_UNUSED(source_column); - Q_UNUSED(source_parent); - return true; -} - -/*! - Returns the source model index corresponding to the given \a - proxyIndex from the sorting filter model. - - \sa mapFromSource() -*/ -QModelIndex QSortFilterProxyModel::mapToSource(const QModelIndex &proxyIndex) const -{ - Q_D(const QSortFilterProxyModel); - return d->proxy_to_source(proxyIndex); -} - -/*! - Returns the model index in the QSortFilterProxyModel given the \a - sourceIndex from the source model. - - \sa mapToSource() -*/ -QModelIndex QSortFilterProxyModel::mapFromSource(const QModelIndex &sourceIndex) const -{ - Q_D(const QSortFilterProxyModel); - return d->source_to_proxy(sourceIndex); -} - -/*! - \reimp -*/ -QItemSelection QSortFilterProxyModel::mapSelectionToSource(const QItemSelection &proxySelection) const -{ - return QAbstractProxyModel::mapSelectionToSource(proxySelection); -} - -/*! - \reimp -*/ -QItemSelection QSortFilterProxyModel::mapSelectionFromSource(const QItemSelection &sourceSelection) const -{ - return QAbstractProxyModel::mapSelectionFromSource(sourceSelection); -} - -/*! - \fn QObject *QSortFilterProxyModel::parent() const - \internal -*/ - -QT_END_NAMESPACE - -#include "moc_qsortfilterproxymodel.cpp" - -#endif // QT_NO_SORTFILTERPROXYMODEL diff --git a/src/widgets/itemviews/qsortfilterproxymodel.h b/src/widgets/itemviews/qsortfilterproxymodel.h deleted file mode 100644 index bbeec1470c..0000000000 --- a/src/widgets/itemviews/qsortfilterproxymodel.h +++ /dev/null @@ -1,205 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSORTFILTERPROXYMODEL_H -#define QSORTFILTERPROXYMODEL_H - -#include - -#ifndef QT_NO_SORTFILTERPROXYMODEL - -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QSortFilterProxyModelPrivate; -class QSortFilterProxyModelLessThan; -class QSortFilterProxyModelGreaterThan; - -class Q_WIDGETS_EXPORT QSortFilterProxyModel : public QAbstractProxyModel -{ - friend class QSortFilterProxyModelLessThan; - friend class QSortFilterProxyModelGreaterThan; - - Q_OBJECT - Q_PROPERTY(QRegExp filterRegExp READ filterRegExp WRITE setFilterRegExp) - Q_PROPERTY(int filterKeyColumn READ filterKeyColumn WRITE setFilterKeyColumn) - Q_PROPERTY(bool dynamicSortFilter READ dynamicSortFilter WRITE setDynamicSortFilter) - Q_PROPERTY(Qt::CaseSensitivity filterCaseSensitivity READ filterCaseSensitivity WRITE setFilterCaseSensitivity) - Q_PROPERTY(Qt::CaseSensitivity sortCaseSensitivity READ sortCaseSensitivity WRITE setSortCaseSensitivity) - Q_PROPERTY(bool isSortLocaleAware READ isSortLocaleAware WRITE setSortLocaleAware) - Q_PROPERTY(int sortRole READ sortRole WRITE setSortRole) - Q_PROPERTY(int filterRole READ filterRole WRITE setFilterRole) - -public: - QSortFilterProxyModel(QObject *parent = 0); - ~QSortFilterProxyModel(); - - void setSourceModel(QAbstractItemModel *sourceModel); - - QModelIndex mapToSource(const QModelIndex &proxyIndex) const; - QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; - - QItemSelection mapSelectionToSource(const QItemSelection &proxySelection) const; - QItemSelection mapSelectionFromSource(const QItemSelection &sourceSelection) const; - - QRegExp filterRegExp() const; - void setFilterRegExp(const QRegExp ®Exp); - - int filterKeyColumn() const; - void setFilterKeyColumn(int column); - - Qt::CaseSensitivity filterCaseSensitivity() const; - void setFilterCaseSensitivity(Qt::CaseSensitivity cs); - - Qt::CaseSensitivity sortCaseSensitivity() const; - void setSortCaseSensitivity(Qt::CaseSensitivity cs); - - bool isSortLocaleAware() const; - void setSortLocaleAware(bool on); - - int sortColumn() const; - Qt::SortOrder sortOrder() const; - - bool dynamicSortFilter() const; - void setDynamicSortFilter(bool enable); - - int sortRole() const; - void setSortRole(int role); - - int filterRole() const; - void setFilterRole(int role); - -public Q_SLOTS: - void setFilterRegExp(const QString &pattern); - void setFilterWildcard(const QString &pattern); - void setFilterFixedString(const QString &pattern); - void clear(); - void invalidate(); - -protected: - virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; - virtual bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const; - virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; - - void filterChanged(); - void invalidateFilter(); - -public: -#ifdef Q_NO_USING_KEYWORD - inline QObject *parent() const { return QObject::parent(); } -#else - using QObject::parent; -#endif - - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &child) const; - - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - bool hasChildren(const QModelIndex &parent = QModelIndex()) const; - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - bool setHeaderData(int section, Qt::Orientation orientation, - const QVariant &value, int role = Qt::EditRole); - - QMimeData *mimeData(const QModelIndexList &indexes) const; - bool dropMimeData(const QMimeData *data, Qt::DropAction action, - int row, int column, const QModelIndex &parent); - - bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()); - bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()); - bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); - bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()); - - void fetchMore(const QModelIndex &parent); - bool canFetchMore(const QModelIndex &parent) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - - QModelIndex buddy(const QModelIndex &index) const; - QModelIndexList match(const QModelIndex &start, int role, - const QVariant &value, int hits = 1, - Qt::MatchFlags flags = - Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const; - QSize span(const QModelIndex &index) const; - void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); - - QStringList mimeTypes() const; - Qt::DropActions supportedDropActions() const; -private: - Q_DECLARE_PRIVATE(QSortFilterProxyModel) - Q_DISABLE_COPY(QSortFilterProxyModel) - - Q_PRIVATE_SLOT(d_func(), void _q_sourceDataChanged(const QModelIndex &source_top_left, const QModelIndex &source_bottom_right)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceAboutToBeReset()) - Q_PRIVATE_SLOT(d_func(), void _q_sourceReset()) - Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutAboutToBeChanged(const QList &sourceParents)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutChanged(const QList &sourceParents)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsInserted(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsRemoved(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeInserted(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsInserted(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsRemoved(const QModelIndex &source_parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) - Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int)) - Q_PRIVATE_SLOT(d_func(), void _q_clearMapping()) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QT_NO_SORTFILTERPROXYMODEL - -#endif // QSORTFILTERPROXYMODEL_H diff --git a/src/widgets/itemviews/qstringlistmodel.cpp b/src/widgets/itemviews/qstringlistmodel.cpp deleted file mode 100644 index 95c0456765..0000000000 --- a/src/widgets/itemviews/qstringlistmodel.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/* - A simple model that uses a QStringList as its data source. -*/ - -#include "qstringlistmodel.h" - -#include - -#ifndef QT_NO_STRINGLISTMODEL - -QT_BEGIN_NAMESPACE - -/*! - \class QStringListModel - \brief The QStringListModel class provides a model that supplies strings to views. - - \ingroup model-view - \inmodule QtWidgets - - QStringListModel is an editable model that can be used for simple - cases where you need to display a number of strings in a view - widget, such as a QListView or a QComboBox. - - The model provides all the standard functions of an editable - model, representing the data in the string list as a model with - one column and a number of rows equal to the number of items in - the list. - - Model indexes corresponding to items are obtained with the - \l{QAbstractListModel::index()}{index()} function, and item flags - are obtained with flags(). Item data is read with the data() - function and written with setData(). The number of rows (and - number of items in the string list) can be found with the - rowCount() function. - - The model can be constructed with an existing string list, or - strings can be set later with the setStringList() convenience - function. Strings can also be inserted in the usual way with the - insertRows() function, and removed with removeRows(). The contents - of the string list can be retrieved with the stringList() - convenience function. - - An example usage of QStringListModel: - - \snippet doc/src/snippets/qstringlistmodel/main.cpp 0 - - \sa QAbstractListModel, QAbstractItemModel, {Model Classes} -*/ - -/*! - Constructs a string list model with the given \a parent. -*/ - -QStringListModel::QStringListModel(QObject *parent) - : QAbstractListModel(parent) -{ -} - -/*! - Constructs a string list model containing the specified \a strings - with the given \a parent. -*/ - -QStringListModel::QStringListModel(const QStringList &strings, QObject *parent) - : QAbstractListModel(parent), lst(strings) -{ -} - -/*! - Returns the number of rows in the model. This value corresponds to the - number of items in the model's internal string list. - - The optional \a parent argument is in most models used to specify - the parent of the rows to be counted. Because this is a list if a - valid parent is specified, the result will always be 0. - - \sa insertRows(), removeRows(), QAbstractItemModel::rowCount() -*/ - -int QStringListModel::rowCount(const QModelIndex &parent) const -{ - if (parent.isValid()) - return 0; - - return lst.count(); -} - -/*! - Returns data for the specified \a role, from the item with the - given \a index. - - If the view requests an invalid index, an invalid variant is returned. - - \sa setData() -*/ - -QVariant QStringListModel::data(const QModelIndex &index, int role) const -{ - if (index.row() < 0 || index.row() >= lst.size()) - return QVariant(); - - if (role == Qt::DisplayRole || role == Qt::EditRole) - return lst.at(index.row()); - - return QVariant(); -} - -/*! - Returns the flags for the item with the given \a index. - - Valid items are enabled, selectable, editable, drag enabled and drop enabled. - - \sa QAbstractItemModel::flags() -*/ - -Qt::ItemFlags QStringListModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return QAbstractItemModel::flags(index) | Qt::ItemIsDropEnabled; - - return QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; -} - -/*! - Sets the data for the specified \a role in the item with the given - \a index in the model, to the provided \a value. - - The dataChanged() signal is emitted if the item is changed. - - \sa Qt::ItemDataRole, data() -*/ - -bool QStringListModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - if (index.row() >= 0 && index.row() < lst.size() - && (role == Qt::EditRole || role == Qt::DisplayRole)) { - lst.replace(index.row(), value.toString()); - emit dataChanged(index, index); - return true; - } - return false; -} - -/*! - Inserts \a count rows into the model, beginning at the given \a row. - - The \a parent index of the rows is optional and is only used for - consistency with QAbstractItemModel. By default, a null index is - specified, indicating that the rows are inserted in the top level of - the model. - - \sa QAbstractItemModel::insertRows() -*/ - -bool QStringListModel::insertRows(int row, int count, const QModelIndex &parent) -{ - if (count < 1 || row < 0 || row > rowCount(parent)) - return false; - - beginInsertRows(QModelIndex(), row, row + count - 1); - - for (int r = 0; r < count; ++r) - lst.insert(row, QString()); - - endInsertRows(); - - return true; -} - -/*! - Removes \a count rows from the model, beginning at the given \a row. - - The \a parent index of the rows is optional and is only used for - consistency with QAbstractItemModel. By default, a null index is - specified, indicating that the rows are removed in the top level of - the model. - - \sa QAbstractItemModel::removeRows() -*/ - -bool QStringListModel::removeRows(int row, int count, const QModelIndex &parent) -{ - if (count <= 0 || row < 0 || (row + count) > rowCount(parent)) - return false; - - beginRemoveRows(QModelIndex(), row, row + count - 1); - - for (int r = 0; r < count; ++r) - lst.removeAt(row); - - endRemoveRows(); - - return true; -} - -static bool ascendingLessThan(const QPair &s1, const QPair &s2) -{ - return s1.first < s2.first; -} - -static bool decendingLessThan(const QPair &s1, const QPair &s2) -{ - return s1.first > s2.first; -} - -/*! - \reimp -*/ -void QStringListModel::sort(int, Qt::SortOrder order) -{ - emit layoutAboutToBeChanged(); - - QList > list; - for (int i = 0; i < lst.count(); ++i) - list.append(QPair(lst.at(i), i)); - - if (order == Qt::AscendingOrder) - qSort(list.begin(), list.end(), ascendingLessThan); - else - qSort(list.begin(), list.end(), decendingLessThan); - - lst.clear(); - QVector forwarding(list.count()); - for (int i = 0; i < list.count(); ++i) { - lst.append(list.at(i).first); - forwarding[list.at(i).second] = i; - } - - QModelIndexList oldList = persistentIndexList(); - QModelIndexList newList; - for (int i = 0; i < oldList.count(); ++i) - newList.append(index(forwarding.at(oldList.at(i).row()), 0)); - changePersistentIndexList(oldList, newList); - - emit layoutChanged(); -} - -/*! - Returns the string list used by the model to store data. -*/ -QStringList QStringListModel::stringList() const -{ - return lst; -} - -/*! - Sets the model's internal string list to \a strings. The model will - notify any attached views that its underlying data has changed. - - \sa dataChanged() -*/ -void QStringListModel::setStringList(const QStringList &strings) -{ - emit beginResetModel(); - lst = strings; - emit endResetModel(); -} - -/*! - \reimp -*/ -Qt::DropActions QStringListModel::supportedDropActions() const -{ - return QAbstractItemModel::supportedDropActions() | Qt::MoveAction; -} - -QT_END_NAMESPACE - -#endif // QT_NO_STRINGLISTMODEL diff --git a/src/widgets/itemviews/qstringlistmodel.h b/src/widgets/itemviews/qstringlistmodel.h deleted file mode 100644 index c2b8042134..0000000000 --- a/src/widgets/itemviews/qstringlistmodel.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSTRINGLISTMODEL_H -#define QSTRINGLISTMODEL_H - -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#ifndef QT_NO_STRINGLISTMODEL - -class Q_WIDGETS_EXPORT QStringListModel : public QAbstractListModel -{ - Q_OBJECT -public: - explicit QStringListModel(QObject *parent = 0); - QStringListModel(const QStringList &strings, QObject *parent = 0); - - int rowCount(const QModelIndex &parent = QModelIndex()) const; - - QVariant data(const QModelIndex &index, int role) const; - bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - - Qt::ItemFlags flags(const QModelIndex &index) const; - - bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()); - bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); - - void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); - - QStringList stringList() const; - void setStringList(const QStringList &strings); - - Qt::DropActions supportedDropActions() const; - -private: - Q_DISABLE_COPY(QStringListModel) - QStringList lst; -}; - -#endif // QT_NO_STRINGLISTMODEL - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QSTRINGLISTMODEL_H diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp index e99dd9ffc5..34db1b364b 100644 --- a/src/widgets/util/qcompleter.cpp +++ b/src/widgets/util/qcompleter.cpp @@ -147,7 +147,7 @@ #ifndef QT_NO_COMPLETER #include "QtWidgets/qscrollbar.h" -#include "QtWidgets/qstringlistmodel.h" +#include "QtCore/qstringlistmodel.h" #include "QtWidgets/qdirmodel.h" #include "QtWidgets/qfilesystemmodel.h" #include "QtWidgets/qheaderview.h" diff --git a/src/widgets/util/qcompleter_p.h b/src/widgets/util/qcompleter_p.h index 639c875568..78e201bd9e 100644 --- a/src/widgets/util/qcompleter_p.h +++ b/src/widgets/util/qcompleter_p.h @@ -59,7 +59,7 @@ #ifndef QT_NO_COMPLETER #include "QtWidgets/qtreeview.h" -#include "QtWidgets/qabstractproxymodel.h" +#include "QtCore/qabstractproxymodel.h" #include "qcompleter.h" #include "QtWidgets/qitemdelegate.h" #include "QtGui/qpainter.h" -- cgit v1.2.3