1 /*
2  * This file is part of Licq, an instant messaging client for UNIX.
3  * Copyright (C) 2007-2010 Licq developers
4  *
5  * Licq is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Licq is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Licq; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #include "maincontactlistproxy.h"
21 
22 #include "config/contactlist.h"
23 
24 #include "contactlist.h"
25 #include "mode2contactlistproxy.h"
26 
27 using namespace LicqQtGui;
28 
MainContactListProxy(ContactListModel * contactList,QObject * parent)29 MainContactListProxy::MainContactListProxy(ContactListModel* contactList, QObject* parent)
30   : SortedContactListProxy(contactList, parent),
31     myContactList(contactList),
32     myThreadedView(false),
33     myMode2View(false),
34     myProxy(NULL)
35 {
36   // Update filter when list configuration changes
37   connect(Config::ContactList::instance(), SIGNAL(currentListChanged()), SLOT(configUpdated()));
38 }
39 
setThreadedView(bool enable,bool mode2)40 void MainContactListProxy::setThreadedView(bool enable, bool mode2)
41 {
42   myThreadedView = enable;
43   myMode2View = (enable && mode2);
44 
45   if (!myMode2View && myProxy != NULL)
46   {
47     // setSourceModel triggers reset() which will cause view to call us again
48     // make sure we set myProxy to NULl first so we won't trigger this block again
49     QAbstractProxyModel* oldProxy = myProxy;
50     myProxy = NULL;
51     setSourceModel(myContactList);
52     delete oldProxy;
53   }
54   else if (myMode2View && myProxy == NULL)
55   {
56     myProxy = new Mode2ContactListProxy(myContactList, this);
57     setSourceModel(myProxy);
58   }
59   else
60   {
61     // No proxy added/removed, just force filter to update
62     invalidateFilter();
63   }
64 }
65 
configUpdated()66 void MainContactListProxy::configUpdated()
67 {
68   invalidateFilter();
69 }
70 
filterAcceptsRow(int source_row,const QModelIndex & source_parent) const71 bool MainContactListProxy::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
72 {
73   QModelIndex item = sourceModel()->index(source_row, 0, source_parent);
74 
75   switch (static_cast<ContactListModel::ItemType>(item.data(ContactListModel::ItemTypeRole).toInt()))
76   {
77     case ContactListModel::GroupItem:
78     {
79       // Filter system groups
80       if (myThreadedView && item.data(ContactListModel::GroupIdRole).toInt() >= ContactListModel::SystemGroupOffset)
81         return false;
82 
83       // Filter empty groups in threaded view
84       // Filter "Other users" (id 0) when empty regardless of configuration
85       if (myThreadedView &&
86           (!Config::ContactList::instance()->showEmptyGroups() ||
87           item.data(ContactListModel::GroupIdRole).toInt() == ContactListModel::OtherUsersGroupId))
88       {
89         // Check for empty groups
90         if (item.data(ContactListModel::UserCountRole).toInt() == 0)
91           return false;
92 
93         // If not showing offline contacts a group with > 0 contacts may also be empty
94         if (!Config::ContactList::instance()->showOffline() &&
95             !item.data(ContactListModel::VisibilityRole).toBool())
96          return false;
97       }
98 
99       break;
100     }
101     case ContactListModel::UserItem:
102     {
103       // Filter offline users unless "Show Offline Users" are enabled
104       if (!Config::ContactList::instance()->showOffline() &&
105           !item.data(ContactListModel::VisibilityRole).toBool())
106         return false;
107 
108       break;
109     }
110     case ContactListModel::BarItem:
111     {
112       // In mode 2 view, if groups are always visible, bars are always needed
113       if (myMode2View && Config::ContactList::instance()->showEmptyGroups())
114         return true;
115 
116       // Filter all sub group headers
117       if (myThreadedView && !myMode2View)
118         return false;
119 
120       ContactListModel::SubGroupType subGroup = static_cast<ContactListModel::SubGroupType>(item.data(ContactListModel::SubGroupRole).toInt());
121 
122       // Filter header bars if config says so, but keep the Not In List Bar (if needed)
123       if (!Config::ContactList::instance()->showDividers() &&
124           subGroup != ContactListModel::NotInListSubGroup)
125         return false;
126 
127       // Filter header for sub groups with no users in them
128       if (item.data(ContactListModel::UserCountRole).toInt() <= 0)
129         return false;
130 
131       // Filter the offline header if offline users are filtered, but keep header if any user has unread events
132       if (!Config::ContactList::instance()->showOffline() &&
133           subGroup == ContactListModel::OfflineSubGroup &&
134           !item.data(ContactListModel::VisibilityRole).toBool())
135         return false;
136 
137       break;
138     }
139     default:
140       // Unknown item type so we probably don't want to show it
141       return false;
142   }
143   return true;
144 }
145