You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

145 lines
5.1 KiB

/*
Copyright (c) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
Authors: David Faure <david.faure@kdab.com>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "krearrangecolumnsproxymodel.h"
class KRearrangeColumnsProxyModelPrivate
{
public:
QVector<int> m_sourceColumns;
};
KRearrangeColumnsProxyModel::KRearrangeColumnsProxyModel(QObject *parent)
: QIdentityProxyModel(parent),
d_ptr(new KRearrangeColumnsProxyModelPrivate)
{
}
KRearrangeColumnsProxyModel::~KRearrangeColumnsProxyModel()
{
}
void KRearrangeColumnsProxyModel::setSourceColumns(const QVector<int> &columns)
{
d_ptr->m_sourceColumns = columns;
}
int KRearrangeColumnsProxyModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
if (!sourceModel()) {
return 0;
}
return d_ptr->m_sourceColumns.count();
}
int KRearrangeColumnsProxyModel::rowCount(const QModelIndex &parent) const
{
Q_ASSERT(parent.isValid() ? parent.model() == this : true);
if (!sourceModel()) {
return 0;
}
// The parent in the source model is on column 0, whatever swapping we are doing
const QModelIndex sourceParent = mapToSource(parent).sibling(parent.row(), 0);
return sourceModel()->rowCount(sourceParent);
}
// We derive from QIdentityProxyModel simply to be able to use
// its mapFromSource method which has friend access to createIndex() in the source model.
QModelIndex KRearrangeColumnsProxyModel::index(int row, int column, const QModelIndex &parent) const
{
Q_ASSERT(parent.isValid() ? parent.model() == this : true);
Q_ASSERT(row >= 0);
Q_ASSERT(column >= 0);
// The parent in the source model is on column 0, whatever swapping we are doing
const QModelIndex sourceParent = mapToSource(parent).sibling(parent.row(), 0);
// Find the child in the source model, we need its internal pointer
const QModelIndex sourceIndex = sourceModel()->index(row, sourceColumnForProxyColumn(column), sourceParent);
if (!sourceIndex.isValid()) {
return QModelIndex();
}
return createIndex(row, column, sourceIndex.internalPointer());
}
QModelIndex KRearrangeColumnsProxyModel::parent(const QModelIndex &child) const
{
Q_ASSERT(child.isValid() ? child.model() == this : true);
const QModelIndex sourceIndex = mapToSource(child);
const QModelIndex sourceParent = sourceIndex.parent();
if (!sourceParent.isValid()) {
return QModelIndex();
}
return createIndex(sourceParent.row(), 0, sourceParent.internalPointer());
}
QVariant KRearrangeColumnsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal) {
const int sourceCol = sourceColumnForProxyColumn(section);
return sourceModel()->headerData(sourceCol, orientation, role);
} else {
return QIdentityProxyModel::headerData(section, orientation, role);
}
}
QModelIndex KRearrangeColumnsProxyModel::sibling(int row, int column, const QModelIndex &idx) const
{
if (column >= d_ptr->m_sourceColumns.count()) {
return QModelIndex();
}
return index(row, column, idx.parent());
}
QModelIndex KRearrangeColumnsProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
if (!sourceIndex.isValid()) {
return QModelIndex();
}
Q_ASSERT(sourceIndex.model() == sourceModel());
const int proxyColumn = proxyColumnForSourceColumn(sourceIndex.column());
return createIndex(sourceIndex.row(), proxyColumn, sourceIndex.internalPointer());
}
QModelIndex KRearrangeColumnsProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
if (!proxyIndex.isValid()) {
return QModelIndex();
}
// This is just an indirect way to call sourceModel->createIndex(row, sourceColumn, pointer)
const QModelIndex fakeIndex = createIndex(proxyIndex.row(), sourceColumnForProxyColumn(proxyIndex.column()), proxyIndex.internalPointer());
return QIdentityProxyModel::mapToSource(fakeIndex);
}
int KRearrangeColumnsProxyModel::proxyColumnForSourceColumn(int sourceColumn) const
{
// If this is too slow, we could add a second QVector with index=logical_source_column value=desired_pos_in_proxy.
return d_ptr->m_sourceColumns.indexOf(sourceColumn);
}
int KRearrangeColumnsProxyModel::sourceColumnForProxyColumn(int proxyColumn) const
{
Q_ASSERT(proxyColumn >= 0);
Q_ASSERT(proxyColumn < d_ptr->m_sourceColumns.size());
return d_ptr->m_sourceColumns.at(proxyColumn);
}