1 /*
2 * This file is part of Licq, an instant messaging client for UNIX.
3 * Copyright (C) 2007-2011 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 "contactgroup.h"
21
22 #include <licq/contactlist/group.h>
23 #include <licq/contactlist/usermanager.h>
24
25 #include "contactbar.h"
26 #include "contactlist.h"
27 #include "contactuser.h"
28
29 using namespace LicqQtGui;
30
ContactGroup(int id,const QString & name,unsigned showMask,unsigned hideMask)31 ContactGroup::ContactGroup(int id, const QString& name, unsigned showMask, unsigned hideMask)
32 : ContactItem(ContactListModel::GroupItem),
33 myGroupId(id),
34 myName(name),
35 myEvents(0),
36 myVisibleContacts(0),
37 myShowMask(showMask),
38 myHideMask(hideMask)
39 {
40 // Put "Other Users" last when sorting
41 if (myGroupId == ContactListModel::OtherUsersGroupId)
42 mySortKey = 65535;
43 else
44 mySortKey = myGroupId;
45
46 update();
47
48 for (int i = 0; i < 3; ++i)
49 myBars[i] = new ContactBar(static_cast<ContactListModel::SubGroupType>(i), this);
50 }
51
ContactGroup(const Licq::Group * group)52 ContactGroup::ContactGroup(const Licq::Group* group)
53 : ContactItem(ContactListModel::GroupItem),
54 myGroupId(group->id()),
55 myName(QString::fromLocal8Bit(group->name().c_str())),
56 mySortKey(group->sortIndex()),
57 myEvents(0),
58 myVisibleContacts(0),
59 myShowMask(0),
60 myHideMask(ContactListModel::IgnoreStatus)
61 {
62 for (int i = 0; i < 3; ++i)
63 myBars[i] = new ContactBar(static_cast<ContactListModel::SubGroupType>(i), this);
64 }
65
~ContactGroup()66 ContactGroup::~ContactGroup()
67 {
68 // Remove all user instances in this group
69 while (!myUsers.isEmpty())
70 delete myUsers.takeFirst();
71
72 for (int i = 0; i < 3; ++i)
73 delete myBars[i];
74 }
75
update()76 void ContactGroup::update()
77 {
78 // System groups and "Other users" aren't present in daemon group list
79 if (myGroupId == ContactListModel::OtherUsersGroupId ||
80 myGroupId >= ContactListModel::SystemGroupOffset)
81 return;
82
83 {
84 Licq::GroupReadGuard g(myGroupId);
85 if (!g.isLocked())
86 return;
87
88 myName = QString::fromLocal8Bit(g->name().c_str());
89 mySortKey = g->sortIndex();
90 }
91
92 emit dataChanged(this);
93 }
94
updateSortKey()95 void ContactGroup::updateSortKey()
96 {
97 // System groups and "Other users" aren't present in daemon group list
98 if (myGroupId == ContactListModel::OtherUsersGroupId ||
99 myGroupId >= ContactListModel::SystemGroupOffset)
100 return;
101
102 Licq::GroupReadGuard g(myGroupId);
103 if (!g.isLocked())
104 return;
105
106 mySortKey = g->sortIndex();
107 }
108
item(int row) const109 ContactItem* ContactGroup::item(int row) const
110 {
111 if (row < 3)
112 return myBars[row];
113 else
114 return myUsers.value(row - 3);
115 }
116
user(ContactUserData * u) const117 ContactUser* ContactGroup::user(ContactUserData* u) const
118 {
119 foreach (ContactUser* instance, myUsers)
120 {
121 if (instance->userData() == u)
122 return instance;
123 }
124
125 return 0;
126 }
127
rowCount() const128 int ContactGroup::rowCount() const
129 {
130 // Add the separator bars
131 return myUsers.size() + 3;
132 }
133
indexOf(ContactUser * user) const134 int ContactGroup::indexOf(ContactUser* user) const
135 {
136 // The separator bars come first so add three to the index
137 return myUsers.indexOf(user) + 3;
138 }
139
addUser(ContactUser * user,ContactListModel::SubGroupType subGroup)140 void ContactGroup::addUser(ContactUser* user, ContactListModel::SubGroupType subGroup)
141 {
142 // Insert user in model
143 emit beginInsert(this, rowCount());
144 myUsers.append(user);
145 emit endInsert();
146
147 // Update group data
148 myEvents += user->numEvents();
149 if (user->visibility())
150 myVisibleContacts++;
151 emit dataChanged(this);
152
153 // Update bar data
154 myBars[subGroup]->countIncrease();
155 myBars[subGroup]->updateNumEvents(user->numEvents());
156 if (user->visibility())
157 myBars[subGroup]->updateVisibility(true);
158 emit barDataChanged(myBars[subGroup], subGroup);
159 }
160
removeUser(ContactUser * user,ContactListModel::SubGroupType subGroup)161 void ContactGroup::removeUser(ContactUser* user, ContactListModel::SubGroupType subGroup)
162 {
163 // Update bar data
164 myBars[subGroup]->countDecrease();
165 myBars[subGroup]->updateNumEvents(-user->numEvents());
166 if (user->visibility())
167 myBars[subGroup]->updateVisibility(false);
168 emit barDataChanged(myBars[subGroup], subGroup);
169
170 // Remove user from model
171 emit beginRemove(this, indexOf(user));
172 myUsers.removeAll(user);
173 emit endRemove();
174
175 // Update group data
176 myEvents -= user->numEvents();
177 if (user->visibility())
178 myVisibleContacts--;
179 emit dataChanged(this);
180 }
181
acceptUser(unsigned extendedStatus)182 bool ContactGroup::acceptUser(unsigned extendedStatus)
183 {
184 // User must not match any bits in the hide mask
185 if (myHideMask != 0 && (extendedStatus & myHideMask))
186 return false;
187
188 // User must match at least one bit in the show mask
189 if (myShowMask != 0 && !(extendedStatus & myShowMask))
190 return false;
191
192 // Default, accept user
193 return true;
194 }
195
updateSubGroup(ContactListModel::SubGroupType oldSubGroup,ContactListModel::SubGroupType newSubGroup,int eventCounter)196 void ContactGroup::updateSubGroup(ContactListModel::SubGroupType oldSubGroup, ContactListModel::SubGroupType newSubGroup, int eventCounter)
197 {
198 myBars[oldSubGroup]->countDecrease();
199 myBars[oldSubGroup]->updateNumEvents(-eventCounter);
200 emit barDataChanged(myBars[oldSubGroup], oldSubGroup);
201
202 myBars[newSubGroup]->countIncrease();
203 myBars[newSubGroup]->updateNumEvents(eventCounter);
204 emit barDataChanged(myBars[newSubGroup], newSubGroup);
205 }
206
updateNumEvents(int counter,ContactListModel::SubGroupType subGroup)207 void ContactGroup::updateNumEvents(int counter, ContactListModel::SubGroupType subGroup)
208 {
209 if (counter == 0)
210 return;
211
212 // Update bar data
213 myBars[subGroup]->updateNumEvents(counter);
214 emit barDataChanged(myBars[subGroup], subGroup);
215
216 // Update group data
217 myEvents += counter;
218 emit dataChanged(this);
219 }
220
updateVisibility(bool increase,ContactListModel::SubGroupType subGroup)221 void ContactGroup::updateVisibility(bool increase, ContactListModel::SubGroupType subGroup)
222 {
223 // Update bar data
224 myBars[subGroup]->updateVisibility(increase);
225 emit barDataChanged(myBars[subGroup], subGroup);
226
227 // Update group data
228 if (increase)
229 myVisibleContacts++;
230 else
231 myVisibleContacts--;
232 emit dataChanged(this);
233 }
234
data(int column,int role) const235 QVariant ContactGroup::data(int column, int role) const
236 {
237 switch (role)
238 {
239 case Qt::DisplayRole:
240 if (column == 0)
241 {
242 int onlineCount = myBars[ContactListModel::OnlineSubGroup]->count();
243 if (onlineCount > 0)
244 return myName + " (" + QString::number(onlineCount) + ")";
245 else
246 return myName;
247 }
248 break;
249
250 case ContactListModel::NameRole:
251 return myName;
252
253 case ContactListModel::ItemTypeRole:
254 return ContactListModel::GroupItem;
255
256 case ContactListModel::SortPrefixRole:
257 return 0;
258
259 case ContactListModel::SortRole:
260 return mySortKey;
261
262 case ContactListModel::UnreadEventsRole:
263 return myEvents;
264
265 case ContactListModel::GroupIdRole:
266 return myGroupId;
267
268 case ContactListModel::UserCountRole:
269 return myUsers.size();
270
271 case ContactListModel::VisibilityRole:
272 return (myVisibleContacts > 0);
273 }
274
275 return QVariant();
276 }
277
setData(const QVariant & value,int role)278 bool ContactGroup::setData(const QVariant& value, int role)
279 {
280 if (role != ContactListModel::NameRole || !value.isValid())
281 return false;
282
283 // Don't allow system groups or "Other users" to be renamed this way
284 if (myGroupId == ContactListModel::OtherUsersGroupId ||
285 myGroupId >= ContactListModel::SystemGroupOffset)
286 return false;
287
288 QString newName = value.toString();
289 if (newName == myName)
290 return true;
291
292 // Don't save new name here, daemon will signal us when name has changed
293 Licq::gUserManager.RenameGroup(myGroupId, newName.toLocal8Bit().constData());
294
295 return true;
296 }
297