[SCM] ktp-common-internals packaging branch, master, updated. debian/15.12.1-2-1839-gf0635e9
Maximiliano Curia
maxy at moszumanska.debian.org
Mon May 9 09:05:53 UTC 2016
Gitweb-URL: http://git.debian.org/?p=pkg-kde/applications/ktp-common-internals.git;a=commitdiff;h=a1a7322
The following commit has been merged in the master branch:
commit a1a732290e24d762c38b8912ba7b931144896f14
Author: David Edmundson <kde at davidedmundson.co.uk>
Date: Mon Nov 19 14:52:31 2012 +0900
Initial start of a grouping model which does not rely on ContactModelItem*
---
KTp/Models/abstract-grouping-proxy-model.cpp | 248 +++++++++++++++++++++++++++
KTp/Models/abstract-grouping-proxy-model.h | 66 +++++++
2 files changed, 314 insertions(+)
diff --git a/KTp/Models/abstract-grouping-proxy-model.cpp b/KTp/Models/abstract-grouping-proxy-model.cpp
new file mode 100644
index 0000000..0d10754
--- /dev/null
+++ b/KTp/Models/abstract-grouping-proxy-model.cpp
@@ -0,0 +1,248 @@
+/*
+ * Turns a list model into a tree allowing nodes to be in multiple groups
+ *
+ * Copyright (C) 2012 David Edmundson <kde at davidedmundson.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "abstract-grouping-proxy-model.h"
+
+#include <QSet>
+
+#include <KDebug>
+
+
+class ProxyNode : public QStandardItem
+{
+public:
+ ProxyNode(const QPersistentModelIndex &sourceIndex);
+ QVariant data(int role) const;
+ void changed(); //expose protected method in QStandardItem
+ QString group() const;
+private:
+ const QPersistentModelIndex m_sourceIndex;
+};
+
+class GroupNode : public QStandardItem {
+public:
+ GroupNode(const QString &groupId);
+ QString group() const;
+ virtual QVariant data(int role) const;
+private:
+ const QString m_groupId;
+};
+
+
+ProxyNode::ProxyNode(const QPersistentModelIndex &sourceIndex):
+ QStandardItem(),
+ m_sourceIndex(sourceIndex)
+{
+}
+
+QVariant ProxyNode::data(int role) const
+{
+ return m_sourceIndex.data(role);
+}
+
+void ProxyNode::changed()
+{
+ QStandardItem::emitDataChanged();
+}
+
+QString ProxyNode::group() const
+{
+ //FIXME is this a hack?
+ GroupNode *groupNode = static_cast<GroupNode*>(parent());
+ if (groupNode) {
+ return groupNode->group();
+ }
+ return QString();
+}
+
+
+
+GroupNode::GroupNode(const QString &groupId):
+ QStandardItem(),
+ m_groupId(groupId)
+{
+}
+
+QString GroupNode::group() const {
+ return m_groupId;
+}
+
+QVariant GroupNode::data(int role) const
+{
+ AbstractGroupingProxyModel *proxyModel = qobject_cast<AbstractGroupingProxyModel*>(model());
+ Q_ASSERT(proxyModel);
+ return proxyModel->dataForGroup(m_groupId, role);
+}
+
+
+AbstractGroupingProxyModel::AbstractGroupingProxyModel(QAbstractItemModel *source):
+ QStandardItemModel(source),
+ m_source(source)
+{
+ if (source->rowCount() > 0) {
+ onRowsInserted(QModelIndex(), 0, source->rowCount());
+ }
+
+ connect(m_source, SIGNAL(modelReset()), SLOT(onModelReset()));
+ connect(m_source, SIGNAL(rowsInserted(QModelIndex, int,int)), SLOT(onRowsInserted(QModelIndex,int,int)));
+ connect(m_source, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), SLOT(onRowsRemoved(QModelIndex,int,int)));
+ connect(m_source, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(onDataChanged(QModelIndex,QModelIndex)));
+}
+
+/* Called when source items inserts a row
+ *
+ * For each new row, create a proxyNode.
+ * If it's at the top level add it to the relevant group nodes.
+ * Otherwise add it to the relevant proxy nodes in our model
+ */
+
+void AbstractGroupingProxyModel::onRowsInserted(const QModelIndex &sourceParent, int start, int end)
+{
+ //if top level in root model
+ if (!sourceParent.parent().isValid()) {
+ for (int i = start; i<=end; i++) {
+ QModelIndex index = m_source->index(i, 0, sourceParent);
+ foreach(const QString &group, groupsForIndex(index)) {
+ addProxyNode(index, itemForGroup(group));
+ }
+ }
+ } else {
+ for (int i = start; i<=end; i++) {
+ QModelIndex index = m_source->index(i, 0, sourceParent);
+ QHash<QPersistentModelIndex, ProxyNode*>::const_iterator it = m_proxyMap.find(index);
+ while (it != m_proxyMap.end() && it.key() == index) {
+ addProxyNode(index, it.value());
+ it++;
+ }
+ }
+ }
+}
+
+void AbstractGroupingProxyModel::addProxyNode(const QModelIndex &sourceIndex, QStandardItem *parent)
+{
+ ProxyNode *proxyNode = new ProxyNode(sourceIndex);
+ m_proxyMap.insertMulti(sourceIndex, proxyNode);
+ parent->appendRow(proxyNode);
+}
+
+/*
+ * Called when a row is remove from the source model model
+ * Find all existing proxy models and delete thems
+*/
+void AbstractGroupingProxyModel::onRowsRemoved(const QModelIndex &sourceParent, int start, int end)
+{
+ for (int i = start; i<=end; i++) {
+ QPersistentModelIndex index = m_source->index(i, 0, sourceParent);
+
+ QHash<QPersistentModelIndex, ProxyNode*>::const_iterator it = m_proxyMap.find(index);
+ while (it != m_proxyMap.end() && it.key() == index) {
+ kDebug() << "removing row" << index.data();
+ it.value()->parent()->removeRow(it.value()->row());
+ ++it;
+ }
+ m_proxyMap.remove(index);
+ }
+}
+
+/*
+ * Called when source model changes data
+ * If it's the top level item in the source model detect if the groups have changed, if so update as appropriately
+ * Find all proxy nodes, and make dataChanged() get emitted
+ */
+
+void AbstractGroupingProxyModel::onDataChanged(const QModelIndex &sourceTopLeft, const QModelIndex &sourceBottomRight)
+{
+ for (int i=sourceTopLeft.row() ; i<=sourceBottomRight.row() ; i++) {
+ QPersistentModelIndex index = m_source->index(i, 0, sourceTopLeft.parent());
+
+ //if top level item
+ if (!sourceTopLeft.parent().isValid()) {
+ //groupsSet has changed...update as appropriate
+ QSet<QString> itemGroups = groupsForIndex(m_source->index(i, 0, sourceTopLeft.parent()));
+ if (m_groupCache[index] != itemGroups) {
+ m_groupCache[index] = itemGroups;
+
+ //loop through existing proxy nodes, and check each one is still valid.
+ QHash<QPersistentModelIndex, ProxyNode*>::const_iterator it = m_proxyMap.find(index);
+ QList<ProxyNode*> removedItems;
+ while (it != m_proxyMap.end() && it.key() == index) {
+ // if proxy's group is still in the item's groups.
+ if (itemGroups.contains(it.value()->group())) {
+ itemGroups.remove(it.value()->group());
+ } else {
+ //remove the proxy item
+ //cache to list and remove once outside the const_iterator
+ removedItems.append(it.value());
+
+ kDebug() << "removing " << index.data().toString() << " from group " << it.value()->group();
+ }
+ ++it;
+ }
+
+ //do the actual removing
+ foreach (ProxyNode *proxy, removedItems) {
+ proxy->parent()->removeRow(proxy->row());
+ m_proxyMap.remove(index, proxy);
+ }
+
+ //remaining items in itemGroups are now the new groups
+ foreach(const QString &group, itemGroups) {
+ ProxyNode *proxyNode = new ProxyNode(index);
+ m_proxyMap.insertMulti(index, proxyNode);
+ itemForGroup(group)->appendRow(proxyNode);
+
+ kDebug() << "adding " << index.data().toString() << " to group " << group;
+ }
+ }
+ }
+
+ //mark all proxy nodes as changed
+ QHash<QPersistentModelIndex, ProxyNode*>::const_iterator it = m_proxyMap.find(index);
+ while (it != m_proxyMap.end() && it.key() == index) {
+ it.value()->changed();
+ ++it;
+ }
+ }
+}
+
+/* Called when source model gets reset
+ * Delete all local caches/maps and wipe the current QStandardItemModel
+ */
+
+void AbstractGroupingProxyModel::onModelReset()
+{
+ clear();
+ m_groupCache.clear();
+ m_proxyMap.clear();
+ m_groupMap.clear();
+ kDebug() << "reset";
+}
+
+QStandardItem *AbstractGroupingProxyModel::itemForGroup(const QString &group)
+{
+ if (m_groupMap.contains(group)) {
+ return m_groupMap[group];
+ } else {
+ GroupNode* item = new GroupNode(group);
+ appendRow(item);
+ m_groupMap[group] = item;
+ return item;
+ }
+}
diff --git a/KTp/Models/abstract-grouping-proxy-model.h b/KTp/Models/abstract-grouping-proxy-model.h
new file mode 100644
index 0000000..5a34d6c
--- /dev/null
+++ b/KTp/Models/abstract-grouping-proxy-model.h
@@ -0,0 +1,66 @@
+/*
+ * Turns a list model into a tree allowing nodes to be in multiple groups
+ *
+ * Copyright (C) 2012 David Edmundson <kde at davidedmundson.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#ifndef ABSTRACTGROUPINGPROXYMODEL_H
+#define ABSTRACTGROUPINGPROXYMODEL_H
+
+#include <QStandardItemModel>
+
+class ProxyNode;
+class GroupNode;
+
+class AbstractGroupingProxyModel : public QStandardItemModel
+{
+ Q_OBJECT
+public:
+ explicit AbstractGroupingProxyModel(QAbstractItemModel *source);
+
+//protected:
+ /** Return a list of all groups this items belongs to. Subclasses must override this*/
+ virtual QSet<QString> groupsForIndex(const QModelIndex &sourceIndex) const = 0;
+ /** Equivalent of QAbstractItemModel::data() called for a specific group header*/
+ virtual QVariant dataForGroup(const QString &group, int role) const = 0;
+
+private slots:
+ void onRowsInserted(const QModelIndex &sourceParent, int start, int end);
+ void onRowsRemoved(const QModelIndex &sourceParent, int start, int end);
+ void onDataChanged(const QModelIndex &sourceTopLeft, const QModelIndex &sourceBottomRight);
+ void onModelReset();
+
+private:
+ /** Create a new proxyNode appended to the given parent in this model*/
+ void addProxyNode(const QModelIndex &sourceIndex, QStandardItem *parent);
+
+
+ /** Returns the standard Item belonging to a particular group name. Creating one if needed*/
+ QStandardItem *itemForGroup(const QString &group);
+
+ QAbstractItemModel *m_source;
+
+ //keep a cache of what groups an item belongs to
+ QHash<QPersistentModelIndex, QSet<QString> > m_groupCache;
+
+ //item -> groups
+ QMultiHash<QPersistentModelIndex, ProxyNode*> m_proxyMap;
+ QHash<QString, QStandardItem*> m_groupMap;
+};
+
+#endif // GROUPPROXYMODEL_H
--
ktp-common-internals packaging
More information about the pkg-kde-commits
mailing list