1 /***************************************************************************
2 * *
3 * This program is free software; you can redistribute it and/or modify *
4 * it under the terms of the GNU General Public License as published by *
5 * the Free Software Foundation; either version 3 of the License, or *
6 * (at your option) any later version. *
7 * *
8 ***************************************************************************/
9
10 #include "FavoriteUsers.h"
11 #include "WulforUtil.h"
12 #include "FavoriteUsersModel.h"
13
14 #include <QMenu>
15 #include <QInputDialog>
16 #include <QKeyEvent>
17 #include <QHeaderView>
18 #include <QItemSelectionModel>
19
20 #include "dcpp/ClientManager.h"
21 #include "dcpp/QueueManager.h"
22 #include "dcpp/User.h"
23 #include "dcpp/CID.h"
24 #include "dcpp/Util.h"
25
26
27 using namespace dcpp;
28
FavoriteUsers(QWidget * parent)29 FavoriteUsers::FavoriteUsers(QWidget *parent) :
30 QWidget(parent)
31 {
32 setupUi(this);
33
34 setUnload(false);
35
36 model = new FavoriteUsersModel(this);
37
38 treeView->setContextMenuPolicy(Qt::CustomContextMenu);
39 treeView->installEventFilter(this);
40 treeView->setModel(model);
41 treeView->header()->setContextMenuPolicy(Qt::CustomContextMenu);
42 treeView->header()->restoreState(WVGET(WS_FAVUSERS_STATE, QByteArray()).toByteArray());
43 treeView->setSortingEnabled(true);
44
45 connect(treeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotContextMenu()));
46 connect(treeView->header(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotHeaderMenu()));
47 connect(checkBox_AUTOGRANT, SIGNAL(toggled(bool)), this, SLOT(slotAutoGrant(bool)));
48
49 connect(this, SIGNAL(coreUserAdded(VarMap)), this, SLOT(addUser(VarMap)), Qt::QueuedConnection);
50 connect(this, SIGNAL(coreUserRemoved(QString)), this, SLOT(remUser(QString)), Qt::QueuedConnection);
51 connect(this, SIGNAL(coreStatusChanged(QString,QString)), this, SLOT(updateUser(QString,QString)), Qt::QueuedConnection);
52
53 WulforSettings *WS = WulforSettings::getInstance();
54 connect(WS, SIGNAL(strValueChanged(QString,QString)), this, SLOT(slotSettingsChanged(QString,QString)));
55
56 FavoriteManager::FavoriteMap ul = FavoriteManager::getInstance()->getFavoriteUsers();
57 VarMap params;
58
59 for (auto &i : ul) {
60 dcpp::FavoriteUser &u = i.second;
61
62 if (WBGET(WB_FAVUSERS_AUTOGRANT)){
63 u.setFlag(FavoriteUser::FLAG_GRANTSLOT);
64 FavoriteManager::getInstance()->setAutoGrant(u.getUser(), true);
65 }
66
67 getParams(params, u);
68 addUser(params);
69 }
70
71 checkBox_AUTOGRANT->setChecked(WBGET(WB_FAVUSERS_AUTOGRANT));
72
73 FavoriteManager::getInstance()->addListener(this);
74
75 ArenaWidget::setState( ArenaWidget::Flags(ArenaWidget::state() | ArenaWidget::Singleton | ArenaWidget::Hidden) );
76 }
77
~FavoriteUsers()78 FavoriteUsers::~FavoriteUsers(){
79 WVSET(WS_FAVUSERS_STATE, treeView->header()->saveState());
80
81 FavoriteManager::getInstance()->removeListener(this);
82
83 delete model;
84 }
85
closeEvent(QCloseEvent * e)86 void FavoriteUsers::closeEvent(QCloseEvent *e){
87 isUnload()? e->accept() : e->ignore();
88 }
89
eventFilter(QObject * obj,QEvent * e)90 bool FavoriteUsers::eventFilter(QObject *obj, QEvent *e){
91 if (e->type() == QEvent::KeyRelease){
92 QKeyEvent *k_e = reinterpret_cast<QKeyEvent*>(e);
93
94 if (k_e->key() == Qt::Key_Delete){
95 if (treeView == reinterpret_cast<QTreeView*>(obj)){
96 QModelIndexList indexes = treeView->selectionModel()->selectedRows(0);
97 QList<FavoriteUserItem*> items;
98
99 for (const auto &i : indexes)
100 items.push_back(reinterpret_cast<FavoriteUserItem*>(i.internalPointer()));
101
102 for (const auto &i : items)
103 handleRemove(i->cid);
104
105 return true;
106 }
107 }
108 }
109
110 return QWidget::eventFilter(obj, e);
111 }
112
getParams(VarMap & params,const FavoriteUser & user)113 void FavoriteUsers::getParams(VarMap ¶ms, const FavoriteUser &user){
114 const UserPtr &u = user.getUser();
115
116 params["CID"] = _q(u->getCID().toBase32());
117 params["NICK"] = _q(user.getNick());
118 params["HUB"] = u->isOnline()? (WulforUtil::getInstance()->getHubNames(u)) : _q(user.getUrl());
119 params["SEEN"] = u->isOnline()? tr("Online") : _q(Util::formatTime("%Y-%m-%d %H:%M", user.getLastSeen()));
120 params["DESC"] = _q(user.getDescription());
121 params["SLOT"] = user.isSet(FavoriteUser::FLAG_GRANTSLOT);
122 }
123
addUserToFav(const QString & id)124 bool FavoriteUsers::addUserToFav(const QString &id){
125 if (id.isEmpty())
126 return false;
127
128 string cid = id.toStdString();
129
130 UserPtr user = ClientManager::getInstance()->findUser(CID(cid));
131
132 if (user){
133 if (user != ClientManager::getInstance()->getMe() && !FavoriteManager::getInstance()->isFavoriteUser(user))
134 FavoriteManager::getInstance()->addFavoriteUser(user);
135 }
136
137 return true;
138 }
139
remUserFromFav(const QString & id)140 bool FavoriteUsers::remUserFromFav(const QString &id){
141 if (id.isEmpty())
142 return false;
143
144 string cid = id.toStdString();
145
146 UserPtr user = ClientManager::getInstance()->findUser(CID(cid));
147
148 if (user){
149 if (user != ClientManager::getInstance()->getMe() && FavoriteManager::getInstance()->isFavoriteUser(user))
150 FavoriteManager::getInstance()->removeFavoriteUser(user);
151 }
152
153 return true;
154 }
155
getUsers() const156 QStringList FavoriteUsers::getUsers() const {
157 return model->getUsers();
158 }
159
addUser(const VarMap & params)160 void FavoriteUsers::addUser(const VarMap ¶ms){
161 model->addUser(params);
162 }
163
updateUser(const QString & _cid,const QString & stat)164 void FavoriteUsers::updateUser(const QString &_cid, const QString &stat){
165 dcpp::CID cid(_tq(_cid));
166 const dcpp::UserPtr &user = ClientManager::getInstance()->findUser(cid);
167
168 QString userUrl = user ? _q(FavoriteManager::getInstance()->getUserURL(user)) : QString();
169 model->updateUserStatus(_cid, stat,
170 (user && user->isOnline()) ? (WulforUtil::getInstance()->getHubNames(user)) : userUrl);
171 }
172
remUser(const QString & cid)173 void FavoriteUsers::remUser(const QString &cid){
174 model->removeUser(cid);
175 }
176
handleRemove(const QString & _cid)177 void FavoriteUsers::handleRemove(const QString & _cid){
178 dcpp::CID cid(_tq(_cid));
179 const dcpp::UserPtr &user = ClientManager::getInstance()->findUser(cid);
180
181 if (user)
182 FavoriteManager::getInstance()->removeFavoriteUser(user);
183 }
184
handleDesc(const QString & _cid)185 void FavoriteUsers::handleDesc(const QString & _cid){
186 FavoriteUserItem *item = model->itemForCID(_cid);
187 static QString old = "";
188
189 if (!item)
190 return;
191
192 dcpp::CID cid(_tq(_cid));
193 const dcpp::UserPtr &user = ClientManager::getInstance()->findUser(cid);
194
195 if (user){
196 QString desc = QInputDialog::getText(this, item->data(COLUMN_USER_NICK).toString(), tr("Description"), QLineEdit::Normal, old);
197
198 if (!desc.isEmpty()){
199 old = desc;
200 item->updateColumn(COLUMN_USER_DESC, desc);
201 FavoriteManager::getInstance()->setUserDescription(user, _tq(desc));
202 }
203 }
204 }
205
getFileList(const VarMap & params)206 void FavoriteUsers::getFileList(const VarMap ¶ms){
207 string cid = params["CID"].toString().toStdString();
208 string hub = params["HUB"].toString().toStdString();
209
210 if (cid.empty())
211 return;
212
213 UserPtr user = ClientManager::getInstance()->findUser(CID(cid));
214 if (user){
215 try {
216 QueueManager::getInstance()->addList(HintedUser(user, hub), QueueItem::FLAG_CLIENT_VIEW, "");
217 } catch(const Exception&) {
218 // ...
219 }
220 }
221 }
222
handleBrowseShare(const QString & cid)223 void FavoriteUsers::handleBrowseShare(const QString &cid){
224 FavoriteManager::FavoriteMap ul = FavoriteManager::getInstance()->getFavoriteUsers();
225
226 auto i = ul.find(CID(_tq(cid)));
227 if (i != ul.end()){
228 dcpp::FavoriteUser &user = i->second;
229
230 VarMap params;
231 getParams(params, user);
232 getFileList(params);
233 }
234 }
235
handleGrant(const QString & cid)236 void FavoriteUsers::handleGrant(const QString &cid){
237 FavoriteManager::FavoriteMap ul = FavoriteManager::getInstance()->getFavoriteUsers();
238
239 auto i = ul.find(CID(_tq(cid)));
240 if (i != ul.end()){
241 dcpp::FavoriteUser &u = i->second;
242
243 if (_q(u.getUser()->getCID().toBase32()) == cid){
244 if (u.isSet(FavoriteUser::FLAG_GRANTSLOT)){
245 u.unsetFlag(FavoriteUser::FLAG_GRANTSLOT);
246 FavoriteManager::getInstance()->setAutoGrant(u.getUser(), false);
247 }
248 else {
249 u.setFlag(FavoriteUser::FLAG_GRANTSLOT);
250 FavoriteManager::getInstance()->setAutoGrant(u.getUser(), true);
251 }
252 }
253 }
254 }
255
slotContextMenu()256 void FavoriteUsers::slotContextMenu(){
257 QModelIndexList indexes = treeView->selectionModel()->selectedRows(0);
258 QList<FavoriteUserItem*> items;
259
260 for (const auto &i : indexes)
261 items.push_back(reinterpret_cast<FavoriteUserItem*>(i.internalPointer()));
262
263 if (items.size() < 1)
264 return;
265
266 QMenu *menu = new QMenu(this);
267 menu->deleteLater();
268
269 QAction *remove = new QAction(tr("Remove"), menu);
270 remove->setIcon(WICON(WulforUtil::eiEDITDELETE));
271
272 QAction *desc = new QAction(tr("Description"), menu);
273 desc->setIcon(WICON(WulforUtil::eiEDIT));
274
275 QAction *grant = new QAction(tr("Grant/Remove slot"), menu);
276 grant->setIcon(WICON(WulforUtil::eiBALL_GREEN));
277
278 QAction *browse = new QAction(tr("Browse Files"), menu);
279 browse->setIcon(WICON(WulforUtil::eiFOLDER_BLUE));
280
281 menu->addActions(QList<QAction*>() << browse << desc << grant << remove);
282
283 QAction *ret = menu->exec(QCursor::pos());
284
285 if (!ret)
286 return;
287
288 if (ret == remove){
289 for (const auto &i : items)
290 handleRemove(i->cid);
291 }
292 else if (ret == grant){
293 for (const auto &i : items)
294 handleGrant(i->cid);
295 }
296 else if(ret == browse){
297 for (const auto &i : items)
298 handleBrowseShare(i->cid);
299 }
300 else {
301 for (const auto &i : items)
302 handleDesc(i->cid);
303 }
304 }
305
slotHeaderMenu()306 void FavoriteUsers::slotHeaderMenu(){
307 WulforUtil::headerMenu(treeView);
308 }
309
slotSettingsChanged(const QString & key,const QString &)310 void FavoriteUsers::slotSettingsChanged(const QString &key, const QString &){
311 if (key == WS_TRANSLATION_FILE)
312 retranslateUi(this);
313 }
314
on(UserAdded,const FavoriteUser & aUser)315 void FavoriteUsers::on(UserAdded, const FavoriteUser& aUser) noexcept {
316 if (WBGET(WB_FAVUSERS_AUTOGRANT))
317 FavoriteManager::getInstance()->setAutoGrant(aUser.getUser(), true);
318
319 VarMap params;
320
321 getParams(params, aUser);
322
323 emit coreUserAdded(params);
324 }
325
on(UserRemoved,const FavoriteUser & aUser)326 void FavoriteUsers::on(UserRemoved, const FavoriteUser& aUser) noexcept {
327 emit coreUserRemoved(_q(aUser.getUser()->getCID().toBase32()));
328 }
329
on(StatusChanged,const FavoriteUser & u)330 void FavoriteUsers::on(StatusChanged, const FavoriteUser& u) noexcept{
331 emit coreStatusChanged(_q(u.getUser()->getCID().toBase32()), u.getUser()->isOnline()?
332 tr("Online")
333 :
334 _q(Util::formatTime("%Y-%m-%d %H:%M", FavoriteManager::getInstance()->getLastSeen(u.getUser()))));
335
336 }
337