29 class KTp::AbstractGroupingProxyModel::Private
32 QAbstractItemModel *source;
35 QHash<QPersistentModelIndex, QSet<QString> > groupCache;
38 QMultiHash<QPersistentModelIndex, ProxyNode*> proxyMap;
39 QHash<QString, GroupNode*> groupMap;
42 class ProxyNode :
public QStandardItem
45 ProxyNode(
const QPersistentModelIndex &sourceIndex);
46 QVariant data(
int role)
const;
48 QString group()
const;
50 const QPersistentModelIndex m_sourceIndex;
53 class GroupNode :
public QStandardItem {
55 GroupNode(
const QString &groupId);
56 QString group()
const;
57 virtual QVariant data(
int role)
const;
60 void setForced(
bool forced);
62 const QString m_groupId;
67 ProxyNode::ProxyNode(
const QPersistentModelIndex &sourceIndex):
69 m_sourceIndex(sourceIndex)
73 QVariant ProxyNode::data(
int role)
const
75 return m_sourceIndex.data(role);
78 void ProxyNode::changed()
80 QStandardItem::emitDataChanged();
83 QString ProxyNode::group()
const
86 GroupNode *groupNode =
static_cast<GroupNode*
>(parent());
88 return groupNode->group();
95 GroupNode::GroupNode(
const QString &groupId):
102 QString GroupNode::group()
const
107 QVariant GroupNode::data(
int role)
const
110 Q_ASSERT(proxyModel);
114 void GroupNode::setForced(
bool forced)
119 bool GroupNode::forced()
const
124 void GroupNode::changed()
126 QStandardItem::emitDataChanged();
135 setRoleNames(source->roleNames());
139 QTimer::singleShot(0,
this, SLOT(onLoad()));
150 GroupNode* groupNode = itemForGroup(group);
151 groupNode->setForced(
true);
156 GroupNode* groupNode = d->groupMap[group];
162 groupNode->setForced(
false);
165 if (groupNode->rowCount() == 0) {
166 takeRow(groupNode->row());
167 d->groupMap.remove(groupNode->group());
173 GroupNode *node = d->groupMap[group];
187 void KTp::AbstractGroupingProxyModel::onRowsInserted(
const QModelIndex &sourceParent,
int start,
int end)
190 if (!sourceParent.parent().isValid()) {
191 for (
int i = start; i <= end; i++) {
192 QModelIndex index = d->source->index(i, 0, sourceParent);
193 Q_FOREACH(
const QString &group, groupsForIndex(index)) {
194 addProxyNode(index, itemForGroup(group));
198 for (
int i = start; i <= end; i++) {
199 QModelIndex index = d->source->index(i, 0, sourceParent);
200 QHash<QPersistentModelIndex, ProxyNode*>::const_iterator it = d->proxyMap.find(index);
201 while (it != d->proxyMap.end() && it.key() == index) {
202 addProxyNode(index, it.value());
209 void KTp::AbstractGroupingProxyModel::addProxyNode(
const QModelIndex &sourceIndex, QStandardItem *parent)
211 ProxyNode *proxyNode =
new ProxyNode(sourceIndex);
212 d->proxyMap.insertMulti(sourceIndex, proxyNode);
213 parent->appendRow(proxyNode);
216 void KTp::AbstractGroupingProxyModel::removeProxyNodes(
const QModelIndex &sourceIndex,
const QList<ProxyNode *> &removedItems)
218 Q_FOREACH(ProxyNode *proxy, removedItems) {
219 QStandardItem *parentItem = proxy->parent();
220 parentItem->removeRow(proxy->row());
221 d->proxyMap.remove(sourceIndex, proxy);
224 if (parentItem->rowCount() == 0 && parentItem->parent() == 0 ) {
225 GroupNode* groupNode =
dynamic_cast<GroupNode*
>(parentItem);
228 if (groupNode->forced() ==
false) {
229 takeRow(groupNode->row());
230 d->groupMap.remove(groupNode->group());
240 void KTp::AbstractGroupingProxyModel::onRowsRemoved(
const QModelIndex &sourceParent,
int start,
int end)
242 for (
int i = start; i<=end; i++) {
243 QPersistentModelIndex index = d->source->index(i, 0, sourceParent);
244 QList<ProxyNode *> itemsToRemove;
246 QHash<QPersistentModelIndex, ProxyNode*>::const_iterator it = d->proxyMap.find(index);
247 while (it != d->proxyMap.end() && it.key() == index) {
248 kDebug() <<
"removing row" << index.data();
249 itemsToRemove.append(it.value());
252 d->groupCache.remove(index);
253 removeProxyNodes(index, itemsToRemove);
263 void KTp::AbstractGroupingProxyModel::onDataChanged(
const QModelIndex &sourceTopLeft,
const QModelIndex &sourceBottomRight)
265 for (
int i = sourceTopLeft.row(); i <= sourceBottomRight.row(); i++) {
266 QPersistentModelIndex index = d->source->index(i, 0, sourceTopLeft.parent());
269 if (!sourceTopLeft.parent().isValid()) {
271 QSet<QString> itemGroups = groupsForIndex(d->source->index(i, 0, sourceTopLeft.parent()));
272 if (d->groupCache[index] != itemGroups) {
273 d->groupCache[index] = itemGroups;
276 QHash<QPersistentModelIndex, ProxyNode*>::const_iterator it = d->proxyMap.find(index);
277 QList<ProxyNode*> removedItems;
278 while (it != d->proxyMap.end() && it.key() == index) {
280 if (itemGroups.contains(it.value()->group())) {
281 itemGroups.remove(it.value()->group());
285 removedItems.append(it.value());
287 kDebug() <<
"removing " << index.data().toString() <<
" from group " << it.value()->group();
292 removeProxyNodes(index, removedItems);
295 Q_FOREACH(
const QString &group, itemGroups) {
296 ProxyNode *proxyNode =
new ProxyNode(index);
297 d->proxyMap.insertMulti(index, proxyNode);
298 itemForGroup(group)->appendRow(proxyNode);
300 kDebug() <<
"adding " << index.data().toString() <<
" to group " << group;
306 QHash<QPersistentModelIndex, ProxyNode*>::const_iterator it = d->proxyMap.find(index);
307 while (it != d->proxyMap.end() && it.key() == index) {
308 it.value()->changed();
315 void KTp::AbstractGroupingProxyModel::onLoad()
317 if (d->source->rowCount() > 0) {
318 onRowsInserted(QModelIndex(), 0, d->source->rowCount()-1);
320 connect(d->source, SIGNAL(modelReset()), SLOT(onModelReset()));
321 connect(d->source, SIGNAL(rowsInserted(QModelIndex,
int,
int)), SLOT(onRowsInserted(QModelIndex,
int,
int)));
322 connect(d->source, SIGNAL(rowsAboutToBeRemoved(QModelIndex,
int,
int)), SLOT(onRowsRemoved(QModelIndex,
int,
int)));
323 connect(d->source, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(onDataChanged(QModelIndex,QModelIndex)));
330 void KTp::AbstractGroupingProxyModel::onModelReset()
333 d->groupCache.clear();
338 if (d->source->rowCount() > 0) {
339 onRowsInserted(QModelIndex(), 0, d->source->rowCount()-1);
343 GroupNode* KTp::AbstractGroupingProxyModel::itemForGroup(
const QString &group)
345 if (d->groupMap.contains(group)) {
346 return d->groupMap[group];
348 GroupNode* item =
new GroupNode(group);
350 d->groupMap[group] = item;