[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [ktp-common-internals] KTp/Models: Respect filters for counters
From:       Dominik Cermak <d.cermak () arcor ! de>
Date:       2012-06-27 15:37:32
Message-ID: 20120627153732.B7F3EA60BE () git ! kde ! org
[Download RAW message or body]

Git commit 3737f85af335b0634d31c7d82a0e222f3475581c by Dominik Cermak.
Committed on 27/06/2012 at 17:30.
Pushed by cermak into branch 'master'.

Respect filters for counters

The counting is done in the AccountsFilterModel now.
So to have those counters one will have to use the AccountsFilterModel.

BUG: 300956
FIXED-IN: 0.5
REVIEW: 105130

M  +190  -3    KTp/Models/accounts-filter-model.cpp
M  +10   -4    KTp/Models/accounts-filter-model.h
M  +3    -24   KTp/Models/accounts-model-item.cpp
M  +0    -2    KTp/Models/accounts-model-item.h
M  +2    -4    KTp/Models/accounts-model.cpp
M  +1    -22   KTp/Models/groups-model-item.cpp
M  +0    -2    KTp/Models/groups-model-item.h
M  +1    -8    KTp/Models/groups-model.cpp

http://commits.kde.org/telepathy-common-internals/3737f85af335b0634d31c7d82a0e222f3475581c


diff --git a/KTp/Models/accounts-filter-model.cpp \
b/KTp/Models/accounts-filter-model.cpp index c17b335..bd8eaa4 100644
--- a/KTp/Models/accounts-filter-model.cpp
+++ b/KTp/Models/accounts-filter-model.cpp
@@ -4,6 +4,7 @@
  * Copyright (C) 2011 David Edmundson <kde@davidedmundson.co.uk>
  * Copyright (C) 2011 Martin Klapetek <martin dot klapetek at gmail dot com>
  * Copyright (C) 2012 Daniele E. Domenichelli <daniele.domenichelli@gmail.com>
+ * Copyright (C) 2012 Dominik Cermak <d.cermak@arcor.de>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -27,6 +28,7 @@
 #include "groups-model-item.h"
 #include "contact-model-item.h"
 #include "accounts-model-item.h"
+#include "proxy-tree-node.h"
 
 #include <presence.h>
 
@@ -70,19 +72,24 @@ public:
     bool filterAcceptsAccount(const QModelIndex &index) const;
     bool filterAcceptsContact(const QModelIndex &index) const;
     bool filterAcceptsGroup(const QModelIndex &index) const;
+
+    QHash<QString, int> m_onlineContactsCounts;
+    QHash<QString, int> m_totalContactsCounts;
 };
 
 bool AccountsFilterModel::Private::filterAcceptsAccount(const QModelIndex &index) \
const  {
-    //hide disabled accounts
+    // Hide disabled accounts
     if (!index.data(AccountsModel::EnabledRole).toBool()) {
         return false;
     }
-    //hide
+
+    // Hide disconnected accounts
     if (index.data(AccountsModel::ConnectionStatusRole).toUInt()
         != Tp::ConnectionStatusConnected) {
         return false;
     }
+
     return true;
 }
 
@@ -303,8 +310,28 @@ bool AccountsFilterModel::Private::filterAcceptsContact(const \
QModelIndex &index  
 bool AccountsFilterModel::Private::filterAcceptsGroup(const QModelIndex &index) \
const  {
+    QVariant item = index.data(AccountsModel::ItemRole);
+    GroupsModelItem *gmItem = item.value<GroupsModelItem*>();
+
     if (presenceTypeFilterFlags != DoNotFilterByPresence) {
-        if (index.data(AccountsModel::OnlineUsersCountRole).toInt() == 0) {
+        // If there is no cached value, create one
+        if (!m_onlineContactsCounts.contains(gmItem->groupName())) {
+            q->countContacts(index);
+        }
+
+        // Don't accept groups with no online contacts
+        if (m_onlineContactsCounts.value(gmItem->groupName()) == 0) {
+            return false;
+        }
+    }
+    else {
+        // If there is no cached value, create one
+        if (!m_totalContactsCounts.contains(gmItem->groupName())) {
+            q->countContacts(index);
+        }
+
+        // Don't accept groups with no total contacts
+        if (m_totalContactsCounts.value(gmItem->groupName()) == 0) {
             return false;
         }
     }
@@ -322,6 +349,86 @@ AccountsFilterModel::~AccountsFilterModel()
     delete d;
 }
 
+QVariant AccountsFilterModel::data(const QModelIndex &index, int role) const
+{
+    if (!index.isValid()) {
+        return QVariant();
+    }
+
+    QModelIndex sourceIndex = mapToSource(index);
+    if (!sourceIndex.isValid()) {
+        return QVariant();
+    }
+
+    // Special handling for the counts
+    if (role == AccountsModel::OnlineUsersCountRole) {
+        QVariant item = sourceIndex.data(AccountsModel::ItemRole);
+        if (item.canConvert<GroupsModelItem*>()) {
+            GroupsModelItem *gmItem = item.value<GroupsModelItem*>();
+            // If there is no cached value, create one
+            if (!d->m_onlineContactsCounts.contains(gmItem->groupName())) {
+                countContacts(sourceIndex);
+            }
+            return d->m_onlineContactsCounts.value(gmItem->groupName());
+        } else if (item.canConvert<AccountsModelItem*>()) {
+            AccountsModelItem *amItem = item.value<AccountsModelItem*>();
+            // If there is no cached value, create one
+            if (!d->m_onlineContactsCounts.contains(amItem->data(AccountsModel::IdRole).toString())) \
{ +                countContacts(sourceIndex);
+            }
+            return d->m_onlineContactsCounts.value(amItem->data(AccountsModel::IdRole).toString());
 +        }
+    } else if (role == AccountsModel::TotalUsersCountRole) {
+        QVariant item = sourceIndex.data(AccountsModel::ItemRole);
+        if (item.canConvert<GroupsModelItem*>()) {
+            GroupsModelItem *gmItem = item.value<GroupsModelItem*>();
+            // If there is no cached value, create one
+            if (!d->m_totalContactsCounts.contains(gmItem->groupName())) {
+                countContacts(sourceIndex);
+            }
+            return d->m_totalContactsCounts.value(gmItem->groupName());
+        } else if (item.canConvert<AccountsModelItem*>()) {
+            AccountsModelItem *amItem = item.value<AccountsModelItem*>();
+            // If there is no cached value, create one
+            if (!d->m_totalContactsCounts.contains(amItem->data(AccountsModel::IdRole).toString())) \
{ +                countContacts(sourceIndex);
+            }
+            return d->m_totalContactsCounts.value(amItem->data(AccountsModel::IdRole).toString());
 +        }
+    }
+
+    // In all other cases just delegate it to the source model
+    return sourceModel()->data(mapToSource(index), role);
+}
+
+void AccountsFilterModel::setSourceModel(QAbstractItemModel *sourceModel)
+{
+    // Disconnect the previous source model
+    disconnect(this->sourceModel(),
+               SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+               this,
+               SLOT(countContacts(QModelIndex)));
+
+    // Clear all cached values as they aren't valid anymore because the source model \
changed. +    d->m_onlineContactsCounts.clear();
+    d->m_totalContactsCounts.clear();
+    QSortFilterProxyModel::setSourceModel(sourceModel);
+
+    // Connect the new source model
+    connect(this->sourceModel(),
+            SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+            this,
+            SLOT(countContacts(QModelIndex)));
+}
+
+void AccountsFilterModel::invalidateFilter()
+{
+    // Clear all cached values as they aren't valid anymore because the filter \
changed. +    d->m_onlineContactsCounts.clear();
+    d->m_totalContactsCounts.clear();
+    QSortFilterProxyModel::invalidateFilter();
+}
+
 AccountsFilterModel::SortMode AccountsFilterModel::sortMode() const
 {
     switch (sortRole()) {
@@ -615,6 +722,86 @@ void \
AccountsFilterModel::setGroupsFilterMatchFlags(Qt::MatchFlags groupsFilterM  }
 }
 
+void AccountsFilterModel::countContacts(const QModelIndex &index) const
+{
+    QVariant item = index.data(AccountsModel::ItemRole);
+    if (item.canConvert<GroupsModelItem*>()) {
+        GroupsModelItem *gmItem = item.value<GroupsModelItem*>();
+
+        // Count the online contacts
+        int tmpCounter = 0;
+
+        for (int i = 0; i < gmItem->size(); ++i) {
+            ProxyTreeNode* proxyNode = \
qobject_cast<ProxyTreeNode*>(gmItem->childAt(i)); +            Q_ASSERT(proxyNode);
+
+            // We want all online contacts that are accepted by the filter
+            if (filterAcceptsRow(gmItem->indexOf(gmItem->childAt(i)), index)
+                && proxyNode->data(AccountsModel::PresenceTypeRole).toUInt() != \
Tp::ConnectionPresenceTypeOffline +                && \
proxyNode->data(AccountsModel::PresenceTypeRole).toUInt() != \
Tp::ConnectionPresenceTypeUnknown) { +                tmpCounter++;
+            }
+        }
+
+        d->m_onlineContactsCounts.insert(gmItem->groupName(), tmpCounter);
+
+        // Now count the total contacts accepted by the filter (but ignore presence \
filter). +        // Save the presenceTypeFilterFlags to reapply them later, because \
we need to disable +        // presence filtering to get the right numbers
+        PresenceTypeFilterFlags saved = presenceTypeFilterFlags();
+        d->presenceTypeFilterFlags = AccountsFilterModel::DoNotFilterByPresence;
+
+        tmpCounter = 0;
+        for (int i = 0; i < gmItem->size(); ++i) {
+            if (filterAcceptsRow(gmItem->indexOf(gmItem->childAt(i)), index)) {
+                tmpCounter++;
+            }
+        }
+
+        // Restore the saved presenceTypeFilterFlags
+        d->presenceTypeFilterFlags = saved;
+
+        d->m_totalContactsCounts.insert(gmItem->groupName(), tmpCounter);
+    } else if (item.canConvert<AccountsModelItem*>()) {
+        AccountsModelItem *amItem = item.value<AccountsModelItem*>();
+
+        // Count the online contacts
+        int tmpCounter = 0;
+
+        for (int i = 0; i < amItem->size(); ++i) {
+            ContactModelItem* contactNode = \
qobject_cast<ContactModelItem*>(amItem->childAt(i)); +            \
Q_ASSERT(contactNode); +
+            // We want all online contacts that are accepted by the filter
+            if (filterAcceptsRow(amItem->indexOf(amItem->childAt(i)), index)
+                && contactNode->data(AccountsModel::PresenceTypeRole).toUInt() != \
Tp::ConnectionPresenceTypeOffline +                && \
contactNode->data(AccountsModel::PresenceTypeRole).toUInt() != \
Tp::ConnectionPresenceTypeUnknown) { +                tmpCounter++;
+            }
+        }
+
+        d->m_onlineContactsCounts.insert(amItem->data(AccountsModel::IdRole).toString(), \
tmpCounter); +
+        // Now count the total contacts accepted by the filter (but ignore presence \
filter). +        // Save the presenceTypeFilterFlags to reapply them later, because \
we need to disable +        // presence filtering to get the right numbers
+        PresenceTypeFilterFlags saved = presenceTypeFilterFlags();
+        d->presenceTypeFilterFlags = AccountsFilterModel::DoNotFilterByPresence;
+
+        tmpCounter = 0;
+        for (int i = 0; i < amItem->size(); ++i) {
+            if (filterAcceptsRow(amItem->indexOf(amItem->childAt(i)), index)) {
+                tmpCounter++;
+            }
+        }
+
+        // Restore the saved presenceTypeFilterFlags
+        d->presenceTypeFilterFlags = saved;
+
+        d->m_totalContactsCounts.insert(amItem->data(AccountsModel::IdRole).toString(), \
tmpCounter); +    }
+}
+
 bool AccountsFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex \
&sourceParent) const  {
     QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
diff --git a/KTp/Models/accounts-filter-model.h b/KTp/Models/accounts-filter-model.h
index 9ed824a..b0d7402 100644
--- a/KTp/Models/accounts-filter-model.h
+++ b/KTp/Models/accounts-filter-model.h
@@ -192,6 +192,10 @@ public:
     AccountsFilterModel(QObject *parent = 0);
     virtual ~AccountsFilterModel();
 
+    virtual QVariant data(const QModelIndex &index, int role) const;
+    virtual void setSourceModel(QAbstractItemModel *sourceModel);
+    void invalidateFilter();
+
     SortMode sortMode() const;
     void resetSortMode();
     Q_SLOT void setSortMode(SortMode sortMode);
@@ -257,12 +261,14 @@ public:
     Q_SLOT void setGroupsFilterMatchFlags(Qt::MatchFlags groupsFilterMatchFlags);
     Q_SIGNAL void groupsFilterMatchFlagsChanged(Qt::MatchFlags \
groupsFilterMatchFlags);  
+    Q_SLOT void countContacts(const QModelIndex &index) const;
+
 protected:
     bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
-    bool lessThan ( const QModelIndex &left, const QModelIndex &right ) const;
-QModelIndexList match(const QModelIndex &start, int role,
-                                          const QVariant &value, int hits,
-                                          Qt::MatchFlags flags) const;
+    bool lessThan (const QModelIndex &left, const QModelIndex &right) const;
+    QModelIndexList match(const QModelIndex &start, int role,
+                          const QVariant &value, int hits,
+                          Qt::MatchFlags flags) const;
 
 private:
     class Private;
diff --git a/KTp/Models/accounts-model-item.cpp b/KTp/Models/accounts-model-item.cpp
index 1d65af3..b85e9e3 100644
--- a/KTp/Models/accounts-model-item.cpp
+++ b/KTp/Models/accounts-model-item.cpp
@@ -34,8 +34,7 @@
 struct AccountsModelItem::Private
 {
     Private(const Tp::AccountPtr &account)
-        : mAccount(account),
-          mOnlineCount(0)
+        : mAccount(account)
     {
     }
 
@@ -43,7 +42,6 @@ struct AccountsModelItem::Private
     void setStatusMessage(const QString &value);
 
     Tp::AccountPtr mAccount;
-    int mOnlineCount;
 };
 
 void AccountsModelItem::Private::setStatus(const QString &value)
@@ -195,10 +193,6 @@ QVariant AccountsModelItem::data(int role) const
         return mPriv->mAccount->connectionStatus();
     case AccountsModel::ConnectionStatusReasonRole:
         return mPriv->mAccount->connectionStatusReason();
-    case AccountsModel::TotalUsersCountRole:
-        return size();
-    case AccountsModel::OnlineUsersCountRole:
-        return mPriv->mOnlineCount;
     default:
         return QVariant();
     }
@@ -300,7 +294,7 @@ void AccountsModelItem::onContactsChanged(const Tp::Contacts \
&addedContacts,  Q_EMIT childrenAdded(this, newNodes);
     }
 
-    countOnlineContacts();
+    onChanged();
 }
 
 void AccountsModelItem::onStatusChanged(Tp::ConnectionStatus status)
@@ -408,22 +402,7 @@ void AccountsModelItem::addKnownContacts()
         Q_EMIT childrenAdded(this, newNodes);
     }
 
-    countOnlineContacts();
-}
-
-void AccountsModelItem::countOnlineContacts()
-{
-    int tmpCounter = 0;
-    for (int i = 0; i < size(); ++i) {
-        ContactModelItem* contactNode = qobject_cast<ContactModelItem*>(childAt(i));
-        Q_ASSERT(contactNode);
-        if (contactNode->data(AccountsModel::PresenceTypeRole).toUInt() != \
                Tp::ConnectionPresenceTypeOffline
-            && contactNode->data(AccountsModel::PresenceTypeRole).toUInt() != \
                Tp::ConnectionPresenceTypeUnknown) {
-            tmpCounter++;
-        }
-    }
-
-    mPriv->mOnlineCount = tmpCounter;
+    onChanged();
 }
 
 #include "accounts-model-item.moc"
diff --git a/KTp/Models/accounts-model-item.h b/KTp/Models/accounts-model-item.h
index 11554a9..5401202 100644
--- a/KTp/Models/accounts-model-item.h
+++ b/KTp/Models/accounts-model-item.h
@@ -55,8 +55,6 @@ public:
 
     void clearContacts();
 
-    void countOnlineContacts();
-
 Q_SIGNALS:
     void connectionStatusChanged(const QString &accountId, int status);
 
diff --git a/KTp/Models/accounts-model.cpp b/KTp/Models/accounts-model.cpp
index 795a1f4..8233a37 100644
--- a/KTp/Models/accounts-model.cpp
+++ b/KTp/Models/accounts-model.cpp
@@ -152,10 +152,7 @@ void AccountsModel::onItemChanged(TreeNode *node)
 {
     if (node->parent()) {
         //if it is a group item
-        if (node->parent() == mPriv->mTree) {
-            qobject_cast<AccountsModelItem*>(node)->countOnlineContacts();
-        } else {
-            qobject_cast<AccountsModelItem*>(node->parent())->countOnlineContacts();
+        if (node->parent() != mPriv->mTree) {
             Q_EMIT dataChanged(index(node->parent()), index(node->parent()));
         }
     }
@@ -173,6 +170,7 @@ void AccountsModel::onItemsAdded(TreeNode *parent, const \
QList<TreeNode *> &node  }
     endInsertRows();
     Q_EMIT accountCountChanged();
+    Q_EMIT dataChanged(index(parent), index(parent));
 }
 
 void AccountsModel::onItemsRemoved(TreeNode *parent, int first, int last)
diff --git a/KTp/Models/groups-model-item.cpp b/KTp/Models/groups-model-item.cpp
index 00dbede..c85ffbf 100644
--- a/KTp/Models/groups-model-item.cpp
+++ b/KTp/Models/groups-model-item.cpp
@@ -35,8 +35,7 @@
 struct GroupsModelItem::Private
 {
     Private(const QString &groupName)
-        : mGroupName(groupName),
-          mOnlineUsersCount(0)
+        : mGroupName(groupName)
     {
     }
 
@@ -44,7 +43,6 @@ struct GroupsModelItem::Private
     QString groupName();
 
     QString mGroupName;
-    int mOnlineUsersCount;
 };
 
 void GroupsModelItem::Private::setGroupName(const QString& value)
@@ -82,10 +80,6 @@ QVariant GroupsModelItem::data(int role) const
         /* drop through*/
     case GroupsModel::GroupNameRole:
         return mPriv->mGroupName;
-    case AccountsModel::TotalUsersCountRole:
-        return size();
-    case AccountsModel::OnlineUsersCountRole:
-        return mPriv->mOnlineUsersCount;
     default:
         return QVariant();
     }
@@ -127,18 +121,3 @@ void GroupsModelItem::removeProxyContact(ProxyTreeNode \
*proxyNode)  //the group counters needs to be updated
     Q_EMIT changed(this);
 }
-
-void GroupsModelItem::countOnlineContacts()
-{
-    int tmpCounter = 0;
-    for (int i = 0; i < size(); ++i) {
-        ProxyTreeNode* proxyNode = qobject_cast<ProxyTreeNode*>(childAt(i));
-        Q_ASSERT(proxyNode);
-        if (proxyNode->data(AccountsModel::PresenceTypeRole).toUInt() != \
                Tp::ConnectionPresenceTypeOffline
-            && proxyNode->data(AccountsModel::PresenceTypeRole).toUInt() != \
                Tp::ConnectionPresenceTypeUnknown) {
-            tmpCounter++;
-        }
-    }
-
-    mPriv->mOnlineUsersCount = tmpCounter;
-}
diff --git a/KTp/Models/groups-model-item.h b/KTp/Models/groups-model-item.h
index 26dcb00..19365d5 100644
--- a/KTp/Models/groups-model-item.h
+++ b/KTp/Models/groups-model-item.h
@@ -54,8 +54,6 @@ public:
     void addProxyContact(ProxyTreeNode* proxyNode);
     void removeProxyContact(ProxyTreeNode* proxyNode);
 
-    void countOnlineContacts();
-
 private Q_SLOTS:
 
 
diff --git a/KTp/Models/groups-model.cpp b/KTp/Models/groups-model.cpp
index 6e295ab..f0d607d 100644
--- a/KTp/Models/groups-model.cpp
+++ b/KTp/Models/groups-model.cpp
@@ -170,14 +170,7 @@ void GroupsModel::onItemChanged(TreeNode* node)
 {
     if (node->parent()) {
         //if it is a group item
-        if (node->parent() == mPriv->mTree) {
-            GroupsModelItem *groupItem = qobject_cast<GroupsModelItem*>(node);
-            Q_ASSERT(groupItem);
-            groupItem->countOnlineContacts();
-        } else {
-            GroupsModelItem *groupItem = \
                qobject_cast<GroupsModelItem*>(node->parent());
-            Q_ASSERT(groupItem);
-            groupItem->countOnlineContacts();
+        if (node->parent() != mPriv->mTree) {
             Q_EMIT dataChanged(index(node->parent()), index(node->parent()));
         }
     }


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic