1 /*
2 * Copyright © 2004-2008 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 "downloadqueue.hh"
23
24 #include <dcpp/ResourceManager.h>
25 #include "search.hh"
26 #include "settingsmanager.hh"
27 #include "wulformanager.hh"
28 #include "WulforUtil.hh"
29
30 using namespace std;
31 using namespace dcpp;
32
DownloadQueue()33 DownloadQueue::DownloadQueue():
34 BookEntry(Entry::DOWNLOAD_QUEUE, _("Download Queue"), "downloadqueue.glade"),
35 currentItems(0),
36 totalItems(0),
37 currentSize(0),
38 totalSize(0)
39 {
40 // Configure the dialogs
41 File::ensureDirectory(SETTING(DOWNLOAD_DIRECTORY));
42 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(getWidget("dirChooserDialog")), Text::fromUtf8(SETTING(DOWNLOAD_DIRECTORY)).c_str());
43 gtk_dialog_set_alternative_button_order(GTK_DIALOG(getWidget("dirChooserDialog")), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1);
44
45 // Initialize directory treeview
46 dirView.setView(GTK_TREE_VIEW(getWidget("dirView")));
47 dirView.insertColumn("Dir", G_TYPE_STRING, TreeView::STRING, -1);
48 dirView.insertHiddenColumn("Path", G_TYPE_STRING);
49 dirView.insertHiddenColumn("File Count", G_TYPE_INT);
50 dirView.finalize();
51 dirStore = gtk_tree_store_newv(dirView.getColCount(), dirView.getGTypes());
52 gtk_tree_view_set_model(dirView.get(), GTK_TREE_MODEL(dirStore));
53 g_object_unref(dirStore);
54 dirSelection = gtk_tree_view_get_selection(dirView.get());
55 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dirStore), dirView.col("Dir"), GTK_SORT_ASCENDING);
56 gtk_tree_view_set_enable_tree_lines(dirView.get(), TRUE);
57
58 // Initialize file treeview
59 fileView.setView(GTK_TREE_VIEW(getWidget("fileView")), TRUE, "downloadqueue");
60 fileView.insertColumn(N_("Filename"), G_TYPE_STRING, TreeView::STRING, 200);
61 fileView.insertColumn(N_("Status"), G_TYPE_STRING, TreeView::STRING, 100);
62 fileView.insertColumn(N_("Size"), G_TYPE_STRING, TreeView::STRING, 100);
63 fileView.insertColumn(N_("Downloaded"), G_TYPE_STRING, TreeView::STRING, 150);
64 fileView.insertColumn(N_("Priority"), G_TYPE_STRING, TreeView::STRING, 75);
65 fileView.insertColumn(N_("Users"), G_TYPE_STRING, TreeView::STRING, 200);
66 fileView.insertColumn(N_("Path"), G_TYPE_STRING, TreeView::STRING, 200);
67 fileView.insertColumn(N_("Exact Size"), G_TYPE_STRING, TreeView::STRING, 100);
68 fileView.insertColumn(N_("Errors"), G_TYPE_STRING, TreeView::STRING, 200);
69 fileView.insertColumn(N_("Added"), G_TYPE_STRING, TreeView::STRING, 120);
70 fileView.insertColumn(N_("TTH"), G_TYPE_STRING, TreeView::STRING, 125);
71 fileView.insertHiddenColumn("Size Sort", G_TYPE_INT64);
72 fileView.insertHiddenColumn("Downloaded Sort", G_TYPE_INT64);
73 fileView.insertHiddenColumn("Target", G_TYPE_STRING);
74 fileView.finalize();
75 fileStore = gtk_list_store_newv(fileView.getColCount(), fileView.getGTypes());
76 gtk_tree_view_set_model(fileView.get(), GTK_TREE_MODEL(fileStore));
77 g_object_unref(fileStore);
78 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(fileView.get()), GTK_SELECTION_MULTIPLE);
79 fileSelection = gtk_tree_view_get_selection(fileView.get());
80 fileView.setSortColumn_gui("Size", "Size Sort");
81 fileView.setSortColumn_gui("Exact Size", "Size Sort");
82 fileView.setSortColumn_gui("Downloaded", "Downloaded Sort");
83 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(fileStore), fileView.col("Filename"), GTK_SORT_ASCENDING);
84 gtk_tree_view_column_set_sort_indicator(gtk_tree_view_get_column(fileView.get(), fileView.col("Filename")), TRUE);
85
86 // Connect the signals to their callback functions.
87 g_signal_connect(getWidget("pausedPriorityItem"), "activate", G_CALLBACK(onDirPriorityClicked_gui), (gpointer)this);
88 g_signal_connect(getWidget("lowestPriorityItem"), "activate", G_CALLBACK(onDirPriorityClicked_gui), (gpointer)this);
89 g_signal_connect(getWidget("lowPrioritytem"), "activate", G_CALLBACK(onDirPriorityClicked_gui), (gpointer)this);
90 g_signal_connect(getWidget("normalPriorityItem"), "activate", G_CALLBACK(onDirPriorityClicked_gui), (gpointer)this);
91 g_signal_connect(getWidget("highPriorityItem"), "activate", G_CALLBACK(onDirPriorityClicked_gui), (gpointer)this);
92 g_signal_connect(getWidget("highestPriorityItem"), "activate", G_CALLBACK(onDirPriorityClicked_gui), (gpointer)this);
93 g_signal_connect(getWidget("moveDirItem"), "activate", G_CALLBACK(onDirMoveClicked_gui), (gpointer)this);
94 g_signal_connect(getWidget("removeDirItem"), "activate", G_CALLBACK(onDirRemoveClicked_gui), (gpointer)this);
95 g_signal_connect(getWidget("searchForAlternatesItem"), "activate", G_CALLBACK(onFileSearchAlternatesClicked_gui), (gpointer)this);
96 g_signal_connect(getWidget("moveFileItem"), "activate", G_CALLBACK(onFileMoveClicked_gui), (gpointer)this);
97 g_signal_connect(getWidget("filePausedItem"), "activate", G_CALLBACK(onFilePriorityClicked_gui), (gpointer)this);
98 g_signal_connect(getWidget("fileLowestPriorityItem"), "activate", G_CALLBACK(onFilePriorityClicked_gui), (gpointer)this);
99 g_signal_connect(getWidget("fileLowPriorityItem"), "activate", G_CALLBACK(onFilePriorityClicked_gui), (gpointer)this);
100 g_signal_connect(getWidget("fileNormalPriorityItem"), "activate", G_CALLBACK(onFilePriorityClicked_gui), (gpointer)this);
101 g_signal_connect(getWidget("fileHighPriorityItem"), "activate", G_CALLBACK(onFilePriorityClicked_gui), (gpointer)this);
102 g_signal_connect(getWidget("fileHighestPriorityItem"), "activate", G_CALLBACK(onFilePriorityClicked_gui), (gpointer)this);
103 g_signal_connect(getWidget("fileRemoveItem"), "activate", G_CALLBACK(onFileRemoveClicked_gui), (gpointer)this);
104 g_signal_connect(getWidget("copyMagnetItem"), "activate", G_CALLBACK(onCopyMagnetClicked_gui), (gpointer)this);
105 g_signal_connect(dirView.get(), "button-press-event", G_CALLBACK(onDirButtonPressed_gui), (gpointer)this);
106 g_signal_connect(dirView.get(), "button-release-event", G_CALLBACK(onDirButtonReleased_gui), (gpointer)this);
107 g_signal_connect(dirView.get(), "key-release-event", G_CALLBACK(onDirKeyReleased_gui), (gpointer)this);
108 g_signal_connect(fileView.get(), "button-press-event", G_CALLBACK(onFileButtonPressed_gui), (gpointer)this);
109 g_signal_connect(fileView.get(), "button-release-event", G_CALLBACK(onFileButtonReleased_gui), (gpointer)this);
110 g_signal_connect(fileView.get(), "key-release-event", G_CALLBACK(onFileKeyReleased_gui), (gpointer)this);
111
112 // Set the pane position
113 gtk_paned_set_position(GTK_PANED(getWidget("pane")), WGETI("downloadqueue-pane-position"));
114 int panePosition = WGETI("downloadqueue-pane-position");
115 if (panePosition > 10)
116 gtk_paned_set_position(GTK_PANED(getWidget("pane")), panePosition);
117 }
118
~DownloadQueue()119 DownloadQueue::~DownloadQueue()
120 {
121 QueueManager::getInstance()->removeListener(this);
122
123 // Save the pane position
124 int panePosition = gtk_paned_get_position(GTK_PANED(getWidget("pane")));
125 if (panePosition > 10)
126 WSET("downloadqueue-pane-position", panePosition);
127
128 gtk_widget_destroy(getWidget("dirChooserDialog"));
129 }
130
show()131 void DownloadQueue::show()
132 {
133 buildList_client();
134 QueueManager::getInstance()->addListener(this);
135 }
136
buildDynamicMenu_gui()137 void DownloadQueue::buildDynamicMenu_gui()
138 {
139 bool showMenus = FALSE;
140 bool showReAddMenu = FALSE;
141 int count = gtk_tree_selection_count_selected_rows(fileSelection);
142
143 if (count == 1)
144 {
145 GtkTreeIter iter;
146 GList *list = gtk_tree_selection_get_selected_rows(fileSelection, NULL);
147 GtkTreePath *path = (GtkTreePath *)g_list_nth_data(list, 0);
148
149 gtk_container_foreach(GTK_CONTAINER(getWidget("browseMenu")), (GtkCallback)gtk_widget_destroy, NULL);
150 gtk_container_foreach(GTK_CONTAINER(getWidget("pmMenu")), (GtkCallback)gtk_widget_destroy, NULL);
151 gtk_container_foreach(GTK_CONTAINER(getWidget("reAddMenu")), (GtkCallback)gtk_widget_destroy, NULL);
152 gtk_container_foreach(GTK_CONTAINER(getWidget("removeMenu")), (GtkCallback)gtk_widget_destroy, NULL);
153 gtk_container_foreach(GTK_CONTAINER(getWidget("removeAllMenu")), (GtkCallback)gtk_widget_destroy, NULL);
154
155 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(fileStore), &iter, path))
156 {
157 GtkWidget *menuItem;
158 string target = fileView.getString(&iter, "Target");
159
160 ///@todo: Fix this. sources & badSources should not be accessible from gui thread.
161 for (SourceIter it = sources[target].begin(); it != sources[target].end(); ++it)
162 {
163 showMenus = TRUE;
164 menuItem = gtk_menu_item_new_with_label(it->first.c_str());
165 gtk_menu_shell_append(GTK_MENU_SHELL(getWidget("browseMenu")), menuItem);
166 g_signal_connect(menuItem, "activate", G_CALLBACK(onFileGetListClicked_gui), (gpointer)this);
167
168 menuItem = gtk_menu_item_new_with_label(it->first.c_str());
169 gtk_menu_shell_append(GTK_MENU_SHELL(getWidget("pmMenu")), menuItem);
170 g_signal_connect(menuItem, "activate", G_CALLBACK(onFileSendPMClicked_gui), (gpointer)this);
171
172 menuItem = gtk_menu_item_new_with_label(it->first.c_str());
173 gtk_menu_shell_append(GTK_MENU_SHELL(getWidget("removeMenu")), menuItem);
174 g_signal_connect(menuItem, "activate", G_CALLBACK(onFileRemoveSourceClicked_gui), (gpointer)this);
175
176 menuItem = gtk_menu_item_new_with_label(it->first.c_str());
177 gtk_menu_shell_append(GTK_MENU_SHELL(getWidget("removeAllMenu")), menuItem);
178 g_signal_connect(menuItem, "activate", G_CALLBACK(onFileRemoveUserFromQueueClicked_gui), (gpointer)this);
179 }
180
181 for (SourceIter it = badSources[target].begin(); it != badSources[target].end(); ++it)
182 {
183 showReAddMenu = TRUE;
184 menuItem = gtk_menu_item_new_with_label(it->first.c_str());
185 gtk_menu_shell_append(GTK_MENU_SHELL(getWidget("reAddMenu")), menuItem);
186 g_signal_connect(menuItem, "activate", G_CALLBACK(onFileReAddSourceClicked_gui), (gpointer)this);
187 }
188 }
189 gtk_tree_path_free(path);
190 g_list_free(list);
191
192 gtk_widget_set_sensitive(getWidget("searchForAlternatesItem"), TRUE);
193 }
194 else
195 gtk_widget_set_sensitive(getWidget("searchForAlternatesItem"), FALSE);
196
197 if (showMenus)
198 {
199 gtk_widget_show_all(getWidget("browseMenu"));
200 gtk_widget_show_all(getWidget("pmMenu"));
201 gtk_widget_show_all(getWidget("removeMenu"));
202 gtk_widget_show_all(getWidget("removeAllMenu"));
203 }
204 if (showReAddMenu)
205 gtk_widget_show_all(getWidget("reAddMenu"));
206
207 gtk_widget_set_sensitive(getWidget("getFileListItem"), showMenus);
208 gtk_widget_set_sensitive(getWidget("sendPrivateMessageItem"), showMenus);
209 gtk_widget_set_sensitive(getWidget("removeSourceItem"), showMenus);
210 gtk_widget_set_sensitive(getWidget("removeUserFromQueueItem"), showMenus);
211 gtk_widget_set_sensitive(getWidget("reAddSourceItem"), showReAddMenu);
212 }
213
setStatus_gui(string text,string statusItem)214 void DownloadQueue::setStatus_gui(string text, string statusItem)
215 {
216 if (!text.empty() && !statusItem.empty())
217 {
218 if (statusItem == "statusMain")
219 text = "[" + Util::getShortTimeString() + "] " + text;
220
221 gtk_statusbar_pop(GTK_STATUSBAR(getWidget(statusItem)), 0);
222 gtk_statusbar_push(GTK_STATUSBAR(getWidget(statusItem)), 0, text.c_str());
223 }
224 }
225
updateStatus_gui()226 void DownloadQueue::updateStatus_gui()
227 {
228 setStatus_gui(F_("Items: %1%", % currentItems), "statusItems");
229 setStatus_gui(F_("Size: %1%", % Util::formatBytes(currentSize)), "statusFileSize");
230 setStatus_gui(F_("Files: %1%", % totalItems), "statusFiles");
231 setStatus_gui(F_("Size: %1%", % Util::formatBytes(totalSize)), "statusTotalSize");
232 }
233
addFiles_gui(vector<StringMap> files,bool firstUpdate)234 void DownloadQueue::addFiles_gui(vector<StringMap> files, bool firstUpdate)
235 {
236 if (files.size() > 0 && currentDir == files[0]["Path"] &&
237 gtk_tree_selection_get_selected(dirSelection, NULL, NULL))
238 {
239 if (firstUpdate)
240 gtk_list_store_clear(fileStore);
241
242 gint sortColumn;
243 GtkSortType sortType;
244 gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(fileStore), &sortColumn, &sortType);
245 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(fileStore), GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, sortType);
246
247 for (vector<StringMap>::const_iterator it = files.begin(); it != files.end(); ++it)
248 addFile_gui(*it, FALSE);
249
250 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(fileStore), sortColumn, sortType);
251 gtk_tree_view_scroll_to_point(fileView.get(), 0, 0);
252 }
253 }
254
addFile_gui(StringMap params,bool updateDirs)255 void DownloadQueue::addFile_gui(StringMap params, bool updateDirs)
256 {
257 GtkTreeIter iter;
258 int64_t size = Util::toInt64(params["Size Sort"]);
259
260 if (gtk_tree_selection_get_selected(dirSelection, NULL, NULL) && currentDir == params["Path"])
261 {
262 ++currentItems;
263 currentSize += size;
264
265 gtk_list_store_append(fileStore, &iter);
266 gtk_list_store_set(fileStore, &iter,
267 fileView.col("Filename"), params["Filename"].c_str(),
268 fileView.col("Users"), params["Users"].c_str(),
269 fileView.col("Status"), params["Status"].c_str(),
270 fileView.col("Size"), params["Size"].c_str(),
271 fileView.col("Exact Size"), params["Exact Size"].c_str(),
272 fileView.col("Size Sort"), size,
273 fileView.col("Downloaded"), params["Downloaded"].c_str(),
274 fileView.col("Downloaded Sort"), Util::toInt64(params["Downloaded Sort"]),
275 fileView.col("Priority"), params["Priority"].c_str(),
276 fileView.col("Path"), params["Path"].c_str(),
277 fileView.col("Errors"), params["Errors"].c_str(),
278 fileView.col("Added"), params["Added"].c_str(),
279 fileView.col("TTH"), params["TTH"].c_str(),
280 fileView.col("Target"), params["Target"].c_str(),
281 -1);
282
283 if (BOOLSETTING(BOLD_QUEUE))
284 setBold_gui();
285 }
286
287 if (updateDirs)
288 {
289 ++totalItems;
290 totalSize += size;
291
292 // Ensure root node
293 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dirStore), &iter))
294 {
295 gtk_tree_store_append(dirStore, &iter, NULL);
296 gtk_tree_store_set(dirStore, &iter,
297 dirView.col("Dir"), "/",
298 dirView.col("Path"), "/",
299 dirView.col("File Count"), 0,
300 -1);
301 }
302
303 if (params["Path"].length() > 1)
304 addDir_gui(params["Path"].substr(1), &iter);
305 }
306
307 updateStatus_gui();
308 }
309
addDir_gui(const string & path,GtkTreeIter * parent)310 void DownloadQueue::addDir_gui(const string &path, GtkTreeIter *parent)
311 {
312 if (path.empty() || parent == NULL)
313 return;
314
315 GtkTreeIter iter;
316 string::size_type i = path.find_first_of(PATH_SEPARATOR);
317 const string &dir = path.substr(0, i);
318 const string &fullpath = dirView.getString(parent, "Path") + dir + PATH_SEPARATOR_STR;
319 bool valid = gtk_tree_model_iter_children(GTK_TREE_MODEL(dirStore), &iter, parent);
320
321 while (valid)
322 {
323 if (dir == dirView.getString(&iter, "Dir"))
324 {
325 addDir_gui(path.substr(i + 1), &iter);
326
327 if (fullpath == dirView.getString(parent, "Path") + path)
328 {
329 int count = dirView.getValue<gint>(&iter, "File Count");
330 gtk_tree_store_set(dirStore, &iter, dirView.col("File Count"), ++count, -1);
331 }
332
333 return;
334 }
335 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(dirStore), &iter);
336 }
337
338 gtk_tree_store_append(dirStore, &iter, parent);
339 gtk_tree_store_set(dirStore, &iter,
340 dirView.col("Dir"), dir.c_str(),
341 dirView.col("Path"), fullpath.c_str(),
342 dirView.col("File Count"), 0,
343 -1);
344
345 GtkTreePath *treePath = gtk_tree_model_get_path(GTK_TREE_MODEL(dirStore), parent);
346 gtk_tree_view_expand_row(dirView.get(), treePath, FALSE);
347 gtk_tree_path_free(treePath);
348
349 if (fullpath == dirView.getString(parent, "Path") + path)
350 {
351 int count = dirView.getValue<gint>(&iter, "File Count");
352 gtk_tree_store_set(dirStore, &iter, dirView.col("File Count"), ++count, -1);
353 }
354
355 addDir_gui(path.substr(i + 1), &iter);
356 }
357
updateFile_gui(StringMap params)358 void DownloadQueue::updateFile_gui(StringMap params)
359 {
360 if (gtk_tree_selection_get_selected(dirSelection, NULL, NULL) && currentDir == params["Path"])
361 {
362 GtkTreeIter iter;
363 GtkTreeModel *m = GTK_TREE_MODEL(fileStore);
364 bool valid = gtk_tree_model_get_iter_first(m, &iter);
365
366 while (valid)
367 {
368 if (fileView.getString(&iter, "Target") == params["Target"])
369 {
370 gtk_list_store_set(fileStore, &iter,
371 fileView.col("Filename"), params["Filename"].c_str(),
372 fileView.col("Users"), params["Users"].c_str(),
373 fileView.col("Status"), params["Status"].c_str(),
374 fileView.col("Size"), params["Size"].c_str(),
375 fileView.col("Exact Size"), params["Exact Size"].c_str(),
376 fileView.col("Size Sort"), Util::toInt64(params["Size Sort"]),
377 fileView.col("Downloaded"), params["Downloaded"].c_str(),
378 fileView.col("Downloaded Sort"), Util::toInt64(params["Downloaded Sort"]),
379 fileView.col("Priority"), params["Priority"].c_str(),
380 fileView.col("Path"), params["Path"].c_str(),
381 fileView.col("Errors"), params["Errors"].c_str(),
382 fileView.col("Added"), params["Added"].c_str(),
383 fileView.col("TTH"), params["TTH"].c_str(),
384 fileView.col("Target"), params["Target"].c_str(),
385 -1);
386 return;
387 }
388 valid = gtk_tree_model_iter_next(m, &iter);
389 }
390 }
391 }
392
removeFile_gui(string target,int64_t size)393 void DownloadQueue::removeFile_gui(string target, int64_t size)
394 {
395 GtkTreeIter iter;
396 bool valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(fileStore), &iter);
397 string path = Util::getFilePath(target);
398
399 while (valid)
400 {
401 if (target == fileView.getString(&iter, "Target"))
402 {
403 --currentItems;
404 currentSize -= size;
405 gtk_list_store_remove(fileStore, &iter);
406 break;
407 }
408 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(fileStore), &iter);
409 }
410
411 --totalItems;
412 totalSize -= size;
413
414 if (path.length() > 1 && gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dirStore), &iter))
415 removeDir_gui(path.substr(1), &iter);
416
417 updateStatus_gui();
418
419 if (BOOLSETTING(BOLD_QUEUE))
420 setBold_gui();
421 }
422
removeDir_gui(const string & path,GtkTreeIter * parent)423 void DownloadQueue::removeDir_gui(const string &path, GtkTreeIter *parent)
424 {
425 if (path.empty() || parent == NULL)
426 return;
427
428 GtkTreeIter iter;
429 string curPath;
430 int count = 0;
431 string::size_type i = path.find_first_of(PATH_SEPARATOR);
432 string dir = path.substr(0, i);
433 string fullpath = dirView.getString(parent, "Path") + path;
434 bool valid = gtk_tree_model_iter_children(GTK_TREE_MODEL(dirStore), &iter, parent);
435
436 while (valid)
437 {
438 if (dir == dirView.getString(&iter, "Dir"))
439 {
440 removeDir_gui(path.substr(i + 1), &iter);
441
442 curPath = dirView.getString(&iter, "Path");
443 count = dirView.getValue<gint>(&iter, "File Count");
444 if (curPath == fullpath)
445 gtk_tree_store_set(dirStore, &iter, dirView.col("File Count"), --count, -1);
446
447 // No files in leaf node
448 if (count <= 0 && !gtk_tree_model_iter_has_child(GTK_TREE_MODEL(dirStore), &iter))
449 {
450 gtk_tree_store_remove(dirStore, &iter);
451 if (currentDir == curPath)
452 {
453 gtk_list_store_clear(fileStore);
454 currentDir.clear();
455 }
456 }
457
458 break;
459 }
460 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(dirStore), &iter);
461 }
462 }
463
updateFileView_gui()464 void DownloadQueue::updateFileView_gui()
465 {
466 GtkTreeIter iter;
467
468 if (gtk_tree_selection_get_selected(dirSelection, NULL, &iter))
469 {
470 string dir = dirView.getString(&iter, "Path");
471 if (dir != currentDir)
472 {
473 gtk_list_store_clear(fileStore);
474 currentDir = dir;
475 currentItems = 0;
476 currentSize = 0;
477
478 typedef Func1<DownloadQueue, string> F1;
479 F1 *func = new F1(this, &DownloadQueue::updateFileView_client, currentDir);
480 WulforManager::get()->dispatchClientFunc(func);
481 }
482 }
483 }
484
sendMessage_gui(string cid)485 void DownloadQueue::sendMessage_gui(string cid)
486 {
487 if (!cid.empty())
488 WulforManager::get()->getMainWindow()->addPrivateMessage_gui(cid);
489 }
490
onDirButtonPressed_gui(GtkWidget * widget,GdkEventButton * event,gpointer data)491 gboolean DownloadQueue::onDirButtonPressed_gui(GtkWidget *widget, GdkEventButton *event, gpointer data)
492 {
493 DownloadQueue *dq = (DownloadQueue *)data;
494 dq->dirPrevious = event->type;
495
496 return FALSE;
497 }
498
onDirButtonReleased_gui(GtkWidget * widget,GdkEventButton * event,gpointer data)499 gboolean DownloadQueue::onDirButtonReleased_gui(GtkWidget *widget, GdkEventButton *event, gpointer data)
500 {
501 DownloadQueue *dq = (DownloadQueue *)data;
502
503 if (dq->dirPrevious == GDK_BUTTON_PRESS && gtk_tree_selection_get_selected(dq->dirSelection, NULL, NULL))
504 {
505 if (event->button == 1)
506 {
507 dq->updateFileView_gui();
508 }
509 else if (event->button == 3)
510 {
511 dq->updateFileView_gui();
512 gtk_menu_popup(GTK_MENU(dq->getWidget("dirMenu")), NULL, NULL,
513 NULL, NULL, 0, gtk_get_current_event_time());
514 }
515 }
516
517 return FALSE;
518 }
519
onDirKeyReleased_gui(GtkWidget * widget,GdkEventKey * event,gpointer data)520 gboolean DownloadQueue::onDirKeyReleased_gui(GtkWidget *widget, GdkEventKey *event, gpointer data)
521 {
522 DownloadQueue *dq = (DownloadQueue *)data;
523 GtkTreeIter iter;
524
525 if (gtk_tree_selection_get_selected(dq->dirSelection, NULL, &iter))
526 {
527 if (event->keyval == GDK_Delete || event->keyval == GDK_BackSpace)
528 {
529 dq->onDirRemoveClicked_gui(NULL, data);
530 }
531 else if (event->keyval == GDK_Menu || (event->keyval == GDK_F10 && event->state & GDK_SHIFT_MASK))
532 {
533 gtk_menu_popup(GTK_MENU(dq->getWidget("dirMenu")), NULL, NULL,
534 NULL, NULL, 0, gtk_get_current_event_time());
535 }
536 else if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up ||
537 event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
538 {
539 dq->updateFileView_gui();
540 }
541 else if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter)
542 {
543 GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(dq->dirStore), &iter);
544 if (gtk_tree_view_row_expanded(dq->dirView.get(), path))
545 gtk_tree_view_collapse_row(dq->dirView.get(), path);
546 else
547 gtk_tree_view_expand_row(dq->dirView.get(), path, FALSE);
548 gtk_tree_path_free(path);
549 }
550 }
551
552 return FALSE;
553 }
554
onFileButtonPressed_gui(GtkWidget * widget,GdkEventButton * event,gpointer data)555 gboolean DownloadQueue::onFileButtonPressed_gui(GtkWidget *widget, GdkEventButton *event, gpointer data)
556 {
557 DownloadQueue *dq = (DownloadQueue *)data;
558
559 if (event->button == 3)
560 {
561 GtkTreePath *path;
562 if (gtk_tree_view_get_path_at_pos(dq->fileView.get(), (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL))
563 {
564 bool selected = gtk_tree_selection_path_is_selected(dq->fileSelection, path);
565 gtk_tree_path_free(path);
566
567 if (selected)
568 return TRUE;
569 }
570 }
571 return FALSE;
572 }
573
onFileButtonReleased_gui(GtkWidget * widget,GdkEventButton * event,gpointer data)574 gboolean DownloadQueue::onFileButtonReleased_gui(GtkWidget *widget, GdkEventButton *event, gpointer data)
575 {
576 DownloadQueue *dq = (DownloadQueue *)data;
577
578 if (event->button == 3 && event->type == GDK_BUTTON_RELEASE)
579 {
580 if (gtk_tree_selection_count_selected_rows(dq->fileSelection) > 0)
581 {
582 dq->buildDynamicMenu_gui();
583 gtk_menu_popup(GTK_MENU(dq->getWidget("fileMenu")), NULL, NULL,
584 NULL, NULL, 0, gtk_get_current_event_time());
585 return TRUE;
586 }
587 }
588 return FALSE;
589 }
590
onFileKeyReleased_gui(GtkWidget * widget,GdkEventKey * event,gpointer data)591 gboolean DownloadQueue::onFileKeyReleased_gui(GtkWidget *widget, GdkEventKey *event, gpointer data)
592 {
593 DownloadQueue *dq = (DownloadQueue *)data;
594 int count = gtk_tree_selection_count_selected_rows(dq->fileSelection);
595
596 if (count > 0)
597 {
598 if (event->keyval == GDK_Delete || event->keyval == GDK_BackSpace)
599 {
600 dq->onFileRemoveClicked_gui(NULL, data);
601 }
602 else if (event->keyval == GDK_Menu || (event->keyval == GDK_F10 && event->state & GDK_SHIFT_MASK))
603 {
604 dq->buildDynamicMenu_gui();
605 gtk_menu_popup(GTK_MENU(dq->getWidget("fileMenu")), NULL, NULL,
606 NULL, NULL, 0, gtk_get_current_event_time());
607 }
608 }
609
610 return FALSE;
611 }
612
onDirPriorityClicked_gui(GtkMenuItem * item,gpointer data)613 void DownloadQueue::onDirPriorityClicked_gui(GtkMenuItem *item, gpointer data)
614 {
615 DownloadQueue *dq = (DownloadQueue *)data;
616 GtkTreeIter iter;
617
618 if (gtk_tree_selection_get_selected(dq->dirSelection, NULL, &iter))
619 {
620 string path = dq->dirView.getString(&iter, "Path");
621 QueueItem::Priority priority;
622
623 if (item == GTK_MENU_ITEM(dq->getWidget("pausedPriorityItem")))
624 priority = QueueItem::PAUSED;
625 else if (item == GTK_MENU_ITEM(dq->getWidget("lowestPriorityItem")))
626 priority = QueueItem::LOWEST;
627 else if (item == GTK_MENU_ITEM(dq->getWidget("lowPrioritytem")))
628 priority = QueueItem::LOW;
629 else if (item == GTK_MENU_ITEM(dq->getWidget("highPriorityItem")))
630 priority = QueueItem::HIGH;
631 else if (item == GTK_MENU_ITEM(dq->getWidget("highestPriorityItem")))
632 priority = QueueItem::HIGHEST;
633 else
634 priority = QueueItem::NORMAL;
635
636 typedef Func2<DownloadQueue, string, QueueItem::Priority> F2;
637 F2 *func = new F2(dq, &DownloadQueue::setPriorityDir_client, path, priority);
638 WulforManager::get()->dispatchClientFunc(func);
639 }
640 }
641
onDirMoveClicked_gui(GtkMenuItem * menuItem,gpointer data)642 void DownloadQueue::onDirMoveClicked_gui(GtkMenuItem *menuItem, gpointer data)
643 {
644 DownloadQueue *dq = (DownloadQueue *)data;
645 GtkTreeIter iter;
646
647 if (gtk_tree_selection_get_selected(dq->dirSelection, NULL, &iter))
648 {
649 string path = Text::fromUtf8(dq->dirView.getString(&iter, "Path"));
650 GtkWidget *dialog = dq->getWidget("dirChooserDialog");
651 gtk_file_chooser_set_action(GTK_FILE_CHOOSER(dialog), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
652 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path.c_str());
653 int response = gtk_dialog_run(GTK_DIALOG(dialog));
654 gtk_widget_hide(dialog);
655
656 if (response == GTK_RESPONSE_OK)
657 {
658 gchar *temp = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
659 if (temp)
660 {
661 string target = Text::toUtf8(temp);
662 g_free(temp);
663
664 if (target[target.length() - 1] != PATH_SEPARATOR)
665 target += PATH_SEPARATOR;
666
667 typedef Func2<DownloadQueue, string, string> F2;
668 F2 *func = new F2(dq, &DownloadQueue::moveDir_client, path, target);
669 WulforManager::get()->dispatchClientFunc(func);
670 }
671 }
672 }
673 }
674
onDirRemoveClicked_gui(GtkMenuItem * menuitem,gpointer data)675 void DownloadQueue::onDirRemoveClicked_gui(GtkMenuItem *menuitem, gpointer data)
676 {
677 DownloadQueue *dq = (DownloadQueue *)data;
678 GtkTreeIter iter;
679
680 if (gtk_tree_selection_get_selected(dq->dirSelection, NULL, &iter))
681 {
682 string path = dq->dirView.getString(&iter, "Path");
683 gtk_list_store_clear(dq->fileStore);
684
685 typedef Func1<DownloadQueue, string> F1;
686 F1 *func = new F1(dq, &DownloadQueue::removeDir_client, path);
687 WulforManager::get()->dispatchClientFunc(func);
688 }
689 }
690
onFileSearchAlternatesClicked_gui(GtkMenuItem * item,gpointer data)691 void DownloadQueue::onFileSearchAlternatesClicked_gui(GtkMenuItem *item, gpointer data)
692 {
693 DownloadQueue *dq = (DownloadQueue *)data;
694 string tth;
695 GtkTreePath *path;
696 GtkTreeIter iter;
697 Search *s;
698 GList *list = gtk_tree_selection_get_selected_rows(dq->fileSelection, NULL);
699
700 for (GList *i = list; i; i = i->next)
701 {
702 path = (GtkTreePath *)i->data;
703 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dq->fileStore), &iter, path))
704 {
705 tth = dq->fileView.getString(&iter, "TTH");
706 if (!tth.empty())
707 {
708 s = WulforManager::get()->getMainWindow()->addSearch_gui();
709 s->putValue_gui(tth, 0, SearchManager::SIZE_DONTCARE, SearchManager::TYPE_TTH);
710 }
711 }
712 gtk_tree_path_free(path);
713 }
714 g_list_free(list);
715 }
716
onCopyMagnetClicked_gui(GtkMenuItem * item,gpointer data)717 void DownloadQueue::onCopyMagnetClicked_gui(GtkMenuItem* item, gpointer data)
718 {
719 DownloadQueue *dq = (DownloadQueue *)data;
720 GtkTreePath *path;
721 GtkTreeIter iter;
722 string magnets, magnet, filename, tth;
723 int64_t size;
724 GList *list = gtk_tree_selection_get_selected_rows(dq->fileSelection, NULL);
725
726 for (GList *i = list; i; i = i->next)
727 {
728 path = (GtkTreePath *)i->data;
729 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dq->fileStore), &iter, path))
730 {
731 filename = dq->fileView.getString(&iter, "Filename");
732 size = dq->fileView.getValue<int64_t>(&iter, "Size Sort");
733 tth = dq->fileView.getString(&iter, "TTH");
734 magnet = WulforUtil::makeMagnet(filename, size, tth);
735
736 if (!magnet.empty())
737 {
738 if (!magnets.empty())
739 magnets += '\n';
740 magnets += magnet;
741 }
742 }
743 gtk_tree_path_free(path);
744 }
745 g_list_free(list);
746
747 if (!magnets.empty())
748 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), magnets.c_str(), magnets.length());
749 }
750
onFileMoveClicked_gui(GtkMenuItem * menuItem,gpointer data)751 void DownloadQueue::onFileMoveClicked_gui(GtkMenuItem *menuItem, gpointer data)
752 {
753 DownloadQueue *dq = (DownloadQueue *)data;
754 typedef Func2<DownloadQueue, string, string> F2;
755 F2 *func;
756 string source;
757 GtkTreePath *path;
758 GtkTreeIter iter;
759 int count = gtk_tree_selection_count_selected_rows(dq->fileSelection);
760 GList *list = gtk_tree_selection_get_selected_rows(dq->fileSelection, NULL);
761 GtkWidget *dialog = dq->getWidget("dirChooserDialog");
762
763 if (gtk_tree_selection_get_selected(dq->dirSelection, NULL, &iter))
764 {
765 string filepath = Text::fromUtf8(dq->dirView.getString(&iter, "Path"));
766 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), filepath.c_str());
767 }
768
769 if (count == 1)
770 {
771 path = (GtkTreePath *)list->data;
772 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dq->fileStore), &iter, path))
773 {
774 string target = Text::fromUtf8(dq->fileView.getString(&iter, "Filename"));
775 gtk_file_chooser_set_action(GTK_FILE_CHOOSER(dialog), GTK_FILE_CHOOSER_ACTION_SAVE);
776 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), target.c_str());
777 int response = gtk_dialog_run(GTK_DIALOG(dialog));
778 gtk_widget_hide(dialog);
779
780 if (response == GTK_RESPONSE_OK)
781 {
782 gchar *tmp = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
783 if (tmp)
784 {
785 target = Text::toUtf8(tmp);
786 g_free(tmp);
787 source = dq->fileView.getString(&iter, "Target");
788 func = new F2(dq, &DownloadQueue::move_client, source, target);
789 WulforManager::get()->dispatchClientFunc(func);
790 }
791 }
792 }
793 gtk_tree_path_free(path);
794 }
795 else if (count > 1)
796 {
797 gtk_file_chooser_set_action(GTK_FILE_CHOOSER(dialog), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
798 int response = gtk_dialog_run(GTK_DIALOG(dialog));
799 gtk_widget_hide(dialog);
800
801 if (response == GTK_RESPONSE_OK)
802 {
803 gchar *tmp = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
804 if (tmp)
805 {
806 string filename;
807 string target = Text::toUtf8(tmp);
808 g_free(tmp);
809
810 if (target[target.length() - 1] != PATH_SEPARATOR)
811 target += PATH_SEPARATOR;
812
813 for (GList *i = list; i; i = i->next)
814 {
815 path = (GtkTreePath *)i->data;
816 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dq->fileStore), &iter, path))
817 {
818 source = dq->fileView.getString(&iter, "Target");
819 filename = dq->fileView.getString(&iter, "Filename");
820 func = new F2(dq, &DownloadQueue::move_client, source, target + filename);
821 WulforManager::get()->dispatchClientFunc(func);
822 }
823 gtk_tree_path_free(path);
824 }
825 }
826 }
827 }
828 g_list_free(list);
829 }
830
onFilePriorityClicked_gui(GtkMenuItem * item,gpointer data)831 void DownloadQueue::onFilePriorityClicked_gui(GtkMenuItem *item, gpointer data)
832 {
833 DownloadQueue *dq = (DownloadQueue *)data;
834 typedef Func2<DownloadQueue, string, QueueItem::Priority> F2;
835 F2 *func;
836 string target;
837 GtkTreePath *path;
838 GtkTreeIter iter;
839 QueueItem::Priority priority;
840 GList *list = gtk_tree_selection_get_selected_rows(dq->fileSelection, NULL);
841
842 for (GList *i = list; i; i = i->next)
843 {
844 path = (GtkTreePath *)i->data;
845 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dq->fileStore), &iter, path))
846 {
847 target = dq->fileView.getString(&iter, "Target");
848
849 if (item == GTK_MENU_ITEM(dq->getWidget("filePausedItem")))
850 priority = QueueItem::PAUSED;
851 else if (item == GTK_MENU_ITEM(dq->getWidget("fileLowestPriorityItem")))
852 priority = QueueItem::LOWEST;
853 else if (item == GTK_MENU_ITEM(dq->getWidget("fileLowPriorityItem")))
854 priority = QueueItem::LOW;
855 else if (item == GTK_MENU_ITEM(dq->getWidget("fileHighPriorityItem")))
856 priority = QueueItem::HIGH;
857 else if (item == GTK_MENU_ITEM(dq->getWidget("fileHighestPriorityItem")))
858 priority = QueueItem::HIGHEST;
859 else
860 priority = QueueItem::NORMAL;
861
862 func = new F2(dq, &DownloadQueue::setPriority_client, target, priority);
863 WulforManager::get()->dispatchClientFunc(func);
864 }
865 gtk_tree_path_free(path);
866 }
867 g_list_free(list);
868 }
869
onFileGetListClicked_gui(GtkMenuItem * item,gpointer data)870 void DownloadQueue::onFileGetListClicked_gui(GtkMenuItem *item, gpointer data)
871 {
872 DownloadQueue *dq = (DownloadQueue *)data;
873 typedef Func2<DownloadQueue, string, string> F2;
874 F2 *func;
875 string nick, target;
876 GtkTreePath *path;
877 GtkTreeIter iter;
878 GList *list = gtk_tree_selection_get_selected_rows(dq->fileSelection, NULL);
879
880 for (GList *i = list; i; i = i->next)
881 {
882 path = (GtkTreePath *)i->data;
883 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dq->fileStore), &iter, path))
884 {
885 target = dq->fileView.getString(&iter, "Target");
886 nick = WulforUtil::getTextFromMenu(item);
887
888 func = new F2(dq, &DownloadQueue::addList_client, target, nick);
889 WulforManager::get()->dispatchClientFunc(func);
890 }
891 gtk_tree_path_free(path);
892 }
893 g_list_free(list);
894 }
895
onFileSendPMClicked_gui(GtkMenuItem * item,gpointer data)896 void DownloadQueue::onFileSendPMClicked_gui(GtkMenuItem *item, gpointer data)
897 {
898 DownloadQueue *dq = (DownloadQueue *)data;
899 typedef Func2<DownloadQueue, string, string> F2;
900 F2 *func;
901 string nick, target;
902 GtkTreePath *path;
903 GtkTreeIter iter;
904 GList *list = gtk_tree_selection_get_selected_rows(dq->fileSelection, NULL);
905
906 for (GList *i = list; i; i = i->next)
907 {
908 path = (GtkTreePath *)i->data;
909 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dq->fileStore), &iter, path))
910 {
911 target = dq->fileView.getString(&iter, "Target");
912 nick = WulforUtil::getTextFromMenu(item);
913
914 func = new F2(dq, &DownloadQueue::sendMessage_client, target, nick);
915 WulforManager::get()->dispatchClientFunc(func);
916 }
917 gtk_tree_path_free(path);
918 }
919 g_list_free(list);
920 }
921
onFileReAddSourceClicked_gui(GtkMenuItem * item,gpointer data)922 void DownloadQueue::onFileReAddSourceClicked_gui(GtkMenuItem *item, gpointer data)
923 {
924 DownloadQueue *dq = (DownloadQueue *)data;
925 typedef Func2<DownloadQueue, string, string> F2;
926 F2 *func;
927 string nick, target;
928 GtkTreePath *path;
929 GtkTreeIter iter;
930 GList *list = gtk_tree_selection_get_selected_rows(dq->fileSelection, NULL);
931
932 for (GList *i = list; i; i = i->next)
933 {
934 path = (GtkTreePath *)i->data;
935 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dq->fileStore), &iter, path))
936 {
937 target = dq->fileView.getString(&iter, "Target");
938 nick = WulforUtil::getTextFromMenu(item);
939
940 func = new F2(dq, &DownloadQueue::reAddSource_client, target, nick);
941 WulforManager::get()->dispatchClientFunc(func);
942 }
943 gtk_tree_path_free(path);
944 }
945 g_list_free(list);
946 }
947
onFileRemoveSourceClicked_gui(GtkMenuItem * item,gpointer data)948 void DownloadQueue::onFileRemoveSourceClicked_gui(GtkMenuItem *item, gpointer data)
949 {
950 DownloadQueue *dq = (DownloadQueue *)data;
951 typedef Func2<DownloadQueue, string, string> F2;
952 F2 *func;
953 string nick, target;
954 GtkTreePath *path;
955 GtkTreeIter iter;
956 GList *list = gtk_tree_selection_get_selected_rows(dq->fileSelection, NULL);
957
958 for (GList *i = list; i; i = i->next)
959 {
960 path = (GtkTreePath *)i->data;
961 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dq->fileStore), &iter, path))
962 {
963 target = dq->fileView.getString(&iter, "Target");
964 nick = WulforUtil::getTextFromMenu(item);
965
966 func = new F2(dq, &DownloadQueue::removeSource_client, target, nick);
967 WulforManager::get()->dispatchClientFunc(func);
968 }
969 gtk_tree_path_free(path);
970 }
971 g_list_free(list);
972 }
973
onFileRemoveUserFromQueueClicked_gui(GtkMenuItem * item,gpointer data)974 void DownloadQueue::onFileRemoveUserFromQueueClicked_gui(GtkMenuItem *item, gpointer data)
975 {
976 DownloadQueue *dq = (DownloadQueue *)data;
977 typedef Func2<DownloadQueue, string, string> F2;
978 F2 *func;
979 string nick, target;
980 GtkTreePath *path;
981 GtkTreeIter iter;
982 GList *list = gtk_tree_selection_get_selected_rows(dq->fileSelection, NULL);
983
984 for (GList *i = list; i; i = i->next)
985 {
986 path = (GtkTreePath *)i->data;
987 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dq->fileStore), &iter, path))
988 {
989 target = dq->fileView.getString(&iter, "Target");
990 nick = WulforUtil::getTextFromMenu(item);
991
992 func = new F2(dq, &DownloadQueue::removeSources_client, target, nick);
993 WulforManager::get()->dispatchClientFunc(func);
994 }
995 gtk_tree_path_free(path);
996 }
997 g_list_free(list);
998 }
999
onFileRemoveClicked_gui(GtkMenuItem * menuitem,gpointer data)1000 void DownloadQueue::onFileRemoveClicked_gui(GtkMenuItem *menuitem, gpointer data)
1001 {
1002 DownloadQueue *dq = (DownloadQueue *)data;
1003 typedef Func1<DownloadQueue, string> F1;
1004 F1 *func;
1005 string target;
1006 GtkTreePath *path;
1007 GtkTreeIter iter;
1008 GList *list = gtk_tree_selection_get_selected_rows(dq->fileSelection, NULL);
1009
1010 for (GList *i = list; i; i = i->next)
1011 {
1012 path = (GtkTreePath *)i->data;
1013 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dq->fileStore), &iter, path))
1014 {
1015 target = dq->fileView.getString(&iter, "Target");
1016 func = new F1(dq, &DownloadQueue::remove_client, target);
1017 WulforManager::get()->dispatchClientFunc(func);
1018 }
1019 gtk_tree_path_free(path);
1020 }
1021 g_list_free(list);
1022 }
1023
buildList_client()1024 void DownloadQueue::buildList_client()
1025 {
1026 StringMap params;
1027 typedef Func2<DownloadQueue, StringMap, bool> F2;
1028 //F2 *func;
1029 const QueueItem::StringMap &ll = QueueManager::getInstance()->lockQueue();
1030
1031 for (QueueItem::StringMap::const_iterator it = ll.begin(); it != ll.end(); ++it)
1032 {
1033 params["Size Sort"] = Util::toString(it->second->getSize());
1034 params["Path"] = Util::getFilePath(*it->first);
1035
1036 addFile_gui(params, TRUE);
1037 //func = new F2(this, &DownloadQueue::addFile_gui, params, TRUE);
1038 //WulforManager::get()->dispatchGuiFunc(func);
1039 }
1040
1041 QueueManager::getInstance()->unlockQueue();
1042 }
1043
move_client(string source,string target)1044 void DownloadQueue::move_client(string source, string target)
1045 {
1046 if (!source.empty() && !target.empty())
1047 QueueManager::getInstance()->move(source, target);
1048 }
1049
moveDir_client(string source,string target)1050 void DownloadQueue::moveDir_client(string source, string target)
1051 {
1052 if (!source.empty() && !target.empty() && target[target.length() - 1] == PATH_SEPARATOR)
1053 {
1054 // Can't modify QueueItem::StringMap in the loop, so we have to queue them.
1055 vector<string> targets;
1056 string *file;
1057 const QueueItem::StringMap &ll = QueueManager::getInstance()->lockQueue();
1058
1059 for (QueueItem::StringMap::const_iterator it = ll.begin(); it != ll.end(); ++it)
1060 {
1061 file = it->first;
1062 if (file->length() >= source.length() && file->substr(0, source.length()) == source)
1063 targets.push_back(*file);
1064 }
1065 QueueManager::getInstance()->unlockQueue();
1066
1067 for (vector<string>::const_iterator it = targets.begin(); it != targets.end(); ++it)
1068 QueueManager::getInstance()->move(*it, target + it->substr(source.length()));
1069 }
1070 }
1071
setPriority_client(string target,QueueItem::Priority p)1072 void DownloadQueue::setPriority_client(string target, QueueItem::Priority p)
1073 {
1074 if (!target.empty())
1075 QueueManager::getInstance()->setPriority(target, p);
1076 }
1077
setPriorityDir_client(string path,QueueItem::Priority p)1078 void DownloadQueue::setPriorityDir_client(string path, QueueItem::Priority p)
1079 {
1080 if (!path.empty() && path[path.length() - 1] == PATH_SEPARATOR)
1081 {
1082 string *file;
1083 const QueueItem::StringMap &ll = QueueManager::getInstance()->lockQueue();
1084
1085 for (QueueItem::StringMap::const_iterator it = ll.begin(); it != ll.end(); ++it)
1086 {
1087 file = it->first;
1088 if (file->length() >= path.length() && file->substr(0, path.length()) == path)
1089 QueueManager::getInstance()->setPriority(*file, p);
1090 }
1091 QueueManager::getInstance()->unlockQueue();
1092 }
1093 }
1094
addList_client(string target,string nick)1095 void DownloadQueue::addList_client(string target, string nick)
1096 {
1097 try
1098 {
1099 if (!target.empty() && !nick.empty() && sources.find(target) != sources.end())
1100 {
1101 SourceIter it = sources[target].find(nick);
1102 if (it != sources[target].end())
1103 {
1104 UserPtr user = ClientManager::getInstance()->findUser(CID(it->second));
1105 if (user)
1106 QueueManager::getInstance()->addList(user, "", QueueItem::FLAG_CLIENT_VIEW);
1107 }
1108 }
1109 }
1110 catch (const Exception &e)
1111 {
1112 typedef Func2<DownloadQueue, string, string> F2;
1113 F2 *func = new F2(this, &DownloadQueue::setStatus_gui, e.getError(), "statusMain");
1114 WulforManager::get()->dispatchGuiFunc(func);
1115 }
1116 }
1117
sendMessage_client(string target,string nick)1118 void DownloadQueue::sendMessage_client(string target, string nick)
1119 {
1120 if (!target.empty() && !nick.empty() && sources.find(target) != sources.end())
1121 {
1122 SourceIter it = sources[target].find(nick);
1123 if (it != sources[target].end())
1124 {
1125 typedef Func1<DownloadQueue, string> F1;
1126 F1 *func = new F1(this, &DownloadQueue::sendMessage_gui, it->second);
1127 WulforManager::get()->dispatchGuiFunc(func);
1128 }
1129 }
1130 }
1131
reAddSource_client(string target,string nick)1132 void DownloadQueue::reAddSource_client(string target, string nick)
1133 {
1134 try
1135 {
1136 if (!target.empty() && !nick.empty() && badSources.find(target) != sources.end())
1137 {
1138 SourceIter it = badSources[target].find(nick);
1139 if (it != badSources[target].end())
1140 {
1141 UserPtr user = ClientManager::getInstance()->findUser(CID(it->second));
1142 if (user)
1143 QueueManager::getInstance()->readd(target, user, "");
1144 }
1145 }
1146 }
1147 catch (const Exception &e)
1148 {
1149 typedef Func2<DownloadQueue, string, string> F2;
1150 F2 *func = new F2(this, &DownloadQueue::setStatus_gui, e.getError(), "statusMain");
1151 WulforManager::get()->dispatchGuiFunc(func);
1152 }
1153 }
1154
removeSource_client(string target,string nick)1155 void DownloadQueue::removeSource_client(string target, string nick)
1156 {
1157 if (!target.empty() && !nick.empty() && sources.find(target) != sources.end())
1158 {
1159 SourceIter it = sources[target].find(nick);
1160 if (it != sources[target].end())
1161 {
1162 UserPtr user = ClientManager::getInstance()->findUser(CID(it->second));
1163 if (user)
1164 QueueManager::getInstance()->removeSource(target, user, QueueItem::Source::FLAG_REMOVED);
1165 }
1166 }
1167 }
1168
removeSources_client(string target,string nick)1169 void DownloadQueue::removeSources_client(string target, string nick)
1170 {
1171 if (!target.empty() && !nick.empty() && sources.find(target) != sources.end())
1172 {
1173 SourceIter it = sources[target].find(nick);
1174 if (it != sources[target].end())
1175 {
1176 UserPtr user = ClientManager::getInstance()->findUser(CID(it->second));
1177 if (user)
1178 QueueManager::getInstance()->removeSource(user, QueueItem::Source::FLAG_REMOVED);
1179 }
1180 }
1181 }
1182
remove_client(string target)1183 void DownloadQueue::remove_client(string target)
1184 {
1185 if (!target.empty())
1186 QueueManager::getInstance()->remove(target);
1187 }
1188
removeDir_client(string path)1189 void DownloadQueue::removeDir_client(string path)
1190 {
1191 if (!path.empty())
1192 {
1193 string *file;
1194 vector<string> targets;
1195 const QueueItem::StringMap &ll = QueueManager::getInstance()->lockQueue();
1196
1197 for (QueueItem::StringMap::const_iterator it = ll.begin(); it != ll.end(); ++it)
1198 {
1199 file = it->first;
1200 if (file->length() >= path.length() && file->substr(0, path.length()) == path)
1201 targets.push_back(*file);
1202 }
1203 QueueManager::getInstance()->unlockQueue();
1204
1205 for (vector<string>::const_iterator it = targets.begin(); it != targets.end(); ++it)
1206 QueueManager::getInstance()->remove(*it);
1207 }
1208 }
1209
updateFileView_client(string path)1210 void DownloadQueue::updateFileView_client(string path)
1211 {
1212 if (!path.empty())
1213 {
1214 vector<StringMap> files;
1215 const QueueItem::StringMap &ll = QueueManager::getInstance()->lockQueue();
1216
1217 for (QueueItem::StringMap::const_iterator it = ll.begin(); it != ll.end(); ++it)
1218 {
1219 if (it->first->length() >= path.length() && it->first->substr(0, it->first->rfind('/') + 1) == path)
1220 {
1221 StringMap params;
1222 getQueueParams_client(it->second, params);
1223 files.push_back(params);
1224 }
1225 }
1226 QueueManager::getInstance()->unlockQueue();
1227
1228 // Updating gui is smoother if we do it in large chunks.
1229 typedef Func2<DownloadQueue, vector<StringMap>, bool> F2;
1230 F2 *func = new F2(this, &DownloadQueue::addFiles_gui, files, TRUE);
1231 WulforManager::get()->dispatchGuiFunc(func);
1232 }
1233 }
1234
getQueueParams_client(QueueItem * item,StringMap & params)1235 void DownloadQueue::getQueueParams_client(QueueItem *item, StringMap ¶ms)
1236 {
1237 string nick;
1238 map<string, string> source;
1239 int online = 0;
1240 int totalSources = item->getSources().size();
1241
1242 params["Filename"] = item->getTargetFileName();
1243 params["Path"] = Util::getFilePath(item->getTarget());
1244 params["Target"] = item->getTarget();
1245
1246 params["Users"] = "";
1247 for (QueueItem::SourceConstIter it = item->getSources().begin(); it != item->getSources().end(); ++it)
1248 {
1249 if (it->getUser()->isOnline())
1250 ++online;
1251
1252 if (params["Users"].size() > 0)
1253 params["Users"] += ", ";
1254
1255 nick = WulforUtil::getNicks(it->getUser());
1256 source[nick] = it->getUser()->getCID().toBase32();
1257 params["Users"] += nick;
1258 }
1259 if (params["Users"].empty())
1260 params["Users"] = _("No users");
1261 sources[item->getTarget()] = source;
1262
1263 // Status
1264 if (item->isWaiting())
1265 params["Status"] = P_("%1% of %2% user online", "%1% of %2% users online", % online % totalSources, totalSources);
1266 else
1267 params["Status"] = _("Running...");
1268
1269 // Size
1270 params["Size Sort"] = Util::toString(item->getSize());
1271 if (item->getSize() < 0)
1272 {
1273 params["Size"] = _("Unknown");
1274 params["Exact Size"] = _("Unknown");
1275 }
1276 else
1277 {
1278 params["Size"] = Util::formatBytes(item->getSize());
1279 params["Exact Size"] = Util::formatExactSize(item->getSize());
1280 }
1281
1282 // Downloaded
1283 params["Downloaded Sort"] = Util::toString(item->getDownloadedBytes());
1284 if (item->getSize() > 0)
1285 {
1286 double percent = (double)item->getDownloadedBytes() * 100.0 / (double)item->getSize();
1287 params["Downloaded"] = Util::formatBytes(item->getDownloadedBytes()) + " (" + Util::toString(percent) + "%)";
1288 }
1289 else
1290 {
1291 params["Downloaded"] = "0 B (0.00%)";
1292 }
1293
1294 // Priority
1295 switch (item->getPriority())
1296 {
1297 case QueueItem::PAUSED:
1298 params["Priority"] = C_("Priority", "Paused");
1299 break;
1300 case QueueItem::LOWEST:
1301 params["Priority"] = C_("Priority", "Lowest");
1302 break;
1303 case QueueItem::LOW:
1304 params["Priority"] = C_("Priority", "Low");
1305 break;
1306 case QueueItem::HIGH:
1307 params["Priority"] = C_("Priority", "High");
1308 break;
1309 case QueueItem::HIGHEST:
1310 params["Priority"] = C_("Priority", "Highest");
1311 break;
1312 default:
1313 params["Priority"] = C_("Priority", "Normal");
1314 }
1315
1316 // Error
1317 source.clear();
1318 params["Errors"] = "";
1319 for (QueueItem::SourceConstIter it = item->getBadSources().begin(); it != item->getBadSources().end(); ++it)
1320 {
1321 nick = WulforUtil::getNicks(it->getUser());
1322 source[nick] = it->getUser()->getCID().toBase32();
1323
1324 if (!it->isSet(QueueItem::Source::FLAG_REMOVED))
1325 {
1326 if (params["Errors"].size() > 0)
1327 params["Errors"] += ", ";
1328 params["Errors"] += nick + " (";
1329
1330 if (it->isSet(QueueItem::Source::FLAG_FILE_NOT_AVAILABLE))
1331 params["Errors"] += _("File not available");
1332 else if (it->isSet(QueueItem::Source::FLAG_PASSIVE))
1333 params["Errors"] += _("Passive user");
1334 else if (it->isSet(QueueItem::Source::FLAG_CRC_FAILED))
1335 params["Errors"] += _("CRC32 inconsistency (SFV-Check)");
1336 else if (it->isSet(QueueItem::Source::FLAG_BAD_TREE))
1337 params["Errors"] += _("Full tree does not match TTH root");
1338 else if (it->isSet(QueueItem::Source::FLAG_SLOW_SOURCE))
1339 params["Errors"] += _("Source too slow");
1340 else if (it->isSet(QueueItem::Source::FLAG_NO_TTHF))
1341 params["Errors"] += _("Remote client does not fully support TTH - cannot download");
1342
1343 params["Errors"] += ")";
1344 }
1345 }
1346 if (params["Errors"].empty())
1347 params["Errors"] = _("No errors");
1348 badSources[item->getTarget()] = source;
1349
1350 // Added
1351 params["Added"] = Util::formatTime("%Y-%m-%d %H:%M", item->getAdded());
1352
1353 // TTH
1354 params["TTH"] = item->getTTH().toBase32();
1355 }
1356
on(QueueManagerListener::Added,QueueItem * item)1357 void DownloadQueue::on(QueueManagerListener::Added, QueueItem *item) throw()
1358 {
1359 StringMap params;
1360 getQueueParams_client(item, params);
1361
1362 typedef Func2<DownloadQueue, StringMap, bool> F2;
1363 F2 *func = new F2(this, &DownloadQueue::addFile_gui, params, TRUE);
1364 WulforManager::get()->dispatchGuiFunc(func);
1365 }
1366
on(QueueManagerListener::Moved,QueueItem * item,const string & oldTarget)1367 void DownloadQueue::on(QueueManagerListener::Moved, QueueItem *item, const string &oldTarget) throw()
1368 {
1369 // Remove the old file
1370 typedef Func2<DownloadQueue, string, int64_t> F2a;
1371 F2a *func1 = new F2a(this, &DownloadQueue::removeFile_gui, oldTarget, item->getSize());
1372 WulforManager::get()->dispatchGuiFunc(func1);
1373
1374 // Add the new file
1375 StringMap params;
1376 getQueueParams_client(item, params);
1377
1378 typedef Func2<DownloadQueue, StringMap, bool> F2b;
1379 F2b *func2 = new F2b(this, &DownloadQueue::addFile_gui, params, TRUE);
1380 WulforManager::get()->dispatchGuiFunc(func2);
1381 }
1382
on(QueueManagerListener::Removed,QueueItem * item)1383 void DownloadQueue::on(QueueManagerListener::Removed, QueueItem *item) throw()
1384 {
1385 typedef Func2<DownloadQueue, string, int64_t> F2;
1386 F2 *func = new F2(this, &DownloadQueue::removeFile_gui, item->getTarget(), item->getSize());
1387 WulforManager::get()->dispatchGuiFunc(func);
1388 }
1389
on(QueueManagerListener::SourcesUpdated,QueueItem * item)1390 void DownloadQueue::on(QueueManagerListener::SourcesUpdated, QueueItem *item) throw()
1391 {
1392 StringMap params;
1393 getQueueParams_client(item, params);
1394
1395 typedef Func1<DownloadQueue, StringMap> F1;
1396 F1 *func = new F1(this, &DownloadQueue::updateFile_gui, params);
1397 WulforManager::get()->dispatchGuiFunc(func);
1398 }
1399
on(QueueManagerListener::StatusUpdated,QueueItem * item)1400 void DownloadQueue::on(QueueManagerListener::StatusUpdated, QueueItem *item) throw()
1401 {
1402 StringMap params;
1403 getQueueParams_client(item, params);
1404
1405 typedef Func1<DownloadQueue, StringMap> F1;
1406 F1 *func = new F1(this, &DownloadQueue::updateFile_gui, params);
1407 WulforManager::get()->dispatchGuiFunc(func);
1408 }
1409