Add the QIdentityProxyModel.
Older commit history is in KDE svn: http://websvn.kde.org/trunk/KDE/kdelibs/kdeui/itemviews/kidentityproxymodel.cpp?view=log Ammended to update the license headers. Merge-request: 900 Reviewed-by: Gabriel de Dietrich <gabriel.dietrich-de@nokia.com> Conflicts: doc/src/frameworks-technologies/model-view-programming.qdoc tests/auto/headers/tst_headers.cpp (cherry picked from b00089261eafbdf5f92ed94d7fb20b402bfcaeb2)
This commit is contained in:
parent
1355da4b0f
commit
d49c561b73
@ -0,0 +1,66 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2011 Klarälvdalens Datakonsult AB,
|
||||||
|
** a KDAB Group company, info@kdab.com,
|
||||||
|
** author Stephen Kelly <stephen.kelly@kdab.com>
|
||||||
|
** 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:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||||
|
** the names of its contributors may be used to endorse or promote
|
||||||
|
** products derived from this software without specific prior written
|
||||||
|
** permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
//! [0]
|
||||||
|
class DateFormatProxyModel : public QIdentityProxyModel
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
|
||||||
|
void setDateFormatString(const QString &formatString)
|
||||||
|
{
|
||||||
|
m_formatString = formatString;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role)
|
||||||
|
{
|
||||||
|
if (role != Qt::DisplayRole)
|
||||||
|
return QIdentityProxyModel::data(index, role);
|
||||||
|
|
||||||
|
const QDateTime dateTime = sourceModel()->data(SourceClass::DateRole).toDateTime();
|
||||||
|
|
||||||
|
return dateTime.toString(m_formatString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_formatString;
|
||||||
|
};
|
||||||
|
//! [0]
|
@ -162,6 +162,7 @@ class Q_CORE_EXPORT QAbstractItemModel : public QObject
|
|||||||
|
|
||||||
friend class QPersistentModelIndexData;
|
friend class QPersistentModelIndexData;
|
||||||
friend class QAbstractItemViewPrivate;
|
friend class QAbstractItemViewPrivate;
|
||||||
|
friend class QIdentityProxyModel;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit QAbstractItemModel(QObject *parent = 0);
|
explicit QAbstractItemModel(QObject *parent = 0);
|
||||||
|
@ -4,6 +4,7 @@ HEADERS += \
|
|||||||
itemviews/qabstractitemview.h \
|
itemviews/qabstractitemview.h \
|
||||||
itemviews/qabstractitemview_p.h \
|
itemviews/qabstractitemview_p.h \
|
||||||
itemviews/qheaderview.h \
|
itemviews/qheaderview.h \
|
||||||
|
itemviews/qidentityproxymodel.h \
|
||||||
itemviews/qlistview.h \
|
itemviews/qlistview.h \
|
||||||
itemviews/qlistview_p.h \
|
itemviews/qlistview_p.h \
|
||||||
itemviews/qbsptree_p.h \
|
itemviews/qbsptree_p.h \
|
||||||
@ -44,6 +45,7 @@ HEADERS += \
|
|||||||
SOURCES += \
|
SOURCES += \
|
||||||
itemviews/qabstractitemview.cpp \
|
itemviews/qabstractitemview.cpp \
|
||||||
itemviews/qheaderview.cpp \
|
itemviews/qheaderview.cpp \
|
||||||
|
itemviews/qidentityproxymodel.cpp \
|
||||||
itemviews/qlistview.cpp \
|
itemviews/qlistview.cpp \
|
||||||
itemviews/qbsptree.cpp \
|
itemviews/qbsptree.cpp \
|
||||||
itemviews/qtableview.cpp \
|
itemviews/qtableview.cpp \
|
||||||
|
582
src/gui/itemviews/qidentityproxymodel.cpp
Normal file
582
src/gui/itemviews/qidentityproxymodel.cpp
Normal file
@ -0,0 +1,582 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2011 Klarälvdalens Datakonsult AB,
|
||||||
|
** a KDAB Group company, info@kdab.com,
|
||||||
|
** author Stephen Kelly <stephen.kelly@kdab.com>
|
||||||
|
** All rights reserved.
|
||||||
|
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||||
|
**
|
||||||
|
** This file is part of the QtGui module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qidentityproxymodel.h"
|
||||||
|
|
||||||
|
#ifndef QT_NO_IDENTITYPROXYMODEL
|
||||||
|
|
||||||
|
#include "qitemselectionmodel.h"
|
||||||
|
#include <private/qabstractproxymodel_p.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QIdentityProxyModelPrivate : public QAbstractProxyModelPrivate
|
||||||
|
{
|
||||||
|
QIdentityProxyModelPrivate()
|
||||||
|
: ignoreNextLayoutAboutToBeChanged(false),
|
||||||
|
ignoreNextLayoutChanged(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_PUBLIC(QIdentityProxyModel)
|
||||||
|
|
||||||
|
bool ignoreNextLayoutAboutToBeChanged;
|
||||||
|
bool ignoreNextLayoutChanged;
|
||||||
|
QList<QPersistentModelIndex> 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
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
if (ignoreNextLayoutAboutToBeChanged)
|
||||||
|
return;
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
if (ignoreNextLayoutChanged)
|
||||||
|
return;
|
||||||
|
|
||||||
|
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
|
115
src/gui/itemviews/qidentityproxymodel.h
Normal file
115
src/gui/itemviews/qidentityproxymodel.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2011 Klarälvdalens Datakonsult AB,
|
||||||
|
** a KDAB Group company, info@kdab.com,
|
||||||
|
** author Stephen Kelly <stephen.kelly@kdab.com>
|
||||||
|
** All rights reserved.
|
||||||
|
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||||
|
**
|
||||||
|
** This file is part of the QtGui module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef QIDENTITYPROXYMODEL_H
|
||||||
|
#define QIDENTITYPROXYMODEL_H
|
||||||
|
|
||||||
|
#include <QtGui/qabstractproxymodel.h>
|
||||||
|
|
||||||
|
#ifndef QT_NO_IDENTITYPROXYMODEL
|
||||||
|
|
||||||
|
QT_BEGIN_HEADER
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
QT_MODULE(Gui)
|
||||||
|
|
||||||
|
class QIdentityProxyModelPrivate;
|
||||||
|
|
||||||
|
class Q_GUI_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
|
||||||
|
|
@ -1502,7 +1502,7 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved(
|
|||||||
\l{Model Subclassing Reference}.
|
\l{Model Subclassing Reference}.
|
||||||
|
|
||||||
\sa QAbstractProxyModel, QAbstractItemModel, {Model/View Programming},
|
\sa QAbstractProxyModel, QAbstractItemModel, {Model/View Programming},
|
||||||
{Basic Sort/Filter Model Example}, {Custom Sort/Filter Model Example}
|
{Basic Sort/Filter Model Example}, {Custom Sort/Filter Model Example}, QIdentityProxyModel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -84,6 +84,7 @@ SUBDIRS=\
|
|||||||
qheaderview \
|
qheaderview \
|
||||||
qicoimageformat \
|
qicoimageformat \
|
||||||
qicon \
|
qicon \
|
||||||
|
qidentityproxymodel \
|
||||||
qimageiohandler \
|
qimageiohandler \
|
||||||
qimagereader \
|
qimagereader \
|
||||||
qimagewriter \
|
qimagewriter \
|
||||||
|
6
tests/auto/qidentityproxymodel/qidentityproxymodel.pro
Normal file
6
tests/auto/qidentityproxymodel/qidentityproxymodel.pro
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
load(qttest_p4)
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD/../modeltest
|
||||||
|
|
||||||
|
SOURCES += tst_qidentityproxymodel.cpp ../modeltest/dynamictreemodel.cpp ../modeltest/modeltest.cpp
|
||||||
|
HEADERS += ../modeltest/dynamictreemodel.h ../modeltest/modeltest.h
|
329
tests/auto/qidentityproxymodel/tst_qidentityproxymodel.cpp
Normal file
329
tests/auto/qidentityproxymodel/tst_qidentityproxymodel.cpp
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2011 Klarälvdalens Datakonsult AB,
|
||||||
|
** a KDAB Group company, info@kdab.com,
|
||||||
|
** author Stephen Kelly <stephen.kelly@kdab.com>
|
||||||
|
** All rights reserved.
|
||||||
|
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||||
|
**
|
||||||
|
** This file is part of the QtGui module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include <QtTest/QtTest>
|
||||||
|
#include "../../shared/util.h"
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
#include <QtGui>
|
||||||
|
|
||||||
|
#include "dynamictreemodel.h"
|
||||||
|
#include "qidentityproxymodel.h"
|
||||||
|
|
||||||
|
//TESTED CLASS=
|
||||||
|
//TESTED_FILES=
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(QModelIndex)
|
||||||
|
|
||||||
|
class tst_QIdentityProxyModel : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
tst_QIdentityProxyModel();
|
||||||
|
virtual ~tst_QIdentityProxyModel();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void initTestCase();
|
||||||
|
void cleanupTestCase();
|
||||||
|
void init();
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void insertRows();
|
||||||
|
void removeRows();
|
||||||
|
void moveRows();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void verifyIdentity(QAbstractItemModel *model, const QModelIndex &parent = QModelIndex());
|
||||||
|
|
||||||
|
private:
|
||||||
|
QStandardItemModel *m_model;
|
||||||
|
QIdentityProxyModel *m_proxy;
|
||||||
|
};
|
||||||
|
|
||||||
|
tst_QIdentityProxyModel::tst_QIdentityProxyModel()
|
||||||
|
: m_model(0), m_proxy(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
tst_QIdentityProxyModel::~tst_QIdentityProxyModel()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QIdentityProxyModel::initTestCase()
|
||||||
|
{
|
||||||
|
qRegisterMetaType<QModelIndex>("QModelIndex");
|
||||||
|
|
||||||
|
m_model = new QStandardItemModel(0, 1);
|
||||||
|
m_proxy = new QIdentityProxyModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QIdentityProxyModel::cleanupTestCase()
|
||||||
|
{
|
||||||
|
delete m_proxy;
|
||||||
|
delete m_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QIdentityProxyModel::init()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QIdentityProxyModel::cleanup()
|
||||||
|
{
|
||||||
|
m_model->clear();
|
||||||
|
m_model->insertColumns(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QIdentityProxyModel::verifyIdentity(QAbstractItemModel *model, const QModelIndex &parent)
|
||||||
|
{
|
||||||
|
const int rows = model->rowCount(parent);
|
||||||
|
const int columns = model->columnCount(parent);
|
||||||
|
const QModelIndex proxyParent = m_proxy->mapFromSource(parent);
|
||||||
|
|
||||||
|
QVERIFY(m_proxy->mapToSource(proxyParent) == parent);
|
||||||
|
QVERIFY(rows == m_proxy->rowCount(proxyParent));
|
||||||
|
QVERIFY(columns == m_proxy->columnCount(proxyParent));
|
||||||
|
|
||||||
|
for (int row = 0; row < rows; ++row) {
|
||||||
|
for (int column = 0; column < columns; ++column) {
|
||||||
|
const QModelIndex idx = model->index(row, column, parent);
|
||||||
|
const QModelIndex proxyIdx = m_proxy->mapFromSource(idx);
|
||||||
|
QVERIFY(proxyIdx.model() == m_proxy);
|
||||||
|
QVERIFY(m_proxy->mapToSource(proxyIdx) == idx);
|
||||||
|
QVERIFY(proxyIdx.isValid());
|
||||||
|
QVERIFY(proxyIdx.row() == row);
|
||||||
|
QVERIFY(proxyIdx.column() == column);
|
||||||
|
QVERIFY(proxyIdx.parent() == proxyParent);
|
||||||
|
QVERIFY(proxyIdx.data() == idx.data());
|
||||||
|
QVERIFY(proxyIdx.flags() == idx.flags());
|
||||||
|
const int childCount = m_proxy->rowCount(proxyIdx);
|
||||||
|
const bool hasChildren = m_proxy->hasChildren(proxyIdx);
|
||||||
|
QVERIFY(model->hasChildren(idx) == hasChildren);
|
||||||
|
QVERIFY((childCount > 0) == hasChildren);
|
||||||
|
|
||||||
|
if (hasChildren)
|
||||||
|
verifyIdentity(model, idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
tests
|
||||||
|
*/
|
||||||
|
|
||||||
|
void tst_QIdentityProxyModel::insertRows()
|
||||||
|
{
|
||||||
|
QStandardItem *parentItem = m_model->invisibleRootItem();
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
|
||||||
|
parentItem->appendRow(item);
|
||||||
|
parentItem = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_proxy->setSourceModel(m_model);
|
||||||
|
|
||||||
|
verifyIdentity(m_model);
|
||||||
|
|
||||||
|
QSignalSpy modelBeforeSpy(m_model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
|
||||||
|
QSignalSpy modelAfterSpy(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)));
|
||||||
|
QSignalSpy proxyBeforeSpy(m_proxy, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
|
||||||
|
QSignalSpy proxyAfterSpy(m_proxy, SIGNAL(rowsInserted(QModelIndex,int,int)));
|
||||||
|
|
||||||
|
QStandardItem *item = new QStandardItem(QString("new item"));
|
||||||
|
parentItem->appendRow(item);
|
||||||
|
|
||||||
|
QVERIFY(modelBeforeSpy.size() == 1 && 1 == proxyBeforeSpy.size());
|
||||||
|
QVERIFY(modelAfterSpy.size() == 1 && 1 == proxyAfterSpy.size());
|
||||||
|
|
||||||
|
QVERIFY(modelBeforeSpy.first().first().value<QModelIndex>() == m_proxy->mapToSource(proxyBeforeSpy.first().first().value<QModelIndex>()));
|
||||||
|
QVERIFY(modelBeforeSpy.first().at(1) == proxyBeforeSpy.first().at(1));
|
||||||
|
QVERIFY(modelBeforeSpy.first().at(2) == proxyBeforeSpy.first().at(2));
|
||||||
|
|
||||||
|
QVERIFY(modelAfterSpy.first().first().value<QModelIndex>() == m_proxy->mapToSource(proxyAfterSpy.first().first().value<QModelIndex>()));
|
||||||
|
QVERIFY(modelAfterSpy.first().at(1) == proxyAfterSpy.first().at(1));
|
||||||
|
QVERIFY(modelAfterSpy.first().at(2) == proxyAfterSpy.first().at(2));
|
||||||
|
|
||||||
|
verifyIdentity(m_model);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QIdentityProxyModel::removeRows()
|
||||||
|
{
|
||||||
|
QStandardItem *parentItem = m_model->invisibleRootItem();
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
|
||||||
|
parentItem->appendRow(item);
|
||||||
|
parentItem = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_proxy->setSourceModel(m_model);
|
||||||
|
|
||||||
|
verifyIdentity(m_model);
|
||||||
|
|
||||||
|
QSignalSpy modelBeforeSpy(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
|
||||||
|
QSignalSpy modelAfterSpy(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
|
||||||
|
QSignalSpy proxyBeforeSpy(m_proxy, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
|
||||||
|
QSignalSpy proxyAfterSpy(m_proxy, SIGNAL(rowsRemoved(QModelIndex,int,int)));
|
||||||
|
|
||||||
|
const QModelIndex topLevel = m_model->index(0, 0, QModelIndex());
|
||||||
|
const QModelIndex secondLevel = m_model->index(0, 0, topLevel);
|
||||||
|
const QModelIndex thirdLevel = m_model->index(0, 0, secondLevel);
|
||||||
|
|
||||||
|
QVERIFY(thirdLevel.isValid());
|
||||||
|
|
||||||
|
m_model->removeRow(0, secondLevel);
|
||||||
|
|
||||||
|
QVERIFY(modelBeforeSpy.size() == 1 && 1 == proxyBeforeSpy.size());
|
||||||
|
QVERIFY(modelAfterSpy.size() == 1 && 1 == proxyAfterSpy.size());
|
||||||
|
|
||||||
|
QVERIFY(modelBeforeSpy.first().first().value<QModelIndex>() == m_proxy->mapToSource(proxyBeforeSpy.first().first().value<QModelIndex>()));
|
||||||
|
QVERIFY(modelBeforeSpy.first().at(1) == proxyBeforeSpy.first().at(1));
|
||||||
|
QVERIFY(modelBeforeSpy.first().at(2) == proxyBeforeSpy.first().at(2));
|
||||||
|
|
||||||
|
QVERIFY(modelAfterSpy.first().first().value<QModelIndex>() == m_proxy->mapToSource(proxyAfterSpy.first().first().value<QModelIndex>()));
|
||||||
|
QVERIFY(modelAfterSpy.first().at(1) == proxyAfterSpy.first().at(1));
|
||||||
|
QVERIFY(modelAfterSpy.first().at(2) == proxyAfterSpy.first().at(2));
|
||||||
|
|
||||||
|
verifyIdentity(m_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QIdentityProxyModel::moveRows()
|
||||||
|
{
|
||||||
|
DynamicTreeModel model;
|
||||||
|
|
||||||
|
{
|
||||||
|
ModelInsertCommand insertCommand(&model);
|
||||||
|
insertCommand.setStartRow(0);
|
||||||
|
insertCommand.setEndRow(9);
|
||||||
|
insertCommand.doCommand();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ModelInsertCommand insertCommand(&model);
|
||||||
|
insertCommand.setAncestorRowNumbers(QList<int>() << 5);
|
||||||
|
insertCommand.setStartRow(0);
|
||||||
|
insertCommand.setEndRow(9);
|
||||||
|
insertCommand.doCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_proxy->setSourceModel(&model);
|
||||||
|
|
||||||
|
verifyIdentity(&model);
|
||||||
|
|
||||||
|
QSignalSpy modelBeforeSpy(&model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
|
||||||
|
QSignalSpy modelAfterSpy(&model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)));
|
||||||
|
QSignalSpy proxyBeforeSpy(m_proxy, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
|
||||||
|
QSignalSpy proxyAfterSpy(m_proxy, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)));
|
||||||
|
|
||||||
|
{
|
||||||
|
ModelMoveCommand moveCommand(&model, 0);
|
||||||
|
moveCommand.setAncestorRowNumbers(QList<int>() << 5);
|
||||||
|
moveCommand.setStartRow(3);
|
||||||
|
moveCommand.setEndRow(4);
|
||||||
|
moveCommand.setDestRow(1);
|
||||||
|
moveCommand.doCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVERIFY(modelBeforeSpy.size() == 1 && 1 == proxyBeforeSpy.size());
|
||||||
|
QVERIFY(modelAfterSpy.size() == 1 && 1 == proxyAfterSpy.size());
|
||||||
|
|
||||||
|
QVERIFY(modelBeforeSpy.first().first().value<QModelIndex>() == m_proxy->mapToSource(proxyBeforeSpy.first().first().value<QModelIndex>()));
|
||||||
|
QVERIFY(modelBeforeSpy.first().at(1) == proxyBeforeSpy.first().at(1));
|
||||||
|
QVERIFY(modelBeforeSpy.first().at(2) == proxyBeforeSpy.first().at(2));
|
||||||
|
QVERIFY(modelBeforeSpy.first().at(3).value<QModelIndex>() == m_proxy->mapToSource(proxyBeforeSpy.first().at(3).value<QModelIndex>()));
|
||||||
|
QVERIFY(modelBeforeSpy.first().at(4) == proxyBeforeSpy.first().at(4));
|
||||||
|
|
||||||
|
QVERIFY(modelAfterSpy.first().first().value<QModelIndex>() == m_proxy->mapToSource(proxyAfterSpy.first().first().value<QModelIndex>()));
|
||||||
|
QVERIFY(modelAfterSpy.first().at(1) == proxyAfterSpy.first().at(1));
|
||||||
|
QVERIFY(modelAfterSpy.first().at(2) == proxyAfterSpy.first().at(2));
|
||||||
|
QVERIFY(modelAfterSpy.first().at(3).value<QModelIndex>() == m_proxy->mapToSource(proxyAfterSpy.first().at(3).value<QModelIndex>()));
|
||||||
|
QVERIFY(modelAfterSpy.first().at(4) == proxyAfterSpy.first().at(4));
|
||||||
|
|
||||||
|
verifyIdentity(&model);
|
||||||
|
|
||||||
|
m_proxy->setSourceModel(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QIdentityProxyModel::reset()
|
||||||
|
{
|
||||||
|
DynamicTreeModel model;
|
||||||
|
|
||||||
|
{
|
||||||
|
ModelInsertCommand insertCommand(&model);
|
||||||
|
insertCommand.setStartRow(0);
|
||||||
|
insertCommand.setEndRow(9);
|
||||||
|
insertCommand.doCommand();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ModelInsertCommand insertCommand(&model);
|
||||||
|
insertCommand.setAncestorRowNumbers(QList<int>() << 5);
|
||||||
|
insertCommand.setStartRow(0);
|
||||||
|
insertCommand.setEndRow(9);
|
||||||
|
insertCommand.doCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_proxy->setSourceModel(&model);
|
||||||
|
|
||||||
|
verifyIdentity(&model);
|
||||||
|
|
||||||
|
QSignalSpy modelBeforeSpy(&model, SIGNAL(modelAboutToBeReset()));
|
||||||
|
QSignalSpy modelAfterSpy(&model, SIGNAL(modelReset()));
|
||||||
|
QSignalSpy proxyBeforeSpy(m_proxy, SIGNAL(modelAboutToBeReset()));
|
||||||
|
QSignalSpy proxyAfterSpy(m_proxy, SIGNAL(modelReset()));
|
||||||
|
|
||||||
|
{
|
||||||
|
ModelResetCommandFixed resetCommand(&model, 0);
|
||||||
|
resetCommand.setAncestorRowNumbers(QList<int>() << 5);
|
||||||
|
resetCommand.setStartRow(3);
|
||||||
|
resetCommand.setEndRow(4);
|
||||||
|
resetCommand.setDestRow(1);
|
||||||
|
resetCommand.doCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVERIFY(modelBeforeSpy.size() == 1 && 1 == proxyBeforeSpy.size());
|
||||||
|
QVERIFY(modelAfterSpy.size() == 1 && 1 == proxyAfterSpy.size());
|
||||||
|
|
||||||
|
verifyIdentity(&model);
|
||||||
|
m_proxy->setSourceModel(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_QIdentityProxyModel)
|
||||||
|
#include "tst_qidentityproxymodel.moc"
|
Loading…
x
Reference in New Issue
Block a user