1 /*
2  * Copyright © 2004-2010 Jens Oknelid, paskharen@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * In addition, as a special exception, compiling, linking, and/or
19  * using OpenSSL with this program is allowed.
20  */
21 
22 #include <sstream>
23 #include <iostream>
24 #include <iomanip>
25 #include <iterator>
26 #include "transfers.hh"
27 #include "WulforUtil.hh"
28 #include "wulformanager.hh"
29 #include "settingsmanager.hh"
30 #include "func.hh"
31 #include "previewmenu.hh"
32 #include "UserCommandMenu.hh"
33 #include <dcpp/Download.h>
34 #include <dcpp/Upload.h>
35 #include <dcpp/ClientManager.h>
36 #include <dcpp/TimerManager.h>
37 #include <dcpp/FavoriteManager.h>
38 
39 using namespace std;
40 using namespace dcpp;
41 
Transfers()42 Transfers::Transfers() :
43     Entry(Entry::TRANSFERS, "transfers.ui")
44 {
45     // menu
46     g_object_ref_sink(getWidget("transferMenu"));
47 
48     // Initialize the user command menu
49     userCommandMenu = new UserCommandMenu(getWidget("userCommandMenu"), ::UserCommand::CONTEXT_USER);
50     addChild(userCommandMenu);
51 
52     // Initialize the preview menu
53     appsPreviewMenu = new PreviewMenu(getWidget("appsPreviewMenu"));
54 
55     // Initialize transfer treeview
56     transferView.setView(GTK_TREE_VIEW(getWidget("transfers")), TRUE, "transfers");
57     transferView.insertColumn(_("User"), G_TYPE_STRING, TreeView::ICON_STRING, 150, "Icon");
58     transferView.insertColumn(_("Hub Name"), G_TYPE_STRING, TreeView::STRING, 100);
59     transferView.insertColumn(_("Progress"), G_TYPE_STRING, TreeView::PROGRESS, 85, "Progress Hidden");
60     transferView.insertColumn(_("Status"), G_TYPE_STRING, TreeView::STRING, 250);
61     transferView.insertColumn(_("Time"), G_TYPE_STRING, TreeView::STRING, 85);
62     transferView.insertColumn(_("Time Left"), G_TYPE_INT64, TreeView::TIME_LEFT, 85);
63     transferView.insertColumn(_("Speed"), G_TYPE_INT64, TreeView::SPEED, 125);
64     transferView.insertColumn(_("Flags"), G_TYPE_STRING, TreeView::STRING, 85);
65     transferView.insertColumn(_("Transferred"), G_TYPE_STRING, TreeView::STRING, 85);
66     transferView.insertColumn(_("Filename"), G_TYPE_STRING, TreeView::STRING, 200);
67     transferView.insertColumn(_("Size"), G_TYPE_INT64, TreeView::SIZE, 125);
68     transferView.insertColumn(_("Path"), G_TYPE_STRING, TreeView::STRING, 200);
69     transferView.insertColumn(_("IP"), G_TYPE_STRING, TreeView::STRING, 175);
70     transferView.insertColumn(_("Encryption"), G_TYPE_STRING, TreeView::STRING, 175);
71     transferView.insertHiddenColumn("Icon", G_TYPE_STRING);
72     transferView.insertHiddenColumn("Progress Hidden", G_TYPE_INT);
73     transferView.insertHiddenColumn("Sort Order", G_TYPE_STRING);
74     transferView.insertHiddenColumn("CID", G_TYPE_STRING);
75     transferView.insertHiddenColumn("Download Position", G_TYPE_INT64); // For keeping track of and calculating parent pos
76     transferView.insertHiddenColumn("Failed", G_TYPE_BOOLEAN);
77     transferView.insertHiddenColumn("Target", G_TYPE_STRING);
78     transferView.insertHiddenColumn("tmpTarget", G_TYPE_STRING);
79     transferView.insertHiddenColumn("Download", G_TYPE_BOOLEAN);
80     transferView.insertHiddenColumn("Hub URL", G_TYPE_STRING);
81     transferView.finalize();
82 
83     transferStore = gtk_tree_store_newv(transferView.getColCount(), transferView.getGTypes());
84     gtk_tree_view_set_model(transferView.get(), GTK_TREE_MODEL(transferStore));
85     g_object_unref(transferStore);
86     transferSelection = gtk_tree_view_get_selection(transferView.get());
87     gtk_tree_selection_set_mode(transferSelection, GTK_SELECTION_MULTIPLE);
88     transferView.setSortColumn_gui(_("User"), "Sort Order");
89     gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(transferStore), transferView.col("Sort Order"), GTK_SORT_ASCENDING);
90     gtk_tree_view_column_set_sort_indicator(gtk_tree_view_get_column(transferView.get(), transferView.col(_("User"))), TRUE);
91     gtk_tree_view_set_fixed_height_mode(transferView.get(), TRUE);
92 
93     g_signal_connect(transferView.get(), "button-press-event", G_CALLBACK(onTransferButtonPressed_gui), (gpointer)this);
94     g_signal_connect(transferView.get(), "button-release-event", G_CALLBACK(onTransferButtonReleased_gui), (gpointer)this);
95     g_signal_connect(getWidget("getFileListItem"), "activate", G_CALLBACK(onGetFileListClicked_gui), (gpointer)this);
96     g_signal_connect(getWidget("matchQueueItem"), "activate", G_CALLBACK(onMatchQueueClicked_gui), (gpointer)this);
97     g_signal_connect(getWidget("sendPrivateMessageItem"), "activate", G_CALLBACK(onPrivateMessageClicked_gui), (gpointer)this);
98     g_signal_connect(getWidget("addToFavoritesItem"), "activate", G_CALLBACK(onAddFavoriteUserClicked_gui), (gpointer)this);
99     g_signal_connect(getWidget("grantExtraSlotItem"), "activate", G_CALLBACK(onGrantExtraSlotClicked_gui), (gpointer)this);
100     g_signal_connect(getWidget("removeUserItem"), "activate", G_CALLBACK(onRemoveUserFromQueueClicked_gui), (gpointer)this);
101     g_signal_connect(getWidget("forceAttemptItem"), "activate", G_CALLBACK(onForceAttemptClicked_gui), (gpointer)this);
102     g_signal_connect(getWidget("closeConnectionItem"), "activate", G_CALLBACK(onCloseConnectionClicked_gui), (gpointer)this);
103 }
104 
~Transfers()105 Transfers::~Transfers()
106 {
107     QueueManager::getInstance()->removeListener(this);
108     DownloadManager::getInstance()->removeListener(this);
109     UploadManager::getInstance()->removeListener(this);
110     ConnectionManager::getInstance()->removeListener(this);
111 
112     g_object_unref(getWidget("transferMenu"));
113     delete appsPreviewMenu;
114 }
115 
show()116 void Transfers::show()
117 {
118     QueueManager::getInstance()->addListener(this);
119     DownloadManager::getInstance()->addListener(this);
120     UploadManager::getInstance()->addListener(this);
121     ConnectionManager::getInstance()->addListener(this);
122 }
123 
popupTransferMenu_gui()124 void Transfers::popupTransferMenu_gui()
125 {
126     // Build user command menu
127     appsPreviewMenu->cleanMenu_gui();
128     userCommandMenu->cleanMenu_gui();
129 
130     GtkTreePath *path;
131     GtkTreeIter iter;
132     GList *list = gtk_tree_selection_get_selected_rows(transferSelection, NULL);
133     string target = "";
134 
135     for (GList *i = list; i; i = i->next)
136     {
137         path = (GtkTreePath *)i->data;
138         if (gtk_tree_model_get_iter(GTK_TREE_MODEL(transferStore), &iter, path))
139         {
140             bool parent = gtk_tree_model_iter_has_child(GTK_TREE_MODEL(transferStore), &iter);
141 
142             do
143             {
144                 if (target.empty())
145                     target = transferView.getString(&iter, "tmpTarget");
146 
147                 string cid = transferView.getString(&iter, "CID");
148                 string hubUrl = transferView.getString(&iter, "Hub URL");
149                 userCommandMenu->addUser(cid);
150                 userCommandMenu->addHub(WulforUtil::getHubAddress(CID(cid), hubUrl));
151             }
152             while (parent && WulforUtil::getNextIter_gui(GTK_TREE_MODEL(transferStore), &iter, TRUE, FALSE));
153         }
154         gtk_tree_path_free(path);
155     }
156     g_list_free(list);
157 
158     userCommandMenu->buildMenu_gui();
159 
160     if (appsPreviewMenu->buildMenu_gui(target))
161         gtk_widget_set_sensitive(getWidget("appsPreviewItem"), TRUE);
162     else gtk_widget_set_sensitive(getWidget("appsPreviewItem"), FALSE);
163 
164     gtk_menu_popup(GTK_MENU(getWidget("transferMenu")), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time());
165     gtk_widget_show_all(getWidget("transferMenu"));
166 }
167 
onGetFileListClicked_gui(GtkMenuItem * item,gpointer data)168 void Transfers::onGetFileListClicked_gui(GtkMenuItem *item, gpointer data)
169 {
170     Transfers *tr = (Transfers *)data;
171     GtkTreeIter iter;
172     GtkTreePath *path;
173     GList *list = gtk_tree_selection_get_selected_rows(tr->transferSelection, NULL);
174     typedef Func2<Transfers, string, string> F2;
175 
176     for (GList *i = list; i; i = i->next)
177     {
178         path = (GtkTreePath *)i->data;
179         if (gtk_tree_model_get_iter(GTK_TREE_MODEL(tr->transferStore), &iter, path))
180         {
181             bool parent = gtk_tree_model_iter_has_child(GTK_TREE_MODEL(tr->transferStore), &iter);
182 
183             do
184             {
185                 string cid = tr->transferView.getString(&iter, "CID");
186                 string hubUrl = tr->transferView.getString(&iter, "Hub URL");
187                 if (!cid.empty())
188                 {
189                     F2 *func = new F2(tr, &Transfers::getFileList_client, cid, hubUrl);
190                     WulforManager::get()->dispatchClientFunc(func);
191                 }
192             }
193             while (parent && WulforUtil::getNextIter_gui(GTK_TREE_MODEL(tr->transferStore), &iter, TRUE, FALSE));
194         }
195         gtk_tree_path_free(path);
196     }
197     g_list_free(list);
198 }
199 
onMatchQueueClicked_gui(GtkMenuItem * item,gpointer data)200 void Transfers::onMatchQueueClicked_gui(GtkMenuItem *item, gpointer data)
201 {
202     Transfers *tr = (Transfers *)data;
203     GtkTreeIter iter;
204     GtkTreePath *path;
205     GList *list = gtk_tree_selection_get_selected_rows(tr->transferSelection, NULL);
206     typedef Func2<Transfers, string, string> F2;
207 
208     for (GList *i = list; i; i = i->next)
209     {
210         path = (GtkTreePath *)i->data;
211         if (gtk_tree_model_get_iter(GTK_TREE_MODEL(tr->transferStore), &iter, path))
212         {
213             bool parent = gtk_tree_model_iter_has_child(GTK_TREE_MODEL(tr->transferStore), &iter);
214 
215             do
216             {
217                 string cid = tr->transferView.getString(&iter, "CID");
218                 string hubUrl = tr->transferView.getString(&iter, "Hub URL");
219                 if (!cid.empty())
220                 {
221                     F2 *func = new F2(tr, &Transfers::matchQueue_client, cid, hubUrl);
222                     WulforManager::get()->dispatchClientFunc(func);
223                 }
224             }
225             while (parent && WulforUtil::getNextIter_gui(GTK_TREE_MODEL(tr->transferStore), &iter, TRUE, FALSE));
226         }
227         gtk_tree_path_free(path);
228     }
229     g_list_free(list);
230 }
231 
onPrivateMessageClicked_gui(GtkMenuItem * item,gpointer data)232 void Transfers::onPrivateMessageClicked_gui(GtkMenuItem *item, gpointer data)
233 {
234     Transfers *tr = (Transfers *)data;
235     string cid;
236     GtkTreeIter iter;
237     GtkTreePath *path;
238     GList *list = gtk_tree_selection_get_selected_rows(tr->transferSelection, NULL);
239 
240     for (GList *i = list; i; i = i->next)
241     {
242         path = (GtkTreePath *)i->data;
243         if (gtk_tree_model_get_iter(GTK_TREE_MODEL(tr->transferStore), &iter, path))
244         {
245             bool parent = gtk_tree_model_iter_has_child(GTK_TREE_MODEL(tr->transferStore), &iter);
246 
247             do
248             {
249                 cid = tr->transferView.getString(&iter, "CID");
250                 if (!cid.empty())
251                     WulforManager::get()->getMainWindow()->addPrivateMessage_gui(Msg::UNKNOWN, cid);
252             }
253             while (parent && WulforUtil::getNextIter_gui(GTK_TREE_MODEL(tr->transferStore), &iter, TRUE, FALSE));
254         }
255         gtk_tree_path_free(path);
256     }
257     g_list_free(list);
258 }
259 
onAddFavoriteUserClicked_gui(GtkMenuItem * item,gpointer data)260 void Transfers::onAddFavoriteUserClicked_gui(GtkMenuItem *item, gpointer data)
261 {
262     Transfers *tr = (Transfers *)data;
263     string cid;
264     GtkTreeIter iter;
265     GtkTreePath *path;
266     GList *list = gtk_tree_selection_get_selected_rows(tr->transferSelection, NULL);
267     typedef Func1<Transfers, string > F1;
268     F1 *func;
269 
270     for (GList *i = list; i; i = i->next)
271     {
272         path = (GtkTreePath *)i->data;
273         if (gtk_tree_model_get_iter(GTK_TREE_MODEL(tr->transferStore), &iter, path))
274         {
275             bool parent = gtk_tree_model_iter_has_child(GTK_TREE_MODEL(tr->transferStore), &iter);
276 
277             do
278             {
279                 cid = tr->transferView.getString(&iter, "CID");
280                 if (!cid.empty())
281                 {
282                     func = new F1(tr, &Transfers::addFavoriteUser_client, cid);
283                     WulforManager::get()->dispatchClientFunc(func);
284                 }
285             }
286             while (parent && WulforUtil::getNextIter_gui(GTK_TREE_MODEL(tr->transferStore), &iter, TRUE, FALSE));
287         }
288         gtk_tree_path_free(path);
289     }
290     g_list_free(list);
291 }
292 
onGrantExtraSlotClicked_gui(GtkMenuItem * item,gpointer data)293 void Transfers::onGrantExtraSlotClicked_gui(GtkMenuItem *item, gpointer data)
294 {
295     Transfers *tr = (Transfers *)data;
296     GtkTreeIter iter;
297     GtkTreePath *path;
298     GList *list = gtk_tree_selection_get_selected_rows(tr->transferSelection, NULL);
299     typedef Func2<Transfers, string, string> F2;
300 
301     for (GList *i = list; i; i = i->next)
302     {
303         path = (GtkTreePath *)i->data;
304         if (gtk_tree_model_get_iter(GTK_TREE_MODEL(tr->transferStore), &iter, path))
305         {
306             bool parent = gtk_tree_model_iter_has_child(GTK_TREE_MODEL(tr->transferStore), &iter);
307 
308             do
309             {
310                 string cid = tr->transferView.getString(&iter, "CID");
311                 string hubUrl = tr->transferView.getString(&iter, "Hub URL");
312                 if (!cid.empty())
313                 {
314                     F2 *func = new F2(tr, &Transfers::grantExtraSlot_client, cid, hubUrl);
315                     WulforManager::get()->dispatchClientFunc(func);
316                 }
317             }
318             while (parent && WulforUtil::getNextIter_gui(GTK_TREE_MODEL(tr->transferStore), &iter, TRUE, FALSE));
319         }
320         gtk_tree_path_free(path);
321     }
322     g_list_free(list);
323 }
324 
onRemoveUserFromQueueClicked_gui(GtkMenuItem * item,gpointer data)325 void Transfers::onRemoveUserFromQueueClicked_gui(GtkMenuItem *item, gpointer data)
326 {
327     Transfers *tr = (Transfers *)data;
328     string cid;
329     GtkTreeIter iter;
330     GtkTreePath *path;
331     GList *list = gtk_tree_selection_get_selected_rows(tr->transferSelection, NULL);
332     typedef Func1<Transfers, string > F1;
333     F1 *func;
334 
335     for (GList *i = list; i; i = i->next)
336     {
337         path = (GtkTreePath *)i->data;
338         if (gtk_tree_model_get_iter(GTK_TREE_MODEL(tr->transferStore), &iter, path))
339         {
340             bool parent = gtk_tree_model_iter_has_child(GTK_TREE_MODEL(tr->transferStore), &iter);
341 
342             do
343             {
344                 cid = tr->transferView.getString(&iter, "CID");
345                 if (!cid.empty())
346                 {
347                     func = new F1(tr, &Transfers::removeUserFromQueue_client, cid);
348                     WulforManager::get()->dispatchClientFunc(func);
349                 }
350             }
351             while (parent && WulforUtil::getNextIter_gui(GTK_TREE_MODEL(tr->transferStore), &iter, TRUE, FALSE));
352         }
353         gtk_tree_path_free(path);
354     }
355     g_list_free(list);
356 }
357 
onForceAttemptClicked_gui(GtkMenuItem * menuItem,gpointer data)358 void Transfers::onForceAttemptClicked_gui(GtkMenuItem *menuItem, gpointer data)
359 {
360     Transfers *tr = (Transfers *)data;
361     string cid;
362     GtkTreeIter iter;
363     GtkTreePath *path;
364     GList *list = gtk_tree_selection_get_selected_rows(tr->transferSelection, NULL);
365     typedef Func1<Transfers, string> F1;
366     F1 *func;
367 
368     for (GList *i = list; i; i = i->next)
369     {
370         path = (GtkTreePath *)i->data;
371         if (gtk_tree_model_get_iter(GTK_TREE_MODEL(tr->transferStore), &iter, path))
372         {
373             cid = tr->transferView.getString(&iter, "CID");
374             gtk_tree_store_set(tr->transferStore, &iter, tr->transferView.col(_("Status")), _("Connecting (forced)..."), -1);
375 
376             func = new F1(tr, &Transfers::forceAttempt_client, cid);
377             WulforManager::get()->dispatchClientFunc(func);
378         }
379         gtk_tree_path_free(path);
380     }
381     g_list_free(list);
382 }
383 
onCloseConnectionClicked_gui(GtkMenuItem * menuItem,gpointer data)384 void Transfers::onCloseConnectionClicked_gui(GtkMenuItem *menuItem, gpointer data)
385 {
386     Transfers *tr = (Transfers *)data;
387     string cid;
388     GtkTreeIter iter;
389     GtkTreePath *path;
390     bool download;
391     GList *list = gtk_tree_selection_get_selected_rows(tr->transferSelection, NULL);
392     typedef Func2<Transfers, string, bool> F2;
393     F2 *func;
394 
395     for (GList *i = list; i; i = i->next)
396     {
397         path = (GtkTreePath *)i->data;
398         if (gtk_tree_model_get_iter(GTK_TREE_MODEL(tr->transferStore), &iter, path))
399         {
400             bool parent = gtk_tree_model_iter_has_child(GTK_TREE_MODEL(tr->transferStore), &iter);
401 
402             do
403             {
404                 cid = tr->transferView.getString(&iter, "CID");
405                 if (!cid.empty())
406                 {
407                     gtk_tree_store_set(tr->transferStore, &iter, tr->transferView.col(_("Status")), _("Closing connection..."), -1);
408                     download = tr->transferView.getValue<gboolean>(&iter, "Download");
409 
410                     func = new F2(tr, &Transfers::closeConnection_client, cid, download);
411                     WulforManager::get()->dispatchClientFunc(func);
412                 }
413             }
414             while (parent && WulforUtil::getNextIter_gui(GTK_TREE_MODEL(tr->transferStore), &iter, TRUE, FALSE));
415         }
416         gtk_tree_path_free(path);
417     }
418     g_list_free(list);
419 }
420 
onTransferButtonPressed_gui(GtkWidget * widget,GdkEventButton * event,gpointer data)421 gboolean Transfers::onTransferButtonPressed_gui(GtkWidget *widget, GdkEventButton *event, gpointer data)
422 {
423     Transfers *tr = (Transfers *)data;
424 
425     if (event->button == 3)
426     {
427         GtkTreePath *path;
428         if (gtk_tree_view_get_path_at_pos(tr->transferView.get(), (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL))
429         {
430             bool selected = gtk_tree_selection_path_is_selected(tr->transferSelection, path);
431             gtk_tree_path_free(path);
432 
433             if (selected)
434                 return TRUE;
435         }
436     }
437 
438     return FALSE;
439 }
440 
onTransferButtonReleased_gui(GtkWidget * widget,GdkEventButton * event,gpointer data)441 gboolean Transfers::onTransferButtonReleased_gui(GtkWidget *widget, GdkEventButton *event, gpointer data)
442 {
443     Transfers *tr = (Transfers *)data;
444     int count = gtk_tree_selection_count_selected_rows(tr->transferSelection);
445 
446     if (count > 0 && event->type == GDK_BUTTON_RELEASE && event->button == 3)
447         tr->popupTransferMenu_gui();
448 
449     return FALSE;
450 }
451 
findParent_gui(const string & target,GtkTreeIter * iter)452 bool Transfers::findParent_gui(const string& target, GtkTreeIter* iter)
453 {
454     dcassert(!target.empty());
455     GtkTreeModel *m = GTK_TREE_MODEL(transferStore);
456     bool valid = gtk_tree_model_get_iter_first(m, iter);
457 
458     while (valid)
459     {
460         if (transferView.getValue<gboolean>(iter, "Download") &&
461                 target == transferView.getString(iter, "Target") &&
462                 transferView.getString(iter, "CID").empty())
463             return TRUE;
464 
465         valid = WulforUtil::getNextIter_gui(m, iter, FALSE, FALSE);
466     }
467 
468     return FALSE;
469 }
470 
findTransfer_gui(const string & cid,bool download,GtkTreeIter * iter)471 bool Transfers::findTransfer_gui(const string& cid, bool download, GtkTreeIter* iter)
472 {
473     GtkTreeModel *m = GTK_TREE_MODEL(transferStore);
474     bool valid = gtk_tree_model_get_iter_first(m, iter);
475 
476     while (valid)
477     {
478         if (cid == transferView.getString(iter, "CID") && !cid.empty())
479         {
480             if (download && transferView.getValue<gboolean>(iter, "Download"))
481                 return TRUE;
482             if (!download && !transferView.getValue<gboolean>(iter, "Download"))
483                 return TRUE;
484         }
485         valid = WulforUtil::getNextIter_gui(m, iter, TRUE, TRUE);
486     }
487 
488     return FALSE;
489 }
490 
addConnection_gui(StringMap params,bool download)491 void Transfers::addConnection_gui(StringMap params, bool download)
492 {
493     GtkTreeIter iter;
494     dcassert(params.find("CID") != params.end());
495     dcassert(findTransfer_gui(params["CID"], download, &iter) == FALSE);    // shouldn't fail, if it's already there we've forgot to remove it or dcpp core sends more than one Connection::Added
496 
497     gtk_tree_store_append(transferStore, &iter, NULL);
498     gtk_tree_store_set(transferStore, &iter,
499         transferView.col(_("User")), params["User"].c_str(),
500         transferView.col(_("Hub Name")), params["Hub Name"].c_str(),
501         transferView.col(_("Status")), params["Status"].c_str(),
502         transferView.col("CID"), params["CID"].c_str(),
503         transferView.col("Icon"), download ? "icon-download" : "icon-upload",
504         transferView.col("Download"), download,
505         transferView.col("Hub URL"), params["Hub URL"].c_str(),
506         -1);
507 }
508 
removeConnection_gui(const string cid,bool download)509 void Transfers::removeConnection_gui(const string cid, bool download)
510 {
511     GtkTreeIter iter;
512     GtkTreeIter parent;
513     bool valid = findTransfer_gui(cid, download, &iter);
514 
515     if (valid)
516     {
517         if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(transferStore), &parent, &iter))
518         {
519             gtk_tree_store_remove(transferStore, &iter);
520 
521             if (!gtk_tree_model_iter_has_child(GTK_TREE_MODEL(transferStore), &parent))
522                 gtk_tree_store_remove(transferStore, &parent);
523             else
524                 updateParent_gui(&parent);
525         }
526         else
527         {
528             gtk_tree_store_remove(transferStore, &iter);
529         }
530     }
531 }
532 
updateParent_gui(GtkTreeIter * iter)533 void Transfers::updateParent_gui(GtkTreeIter* iter)
534 {
535     int active = 0;
536     GtkTreeIter child;
537     string sprogress, users, status;
538     set<string> hubs;
539     int64_t speed = 0;
540     int64_t position = 0;
541     int64_t totalSize = 0;
542     int64_t timeLeft = 0;
543     double progress = 0.0;
544     ostringstream susers;
545     ostringstream tmpHubs;
546 
547     position = transferView.getValue<int64_t>(iter, "Download Position");
548     totalSize = transferView.getValue<int64_t>(iter, _("Size"));
549 
550     // Get Totals
551     if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(transferStore), iter))
552     {
553         child = *iter;
554         bool valid = WulforUtil::getNextIter_gui(GTK_TREE_MODEL(transferStore), &child, TRUE, FALSE);
555         while (valid)
556         {
557             if (transferView.getValue<int>(&child, "Failed") == 0 &&
558                 transferView.getString(&child, "Sort Order").substr(0,1) == "d")
559             {
560                 active++;
561                 speed += transferView.getValue<int64_t>(&child, _("Speed"));
562                 position += transferView.getValue<int64_t>(&child, "Download Position");
563             }
564             users += transferView.getString(&child, _("User")) + string(", ");
565             hubs.insert(transferView.getString(&child, _("Hub Name")));
566             valid = WulforUtil::getNextIter_gui(GTK_TREE_MODEL(transferStore), &child, TRUE, FALSE);
567         }
568     }
569 
570     if (totalSize > 0)
571         progress = (double)(position * 100.0) / totalSize;
572     if (speed > 0)
573         timeLeft = (totalSize - position) / speed;
574 
575     susers << setiosflags(ios::fixed) << setprecision(1);
576     susers << active << "/" << gtk_tree_model_iter_n_children(GTK_TREE_MODEL(transferStore), iter);
577 
578     if (transferView.getValue<gboolean>(iter, "Failed") == 0)
579     {
580         if (active)
581             status = _("Downloading");
582         else
583             status = _("Waiting for slot");
584     }
585     else
586     {
587         status = transferView.getString(iter, _("Status"));
588     }
589 
590     sprogress = Util::toString(static_cast<int>(progress)) + "%";
591 
592     std::copy(hubs.begin(), hubs.end(), std::ostream_iterator<string>(tmpHubs, ", "));
593 
594     gtk_tree_store_set(transferStore, iter,
595         transferView.col(_("User")), susers.str().c_str(),
596         transferView.col(_("Hub Name")), tmpHubs.str().substr(0, tmpHubs.str().length()-2).c_str(),
597         transferView.col(_("Speed")), speed,
598         transferView.col(_("Transferred")), Util::formatBytes(position).c_str(),
599         transferView.col(_("Time Left")), timeLeft,
600         transferView.col(_("Progress")), sprogress.c_str(),
601         transferView.col(_("Status")), status.c_str(),
602         transferView.col("Progress Hidden"), static_cast<int>(progress),
603         transferView.col("Sort Order"), active ? (string("d").append(users)).c_str() : (string("w").append(users)).c_str(),
604         -1);
605 }
606 
updateTransfer_gui(StringMap params,bool download,Sound::TypeSound sound)607 void Transfers::updateTransfer_gui(StringMap params, bool download, Sound::TypeSound sound)
608 {
609     dcassert(!params["CID"].empty());
610 
611     GtkTreeIter iter, parent;
612     if (!findTransfer_gui(params["CID"], download, &iter))
613     {
614         dcdebug(_("Transfers::updateTransfer, CID not found %s\n"), params["CID"].c_str());
615         // Transfer not found. Usually this *shouldn't* happen, but I guess it's possible since tick updates are sent by TimerManager
616         // and removing is handled by dl manager.
617 
618         return;
619     }
620 
621     int failed = transferView.getValue<int>(&iter, "Failed");
622     if (failed && params.find("Failed") != params.end())
623         failed = Util::toInt(params["Failed"]);
624 
625     if (failed) // Transfer had failed already. We won't update the transfer before the fail status changes.
626         return;
627     for (auto it = params.begin(); it != params.end(); ++it)
628     {
629         if (it->first == "Size" || it->first ==  "Speed" || it->first == "Download Position" || it->first ==  "Time Left")
630             gtk_tree_store_set(transferStore, &iter, transferView.col(_(it->first.c_str())), Util::toInt64(it->second), -1);
631         else if (it->first == "Progress Hidden" || it->first == "Failed")
632             gtk_tree_store_set(transferStore, &iter, transferView.col(it->first), Util::toInt(it->second), -1);
633         else if (!it->second.empty())
634             gtk_tree_store_set(transferStore, &iter, transferView.col(_(it->first.c_str())), it->second.c_str(), -1);
635     }
636     if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(transferStore), &parent, &iter))
637         updateParent_gui(&parent);
638     playSound_gui(sound);
639 }
640 
updateFilePosition_gui(const string cid,int64_t filePosition)641 void Transfers::updateFilePosition_gui(const string cid, int64_t filePosition)
642 {
643     GtkTreeIter iter;
644     GtkTreeIter parent;
645 
646     if (!findTransfer_gui(cid, TRUE, &iter))
647         return;
648 
649     if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(transferStore), &parent, &iter))
650     {
651         gtk_tree_store_set(transferStore, &parent,
652             transferView.col("Download Position"), filePosition,
653             -1);
654         updateParent_gui(&parent);
655     }
656 }
657 
initTransfer_gui(StringMap params)658 void Transfers::initTransfer_gui(StringMap params)
659 {
660     dcassert(!params["CID"].empty() && !params["Target"].empty());
661 
662     bool oldParentValid = FALSE;
663     bool newParentValid = FALSE;
664     bool needParent;
665     GtkTreeIter iter;
666     GtkTreeIter oldParent;
667     GtkTreeIter newParent;
668     GtkTreeIter newIter;
669 
670     // We could use && BOOLSETTING(SEGMENTED_DL) here to group only when segmented is enabled,
671     // but then the transfer should be worked out to display the whole size of the file. As
672     // it currently only shows the size of a transfer (and always starts from 0)
673     needParent = (params["Filename"] != string(_("File list"))) && BOOLSETTING(SEGMENTED_DL);
674 
675     if (!findTransfer_gui(params["CID"], TRUE, &iter))
676     {
677         dcassert(0); // not really fatal only annoying as the dl can't be seen, can be ignored in release build
678         return;
679     }
680 
681     oldParentValid = gtk_tree_model_iter_parent(GTK_TREE_MODEL(transferStore), &oldParent, &iter);
682     if (needParent)
683     {
684         newParentValid = findParent_gui(params["Target"], &newParent);
685 
686         if (newParentValid)
687         {
688             string target = oldParentValid ? transferView.getString(&oldParent, "Target") : transferView.getString(&iter, "Target");
689             if (target != transferView.getString(&newParent, "Target")) // is the file changing
690             {
691                 newIter = WulforUtil::copyRow_gui(transferStore, &iter, &newParent);
692                 gtk_tree_store_remove(transferStore, &iter);
693                 iter = newIter;
694             }
695             else
696             {
697                 if (transferView.getValue<int>(&newParent, "Failed"))
698                 {
699                     gtk_tree_store_set(transferStore, &newParent,
700                         transferView.col("Failed"), FALSE,
701                         -1);
702                 }
703 
704                 oldParentValid = FALSE; // Don't update the parentRow twice, since old and new are the same (and definately don't remove twice)
705             }
706         }
707         else
708         {
709             string filename = params["Filename"];
710             if (filename.find(_("TTH: ")) != string::npos)
711                 filename = filename.substr((string(_("TTH: "))).length());
712             gtk_tree_store_append(transferStore, &newParent, NULL);
713             newParentValid = TRUE;
714             gtk_tree_store_set(transferStore, &newParent,
715                 transferView.col(_("Filename")), filename.c_str(),
716                 transferView.col(_("Path")), params["Path"].c_str(),
717                 transferView.col(_("Size")), Util::toInt64(params["File Size"]),
718                 transferView.col("Icon"), "icon-download",
719                 transferView.col("Download"), TRUE,
720                 transferView.col("Target"), params["Target"].c_str(),
721                 -1);
722 
723             newIter = WulforUtil::copyRow_gui(transferStore, &iter, &newParent);
724             gtk_tree_store_remove(transferStore, &iter);
725             iter = newIter;
726         }
727 
728         gtk_tree_store_set(transferStore, &newParent,
729                 transferView.col(_("Size")), Util::toInt64(params["File Size"]),
730                 transferView.col("Download Position"), Util::toInt64(params["File Position"]),
731                 -1);
732     }
733     else if (oldParentValid) // No need for parent, but we have one anyway => move row to top-level
734     {
735         newIter = WulforUtil::copyRow_gui(transferStore, &iter, NULL);
736         gtk_tree_store_remove(transferStore, &iter);
737         iter = newIter;
738     }
739 
740     if (oldParentValid)
741     {
742         if (!gtk_tree_model_iter_n_children(GTK_TREE_MODEL(transferStore), &oldParent))
743             gtk_tree_store_remove(transferStore, &oldParent);
744         else
745             updateParent_gui(&oldParent);
746     }
747     if (newParentValid)
748     {
749         updateParent_gui(&newParent);
750     }
751 }
752 
finishParent_gui(const string target,const string status,Sound::TypeSound sound)753 void Transfers::finishParent_gui(const string target, const string status, Sound::TypeSound sound)
754 {
755     GtkTreeIter iter;
756     if (findParent_gui(target, &iter))
757     {
758         if (!gtk_tree_model_iter_has_child(GTK_TREE_MODEL(transferStore), &iter))
759             return;
760 
761         if (transferView.getValue<gboolean>(&iter, "Failed") == 0)
762         {
763             gtk_tree_store_set(transferStore, &iter,
764                 transferView.col(_("Status")), status.c_str(),
765                 transferView.col("Failed"), (gboolean)1,
766                 transferView.col(_("Speed")), (uint64_t)-1,
767                 -1);
768         }
769     }
770 
771     playSound_gui(sound);
772 }
773 
playSound_gui(Sound::TypeSound sound)774 void Transfers::playSound_gui(Sound::TypeSound sound)
775 {
776     if (sound != Sound::NONE)
777         Sound::get()->playSound(sound);
778 }
779 
getFileList_client(string cid,string hubUrl)780 void Transfers::getFileList_client(string cid, string hubUrl)
781 {
782     try
783     {
784         if (!cid.empty() && !hubUrl.empty())
785         {
786             UserPtr user = ClientManager::getInstance()->getUser(CID(cid));
787             QueueManager::getInstance()->addList(HintedUser(user, hubUrl), QueueItem::FLAG_CLIENT_VIEW);
788         }
789     }
790     catch (const Exception&)
791     {
792     }
793 }
794 
matchQueue_client(string cid,string hubUrl)795 void Transfers::matchQueue_client(string cid, string hubUrl)
796 {
797     try
798     {
799         if (!cid.empty() && !hubUrl.empty())
800         {
801             UserPtr user = ClientManager::getInstance()->getUser(CID(cid));
802             QueueManager::getInstance()->addList(HintedUser(user, hubUrl), QueueItem::FLAG_MATCH_QUEUE);
803         }
804     }
805     catch (const Exception&)
806     {
807     }
808 }
809 
addFavoriteUser_client(string cid)810 void Transfers::addFavoriteUser_client(string cid)
811 {
812     if (!cid.empty())
813     {
814         UserPtr user = ClientManager::getInstance()->getUser(CID(cid));
815         FavoriteManager::getInstance()->addFavoriteUser(user);
816     }
817 }
818 
grantExtraSlot_client(string cid,string hubUrl)819 void Transfers::grantExtraSlot_client(string cid, string hubUrl)
820 {
821     if (!cid.empty() && !hubUrl.empty())
822     {
823         UserPtr user = ClientManager::getInstance()->getUser(CID(cid));
824         UploadManager::getInstance()->reserveSlot(HintedUser(user, hubUrl));
825     }
826 }
827 
removeUserFromQueue_client(string cid)828 void Transfers::removeUserFromQueue_client(string cid)
829 {
830     if (!cid.empty())
831     {
832         UserPtr user = ClientManager::getInstance()->getUser(CID(cid));
833         QueueManager::getInstance()->removeSource(user, QueueItem::Source::FLAG_REMOVED);
834     }
835 }
836 
forceAttempt_client(string cid)837 void Transfers::forceAttempt_client(string cid)
838 {
839     if (!cid.empty())
840     {
841         UserPtr user = ClientManager::getInstance()->findUser(CID(cid));
842         ConnectionManager::getInstance()->force(user);
843     }
844 }
845 
closeConnection_client(string cid,bool download)846 void Transfers::closeConnection_client(string cid, bool download)
847 {
848     if (!cid.empty())
849     {
850         UserPtr user = ClientManager::getInstance()->findUser(CID(cid));
851         ConnectionManager::getInstance()->disconnect(user, download);
852     }
853 }
854 
getParams_client(StringMap & params,ConnectionQueueItem * cqi)855 void Transfers::getParams_client(StringMap& params, ConnectionQueueItem* cqi)
856 {
857     // NOTE: const HintedUser& getUser() const { return user; }
858     const HintedUser &user = cqi->getUser();
859 
860     params["CID"] = user.user->getCID().toBase32();
861     params["User"] = WulforUtil::getNicks(user);
862     params["Hub Name"] = WulforUtil::getHubNames(user);
863     params["Failed"] = "0";
864     params["Hub URL"] = user.hint;
865 }
866 
getParams_client(StringMap & params,Transfer * tr)867 void Transfers::getParams_client(StringMap& params, Transfer* tr)
868 {
869     // NOTE: const HintedUser getHintedUser() const;
870     const HintedUser user = tr->getHintedUser();
871     double percent = 0.0;
872 
873     params["CID"] = user.user->getCID().toBase32();
874     if (tr->getType() == Transfer::TYPE_FULL_LIST || tr->getType() == Transfer::TYPE_PARTIAL_LIST)
875         params["Filename"] = _("File list");
876     else if (tr->getType() == Transfer::TYPE_TREE)
877         params["Filename"] = _("TTH: ") + Util::getFileName(tr->getPath());
878     else
879         params["Filename"] = Util::getFileName(tr->getPath());
880     params["User"] = WulforUtil::getNicks(user);
881     params["Hub Name"] = WulforUtil::getHubNames(user);
882     params["Path"] = Util::getFilePath(tr->getPath());
883     params["Size"] = Util::toString(tr->getSize());
884     params["Download Position"] = Util::toString(tr->getPos());
885     params["Speed"] = Util::toString(tr->getAverageSpeed());
886     if (tr->getSize() > 0)
887         percent = static_cast<double>(tr->getPos() * 100.0)/ tr->getSize();
888     params["Progress Hidden"] = Util::toString(static_cast<int>(percent));
889     params["IP"] = tr->getUserConnection().getRemoteIp();
890     params["Time Left"] = tr->getSecondsLeft() > 0 ? Util::toString(tr->getSecondsLeft()) : "-1";
891     params["Target"] = tr->getPath();
892     params["Hub URL"] = tr->getUserConnection().getHubUrl();
893     params["Encryption"] = tr->getUserConnection().isSecure() ? tr->getUserConnection().getCipherName() : _("Plain");
894 }
895 
on(DownloadManagerListener::Requesting,Download * dl)896 void Transfers::on(DownloadManagerListener::Requesting, Download* dl) noexcept
897 {
898     StringMap params;
899 
900     getParams_client(params, dl);
901 
902     params["File Size"] = Util::toString(QueueManager::getInstance()->getSize(dl->getPath()));
903     params["File Position"] = Util::toString(QueueManager::getInstance()->getPos(dl->getPath()));
904     params["Sort Order"] = "w" + params["User"];
905     params["Status"] = _("Requesting");
906     params["Failed"] = "0";
907 
908     typedef Func1<Transfers, StringMap> F1;
909     F1* f1 = new F1(this, &Transfers::initTransfer_gui, params);
910     WulforManager::get()->dispatchGuiFunc(f1);
911 }
912 
on(DownloadManagerListener::Starting,Download * dl)913 void Transfers::on(DownloadManagerListener::Starting, Download* dl) noexcept
914 {
915     StringMap params;
916 
917     getParams_client(params, dl);
918     params["Status"] = _("Download starting...");
919     params["Sort Order"] = "d" + params["User"];
920     params["Failed"] = "0";
921     params["tmpTarget"] = dl->getTempTarget();
922 
923     typedef Func3<Transfers, StringMap, bool, Sound::TypeSound> F3;
924     F3* f3 = new F3(this, &Transfers::updateTransfer_gui, params, TRUE, Sound::NONE);
925     WulforManager::get()->dispatchGuiFunc(f3);
926 }
927 
on(DownloadManagerListener::Tick,const DownloadList & dls)928 void Transfers::on(DownloadManagerListener::Tick, const DownloadList& dls) noexcept
929 {
930     for (auto it = dls.begin(); it != dls.end(); ++it)
931     {
932         Download* dl = *it;
933         StringMap params;
934         string flags;
935 
936         getParams_client(params, *it);
937 
938         if (dl->getUserConnection().isSecure())
939         {
940             if (dl->getUserConnection().isTrusted())
941                 flags += _("[S]");
942             else
943                 flags += _("[U]");
944         }
945         if (dl->isSet(Download::FLAG_TTH_CHECK))
946             flags += _("[T]");
947         if (dl->isSet(Download::FLAG_ZDOWNLOAD))
948             flags += _("[Z]");
949 
950         params["Flags"] = flags;
951         params["Transferred"] = Util::formatBytes(dl->getPos());
952         params["Time"] = Util::formatSeconds((GET_TICK() - dl->getStart()) / 1000);
953         params["Progress"] = params["Progress Hidden"] + "%";
954         params["Status"] = _("Downloading");
955 
956         typedef Func3<Transfers, StringMap, bool, Sound::TypeSound> F3;
957         F3* f3 = new F3(this, &Transfers::updateTransfer_gui, params, TRUE, Sound::NONE);
958         WulforManager::get()->dispatchGuiFunc(f3);
959     }
960 }
961 
on(DownloadManagerListener::Complete,Download * dl)962 void Transfers::on(DownloadManagerListener::Complete, Download* dl) noexcept
963 {
964     StringMap params;
965 
966     getParams_client(params, dl);
967     params["Status"] = _("Download complete...");
968     params["Progress Hidden"] = "100";
969     params["Progress"] = "100%";
970     params["Sort Order"] = "w" + params["User"];
971     params["Speed"] = "-1";
972 
973     int64_t pos = QueueManager::getInstance()->getPos(dl->getPath()) + dl->getPos();
974 
975     typedef Func3<Transfers, StringMap, bool, Sound::TypeSound> F3;
976     F3* f3 = new F3(this, &Transfers::updateTransfer_gui, params, TRUE, Sound::NONE);
977     WulforManager::get()->dispatchGuiFunc(f3);
978 
979     typedef Func2<Transfers, const string, int64_t> F2b;
980     F2b* f2b = new F2b(this, &Transfers::updateFilePosition_gui, params["CID"], pos);
981     WulforManager::get()->dispatchGuiFunc(f2b);
982 }
983 
on(DownloadManagerListener::Failed,Download * dl,const string & reason)984 void Transfers::on(DownloadManagerListener::Failed, Download* dl, const string& reason) noexcept
985 {
986     onFailed(dl, reason);
987 }
988 
on(QueueManagerListener::CRCFailed,Download * dl,const string & reason)989 void Transfers::on(QueueManagerListener::CRCFailed, Download* dl, const string& reason) noexcept
990 {
991     onFailed(dl, reason);
992 }
993 
onFailed(Download * dl,const string & reason)994 void Transfers::onFailed(Download* dl, const string& reason) {
995     StringMap params;
996     getParams_client(params, dl);
997     params["Status"] = reason;
998     params["Sort Order"] = "w" + params["User"];
999     params["Failed"] = "1";
1000     params["Speed"] = "-1";
1001     params["Time Left"] = "-1";
1002 
1003     int64_t pos = QueueManager::getInstance()->getPos(dl->getPath()) + dl->getPos();
1004 
1005     typedef Func3<Transfers, StringMap, bool, Sound::TypeSound> F3;
1006     F3* f3 = new F3(this, &Transfers::updateTransfer_gui, params, TRUE, Sound::NONE);
1007     WulforManager::get()->dispatchGuiFunc(f3);
1008 
1009     typedef Func2<Transfers, const string, int64_t> F2b;
1010     F2b* f2b = new F2b(this, &Transfers::updateFilePosition_gui, params["CID"], pos);
1011     WulforManager::get()->dispatchGuiFunc(f2b);
1012 }
1013 
on(ConnectionManagerListener::Added,ConnectionQueueItem * cqi)1014 void Transfers::on(ConnectionManagerListener::Added, ConnectionQueueItem* cqi) noexcept
1015 {
1016     StringMap params;
1017     getParams_client(params, cqi);
1018     params["Status"] = _("Connecting...");
1019 
1020     typedef Func2<Transfers, StringMap, bool> F2;
1021     F2* f2 = new F2(this, &Transfers::addConnection_gui, params, cqi->getDownload());
1022     WulforManager::get()->dispatchGuiFunc(f2);
1023 }
1024 
on(ConnectionManagerListener::Connected,ConnectionQueueItem * cqi)1025 void Transfers::on(ConnectionManagerListener::Connected, ConnectionQueueItem* cqi) noexcept
1026 {
1027     StringMap params;
1028     getParams_client(params, cqi);
1029     params["Status"] = _("Connected");
1030 
1031     typedef Func3<Transfers, StringMap, bool, Sound::TypeSound> F3;
1032     F3* f3 = new F3(this, &Transfers::updateTransfer_gui, params, cqi->getDownload(), Sound::NONE);
1033     WulforManager::get()->dispatchGuiFunc(f3);
1034 }
1035 
on(ConnectionManagerListener::Removed,ConnectionQueueItem * cqi)1036 void Transfers::on(ConnectionManagerListener::Removed, ConnectionQueueItem* cqi) noexcept
1037 {
1038     string cid = cqi->getUser().user->getCID().toBase32();
1039     typedef Func2<Transfers, const string, bool> F2;
1040     F2* f2 = new F2(this, &Transfers::removeConnection_gui, cid, cqi->getDownload());
1041     WulforManager::get()->dispatchGuiFunc(f2);
1042 }
1043 
on(ConnectionManagerListener::Failed,ConnectionQueueItem * cqi,const string & reason)1044 void Transfers::on(ConnectionManagerListener::Failed, ConnectionQueueItem* cqi, const string& reason) noexcept
1045 {
1046     StringMap params;
1047     getParams_client(params, cqi);
1048     params["Status"] = reason;
1049     params["Failed"] = "1";
1050     params["Sort Order"] = "w" + params["User"];
1051     params["Speed"] = "-1";
1052     params["Time Left"] = "-1";
1053 
1054     typedef Func3<Transfers, StringMap, bool, Sound::TypeSound> F3;
1055     F3* f3 = new F3(this, &Transfers::updateTransfer_gui, params, cqi->getDownload(), Sound::NONE);
1056     WulforManager::get()->dispatchGuiFunc(f3);
1057 }
1058 
on(ConnectionManagerListener::StatusChanged,ConnectionQueueItem * cqi)1059 void Transfers::on(ConnectionManagerListener::StatusChanged, ConnectionQueueItem* cqi) noexcept
1060 {
1061     StringMap params;
1062     getParams_client(params, cqi);
1063 
1064     if (cqi->getState() == ConnectionQueueItem::CONNECTING)
1065         params["Status"] = _("Connecting");
1066     else
1067         params["Status"] = _("Waiting to retry");
1068     params["Sort Order"] = "w" + params["User"];
1069 
1070     typedef Func3<Transfers, StringMap, bool, Sound::TypeSound> F3;
1071     F3* f3 = new F3(this, &Transfers::updateTransfer_gui, params, cqi->getDownload(), Sound::NONE);
1072     WulforManager::get()->dispatchGuiFunc(f3);
1073 }
1074 
on(QueueManagerListener::Finished,QueueItem * qi,const string & dir,int64_t size)1075 void Transfers::on(QueueManagerListener::Finished, QueueItem* qi, const string& dir, int64_t size) noexcept
1076 {
1077     string target = qi->getTarget();
1078     Sound::TypeSound sound = Sound::DOWNLOAD_FINISHED;
1079 
1080     if (qi->isSet(QueueItem::FLAG_CLIENT_VIEW | QueueItem::FLAG_USER_LIST))
1081     {
1082         sound = Sound::DOWNLOAD_FINISHED_USER_LIST;
1083     }
1084     else if (qi->isSet(QueueItem::FLAG_XML_BZLIST))
1085     {
1086         sound = Sound::NONE;
1087     }
1088 
1089     typedef Func3<Transfers, const string, const string, Sound::TypeSound> F3;
1090     F3* f3 = new F3(this, &Transfers::finishParent_gui, target, _("Download finished"), sound);
1091     WulforManager::get()->dispatchGuiFunc(f3);
1092 }
1093 
on(QueueManagerListener::Removed,QueueItem * qi)1094 void Transfers::on(QueueManagerListener::Removed, QueueItem* qi) noexcept
1095 {
1096     string target = qi->getTarget();
1097 
1098     typedef Func3<Transfers, const string, const string, Sound::TypeSound> F3;
1099     F3* f3 = new F3(this, &Transfers::finishParent_gui, target, _("Download removed"), Sound::NONE);
1100     WulforManager::get()->dispatchGuiFunc(f3);
1101 }
1102 
on(UploadManagerListener::Starting,Upload * ul)1103 void Transfers::on(UploadManagerListener::Starting, Upload* ul) noexcept
1104 {
1105     StringMap params;
1106 
1107     getParams_client(params, ul);
1108     params["Status"] = _("Upload starting...");
1109     params["Sort Order"] = "u" + params["User"];
1110     params["Failed"] = "0";
1111     params["tmpTarget"] = _("none"); //fix open 'tmp' file
1112 
1113     typedef Func3<Transfers, StringMap, bool, Sound::TypeSound> F3;
1114     F3* f3 = new F3(this, &Transfers::updateTransfer_gui, params, FALSE, Sound::NONE);
1115     WulforManager::get()->dispatchGuiFunc(f3);
1116 }
1117 
on(UploadManagerListener::Tick,const UploadList & uls)1118 void Transfers::on(UploadManagerListener::Tick, const UploadList& uls) noexcept
1119 {
1120     for (auto it = uls.begin(); it != uls.end(); ++it)
1121     {
1122         Upload* ul = *it;
1123         StringMap params;
1124         string flags;
1125 
1126         getParams_client(params, ul);
1127 
1128         if (ul->getUserConnection().isSecure())
1129         {
1130             if (ul->getUserConnection().isTrusted())
1131                 flags += _("[S]");
1132             else
1133                 flags += _("[U]");
1134         }
1135         if (ul->isSet(Upload::FLAG_ZUPLOAD))
1136             flags += _("[Z]");
1137 
1138         params["Flags"] = flags;
1139         params["Transferred"] = Util::formatBytes(ul->getPos());
1140         params["Time"] = Util::formatSeconds((GET_TICK() - ul->getStart()) / 1000);
1141         params["Progress"] = params["Progress Hidden"] + "%";
1142         params["Status"] = _("Uploading");
1143 
1144         typedef Func3<Transfers, StringMap, bool, Sound::TypeSound> F3;
1145         F3* f3 = new F3(this, &Transfers::updateTransfer_gui, params, FALSE, Sound::NONE);
1146         WulforManager::get()->dispatchGuiFunc(f3);
1147     }
1148 }
1149 
on(UploadManagerListener::Complete,Upload * ul)1150 void Transfers::on(UploadManagerListener::Complete, Upload* ul) noexcept
1151 {
1152     StringMap params;
1153 
1154     getParams_client(params, ul);
1155     params["Status"] = _("Upload complete...");
1156     params["Progress Hidden"] = "100";
1157     params["Progress"] = "100%";
1158     params["Sort Order"] = "w" + params["User"];
1159     params["Speed"] = "-1";
1160 
1161     typedef Func3<Transfers, StringMap, bool, Sound::TypeSound> F3;
1162     F3* f3 = new F3(this, &Transfers::updateTransfer_gui, params, FALSE, Sound::UPLOAD_FINISHED);
1163     WulforManager::get()->dispatchGuiFunc(f3);
1164 }
1165 
on(UploadManagerListener::Failed,Upload * ul,const string & reason)1166 void Transfers::on(UploadManagerListener::Failed, Upload* ul, const string& reason) noexcept
1167 {
1168     StringMap params;
1169     getParams_client(params, ul);
1170     params["Status"] = reason;
1171     params["Sort Order"] = "w" + params["User"];
1172     params["Failed"] = "1";
1173     params["Speed"] = "-1";
1174     params["Time Left"] = "-1";
1175 
1176     typedef Func3<Transfers, StringMap, bool, Sound::TypeSound> F3;
1177     F3* f3 = new F3(this, &Transfers::updateTransfer_gui, params, FALSE, Sound::NONE);
1178     WulforManager::get()->dispatchGuiFunc(f3);
1179 }
1180