Hello community,
here is the log from the commit of package kitemmodels for openSUSE:Factory checked in at 2015-09-02 07:46:39
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kitemmodels (Old)
and /work/SRC/openSUSE:Factory/.kitemmodels.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kitemmodels"
Changes:
--------
--- /work/SRC/openSUSE:Factory/kitemmodels/kitemmodels.changes 2015-07-14 17:28:10.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.kitemmodels.new/kitemmodels.changes 2015-09-02 07:46:40.000000000 +0200
@@ -1,0 +2,13 @@
+Tue Aug 4 19:20:32 UTC 2015 - hrvoje.senjan@gmail.com
+
+- Update to 5.13.0
+ * The Qt version requirement has been bumped from 5.2 to 5.3
+ * Debug output has been ported to categorized output, for less
+ noise by default
+ * Docbook documentation has been reviewed and updated
+ * New proxy: KExtraColumnsProxyModel, allows to add columns to
+ an existing model.
+ * For more details please see:
+ https://www.kde.org/announcements/kde-frameworks-5.13.0.php
+
+-------------------------------------------------------------------
Old:
----
kitemmodels-5.12.0.tar.xz
New:
----
kitemmodels-5.13.0.tar.xz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ kitemmodels.spec ++++++
--- /var/tmp/diff_new_pack.WQKJtF/_old 2015-09-02 07:46:41.000000000 +0200
+++ /var/tmp/diff_new_pack.WQKJtF/_new 2015-09-02 07:46:41.000000000 +0200
@@ -17,15 +17,15 @@
%define lname libKF5ItemModels5
-%define _tar_path 5.12
+%define _tar_path 5.13
Name: kitemmodels
-Version: 5.12.0
+Version: 5.13.0
Release: 0
BuildRequires: cmake >= 2.8.12
BuildRequires: extra-cmake-modules >= %{_tar_path}
BuildRequires: fdupes
BuildRequires: kf5-filesystem
-BuildRequires: pkgconfig(Qt5Core) >= 5.2.0
+BuildRequires: cmake(Qt5Core) >= 5.3.0
Summary: Set of item models extending the Qt model-view framework
License: LGPL-2.1+
Group: System/GUI/KDE
@@ -50,7 +50,7 @@
Group: Development/Libraries/KDE
Requires: %lname = %{version}
Requires: extra-cmake-modules
-Requires: pkgconfig(Qt5Core) >= 5.2.0
+Requires: cmake(Qt5Core) >= 5.3.0
%description devel
KItemModels provides a set of item models extending the Qt model-view framework.
++++++ kitemmodels-5.12.0.tar.xz -> kitemmodels-5.13.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kitemmodels-5.12.0/CMakeLists.txt new/kitemmodels-5.13.0/CMakeLists.txt
--- old/kitemmodels-5.12.0/CMakeLists.txt 2015-07-04 22:37:34.000000000 +0200
+++ new/kitemmodels-5.13.0/CMakeLists.txt 2015-08-01 14:41:18.000000000 +0200
@@ -3,7 +3,7 @@
project(KItemModels)
include(FeatureSummary)
-find_package(ECM 5.12.0 NO_MODULE)
+find_package(ECM 5.13.0 NO_MODULE)
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules")
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES)
@@ -14,7 +14,7 @@
include(KDEFrameworkCompilerSettings)
include(KDECMakeSettings)
-set(REQUIRED_QT_VERSION 5.2.0)
+set(REQUIRED_QT_VERSION 5.3.0)
find_package(Qt5Core ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
@@ -23,7 +23,7 @@
include(ECMSetupVersion)
include(ECMGenerateHeaders)
-set(KF5_VERSION "5.12.0") # handled by release scripts
+set(KF5_VERSION "5.13.0") # handled by release scripts
ecm_setup_version(${KF5_VERSION} VARIABLE_PREFIX KITEMMODELS
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kitemmodels_version.h"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kitemmodels-5.12.0/README.md new/kitemmodels-5.13.0/README.md
--- old/kitemmodels-5.12.0/README.md 2015-07-04 22:37:34.000000000 +0200
+++ new/kitemmodels-5.13.0/README.md 2015-08-01 14:41:18.000000000 +0200
@@ -10,6 +10,7 @@
breadcrumbs
* KCheckableProxyModel - Adds a checkable capability to a source model
* KDescendantsProxyModel - Proxy Model for restructuring a Tree into a list
+* KExtraColumnsProxyModel - Adds columns after existing columns
* KLinkItemSelectionModel - Share a selection in multiple views which do not
have the same source model
* KModelIndexProxyMapper - Mapping of indexes and selections through proxy
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kitemmodels-5.12.0/autotests/CMakeLists.txt new/kitemmodels-5.13.0/autotests/CMakeLists.txt
--- old/kitemmodels-5.12.0/autotests/CMakeLists.txt 2015-07-04 22:37:34.000000000 +0200
+++ new/kitemmodels-5.13.0/autotests/CMakeLists.txt 2015-08-01 14:41:18.000000000 +0200
@@ -16,6 +16,7 @@
ecm_add_tests(
kdescendantsproxymodel_smoketest.cpp
+ kextracolumnsproxymodeltest.cpp
klinkitemselectionmodeltest.cpp
testmodelqueuedconnections.cpp
kselectionproxymodeltest.cpp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kitemmodels-5.12.0/autotests/kextracolumnsproxymodeltest.cpp new/kitemmodels-5.13.0/autotests/kextracolumnsproxymodeltest.cpp
--- old/kitemmodels-5.12.0/autotests/kextracolumnsproxymodeltest.cpp 1970-01-01 01:00:00.000000000 +0100
+++ new/kitemmodels-5.13.0/autotests/kextracolumnsproxymodeltest.cpp 2015-08-01 14:41:18.000000000 +0200
@@ -0,0 +1,339 @@
+/*
+ Copyright (c) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+ Authors: David Faure
+
+ 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 <QSignalSpy>
+#include <QSortFilterProxyModel>
+#include <QTest>
+#include <QDebug>
+#include <QStandardItemModel>
+
+#include <QTreeView>
+
+#include
+#include "test_model_helpers.h"
+using namespace TestModelHelpers;
+
+Q_DECLARE_METATYPE(QModelIndex)
+
+class tst_KExtraColumnsProxyModel : public QObject
+{
+ Q_OBJECT
+
+private:
+ class NoExtraColumns : public KExtraColumnsProxyModel
+ {
+ QVariant extraColumnData(const QModelIndex &, int, int, int) const Q_DECL_OVERRIDE
+ {
+ Q_ASSERT(0);
+ return QVariant();
+ }
+ };
+
+ class TwoExtraColumnsProxyModel : public KExtraColumnsProxyModel
+ {
+ public:
+ TwoExtraColumnsProxyModel() : KExtraColumnsProxyModel(), m_extraColumnData('Z')
+ {
+ appendColumn("H5");
+ appendColumn("H6");
+ }
+ QVariant extraColumnData(const QModelIndex &, int row, int extraColumn, int role) const Q_DECL_OVERRIDE
+ {
+ Q_ASSERT(role == Qt::DisplayRole);
+ switch (extraColumn) {
+ case 0:
+ return QString(m_extraColumnData);
+ case 1:
+ return QString::number(row);
+ default:
+ Q_ASSERT(0);
+ return QVariant();
+ }
+ }
+ bool setExtraColumnData(const QModelIndex &parent, int row, int extraColumn, const QVariant &data, int role) Q_DECL_OVERRIDE {
+ if (extraColumn == 0 && role == Qt::EditRole)
+ {
+ m_extraColumnData = data.toString().at(0);
+ extraColumnDataChanged(QModelIndex(), 0, extraColumn, QVector<int>() << Qt::EditRole);
+ return true;
+ }
+ return KExtraColumnsProxyModel::setExtraColumnData(parent, row, extraColumn, data, role);
+ }
+ void changeExtraColumnData() {
+ m_extraColumnData = '<';
+ extraColumnDataChanged(QModelIndex(), 0, 0, QVector<int>() << Qt::EditRole);
+ }
+ private:
+ QChar m_extraColumnData;
+ };
+
+private Q_SLOTS:
+
+ void initTestCase()
+ {
+ qRegisterMetaType<QModelIndex>();
+ }
+
+ void init()
+ {
+ // Prepare the source model to use later on
+ mod.clear();
+ mod.appendRow(makeStandardItems(QStringList() << "A" << "B" << "C" << "D"));
+ mod.item(0, 0)->appendRow(makeStandardItems(QStringList() << "m" << "n" << "o" << "p"));
+ mod.item(0, 0)->appendRow(makeStandardItems(QStringList() << "q" << "r" << "s" << "t"));
+ mod.appendRow(makeStandardItems(QStringList() << "E" << "F" << "G" << "H"));
+ mod.item(1, 0)->appendRow(makeStandardItems(QStringList() << "x" << "y" << "z" << "."));
+ mod.setHorizontalHeaderLabels(QStringList() << "H1" << "H2" << "H3" << "H4");
+
+ QCOMPARE(extractRowTexts(&mod, 0), QString("ABCD"));
+ QCOMPARE(extractRowTexts(&mod, 0, mod.index(0, 0)), QString("mnop"));
+ QCOMPARE(extractRowTexts(&mod, 1, mod.index(0, 0)), QString("qrst"));
+ QCOMPARE(extractRowTexts(&mod, 1), QString("EFGH"));
+ QCOMPARE(extractRowTexts(&mod, 0, mod.index(1, 0)), QString("xyz."));
+ QCOMPARE(extractHorizontalHeaderTexts(&mod), QString("H1H2H3H4"));
+
+ // test code to see the model
+ // showModel(&mod);
+ }
+
+ void shouldDoNothingIfNoExtraColumns()
+ {
+ // Given a extra-columns proxy
+ NoExtraColumns pm;
+
+ // When setting it to a source model
+ pm.setSourceModel(&mod);
+
+ // Then the proxy should show the same as the model
+ QCOMPARE(pm.rowCount(), mod.rowCount());
+ QCOMPARE(pm.columnCount(), mod.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), QString("ABCD"));
+ QCOMPARE(extractRowTexts(&pm, 0, pm.index(0, 0)), QString("mnop"));
+ QCOMPARE(extractRowTexts(&pm, 1, pm.index(0, 0)), QString("qrst"));
+ QCOMPARE(extractRowTexts(&pm, 1), QString("EFGH"));
+ QCOMPARE(extractRowTexts(&pm, 0, pm.index(1, 0)), QString("xyz."));
+ QCOMPARE(extractHorizontalHeaderTexts(&pm), QString("H1H2H3H4"));
+ }
+
+ void shouldShowExtraColumns()
+ {
+ // Given a extra-columns proxy with two extra columns
+ TwoExtraColumnsProxyModel pm;
+
+ // When setting it to a source model
+ pm.setSourceModel(&mod);
+
+ // Then the proxy should show the extra column
+ QCOMPARE(extractRowTexts(&pm, 0), QString("ABCDZ0"));
+ QCOMPARE(extractRowTexts(&pm, 0, pm.index(0, 0)), QString("mnopZ0"));
+ QCOMPARE(extractRowTexts(&pm, 1, pm.index(0, 0)), QString("qrstZ1"));
+ QCOMPARE(extractRowTexts(&pm, 1), QString("EFGHZ1"));
+ QCOMPARE(extractRowTexts(&pm, 0, pm.index(1, 0)), QString("xyz.Z0"));
+ QCOMPARE(extractHorizontalHeaderTexts(&pm), QString("H1H2H3H4H5H6"));
+
+ // 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("0,4,"));
+ QCOMPARE(indexToText(pm.index(0, 4, secondParent).parent()), indexToText(secondParent));
+ QVERIFY(indexToText(pm.index(0, 5)).startsWith("0,5,"));
+ QCOMPARE(indexToText(pm.index(0, 5, secondParent).parent()), indexToText(secondParent));
+
+ QVERIFY(!pm.canFetchMore(QModelIndex()));
+ }
+
+ void shouldHandleDataChanged()
+ {
+ // Given a extra-columns proxy, with two extra columns
+ TwoExtraColumnsProxyModel pm;
+ setup(pm);
+ QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+
+ // When a cell in a source model changes
+ mod.item(0, 2)->setData("c", Qt::EditRole);
+
+ // Then the change should be notified to the proxy
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(dataChangedSpy.at(0).at(0).value<QModelIndex>(), pm.index(0, 2));
+ QCOMPARE(extractRowTexts(&pm, 0), QString("ABcDZ0"));
+ }
+
+ void shouldHandleDataChangedInExtraColumn()
+ {
+ // Given a extra-columns proxy, with two extra columns
+ TwoExtraColumnsProxyModel pm;
+ setup(pm);
+ QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+
+ // When the proxy wants to signal a change in an extra column
+ pm.changeExtraColumnData();
+
+ // Then the change should be available and notified
+ QCOMPARE(extractRowTexts(&pm, 0), QString("ABCD<0"));
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(dataChangedSpy.at(0).at(0).value<QModelIndex>(), pm.index(0, 4));
+ }
+
+ void shouldHandleSetDataInNormalColumn()
+ {
+ // Given a extra-columns proxy, with two extra columns
+ TwoExtraColumnsProxyModel pm;
+ setup(pm);
+ QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+
+ // When editing a cell in the proxy
+ QVERIFY(pm.setData(pm.index(0, 2), "c", Qt::EditRole));
+
+ // Then the change should be available and notified
+ QCOMPARE(extractRowTexts(&pm, 0), QString("ABcDZ0"));
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(dataChangedSpy.at(0).at(0).value<QModelIndex>(), pm.index(0, 2));
+ }
+
+ void shouldHandleSetDataInExtraColumn()
+ {
+ // Given a extra-columns proxy, with two extra columns
+ TwoExtraColumnsProxyModel pm;
+ setup(pm);
+ QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+
+ // When editing a cell in the proxy
+ QVERIFY(pm.setData(pm.index(0, 4), "-", Qt::EditRole));
+
+ // Then the change should be available and notified
+ QCOMPARE(extractRowTexts(&pm, 0), QString("ABCD-0"));
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(dataChangedSpy.at(0).at(0).value<QModelIndex>(), pm.index(0, 4));
+ }
+
+ void shouldHandleRowInsertion()
+ {
+ // Given a extra-columns proxy, with two extra columns
+ TwoExtraColumnsProxyModel pm;
+ setup(pm);
+
+ QSignalSpy rowATBISpy(&pm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
+ QSignalSpy rowInsertedSpy(&pm, SIGNAL(rowsInserted(QModelIndex,int,int)));
+
+ // When a source model inserts a new (child) row
+ mod.item(1, 0)->appendRow(makeStandardItems(QStringList() << "1" << "2" << "3" << "4"));
+
+ // Then the proxy should notify its users and show changes
+ QCOMPARE(rowSpyToText(rowATBISpy), QString("1,1"));
+ QCOMPARE(rowSpyToText(rowInsertedSpy), QString("1,1"));
+ QCOMPARE(pm.rowCount(), 2);
+ QCOMPARE(extractRowTexts(&pm, 0), QString("ABCDZ0"));
+ QCOMPARE(extractRowTexts(&pm, 0, pm.index(0, 0)), QString("mnopZ0"));
+ QCOMPARE(extractRowTexts(&pm, 1, pm.index(0, 0)), QString("qrstZ1"));
+ QCOMPARE(extractRowTexts(&pm, 1), QString("EFGHZ1"));
+ QCOMPARE(extractRowTexts(&pm, 0, pm.index(1, 0)), QString("xyz.Z0"));
+ QCOMPARE(extractRowTexts(&pm, 1, pm.index(1, 0)), QString("1234Z1"));
+ QCOMPARE(extractHorizontalHeaderTexts(&pm), QString("H1H2H3H4H5H6"));
+ }
+
+ void shouldHandleColumnInsertion()
+ {
+ // Given a extra-columns proxy, with two extra columns
+ TwoExtraColumnsProxyModel pm;
+ setup(pm);
+
+ QCOMPARE(pm.columnCount(), 6);
+ QCOMPARE(mod.columnCount(), 4);
+
+ QSignalSpy colATBISpy(&pm, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)));
+ QSignalSpy colInsertedSpy(&pm, SIGNAL(columnsInserted(QModelIndex,int,int)));
+
+ // When a source model inserts a new column
+ mod.setColumnCount(5); // like QStandardItem::setChild does
+ QCOMPARE(mod.columnCount(), 5);
+ // QStandardItemModel is quite dumb, it records the number of columns in each item
+ for (int row = 0; row < mod.rowCount(); ++row) {
+ mod.item(row, 0)->setColumnCount(5);
+ }
+
+ // Then the proxy should notify its users and show changes
+ QCOMPARE(rowSpyToText(colATBISpy), QString("4,4;4,4;4,4")); // QStandardItemModel emits it for each parent
+ QCOMPARE(rowSpyToText(colInsertedSpy), QString("4,4;4,4;4,4"));
+ QCOMPARE(pm.columnCount(), 7);
+ QCOMPARE(extractRowTexts(&pm, 0), QString("ABCD Z0"));
+ QCOMPARE(extractRowTexts(&pm, 0, pm.index(0, 0)), QString("mnop Z0"));
+ QCOMPARE(extractRowTexts(&pm, 1, pm.index(0, 0)), QString("qrst Z1"));
+ QCOMPARE(extractRowTexts(&pm, 1), QString("EFGH Z1"));
+ QCOMPARE(extractRowTexts(&pm, 0, pm.index(1, 0)), QString("xyz. Z0"));
+ QCOMPARE(extractHorizontalHeaderTexts(&pm), QString("H1H2H3H45H5H6")); // '5' was inserted in there
+ }
+
+ // row removal, layoutChanged, modelReset -> same thing, works via QIdentityProxyModel
+ // missing: test for mapSelectionToSource
+
+ void shouldHandleLayoutChanged()
+ {
+ // Given a extra-columns proxy, with two extra columns
+ TwoExtraColumnsProxyModel pm;
+ // And a QSFPM underneath
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&mod);
+ pm.setSourceModel(&proxy);
+ // And a selection
+ QItemSelectionModel selection(&pm);
+ selection.select(pm.index(0, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows);
+
+ // When sorting
+ pm.sort(0, Qt::DescendingOrder);
+ QCOMPARE(extractRowTexts(&pm, 0), QString("EFGHZ0"));
+ QCOMPARE(extractRowTexts(&pm, 1), QString("ABCDZ1"));
+ }
+
+private:
+
+ void setup(KExtraColumnsProxyModel &pm)
+ {
+ pm.setSourceModel(&mod);
+ }
+
+ static QString indexToText(const QModelIndex &index)
+ {
+ if (!index.isValid()) {
+ return "invalid";
+ }
+ return QString::number(index.row()) + "," + QString::number(index.column()) + ","
+ + QString::number(reinterpret_cast<qulonglong>(index.internalPointer()), 16)
+ + " in " + QString::number(reinterpret_cast<qulonglong>(index.model()), 16);
+ }
+
+ QStandardItemModel mod;
+};
+
+QTEST_MAIN(tst_KExtraColumnsProxyModel)
+
+#include "kextracolumnsproxymodeltest.moc"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kitemmodels-5.12.0/autotests/test_model_helpers.h new/kitemmodels-5.13.0/autotests/test_model_helpers.h
--- old/kitemmodels-5.12.0/autotests/test_model_helpers.h 2015-07-04 22:37:34.000000000 +0200
+++ new/kitemmodels-5.13.0/autotests/test_model_helpers.h 2015-08-01 14:41:18.000000000 +0200
@@ -58,5 +58,20 @@
return result;
}
+inline QString rowSpyToText(const QSignalSpy &spy)
+{
+ if (!spy.isValid()) {
+ return QString::fromLatin1("THE SIGNALSPY IS INVALID!");
+ }
+ QString str;
+ for (int i = 0; i < spy.count(); ++i) {
+ str += spy.at(i).at(1).toString() + ',' + spy.at(i).at(2).toString();
+ if (i + 1 < spy.count()) {
+ str += QLatin1Char(';');
+ }
+ }
+ return str;
+}
+
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kitemmodels-5.12.0/src/CMakeLists.txt new/kitemmodels-5.13.0/src/CMakeLists.txt
--- old/kitemmodels-5.12.0/src/CMakeLists.txt 2015-07-04 22:37:34.000000000 +0200
+++ new/kitemmodels-5.13.0/src/CMakeLists.txt 2015-08-01 14:41:18.000000000 +0200
@@ -3,6 +3,7 @@
kbreadcrumbselectionmodel.cpp
kcheckableproxymodel.cpp
kdescendantsproxymodel.cpp
+ kextracolumnsproxymodel.cpp
klinkitemselectionmodel.cpp
kmodelindexproxymapper.cpp
krearrangecolumnsproxymodel.cpp
@@ -27,6 +28,7 @@
HEADER_NAMES
KBreadcrumbSelectionModel
KCheckableProxyModel
+ KExtraColumnsProxyModel
KLinkItemSelectionModel
KRearrangeColumnsProxyModel
KRecursiveFilterProxyModel
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kitemmodels-5.12.0/src/kextracolumnsproxymodel.cpp new/kitemmodels-5.13.0/src/kextracolumnsproxymodel.cpp
--- old/kitemmodels-5.12.0/src/kextracolumnsproxymodel.cpp 1970-01-01 01:00:00.000000000 +0100
+++ new/kitemmodels-5.13.0/src/kextracolumnsproxymodel.cpp 2015-08-01 14:41:18.000000000 +0200
@@ -0,0 +1,315 @@
+/*
+ Copyright (c) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+ Authors: David Faure
+
+ 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 "kextracolumnsproxymodel.h"
+#include <QItemSelection>
+#include <QDebug>
+
+class KExtraColumnsProxyModelPrivate
+{
+ Q_DECLARE_PUBLIC(KExtraColumnsProxyModel)
+ KExtraColumnsProxyModel *const q_ptr;
+
+public:
+ KExtraColumnsProxyModelPrivate(KExtraColumnsProxyModel *model)
+ : q_ptr(model)
+ {
+ }
+
+ void _ec_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
+ void _ec_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
+
+ // Configuration (doesn't change once source model is plugged in)
+ QVector<QString> m_extraHeaders;
+
+ // for layoutAboutToChanged/layoutChanged
+ QVector<QPersistentModelIndex> layoutChangePersistentIndexes;
+ QVector<int> layoutChangeProxyColumns;
+ QModelIndexList proxyIndexes;
+};
+
+KExtraColumnsProxyModel::KExtraColumnsProxyModel(QObject *parent)
+ : QIdentityProxyModel(parent),
+ d_ptr(new KExtraColumnsProxyModelPrivate(this))
+{
+}
+
+KExtraColumnsProxyModel::~KExtraColumnsProxyModel()
+{
+}
+
+void KExtraColumnsProxyModel::appendColumn(const QString &header)
+{
+ Q_D(KExtraColumnsProxyModel);
+ d->m_extraHeaders.append(header);
+}
+
+bool KExtraColumnsProxyModel::setExtraColumnData(const QModelIndex &parent, int row, int extraColumn, const QVariant &data, int role)
+{
+ Q_UNUSED(parent);
+ Q_UNUSED(row);
+ Q_UNUSED(extraColumn);
+ Q_UNUSED(data);
+ Q_UNUSED(role);
+ return false;
+}
+
+void KExtraColumnsProxyModel::extraColumnDataChanged(const QModelIndex &parent, int row, int extraColumn, const QVector<int> & roles)
+{
+ const QModelIndex idx = index(row, proxyColumnForExtraColumn(extraColumn), parent);
+ emit dataChanged(idx, idx, roles);
+}
+
+void KExtraColumnsProxyModel::setSourceModel(QAbstractItemModel *model)
+{
+ if (sourceModel()) {
+ disconnect(sourceModel(), SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
+ this, SLOT(_ec_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+ disconnect(sourceModel(), SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
+ this, SLOT(_ec_sourceLayoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+ }
+
+ QIdentityProxyModel::setSourceModel(model);
+
+ if (model) {
+ // The handling of persistent model indexes assumes mapToSource can be called for any index
+ // This breaks for the extra column, so we'll have to do it ourselves
+ disconnect(model, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
+ this, SLOT(_q_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+ disconnect(model, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
+ this, SLOT(_q_sourceLayoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+ connect(model, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
+ this, SLOT(_ec_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+ connect(model, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
+ this, SLOT(_ec_sourceLayoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+ }
+}
+
+QModelIndex KExtraColumnsProxyModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ if (!proxyIndex.isValid()) { // happens in e.g. rowCount(mapToSource(parent))
+ return QModelIndex();
+ }
+ const int column = proxyIndex.column();
+ if (column >= sourceModel()->columnCount()) {
+ qDebug() << "Returning invalid index in mapToSource";
+ return QModelIndex();
+ }
+ return QIdentityProxyModel::mapToSource(proxyIndex);
+}
+
+QModelIndex KExtraColumnsProxyModel::sibling(int row, int column, const QModelIndex &idx) const
+{
+ if (idx.column() >= sourceModel()->columnCount()) {
+ return index(row, column, parent(idx));
+ }
+ return mapFromSource(sourceModel()->sibling(row, column, mapToSource(idx)));
+}
+
+QItemSelection KExtraColumnsProxyModel::mapSelectionToSource(const QItemSelection &selection) const
+{
+ Q_D(const KExtraColumnsProxyModel);
+ QItemSelection sourceSelection;
+
+ if (!sourceModel()) {
+ return sourceSelection;
+ }
+
+ // mapToSource will give invalid index for our additional columns, so truncate the selection
+ // to the columns known by the source model
+ const int sourceColumnCount = sourceModel()->columnCount();
+ QItemSelection::const_iterator it = selection.constBegin();
+ const QItemSelection::const_iterator end = selection.constEnd();
+ for (; it != end; ++it) {
+ Q_ASSERT(it->model() == this);
+ QModelIndex topLeft = it->topLeft();
+ Q_ASSERT(topLeft.isValid());
+ Q_ASSERT(topLeft.model() == this);
+ topLeft = topLeft.sibling(topLeft.row(), 0);
+ QModelIndex bottomRight = it->bottomRight();
+ Q_ASSERT(bottomRight.isValid());
+ Q_ASSERT(bottomRight.model() == this);
+ if (bottomRight.column() >= sourceColumnCount) {
+ bottomRight = bottomRight.sibling(bottomRight.row(), sourceColumnCount - 1);
+ }
+ // This can lead to duplicate source indexes, so use merge().
+ const QItemSelectionRange range(mapToSource(topLeft), mapToSource(bottomRight));
+ QItemSelection newSelection; newSelection << range;
+ sourceSelection.merge(newSelection, QItemSelectionModel::Select);
+ }
+
+ return sourceSelection;
+}
+
+int KExtraColumnsProxyModel::columnCount(const QModelIndex &parent) const
+{
+ Q_D(const KExtraColumnsProxyModel);
+ return QIdentityProxyModel::columnCount(parent) + d->m_extraHeaders.count();
+}
+
+QVariant KExtraColumnsProxyModel::data(const QModelIndex &index, int role) const
+{
+ Q_D(const KExtraColumnsProxyModel);
+ const int extraCol = extraColumnForProxyColumn(index.column());
+ if (extraCol >= 0 && !d->m_extraHeaders.isEmpty()) {
+ return extraColumnData(index.parent(), index.row(), extraCol, role);
+ }
+ return sourceModel()->data(mapToSource(index), role);
+}
+
+bool KExtraColumnsProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ Q_D(const KExtraColumnsProxyModel);
+ const int extraCol = extraColumnForProxyColumn(index.column());
+ if (extraCol >= 0 && !d->m_extraHeaders.isEmpty()) {
+ return setExtraColumnData(index.parent(), index.row(), extraCol, value, role);
+ }
+ return sourceModel()->setData(mapToSource(index), value, role);
+}
+
+Qt::ItemFlags KExtraColumnsProxyModel::flags(const QModelIndex &index) const
+{
+ const int extraCol = extraColumnForProxyColumn(index.column());
+ if (extraCol >= 0) {
+ // extra columns are readonly
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+ }
+ return sourceModel()->flags(mapToSource(index));
+}
+
+QVariant KExtraColumnsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ Q_D(const KExtraColumnsProxyModel);
+ if (orientation == Qt::Horizontal) {
+ const int extraCol = extraColumnForProxyColumn(section);
+ if (extraCol >= 0) {
+ // Only text is supported, in headers for extra columns
+ if (role == Qt::DisplayRole) {
+ return d->m_extraHeaders.at(extraCol);
+ }
+ return QVariant();
+ }
+ }
+ return QIdentityProxyModel::headerData(section, orientation, role);
+}
+
+QModelIndex KExtraColumnsProxyModel::index(int row, int column, const QModelIndex &parent) const
+{
+ const int extraCol = extraColumnForProxyColumn(column);
+ if (extraCol >= 0) {
+ // We store the internal pointer of the index for column 0 in the proxy index for extra columns.
+ // This will be useful in the parent method.
+ return createIndex(row, column, QIdentityProxyModel::index(row, 0, parent).internalPointer());
+ }
+ return QIdentityProxyModel::index(row, column, parent);
+}
+
+QModelIndex KExtraColumnsProxyModel::parent(const QModelIndex &child) const
+{
+ const int extraCol = extraColumnForProxyColumn(child.column());
+ if (extraCol >= 0) {
+ // Create an index for column 0 and use that to get the parent.
+ const QModelIndex proxySibling = createIndex(child.row(), 0, child.internalPointer());
+ return QIdentityProxyModel::parent(proxySibling);
+ }
+ return QIdentityProxyModel::parent(child);
+}
+
+int KExtraColumnsProxyModel::extraColumnForProxyColumn(int proxyColumn) const
+{
+ const int sourceColumnCount = sourceModel()->columnCount();
+ if (proxyColumn >= sourceColumnCount) {
+ return proxyColumn - sourceColumnCount;
+ }
+ return -1;
+}
+
+int KExtraColumnsProxyModel::proxyColumnForExtraColumn(int extraColumn) const
+{
+ return sourceModel()->columnCount() + extraColumn;
+}
+
+void KExtraColumnsProxyModelPrivate::_ec_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
+{
+ Q_Q(KExtraColumnsProxyModel);
+ const QModelIndexList persistentIndexList = q->persistentIndexList();
+ layoutChangePersistentIndexes.reserve(persistentIndexList.size());
+ layoutChangeProxyColumns.reserve(persistentIndexList.size());
+
+ foreach (QPersistentModelIndex proxyPersistentIndex, persistentIndexList) {
+ proxyIndexes << proxyPersistentIndex;
+ Q_ASSERT(proxyPersistentIndex.isValid());
+ const int column = proxyPersistentIndex.column();
+ layoutChangeProxyColumns << column;
+ if (column >= q->sourceModel()->columnCount()) {
+ proxyPersistentIndex = proxyPersistentIndex.sibling(proxyPersistentIndex.row(), 0);
+ }
+ const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
+ Q_ASSERT(srcPersistentIndex.isValid());
+ layoutChangePersistentIndexes << srcPersistentIndex;
+ }
+
+ QList<QPersistentModelIndex> parents;
+ parents.reserve(sourceParents.size());
+ foreach (const QPersistentModelIndex &parent, sourceParents) {
+ if (!parent.isValid()) {
+ parents << QPersistentModelIndex();
+ continue;
+ }
+ const QModelIndex mappedParent = q->mapFromSource(parent);
+ Q_ASSERT(mappedParent.isValid());
+ parents << mappedParent;
+ }
+
+ emit q->layoutAboutToBeChanged(parents, hint);
+}
+
+void KExtraColumnsProxyModelPrivate::_ec_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
+{
+ Q_Q(KExtraColumnsProxyModel);
+ for (int i = 0; i < proxyIndexes.size(); ++i) {
+ const QModelIndex proxyIdx = proxyIndexes.at(i);
+ QModelIndex newProxyIdx = q->mapFromSource(layoutChangePersistentIndexes.at(i));
+ if (proxyIdx.column() >= q->sourceModel()->columnCount()) {
+ newProxyIdx = newProxyIdx.sibling(newProxyIdx.row(), layoutChangeProxyColumns.at(i));
+ }
+ q->changePersistentIndex(proxyIdx, newProxyIdx);
+ }
+
+ layoutChangePersistentIndexes.clear();
+ layoutChangeProxyColumns.clear();
+ proxyIndexes.clear();
+
+ QList<QPersistentModelIndex> parents;
+ parents.reserve(sourceParents.size());
+ foreach (const QPersistentModelIndex &parent, sourceParents) {
+ if (!parent.isValid()) {
+ parents << QPersistentModelIndex();
+ continue;
+ }
+ const QModelIndex mappedParent = q->mapFromSource(parent);
+ Q_ASSERT(mappedParent.isValid());
+ parents << mappedParent;
+ }
+
+ emit q->layoutChanged(parents, hint);
+}
+
+#include "moc_kextracolumnsproxymodel.cpp"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kitemmodels-5.12.0/src/kextracolumnsproxymodel.h new/kitemmodels-5.13.0/src/kextracolumnsproxymodel.h
--- old/kitemmodels-5.12.0/src/kextracolumnsproxymodel.h 1970-01-01 01:00:00.000000000 +0100
+++ new/kitemmodels-5.13.0/src/kextracolumnsproxymodel.h 2015-08-01 14:41:18.000000000 +0200
@@ -0,0 +1,142 @@
+/*
+ Copyright (c) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+ Authors: David Faure
+
+ 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.
+*/
+
+#ifndef KEXTRACOLUMNSPROXYMODEL_H
+#define KEXTRACOLUMNSPROXYMODEL_H
+
+#include <QIdentityProxyModel>
+#include <QScopedPointer>
+#include "kitemmodels_export.h"
+
+class KExtraColumnsProxyModelPrivate;
+
+/**
+ * This proxy appends extra columns (after all existing columns).
+ *
+ * The proxy supports source models that have a tree structure.
+ * It also supports editing, and propagating changes from the source model.
+ * Row insertion/removal, column insertion/removal in the source model are supported.
+ *
+ * Not supported: adding/removing extra columns at runtime; having a different number of columns in subtrees;
+ * drag-n-drop support in the extra columns; moving columns.
+ *
+ * Derive from KExtraColumnsProxyModel, call appendColumn (typically in the constructor) for each extra column,
+ * and reimplement extraColumnData() to allow KExtraColumnsProxyModel to retrieve the data to show in the extra columns.
+ *
+ * If you want your new column(s) to be somewhere else than at the right of the existing columns, you can
+ * use a KRearrangeColumnsProxyModel on top.
+ *
+ * Author: David Faure, KDAB
+ * @since 5.13
+ */
+class KITEMMODELS_EXPORT KExtraColumnsProxyModel : public QIdentityProxyModel
+{
+ Q_OBJECT
+public:
+ /**
+ * Base class constructor.
+ * Remember to call setSourceModel afterwards, and appendColumn.
+ */
+ explicit KExtraColumnsProxyModel(QObject *parent = 0);
+ /**
+ * Destructor.
+ */
+ ~KExtraColumnsProxyModel();
+
+ // API
+
+ /**
+ * Appends an extra column.
+ * @param header an optional text for the horizontal header
+ */
+ void appendColumn(const QString &header = QString());
+
+ /**
+ * This method is called by data() for extra columns.
+ * Reimplement this method to return the data for the extra columns.
+ *
+ * @param parent the parent model index (only useful in tree models)
+ * @param row the row number for which the model is querying for data (child of @p parent, if set)
+ * @param extraColumn the number of the extra column, starting at 0 (this doesn't require knowing how many columns the source model has)
+ * @param role the role being queried
+ * @return the data at @p row and @p extraColumn
+ */
+ virtual QVariant extraColumnData(const QModelIndex &parent, int row, int extraColumn, int role = Qt::DisplayRole) const = 0;
+
+ /**
+ * This method is called by setData() for extra columns.
+ * Reimplement this method to set the data for the extra columns, if editing is supported.
+ * Remember to call extraColumnDataChanged() after changing the data storage.
+ * The default implementation returns false.
+ */
+ virtual bool setExtraColumnData(const QModelIndex &parent, int row, int extraColumn, const QVariant &data, int role = Qt::EditRole);
+
+ /**
+ * This method can be called by your derived class when the data in an extra column has changed.
+ * The use case is data that changes "by itself", unrelated to setData.
+ */
+ void extraColumnDataChanged(const QModelIndex &parent, int row, int extraColumn, const QVector<int> &roles);
+
+ /**
+ * Returns the extra column number (0, 1, ...) for a given column number of the proxymodel.
+ * This basically means subtracting the amount of columns in the source model.
+ */
+ int extraColumnForProxyColumn(int proxyColumn) const;
+ /**
+ * Returns the proxy column number for a given extra column number (starting at 0).
+ * This basically means adding the amount of columns in the source model.
+ */
+ int proxyColumnForExtraColumn(int extraColumn) const;
+
+
+ // Implementation
+ /// @reimp
+ void setSourceModel(QAbstractItemModel *model) Q_DECL_OVERRIDE;
+ /// @reimp
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const Q_DECL_OVERRIDE;
+ /// @reimp
+ QItemSelection mapSelectionToSource(const QItemSelection &selection) const Q_DECL_OVERRIDE;
+ /// @reimp
+ int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+ /// @reimp
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+ /// @reimp
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE;
+ /// @reimp
+ QModelIndex sibling(int row, int column, const QModelIndex &idx) const Q_DECL_OVERRIDE;
+ /// @reimp
+ Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
+ /// @reimp
+ QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+ /// @reimp
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+ /// @reimp
+ QModelIndex parent(const QModelIndex &child) const Q_DECL_OVERRIDE;
+
+private:
+ Q_DECLARE_PRIVATE(KExtraColumnsProxyModel)
+ Q_PRIVATE_SLOT(d_func(), void _ec_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint))
+ Q_PRIVATE_SLOT(d_func(), void _ec_sourceLayoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint))
+ const QScopedPointer<KExtraColumnsProxyModelPrivate> d_ptr;
+
+};
+
+#endif