Commit 381acbc2 authored by David Faure's avatar David Faure

Port StatisticsProxyModel to KExtraColumnsProxyModel.

* this fixes sibling() - the unittest confirmed Dan's assessment that
sibling() got broken for StatisticsProxyModel with Qt5.

* this reduces the number of dataChanged signals emitted by the proxy:
instead of dataChanged((row,0) (row,0)) + dataChanged((row,1) (row,3))
the proxy now emits dataChanged((row,0) (row,3)) directly

* I also removed the code emitting dataChanged for parent indexes,
the reasoning was "so that cumulative totals can be updated", but there
are no cumulative totals anywhere in this proxy (other than the tooltip).

* the awful model-index-struct-casting hack is no longer necessary,
the code is much simpler, there are now unittests (both here and for
the base class KExtraColumnsProxyModel in kitemmodels)...

BUG: 355229
parent a761b38d
......@@ -97,6 +97,7 @@ add_akonadi_test(newmailnotifierattributetest.cpp)
add_akonadi_test(pop3resourceattributetest.cpp)
add_akonadi_test_widgets(actionstatemanagertest.cpp)
add_akonadi_test(tagmodeltest.cpp)
add_akonadi_test(statisticsproxymodeltest.cpp)
add_akonadi_test(sharedvaluepooltest.cpp)
add_akonadi_test(jobtest.cpp)
......
/*
Copyright (c) 2016 David Faure <faure@kde.org>
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 <collectionstatistics.h>
#include <qtest.h>
#include <statisticsproxymodel.h>
#include <QStandardItemModel>
#include <AkonadiCore/Collection>
#include <EntityTreeModel>
#include "test_model_helpers.h"
using namespace TestModelHelpers;
using Akonadi::StatisticsProxyModel;
class StatisticsProxyModelTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void init();
void shouldDoNothingIfNoExtraColumns();
void shouldShowExtraColumns();
void shouldShowToolTip();
void shouldHandleDataChanged();
void shouldHandleDataChangedInExtraColumn();
private:
QStandardItemModel m_model;
};
// Helper functions
static QString indexToText(const QModelIndex &index)
{
if (!index.isValid()) {
return QStringLiteral("invalid");
}
return QString::number(index.row()) + QLatin1Char(',') + QString::number(index.column()) + QLatin1Char(',')
+ QString::number(reinterpret_cast<qulonglong>(index.internalPointer()), 16)
+ QLatin1String(" in ") + QString::number(reinterpret_cast<qulonglong>(index.model()), 16);
}
static QString indexRowCol(const QModelIndex &index)
{
if (!index.isValid()) {
return QStringLiteral("invalid");
}
return QString::number(index.row()) + QLatin1Char(',') + QString::number(index.column());
}
static Akonadi::CollectionStatistics makeStats(qint64 unread, qint64 count, qint64 size)
{
Akonadi::CollectionStatistics stats;
stats.setUnreadCount(unread);
stats.setCount(count);
stats.setSize(size);
return stats;
}
void StatisticsProxyModelTest::initTestCase()
{
}
void StatisticsProxyModelTest::init()
{
// Prepare the source model to use later on
m_model.clear();
m_model.appendRow(makeStandardItems(QStringList() << QStringLiteral("A") << QStringLiteral("B") << QStringLiteral("C") << QStringLiteral("D")));
m_model.item(0, 0)->appendRow(makeStandardItems(QStringList() << QStringLiteral("m") << QStringLiteral("n") << QStringLiteral("o") << QStringLiteral("p")));
m_model.item(0, 0)->appendRow(makeStandardItems(QStringList() << QStringLiteral("q") << QStringLiteral("r") << QStringLiteral("s") << QStringLiteral("t")));
m_model.appendRow(makeStandardItems(QStringList() << QStringLiteral("E") << QStringLiteral("F") << QStringLiteral("G") << QStringLiteral("H")));
m_model.item(1, 0)->appendRow(makeStandardItems(QStringList() << QStringLiteral("x") << QStringLiteral("y") << QStringLiteral("z") << QStringLiteral(".")));
m_model.setHorizontalHeaderLabels(QStringList() << QStringLiteral("H1") << QStringLiteral("H2") << QStringLiteral("H3") << QStringLiteral("H4"));
// Set Collection c1 for row A
Akonadi::Collection c1(1);
c1.setName(QStringLiteral("c1"));
c1.setStatistics(makeStats(2, 6, 9)); // unread, count, size in bytes
m_model.item(0, 0)->setData(QVariant::fromValue(c1), Akonadi::EntityTreeModel::CollectionRole);
// Set Collection c2 for first child (row m)
Akonadi::Collection c2(2);
c2.setName(QStringLiteral("c2"));
c2.setStatistics(makeStats(1, 3, 4)); // unread, count, size in bytes
m_model.item(0, 0)->child(0)->setData(QVariant::fromValue(c2), Akonadi::EntityTreeModel::CollectionRole);
// Set Collection c2 for first child (row m)
Akonadi::Collection c3(3);
c3.setName(QStringLiteral("c3"));
c3.setStatistics(makeStats(0, 1, 1)); // unread, count, size in bytes
m_model.item(0, 0)->child(1)->setData(QVariant::fromValue(c3), Akonadi::EntityTreeModel::CollectionRole);
QCOMPARE(extractRowTexts(&m_model, 0), QStringLiteral("ABCD"));
QCOMPARE(extractRowTexts(&m_model, 0, m_model.index(0, 0)), QStringLiteral("mnop"));
QCOMPARE(extractRowTexts(&m_model, 1, m_model.index(0, 0)), QStringLiteral("qrst"));
QCOMPARE(extractRowTexts(&m_model, 1), QStringLiteral("EFGH"));
QCOMPARE(extractRowTexts(&m_model, 0, m_model.index(1, 0)), QStringLiteral("xyz."));
QCOMPARE(extractHorizontalHeaderTexts(&m_model), QStringLiteral("H1H2H3H4"));
}
void StatisticsProxyModelTest::shouldDoNothingIfNoExtraColumns()
{
// Given a statistics proxy with no extra columns
StatisticsProxyModel pm;
pm.setExtraColumnsEnabled(false);
// When setting it to a source model
pm.setSourceModel(&m_model);
// Then the proxy should show the same as the model
QCOMPARE(pm.rowCount(), m_model.rowCount());
QCOMPARE(pm.columnCount(), m_model.columnCount());
QCOMPARE(pm.rowCount(pm.index(0, 0)), 2);
QCOMPARE(pm.index(0, 0).parent(), QModelIndex());
// (verify that the mapFromSource(mapToSource(x)) == x roundtrip works)
for (int row = 0; row < pm.rowCount(); ++row) {
for (int col = 0; col < pm.columnCount(); ++col) {
QCOMPARE(pm.mapFromSource(pm.mapToSource(pm.index(row, col))), pm.index(row, col));
}
}
QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABCD"));
QCOMPARE(extractRowTexts(&pm, 0, pm.index(0, 0)), QStringLiteral("mnop"));
QCOMPARE(extractRowTexts(&pm, 1, pm.index(0, 0)), QStringLiteral("qrst"));
QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("EFGH"));
QCOMPARE(extractRowTexts(&pm, 0, pm.index(1, 0)), QStringLiteral("xyz."));
QCOMPARE(extractHorizontalHeaderTexts(&pm), QStringLiteral("H1H2H3H4"));
}
void StatisticsProxyModelTest::shouldShowExtraColumns()
{
// Given a extra-columns proxy with three extra columns
StatisticsProxyModel pm;
// When setting it to a source model
pm.setSourceModel(&m_model);
// Then the proxy should show the extra column
QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABCD269 B"));
QCOMPARE(extractRowTexts(&pm, 0, pm.index(0, 0)), QStringLiteral("mnop134 B"));
QCOMPARE(extractRowTexts(&pm, 1, pm.index(0, 0)), QStringLiteral("qrst 11 B"));
QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("EFGH "));
QCOMPARE(extractRowTexts(&pm, 0, pm.index(1, 0)), QStringLiteral("xyz. "));
QCOMPARE(extractHorizontalHeaderTexts(&pm), QStringLiteral("H1H2H3H4UnreadTotalSize"));
// Verify tree structure of proxy
const QModelIndex secondParent = pm.index(1, 0);
QVERIFY(!secondParent.parent().isValid());
QCOMPARE(indexToText(pm.index(0, 0, secondParent).parent()), indexToText(secondParent));
QCOMPARE(indexToText(pm.index(0, 3, secondParent).parent()), indexToText(secondParent));
QVERIFY(indexToText(pm.index(0, 4)).startsWith(QStringLiteral("0,4,")));
QCOMPARE(indexToText(pm.index(0, 4, secondParent).parent()), indexToText(secondParent));
QVERIFY(indexToText(pm.index(0, 5)).startsWith(QStringLiteral("0,5,")));
QCOMPARE(indexToText(pm.index(0, 5, secondParent).parent()), indexToText(secondParent));
QCOMPARE(pm.index(0, 0).sibling(0, 4).column(), 4);
QCOMPARE(pm.index(0, 4).sibling(0, 1).column(), 1);
QVERIFY(!pm.canFetchMore(QModelIndex()));
}
void StatisticsProxyModelTest::shouldShowToolTip()
{
// Given a extra-columns proxy with three extra columns
StatisticsProxyModel pm;
pm.setSourceModel(&m_model);
// When enabling tooltips and getting the tooltip for the first folder
pm.setToolTipEnabled(true);
QString toolTip = pm.index(0, 0).data(Qt::ToolTipRole).toString();
// Then the tooltip should contain the expected information
toolTip.remove(QLatin1String("<strong>"));
toolTip.remove(QLatin1String("</strong>"));
QVERIFY2(toolTip.contains(QLatin1String("Total Messages: 6")), qPrintable(toolTip));
QVERIFY2(toolTip.contains(QLatin1String("Unread Messages: 2")), qPrintable(toolTip));
QVERIFY2(toolTip.contains(QLatin1String("Storage Size: 9 B")), qPrintable(toolTip));
QVERIFY2(toolTip.contains(QLatin1String("Subfolder Storage Size: 5 B")), qPrintable(toolTip));
}
void StatisticsProxyModelTest::shouldHandleDataChanged()
{
// Given a extra-columns proxy with three extra columns
StatisticsProxyModel pm;
pm.setSourceModel(&m_model);
QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
// When ETM says the collection changed
m_model.item(0, 0)->setData(QStringLiteral("a"), Qt::EditRole);
// Then the change should be notified to the proxy -- including the extra columns
QCOMPARE(dataChangedSpy.count(), 1);
QCOMPARE(indexRowCol(dataChangedSpy.at(0).at(0).toModelIndex()), QStringLiteral("0,0"));
QCOMPARE(indexRowCol(dataChangedSpy.at(0).at(1).toModelIndex()), QStringLiteral("0,6"));
QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("aBCD269 B"));
}
void StatisticsProxyModelTest::shouldHandleDataChangedInExtraColumn()
{
// Given a extra-columns proxy with three extra columns
StatisticsProxyModel pm;
pm.setSourceModel(&m_model);
QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
// When the proxy wants to signal a change in an extra column
Akonadi::Collection c1(1);
c1.setName(QStringLiteral("c1"));
c1.setStatistics(makeStats(3, 5, 8)); // changed: unread, count, size in bytes
m_model.item(0, 0)->setData(QVariant::fromValue(c1), Akonadi::EntityTreeModel::CollectionRole);
// Then the change should be available and notified
QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABCD358 B"));
QCOMPARE(dataChangedSpy.count(), 1);
QCOMPARE(indexRowCol(dataChangedSpy.at(0).at(0).toModelIndex()), QStringLiteral("0,0"));
QCOMPARE(indexRowCol(dataChangedSpy.at(0).at(1).toModelIndex()), QStringLiteral("0,6"));
}
#include "statisticsproxymodeltest.moc"
QTEST_MAIN(StatisticsProxyModelTest)
/*
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 <QString>
#include <QStandardItem>
#include <QSignalSpy>
namespace TestModelHelpers
{
// Prepares one row for a QStandardItemModel
inline QList<QStandardItem *> makeStandardItems(const QStringList &texts)
{
QList<QStandardItem *> items;
foreach (const QString &txt, texts) {
items << new QStandardItem(txt);
}
return items;
}
// Extracts a full row from a model as a string
// Works best if every cell contains only one character
inline QString extractRowTexts(QAbstractItemModel *model, int row, const QModelIndex &parent = QModelIndex())
{
QString result;
const int colCount = model->columnCount();
for (int col = 0; col < colCount; ++col) {
const QString txt = model->index(row, col, parent).data().toString();
result += txt.isEmpty() ? QStringLiteral(" ") : txt;
}
return result;
}
// Extracts all headers
inline QString extractHorizontalHeaderTexts(QAbstractItemModel *model)
{
QString result;
const int colCount = model->columnCount();
for (int col = 0; col < colCount; ++col) {
const QString txt = model->headerData(col, Qt::Horizontal).toString();
result += txt.isEmpty() ? QStringLiteral(" ") : txt;
}
return result;
}
inline QString rowSpyToText(const QSignalSpy &spy)
{
if (!spy.isValid()) {
return QStringLiteral("THE SIGNALSPY IS INVALID!");
}
QString str;
for (int i = 0; i < spy.count(); ++i) {
str += spy.at(i).at(1).toString() + QLatin1Char(',') + spy.at(i).at(2).toString();
if (i + 1 < spy.count()) {
str += QLatin1Char(';');
}
}
return str;
}
}
/*
Copyright (c) 2009 Kevin Ottens <ervin@kde.org>
2016 David Faure <faure@kde.org>
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
......@@ -19,6 +20,7 @@
#include "statisticsproxymodel.h"
#include "akonadicore_debug.h"
#include "kitemmodels_version.h"
#include "entitytreemodel.h"
#include "collectionutils.h"
......@@ -45,7 +47,7 @@ class Q_DECL_HIDDEN StatisticsProxyModel::Private
{
public:
Private(StatisticsProxyModel *parent)
: mParent(parent), mToolTipEnabled(false), mExtraColumnsEnabled(true)
: q(parent), mToolTipEnabled(false), mExtraColumnsEnabled(false)
{
}
......@@ -69,11 +71,9 @@ public:
int sourceColumnCount() const
{
return mParent->sourceModel()->columnCount();
return q->sourceModel()->columnCount();
}
QModelIndex sourceIndexAtFirstColumn(const QModelIndex &proxyIndex) const;
QString toolTipForCollection(const QModelIndex &index, const Collection &collection)
{
QString bckColor = QApplication::palette().color(QPalette::ToolTipBase).name();
......@@ -119,7 +119,7 @@ public:
}
}
KFormat formatter;
KFormat formatter;
qint64 currentFolderSize(collection.statistics().size());
tipInfo += QStringLiteral(
" <strong>%1</strong>: %2<br>\n"
......@@ -182,113 +182,47 @@ public:
return tip;
}
void proxyDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
void sourceLayoutAboutToBeChanged();
void sourceLayoutChanged();
QVector<QModelIndex> m_proxyIndexes;
QVector<QPersistentModelIndex> m_persistentSourceFirstColumn;
void _k_sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
StatisticsProxyModel *mParent;
StatisticsProxyModel *q;
bool mToolTipEnabled;
bool mExtraColumnsEnabled;
};
void StatisticsProxyModel::Private::proxyDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
void StatisticsProxyModel::Private::_k_sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
if (mExtraColumnsEnabled) {
// Ugly hack.
// The proper solution is a KExtraColumnsProxyModel, but this will do for now.
QModelIndex parent = topLeft.parent();
int parentColumnCount = mParent->columnCount(parent);
QModelIndex extraTopLeft = mParent->index(topLeft.row(), parentColumnCount - 1 - 3, parent);
QModelIndex extraBottomRight = mParent->index(bottomRight.row(), parentColumnCount - 1, parent);
mParent->disconnect(mParent, SIGNAL(dataChanged(QModelIndex,QModelIndex)), mParent, SLOT(proxyDataChanged(QModelIndex,QModelIndex)));
emit mParent->dataChanged(extraTopLeft, extraBottomRight);
// We get this signal when the statistics of a row changes.
// However, we need to emit data changed for the statistics of all ancestor rows too
// so that recursive totals can be updated.
while (parent.isValid()) {
const QModelIndex left = mParent->index(parent.row(), parentColumnCount - 1 - 3, parent.parent());
const QModelIndex right = mParent->index(parent.row(), parentColumnCount - 1, parent.parent());
emit mParent->dataChanged(left, right);
parent = parent.parent();
parentColumnCount = mParent->columnCount(parent);
}
mParent->connect(mParent, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
SLOT(proxyDataChanged(QModelIndex,QModelIndex)));
QModelIndex proxyTopLeft(q->mapFromSource(topLeft));
QModelIndex proxyBottomRight(q->mapFromSource(bottomRight));
// Emit data changed for the whole row (bug #222292)
if (mExtraColumnsEnabled && topLeft.column() == 0) { // in theory we could filter on roles, but ETM doesn't set any yet
const int lastColumn = q->columnCount() - 1;
proxyBottomRight = proxyBottomRight.sibling(proxyBottomRight.row(), lastColumn);
}
emit q->dataChanged(proxyTopLeft, proxyBottomRight, roles);
}
void StatisticsProxyModel::Private::sourceLayoutAboutToBeChanged()
void StatisticsProxyModel::setSourceModel(QAbstractItemModel *model)
{
// QIdentityProxyModel took care of the first columnCount() columns
// We have to take care of the extra columns (by storing persistent indexes in column 0,
// waiting for the source to update them, and then looking at where they ended up)
QModelIndexList persistent = mParent->persistentIndexList();
const int columnCount = mParent->sourceModel()->columnCount();
foreach (const QModelIndex &proxyPersistentIndex, persistent) {
if (proxyPersistentIndex.column() >= columnCount) {
m_proxyIndexes << proxyPersistentIndex;
m_persistentSourceFirstColumn << QPersistentModelIndex(sourceIndexAtFirstColumn(proxyPersistentIndex));
}
if (sourceModel()) {
disconnect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
this, SLOT(_k_sourceDataChanged(QModelIndex,QModelIndex,QVector<int>)));
}
}
void StatisticsProxyModel::Private::sourceLayoutChanged()
{
QModelIndexList oldList;
QModelIndexList newList;
for (int i = 0; i < m_proxyIndexes.size(); ++i) {
const QModelIndex oldProxyIndex = m_proxyIndexes.at(i);
const QModelIndex proxyIndexFirstCol = mParent->mapFromSource(m_persistentSourceFirstColumn.at(i));
const QModelIndex newProxyIndex = proxyIndexFirstCol.sibling(proxyIndexFirstCol.row(), oldProxyIndex.column());
if (newProxyIndex != oldProxyIndex) {
oldList.append(oldProxyIndex);
newList.append(newProxyIndex);
}
}
mParent->changePersistentIndexList(oldList, newList);
m_persistentSourceFirstColumn.clear();
m_proxyIndexes.clear();
}
void StatisticsProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
// Order is important here. sourceLayoutChanged must be called *before* any downstreams react
// to the layoutChanged so that it can have the QPersistentModelIndexes uptodate in time.
disconnect(this, SIGNAL(layoutChanged()), this, SLOT(sourceLayoutChanged()));
connect(this, SIGNAL(layoutChanged()), SLOT(sourceLayoutChanged()));
QIdentityProxyModel::setSourceModel(sourceModel);
// This one should come *after* any downstream handlers of layoutAboutToBeChanged.
// The connectNotify stuff below ensures that it remains the last one.
disconnect(this, SIGNAL(layoutAboutToBeChanged()), this, SLOT(sourceLayoutAboutToBeChanged()));
connect(this, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged()));
}
void StatisticsProxyModel::connectNotify(const QMetaMethod &signal)
{
static bool ignore = false;
if (ignore || signal == QMetaMethod::fromSignal(&StatisticsProxyModel::layoutAboutToBeChanged)) {
return QIdentityProxyModel::connectNotify(signal);
KExtraColumnsProxyModel::setSourceModel(model);
if (model) {
// Disconnect the default handling of dataChanged in QIdentityProxyModel, so we can extend it to the whole row
disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QVector<int>)));
connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
this, SLOT(_k_sourceDataChanged(QModelIndex,QModelIndex,QVector<int>)));
}
ignore = true;
disconnect(this, SIGNAL(layoutAboutToBeChanged()), this, SLOT(sourceLayoutAboutToBeChanged()));
connect(this, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged()));
ignore = false;
QIdentityProxyModel::connectNotify(signal);
}
StatisticsProxyModel::StatisticsProxyModel(QObject *parent)
: QIdentityProxyModel(parent),
: KExtraColumnsProxyModel(parent),
d(new Private(this))
{
connect(this, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
SLOT(proxyDataChanged(QModelIndex,QModelIndex)));
setExtraColumnsEnabled(true);
}
StatisticsProxyModel::~StatisticsProxyModel()
......@@ -308,7 +242,20 @@ bool StatisticsProxyModel::isToolTipEnabled() const
void StatisticsProxyModel::setExtraColumnsEnabled(bool enable)
{
if (d->mExtraColumnsEnabled == enable)
return;
d->mExtraColumnsEnabled = enable;
if (enable) {
KExtraColumnsProxyModel::appendColumn(i18nc("number of unread entities in the collection", "Unread"));
KExtraColumnsProxyModel::appendColumn(i18nc("number of entities in the collection", "Total"));
KExtraColumnsProxyModel::appendColumn(i18nc("collection size", "Size"));
} else {
#if KITEMMODELS_VERSION >= QT_VERSION_CHECK(5, 24, 0)
KExtraColumnsProxyModel::removeExtraColumn(2);
KExtraColumnsProxyModel::removeExtraColumn(1);
KExtraColumnsProxyModel::removeExtraColumn(0);
#endif
}
}
bool StatisticsProxyModel::isExtraColumnsEnabled() const
......@@ -316,163 +263,71 @@ bool StatisticsProxyModel::isExtraColumnsEnabled() const
return d->mExtraColumnsEnabled;
}
QModelIndex StatisticsProxyModel::index(int row, int column, const QModelIndex &parent) const
QVariant StatisticsProxyModel::extraColumnData(const QModelIndex &parent, int row, int extraColumn, int role) const
{
if (!hasIndex(row, column, parent)) {
return QModelIndex();
}
int sourceColumn = column;
if (column >= d->sourceColumnCount()) {
sourceColumn = 0;
}
QModelIndex i = QIdentityProxyModel::index(row, sourceColumn, parent);
return createIndex(i.row(), column, i.internalPointer());
}
struct SourceModelIndex {
SourceModelIndex(int _r, int _c, void *_p, QAbstractItemModel *_m)
: r(_r), c(_c), p(_p), m(_m) {}
operator QModelIndex()
{
return reinterpret_cast<QModelIndex &>(*this);
}
int r, c;
void *p;
const QAbstractItemModel *m;
};
QModelIndex StatisticsProxyModel::Private::sourceIndexAtFirstColumn(const QModelIndex &proxyIndex) const
{
// We rely on the fact that the internal pointer is the same for column 0 and for the extra columns
return SourceModelIndex(proxyIndex.row(), 0, proxyIndex.internalPointer(), mParent->sourceModel());
}
QModelIndex StatisticsProxyModel::parent(const QModelIndex &child) const
{
if (!sourceModel()) {
return QModelIndex();
}
Q_ASSERT(child.isValid() ? child.model() == this : true);
if (child.column() >= d->sourceColumnCount()) {
// We need to get hold of the source index at column 0. But we can't do that
// via the proxy index at column 0, because sibling() or index() needs the
// parent index, and that's *exactly* what we're trying to determine here.
// So the only way is to create a source index ourselves.
const QModelIndex sourceIndex = d->sourceIndexAtFirstColumn(child);
const QModelIndex sourceParent = sourceIndex.parent();
//qCDebug(AKONADICORE_LOG) << "parent of" << child.data() << "is" << sourceParent.data();
return mapFromSource(sourceParent);
} else {
return QIdentityProxyModel::parent(child);