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 "sharebrowser.hh"
23 #include <iostream>
24 #include <dcpp/FavoriteManager.h>
25 #include <dcpp/ShareManager.h>
26 #include <dcpp/Text.h>
27 #include <dcpp/ADLSearch.h>
28 #include "search.hh"
29 #include "settingsmanager.hh"
30 #include "UserCommandMenu.hh"
31 #include "wulformanager.hh"
32 #include "WulforUtil.hh"
33
34 using namespace std;
35 using namespace dcpp;
36
ShareBrowser(UserPtr user,const string & file,const string & initialDirectory,bool full)37 ShareBrowser::ShareBrowser(UserPtr user, const string &file, const string &initialDirectory, bool full):
38 BookEntry(Entry::SHARE_BROWSER, _("List: ") + WulforUtil::getNicks(user, ""), "sharebrowser.ui", user->getCID().toBase32()),
39 user(user),
40 file(file),
41 initialDirectory(initialDirectory),
42 listing(HintedUser(user, "")),
43 shareSize(0),
44 currentSize(0),
45 shareItems(0),
46 currentItems(0),
47 updateFileView(TRUE),
48 skipHits(0),
49 full(full)
50 {
51 #if !GTK_CHECK_VERSION(3,0,0)
52 gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR(getWidget("mainStatus")),FALSE);
53 gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR(getWidget("itemsStatus")),FALSE);
54 gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR(getWidget("sizeStatus")),FALSE);
55 gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR(getWidget("filesStatus")),FALSE);
56 gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR(getWidget("totalStatus")),FALSE);
57 #endif
58
59 // Use the nick from the file name in case the user is offline and core only returns CID
60 nick = WulforUtil::getNicks(user, "");
61 if (nick.find(user->getCID().toBase32(), 1) != string::npos)
62 {
63 string name = Util::getFileName(file);
64 string::size_type loc = name.find('.');
65 nick = name.substr(0, loc);
66 setLabel_gui(_("List: ") + nick);
67 }
68
69 // Configure the dialogs
70 File::ensureDirectory(SETTING(DOWNLOAD_DIRECTORY));
71 gtk_dialog_set_alternative_button_order(GTK_DIALOG(getWidget("findDialog")), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1);
72 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(getWidget("dirChooserDialog")), Text::fromUtf8(SETTING(DOWNLOAD_DIRECTORY)).c_str());
73 gtk_dialog_set_alternative_button_order(GTK_DIALOG(getWidget("dirChooserDialog")), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1);
74
75 // menu
76 g_object_ref_sink(getWidget("dirMenu"));
77 g_object_ref_sink(getWidget("fileMenu"));
78
79 // Set the pane position
80 gtk_paned_set_position(GTK_PANED(getWidget("pane")), WGETI("sharebrowser-pane-position"));
81
82 // Initialize the file TreeView
83 fileView.setView(GTK_TREE_VIEW(getWidget("fileView")), true, "sharebrowser");
84 fileView.insertColumn(_("Filename"), G_TYPE_STRING, TreeView::ICON_STRING, 400, "Icon");
85 fileView.insertColumn(_("Size"), G_TYPE_STRING, TreeView::STRINGR, 80);
86 fileView.insertColumn(_("Type"), G_TYPE_STRING, TreeView::STRING, 50);
87 fileView.insertColumn(_("TTH"), G_TYPE_STRING, TreeView::STRING, 150);
88 fileView.insertColumn(_("Exact Size"), G_TYPE_STRING, TreeView::STRINGR, 105);
89 fileView.insertColumn(_("Bitrate"), G_TYPE_STRING, TreeView::STRING, 50);
90 fileView.insertColumn(_("Resolution"), G_TYPE_STRING, TreeView::STRING, 70);
91 fileView.insertColumn(_("Video"), G_TYPE_STRING, TreeView::STRING, 100);
92 fileView.insertColumn(_("Audio"), G_TYPE_STRING, TreeView::STRING, 70);
93 fileView.insertColumn(_("Downloaded"), G_TYPE_STRING, TreeView::STRING, 70);
94 fileView.insertColumn(_("Shared"), G_TYPE_STRING, TreeView::STRING, 70);
95 fileView.insertHiddenColumn("DL File", G_TYPE_POINTER);
96 fileView.insertHiddenColumn("Icon", G_TYPE_STRING);
97 fileView.insertHiddenColumn("Size Order", G_TYPE_INT64);
98 fileView.insertHiddenColumn("File Order", G_TYPE_STRING);
99 fileView.insertHiddenColumn("Shared Order", G_TYPE_INT64);
100 fileView.finalize();
101 fileStore = gtk_list_store_newv(fileView.getColCount(), fileView.getGTypes());
102 gtk_tree_view_set_model(fileView.get(), GTK_TREE_MODEL(fileStore));
103 g_object_unref(fileStore);
104 fileSelection = gtk_tree_view_get_selection(fileView.get());
105 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(fileView.get()), GTK_SELECTION_MULTIPLE);
106 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(fileStore), fileView.col("File Order"), GTK_SORT_ASCENDING);
107 gtk_tree_view_column_set_sort_indicator(gtk_tree_view_get_column(fileView.get(), fileView.col(_("Filename"))), TRUE);
108 gtk_tree_view_set_fixed_height_mode(fileView.get(), TRUE);
109 fileView.setSortColumn_gui(_("Filename"), "File Order");
110 fileView.setSortColumn_gui(_("Size"), "Size Order");
111 fileView.setSortColumn_gui(_("Exact Size"), "Size Order");
112 fileView.setSortColumn_gui(_("Shared"), "Shared Order");
113
114 // Initialize the directory treeview
115 dirView.setView(GTK_TREE_VIEW(getWidget("dirView")));
116 dirView.insertColumn(_("Dir"), G_TYPE_STRING, TreeView::ICON_STRING, -1, "Icon");
117 dirView.insertHiddenColumn("DL Dir", G_TYPE_POINTER);
118 dirView.insertHiddenColumn("Icon", G_TYPE_STRING);
119 dirView.finalize();
120 dirStore = gtk_tree_store_newv(dirView.getColCount(), dirView.getGTypes());
121 gtk_tree_view_set_model(dirView.get(), GTK_TREE_MODEL(dirStore));
122 g_object_unref(dirStore);
123 dirSelection = gtk_tree_view_get_selection(dirView.get());
124 gtk_tree_view_set_enable_tree_lines(dirView.get(), TRUE);
125
126 // Initialize the user command menus
127 fileUserCommandMenu = new UserCommandMenu(getWidget("fileUserCommandMenu"), ::UserCommand::CONTEXT_FILELIST);
128 addChild(fileUserCommandMenu);
129 dirUserCommandMenu = new UserCommandMenu(getWidget("dirUserCommandMenu"), ::UserCommand::CONTEXT_FILELIST);
130 addChild(dirUserCommandMenu);
131
132 // Connect the signals to their callback functions.
133 g_signal_connect(fileView.get(), "button-press-event", G_CALLBACK(onButtonPressed_gui), (gpointer)this);
134 g_signal_connect(fileView.get(), "button-release-event", G_CALLBACK(onFileButtonReleased_gui), (gpointer)this);
135 g_signal_connect(fileView.get(), "key-release-event", G_CALLBACK(onFileKeyReleased_gui), (gpointer)this);
136 g_signal_connect(dirView.get(), "button-press-event", G_CALLBACK(onButtonPressed_gui), (gpointer)this);
137 g_signal_connect(dirView.get(), "button-release-event", G_CALLBACK(onDirButtonReleased_gui), (gpointer)this);
138 g_signal_connect(dirView.get(), "key-release-event", G_CALLBACK(onDirKeyReleased_gui), (gpointer)this);
139 g_signal_connect(getWidget("matchButton"), "clicked", G_CALLBACK(onMatchButtonClicked_gui), (gpointer)this);
140 g_signal_connect(getWidget("findButton"), "clicked", G_CALLBACK(onFindButtonClicked_gui), (gpointer)this);
141 g_signal_connect(getWidget("nextButton"), "clicked", G_CALLBACK(onNextButtonClicked_gui), (gpointer)this);
142 g_signal_connect(getWidget("dirDownloadItem"), "activate", G_CALLBACK(onDownloadDirClicked_gui), (gpointer)this);
143 g_signal_connect(getWidget("fileDownloadItem"), "activate", G_CALLBACK(onDownloadClicked_gui), (gpointer)this);
144 g_signal_connect(getWidget("searchForAlternatesItem"), "activate", G_CALLBACK(onSearchAlternatesClicked_gui), (gpointer)this);
145 g_signal_connect(getWidget("copyMagnetItem"), "activate", G_CALLBACK(onCopyMagnetClicked_gui), (gpointer)this);
146 g_signal_connect(getWidget("copyPictureItem"), "activate", G_CALLBACK(onCopyPictureClicked_gui), (gpointer)this);
147
148 #if !GLIB_CHECK_VERSION(2,32,0)
149 GError *error = NULL;
150 g_thread_create(threadLoad_list, (gpointer)this, FALSE, &error);
151 if (error)
152 {
153 cerr << "Unable to create filelist loader thread: " << error->message << endl;
154 g_error_free(error);
155 }
156 #else
157 g_thread_new("filelistloader",threadLoad_list, (gpointer)this);
158 #endif
159 }
160
~ShareBrowser()161 ShareBrowser::~ShareBrowser()
162 {
163 // Save the pane position
164 int panePosition = gtk_paned_get_position(GTK_PANED(getWidget("pane")));
165 WSET("sharebrowser-pane-position", panePosition);
166
167 gtk_widget_destroy(getWidget("findDialog"));
168 gtk_widget_destroy(getWidget("dirChooserDialog"));
169
170 g_object_unref(getWidget("dirMenu"));
171 g_object_unref(getWidget("fileMenu"));
172 }
isFull()173 bool ShareBrowser::isFull()
174 {
175 return full;
176 }
177
show()178 void ShareBrowser::show()
179 {
180 updateStatus_gui();
181 WulforManager::get()->getMainWindow()->setMainStatus_gui(_("File list loaded"));
182 }
183
threadLoad_list(gpointer data)184 gpointer ShareBrowser::threadLoad_list(gpointer data)
185 {
186 ShareBrowser *man = (ShareBrowser *)data;
187 man->setStatus_gui("mainStatus", _("Parse and build tree..."));
188 if (man->buildList_gui())
189 man->setStatus_gui("mainStatus", _("Done"));
190 return NULL;
191 }
192
buildList_gui()193 bool ShareBrowser::buildList_gui()
194 {
195 // Load the xml file containing the share list.
196 try
197 {
198 // Set name of root entry to user nick.
199 listing.getRoot()->setName(nick);
200
201 if (full) {
202 listing.loadFile(file);
203
204 // Search ADL
205 ADLSearchManager::getInstance()->matchListing(listing);
206 }
207 // Add entries to dir tree view starting with the root entry.
208 buildDirs_gui(listing.getRoot(), NULL);
209
210 if (full) {
211 openDir_gui(initialDirectory);
212 }
213 }
214 catch (const Exception &e)
215 {
216 setStatus_gui("mainStatus", _("Unable to load file list: ") + e.getError());
217 return FALSE;
218 }
219 return TRUE;
220 }
221
222 /*
223 * Selects the directory in the tree view, and shows that directory's contents.
224 */
openDir_gui(const string & dir)225 void ShareBrowser::openDir_gui(const string &dir)
226 {
227 GtkTreeIter iter;
228
229 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dirStore), &iter))
230 {
231 GtkTreePath *path;
232 DirectoryListing::Directory *directory;
233
234 if (findDir_gui(dir, &iter))
235 path = gtk_tree_model_get_path(GTK_TREE_MODEL(dirStore), &iter);
236 else
237 path = gtk_tree_path_new_first();
238
239 directory = dirView.getValue<gpointer, DirectoryListing::Directory *>(&iter, "DL Dir");
240
241 gtk_tree_view_expand_to_path(dirView.get(), path);
242 gtk_tree_view_scroll_to_cell(dirView.get(), path, gtk_tree_view_get_column(dirView.get(), 0), FALSE, 0.0, 0.0);
243 gtk_tree_view_set_cursor(dirView.get(), path, NULL, FALSE);
244 gtk_tree_path_free(path);
245
246 updateFiles_gui(directory);
247 }
248 }
249
findDir_gui(const string & dir,GtkTreeIter * parent)250 bool ShareBrowser::findDir_gui(const string &dir, GtkTreeIter *parent)
251 {
252 if (dir.empty())
253 return TRUE;
254
255 string::size_type i = dir.find_first_of(PATH_SEPARATOR);
256 const string ¤t = dir.substr(0, i);
257 GtkTreeIter iter;
258 bool valid = gtk_tree_model_iter_children(GTK_TREE_MODEL(dirStore), &iter, parent);
259
260 while (valid)
261 {
262 if (dirView.getString(&iter, _("Dir")) == current)
263 {
264 *parent = iter;
265 return findDir_gui(dir.substr(i + 1), parent);
266 }
267
268 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(dirStore), &iter);
269 }
270
271 return FALSE;
272 }
273
buildDirs_gui(DirectoryListing::Directory * dir,GtkTreeIter * iter)274 void ShareBrowser::buildDirs_gui(DirectoryListing::Directory *dir, GtkTreeIter *iter)
275 {
276 DirectoryListing::Directory::Iter it;
277 DirectoryListing::File::Iter file;
278 GtkTreeIter newIter;
279
280 gtk_tree_store_append(dirStore, &newIter, iter);
281 gtk_tree_store_set(dirStore, &newIter, dirView.col(_("Dir")), dir->getName().c_str(), -1);
282
283 gtk_tree_store_set(dirStore, &newIter,
284 dirView.col("DL Dir"), (gpointer)dir,
285 dirView.col("Icon"), "icon-directory",
286 -1);
287
288 for (file = dir->files.begin(); file != dir->files.end(); ++file)
289 {
290 shareItems++;
291 shareSize += (*file)->getSize();
292 }
293
294 // Recursive call for all subdirs of current dir.
295 std::sort(dir->directories.begin(), dir->directories.end(), DirectoryListing::Directory::DirSort());
296 for (it = dir->directories.begin(); it != dir->directories.end(); ++it)
297 buildDirs_gui(*it, &newIter);
298 }
299
updateFiles_gui(DirectoryListing::Directory * dir)300 void ShareBrowser::updateFiles_gui(DirectoryListing::Directory *dir)
301 {
302 DirectoryListing::Directory::List *dirs = &(dir->directories);
303 DirectoryListing::Directory::Iter it_dir;
304 DirectoryListing::File::List *files = &(dir->files);
305 DirectoryListing::File::Iter it_file;
306 GtkTreeIter iter;
307 int64_t size;
308 gint sortColumn;
309 GtkSortType sortType;
310
311 currentSize = 0;
312 currentItems = 0;
313
314 gtk_list_store_clear(fileStore);
315
316 gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(fileStore), &sortColumn, &sortType);
317 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(fileStore), GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, sortType);
318
319 // Add directories to the store.
320 for (it_dir = dirs->begin(); it_dir != dirs->end(); ++it_dir)
321 {
322 gtk_list_store_append(fileStore, &iter);
323 gtk_list_store_set(fileStore, &iter,
324 fileView.col(_("Filename")), Util::getFileName((*it_dir)->getName()).c_str(),
325 fileView.col("File Order"), Util::getFileName("d"+(*it_dir)->getName()).c_str(),
326 -1);
327
328 size = (*it_dir)->getTotalSize(false);
329 gtk_list_store_set(fileStore, &iter,
330 fileView.col("Icon"), "icon-directory",
331 fileView.col(_("Size")), Util::formatBytes(size).c_str(),
332 fileView.col(_("Exact Size")), Util::formatExactSize(size).c_str(),
333 fileView.col("Size Order"), size,
334 fileView.col(_("Type")), _("Directory"),
335 fileView.col("DL File"), (gpointer)(*it_dir),
336 fileView.col(_("TTH")), "",
337 -1);
338
339 currentSize += size;
340 currentItems++;
341 }
342
343 // Add files to the store.
344 for (it_file = files->begin(); it_file != files->end(); ++it_file)
345 {
346 gtk_list_store_append(fileStore, &iter);
347
348 // If ext is empty we cannot do substr on it.
349 string ext = Util::getFileExt((*it_file)->getName());
350 if(!ext.empty())
351 ext = ext.substr(1);
352
353 gtk_list_store_set(fileStore, &iter,
354 fileView.col(_("Filename")), Util::getFileName((*it_file)->getName()).c_str(),
355 fileView.col(_("Type")), ext.c_str(),
356 fileView.col("File Order"), Util::getFileName("f"+(*it_file)->getName()).c_str(),
357 -1);
358
359 size = (*it_file)->getSize();
360 gtk_list_store_set(fileStore, &iter,
361 fileView.col("Icon"), "icon-file",
362 fileView.col(_("Size")), Util::formatBytes(size).c_str(),
363 fileView.col(_("Exact Size")), Util::formatExactSize(size).c_str(),
364 fileView.col("Size Order"), size,
365 fileView.col("DL File"), (gpointer)(*it_file),
366 fileView.col(_("TTH")), (*it_file)->getTTH().toBase32().c_str(),
367 fileView.col(_("Bitrate")), ((*it_file)->mediaInfo.bitrate) ? (Util::toString((*it_file)->mediaInfo.bitrate)).c_str() : Util::emptyString.c_str(),
368 fileView.col(_("Resolution")), !(*it_file)->mediaInfo.video_info.empty() ? (*it_file)->mediaInfo.resolution.c_str() : Util::emptyString.c_str(),
369 fileView.col(_("Video")), (*it_file)->mediaInfo.video_info.c_str(),
370 fileView.col(_("Audio")), (*it_file)->mediaInfo.audio_info.c_str(),
371 fileView.col(_("Downloaded")), (Util::toString((*it_file)->getHit())).c_str(),
372 fileView.col(_("Shared")), (Util::formatTime("%Y-%m-%d %H:%M", (*it_file)->getTS())).c_str(),
373 fileView.col("Shared Order"), (*it_file)->getTS(),
374 -1);
375
376 currentSize += size;
377 currentItems++;
378 }
379
380 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(fileStore), sortColumn, sortType);
381 //gtk_tree_view_scroll_to_point(fileView.get(), 0, 0);
382 updateStatus_gui();
383 updateFileView = TRUE;
384 }
385
updateStatus_gui()386 void ShareBrowser::updateStatus_gui()
387 {
388 string items, files, size, total;
389 files = _("Files: ") + Util::toString(shareItems);
390 total = _("Total: ") + Util::formatBytes(shareSize);
391
392 if (gtk_tree_selection_get_selected(dirSelection, NULL, NULL))
393 {
394 items = _("Items: ") + Util::toString(currentItems);
395 size = _("Size: ") + Util::formatBytes(currentSize);
396 }
397 else
398 {
399 items = _("Items: 0");
400 size = _("Size: 0 B");
401 }
402
403 setStatus_gui("itemsStatus", items);
404 setStatus_gui("sizeStatus", size);
405 setStatus_gui("filesStatus", files);
406 setStatus_gui("totalStatus", total);
407 }
408
setStatus_gui(string statusBar,string msg)409 void ShareBrowser::setStatus_gui(string statusBar, string msg)
410 {
411 gtk_statusbar_pop(GTK_STATUSBAR(getWidget(statusBar)), 0);
412 gtk_statusbar_push(GTK_STATUSBAR(getWidget(statusBar)), 0, msg.c_str());
413 }
414
fileViewSelected_gui()415 void ShareBrowser::fileViewSelected_gui()
416 {
417 gpointer ptr;
418 string fileOrder;
419 GtkTreeIter iter, parentIter;
420 GtkTreeModel *m = GTK_TREE_MODEL(fileStore);
421 GList *list = gtk_tree_selection_get_selected_rows(fileSelection, NULL);
422 GtkTreePath *path = (GtkTreePath *)g_list_nth_data(list, 0);
423
424 if (gtk_tree_model_get_iter(m, &iter, path))
425 {
426 ptr = fileView.getValue<gpointer>(&iter, "DL File");
427 fileOrder = fileView.getString(&iter, "File Order");
428 int64_t filesize = fileView.getValue<int64_t>(&iter, "Size Order");
429
430 if (fileOrder[0] == 'd' && gtk_tree_selection_get_selected(dirSelection, NULL, &parentIter))
431 {
432 m = GTK_TREE_MODEL(dirStore);
433 gboolean valid = gtk_tree_model_iter_children(m, &iter, &parentIter);
434
435 while (valid && ptr != dirView.getValue<gpointer>(&iter, "DL Dir"))
436 valid = gtk_tree_model_iter_next(m, &iter);
437
438 if (!full && !filesize) {
439 typedef Func1<ShareBrowser, DirectoryListing::Directory*> F1;
440 F1 *func = new F1(this,&ShareBrowser::downloadChangedDir,
441 (DirectoryListing::Directory *)dirView.getValue<gpointer>(&iter, "DL Dir"));
442 WulforManager::get()->dispatchClientFunc(func);
443 path = gtk_tree_model_get_path(m, &iter);
444 gtk_tree_view_expand_to_path(dirView.get(), path);
445 gtk_tree_view_set_cursor(dirView.get(), path, NULL, FALSE);
446 } else {
447 updateFiles_gui((DirectoryListing::Directory *)ptr);
448 }
449 }
450 else
451 downloadSelectedFiles_gui(Text::fromUtf8(SETTING(DOWNLOAD_DIRECTORY)));
452 }
453
454 gtk_tree_path_free(path);
455 g_list_free(list);
456 }
457
downloadSelectedFiles_gui(const string & target)458 void ShareBrowser::downloadSelectedFiles_gui(const string &target)
459 {
460 gpointer ptr;
461 string fileOrder;
462 string filename;
463 GtkTreeIter iter;
464 GtkTreePath *path;
465 DirectoryListing::File *file;
466 DirectoryListing::Directory *dir;
467 GList *list = gtk_tree_selection_get_selected_rows(fileSelection, NULL);
468
469 for (GList *i = list; i; i = i->next)
470 {
471 path = (GtkTreePath *)i->data;
472 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(fileStore), &iter, path))
473 {
474 ptr = fileView.getValue<gpointer>(&iter, "DL File");
475 fileOrder = fileView.getString(&iter, "File Order");
476
477 if (fileOrder[0] == 'd')
478 {
479 dir = (DirectoryListing::Directory *)ptr;
480
481 typedef Func2<ShareBrowser, DirectoryListing::Directory *, string> F2;
482 F2 * func = new F2(this, &ShareBrowser::downloadDir_client, dir, target);
483 WulforManager::get()->dispatchClientFunc(func);
484 }
485 else
486 {
487 file = (DirectoryListing::File *)ptr;
488
489 string filename = Util::getFileName(file->getName());
490
491 typedef Func2<ShareBrowser, DirectoryListing::File *, string> F2;
492 F2 * func = new F2(this, &ShareBrowser::downloadFile_client, file, target + filename);
493 WulforManager::get()->dispatchClientFunc(func);
494 }
495 }
496 gtk_tree_path_free(path);
497 }
498 g_list_free(list);
499 }
500
downloadSelectedDirs_gui(const string & target)501 void ShareBrowser::downloadSelectedDirs_gui(const string &target)
502 {
503 DirectoryListing::Directory *dir;
504 GtkTreeIter iter;
505
506 if (gtk_tree_selection_get_selected(dirSelection, NULL, &iter))
507 {
508 dir = dirView.getValue<gpointer, DirectoryListing::Directory *>(&iter, "DL Dir");
509
510 typedef Func2<ShareBrowser, DirectoryListing::Directory *, string> F2;
511 F2 * func = new F2(this, &ShareBrowser::downloadDir_client, dir, target);
512 WulforManager::get()->dispatchClientFunc(func);
513 }
514 }
515
popupFileMenu_gui()516 void ShareBrowser::popupFileMenu_gui()
517 {
518 GtkWidget *menuItem;
519
520 // Clean menus
521 gtk_container_foreach(GTK_CONTAINER(getWidget("fileDownloadMenu")), (GtkCallback)gtk_widget_destroy, NULL);
522 fileUserCommandMenu->cleanMenu_gui();
523
524 // Build file download menu
525 StringPairList spl = FavoriteManager::getInstance()->getFavoriteDirs();
526 if (!spl.empty())
527 {
528 for (StringPairIter i = spl.begin(); i != spl.end(); ++i)
529 {
530 menuItem = gtk_menu_item_new_with_label(i->second.c_str());
531 g_object_set_data_full(G_OBJECT(menuItem), "fav", g_strdup(i->first.c_str()), g_free);
532 g_signal_connect(menuItem, "activate", G_CALLBACK(onDownloadFavoriteClicked_gui), (gpointer)this);
533 gtk_menu_shell_append(GTK_MENU_SHELL(getWidget("fileDownloadMenu")), menuItem);
534 }
535 menuItem = gtk_separator_menu_item_new();
536 gtk_menu_shell_append(GTK_MENU_SHELL(getWidget("fileDownloadMenu")), menuItem);
537 }
538
539 menuItem = gtk_menu_item_new_with_label(_("Browse..."));
540 g_signal_connect(menuItem, "activate", G_CALLBACK(onDownloadToClicked_gui), (gpointer)this);
541 gtk_menu_shell_append(GTK_MENU_SHELL(getWidget("fileDownloadMenu")), menuItem);
542
543 // Build user command menu
544 StringList hubs = WulforUtil::getHubAddress(listing.getUser().user->getCID(), "");
545 fileUserCommandMenu->addHub(hubs);
546 GtkTreeIter iter;
547 GList *list = gtk_tree_selection_get_selected_rows(fileSelection, NULL);
548 string cid = listing.getUser().user->getCID().toBase32();
549
550 for (GList *i = list; i; i = i->next)
551 {
552 GtkTreePath *path = (GtkTreePath *)i->data;
553 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(fileStore), &iter, path))
554 {
555 string filepath;
556 string fileOrder = fileView.getString(&iter, "File Order");
557 gpointer ptr = fileView.getValue<gpointer>(&iter, "DL File");
558
559 if (fileOrder[0] == 'd')
560 {
561 DirectoryListing::Directory *dir = (DirectoryListing::Directory *)ptr;
562 filepath = listing.getPath(dir->getParent());
563 }
564 else
565 {
566 DirectoryListing::File *file = (DirectoryListing::File *)ptr;
567 filepath = listing.getPath(file);
568 }
569
570 fileUserCommandMenu->addFile(cid,
571 fileView.getString(&iter, _("Filename")),
572 filepath,
573 fileView.getValue<int64_t>(&iter, "Size Order"),
574 fileView.getString(&iter, _("TTH")));
575 }
576 gtk_tree_path_free(path);
577 }
578 g_list_free(list);
579 fileUserCommandMenu->buildMenu_gui();
580
581 gtk_menu_popup(GTK_MENU(getWidget("fileMenu")), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time());
582 gtk_widget_show_all(getWidget("fileMenu"));
583 }
584
popupDirMenu_gui()585 void ShareBrowser::popupDirMenu_gui()
586 {
587 GtkWidget *menuItem;
588
589 // Clean menus
590 gtk_container_foreach(GTK_CONTAINER(getWidget("dirDownloadMenu")), (GtkCallback)gtk_widget_destroy, NULL);
591 dirUserCommandMenu->cleanMenu_gui();
592
593 StringPairList spl = FavoriteManager::getInstance()->getFavoriteDirs();
594 if (!spl.empty())
595 {
596 for (StringPairIter i = spl.begin(); i != spl.end(); ++i)
597 {
598 menuItem = gtk_menu_item_new_with_label(i->second.c_str());
599 g_object_set_data_full(G_OBJECT(menuItem), "fav", g_strdup(i->first.c_str()), g_free);
600 g_signal_connect(menuItem, "activate", G_CALLBACK(onDownloadFavoriteDirClicked_gui), (gpointer)this);
601 gtk_menu_shell_append(GTK_MENU_SHELL(getWidget("dirDownloadMenu")), menuItem);
602 }
603 menuItem = gtk_separator_menu_item_new();
604 gtk_menu_shell_append(GTK_MENU_SHELL(getWidget("dirDownloadMenu")), menuItem);
605 }
606
607 menuItem = gtk_menu_item_new_with_label(_("Browse..."));
608 g_signal_connect(menuItem, "activate", G_CALLBACK(onDownloadDirToClicked_gui), (gpointer)this);
609 gtk_menu_shell_append(GTK_MENU_SHELL(getWidget("dirDownloadMenu")), menuItem);
610
611 // Add user commands.
612 GtkTreeIter iter;
613 if (gtk_tree_selection_get_selected(dirSelection, NULL, &iter))
614 {
615 string filename;
616 string filepath;
617 string cid = listing.getUser().user->getCID().toBase32();
618 StringList hubs = WulforUtil::getHubAddress(listing.getUser().user->getCID(), "");
619 DirectoryListing::Directory *dir = dirView.getValue<DirectoryListing::Directory *>(&iter, "DL Dir");
620
621 if (dir != listing.getRoot())
622 {
623 filename = dirView.getString(&iter, _("Dir"));
624 filepath = listing.getPath(dir->getParent());
625 }
626 dirUserCommandMenu->addFile(cid, filename, filepath);
627 dirUserCommandMenu->addHub(hubs);
628 dirUserCommandMenu->buildMenu_gui();
629 }
630
631 gtk_menu_popup(GTK_MENU(getWidget("dirMenu")), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time());
632 gtk_widget_show_all(getWidget("dirMenu"));
633 }
634
635 /*
636 * Searches the directories iteratively for the requested pattern. Uses a pre-order
637 * traversal method, with the exception that it searches the parent's dir name first.
638 * Instead of keeping track of the last directory its search ended at, it counts
639 * the number of matches and re-searches the listing, skipping matches until it
640 * reaches the newest one. Slightly slower, but simpler.
641 */
find_gui()642 void ShareBrowser::find_gui()
643 {
644 string name;
645 bool findLeafNode = TRUE;
646 int cursorPos, hits = 0;
647 DirectoryListing::Directory *dir;
648 DirectoryListing::File::Iter file;
649 GtkTreeIter iter;
650 GtkTreeModel *m = GTK_TREE_MODEL(dirStore);
651 GtkTreePath *dirPath = gtk_tree_path_new_first();
652
653 if (!gtk_tree_path_get_depth(dirPath) || !gtk_tree_model_get_iter(m, &iter, dirPath))
654 {
655 gtk_tree_path_free(dirPath);
656 return;
657 }
658
659 gint sortColumn;
660 GtkSortType sortType;
661 gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(fileStore), &sortColumn, &sortType);
662 if (sortColumn != fileView.col("File Order") || sortType != GTK_SORT_ASCENDING)
663 {
664 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(fileStore), fileView.col("File Order"), GTK_SORT_ASCENDING);
665 gtk_tree_view_column_set_sort_indicator(gtk_tree_view_get_column(fileView.get(), fileView.col(_("Filename"))), TRUE);
666 }
667
668 while (TRUE)
669 {
670 // Drill down until we reach a leaf node (e.g. a dir with no child dirs).
671 if (findLeafNode)
672 {
673 do
674 {
675 name = Text::toLower(dirView.getString(&iter, _("Dir")));
676 // We found a matching directory name.
677 if (name.find(search, 0) != string::npos && hits++ == skipHits)
678 {
679 skipHits = hits;
680 gtk_tree_view_expand_to_path(dirView.get(), dirPath);
681 gtk_tree_view_set_cursor(dirView.get(), dirPath, NULL, FALSE);
682 dir = dirView.getValue<gpointer, DirectoryListing::Directory *>(&iter, "DL Dir");
683 updateFiles_gui(dir);
684 gtk_widget_grab_focus(GTK_WIDGET(dirView.get()));
685 updateFileView = FALSE;
686 gtk_tree_path_free(dirPath);
687 setStatus_gui("mainStatus", _("Found a match"));
688 return;
689 }
690 gtk_tree_path_down(dirPath);
691 }
692 while (gtk_tree_model_get_iter(m, &iter, dirPath));
693 }
694
695 // Come back up one directory. If we can't, then we've returned to the root and are done.
696 if (!gtk_tree_path_up(dirPath) || !gtk_tree_path_get_depth(dirPath) ||
697 !gtk_tree_model_get_iter(m, &iter, dirPath))
698 {
699 setStatus_gui("mainStatus", _("No matches"));
700 gtk_tree_path_free(dirPath);
701 return;
702 }
703
704 // Search the files that are contained in this directory.
705 dir = dirView.getValue<gpointer, DirectoryListing::Directory *>(&iter, "DL Dir");
706 std::sort(dir->files.begin(), dir->files.end(), DirectoryListing::File::FileSort());
707
708 for (file = dir->files.begin(), cursorPos = dir->directories.size(); file != dir->files.end(); ++file, ++cursorPos)
709 {
710 name = Text::toLower((*file)->getName());
711
712 // We found a matching file. Update the cursors and the fileView if necessary.
713 if (name.find(search, 0) != string::npos && hits++ == skipHits)
714 {
715 if (updateFileView)
716 {
717 gtk_tree_view_expand_to_path(dirView.get(), dirPath);
718 gtk_tree_view_set_cursor(dirView.get(), dirPath, NULL, FALSE);
719 updateFiles_gui(dir);
720 updateFileView = FALSE;
721 }
722
723 skipHits = hits;
724 // Keeping track of the current index allows us to quickly get the path to the file.
725 GtkTreePath *path = gtk_tree_path_new_from_string(Util::toString(cursorPos).c_str());
726 gtk_tree_view_set_cursor(fileView.get(), path, NULL, FALSE);
727 gtk_widget_grab_focus(GTK_WIDGET(fileView.get()));
728 gtk_tree_path_free(path);
729 gtk_tree_path_free(dirPath);
730 setStatus_gui("mainStatus", _("Found a match"));
731 return;
732 }
733 }
734 updateFileView = TRUE;
735
736 // Determine if we are to go to the next sibling or back to the parent dir.
737 gtk_tree_path_next(dirPath);
738 if (!gtk_tree_model_get_iter(m, &iter, dirPath))
739 findLeafNode = FALSE;
740 else
741 findLeafNode = TRUE;
742 }
743 }
744
onButtonPressed_gui(GtkWidget * widget,GdkEventButton * event,gpointer data)745 gboolean ShareBrowser::onButtonPressed_gui(GtkWidget *widget, GdkEventButton *event, gpointer data)
746 {
747 ShareBrowser *sb = (ShareBrowser *)data;
748 sb->oldType = event->type;
749
750 if (event->button == 3)
751 {
752 GtkTreePath *path;
753
754 if (gtk_tree_view_get_path_at_pos(sb->fileView.get(), (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL))
755 {
756 bool selected = gtk_tree_selection_path_is_selected(sb->fileSelection, path);
757 gtk_tree_path_free(path);
758
759 if (selected)
760 return TRUE;
761 }
762 }
763
764 return FALSE;
765 }
766
onFileButtonReleased_gui(GtkWidget * widget,GdkEventButton * event,gpointer data)767 gboolean ShareBrowser::onFileButtonReleased_gui(GtkWidget *widget, GdkEventButton *event, gpointer data)
768 {
769 ShareBrowser *sb = (ShareBrowser *)data;
770 gint count = gtk_tree_selection_count_selected_rows(sb->fileSelection);
771
772 if (count > 0 && event->type == GDK_BUTTON_RELEASE && event->button == 3)
773 sb->popupFileMenu_gui();
774 else if (count == 1 && sb->oldType == GDK_2BUTTON_PRESS && event->button == 1)
775 sb->fileViewSelected_gui();
776
777 return FALSE;
778 }
779
onFileKeyReleased_gui(GtkWidget * widget,GdkEventKey * event,gpointer data)780 gboolean ShareBrowser::onFileKeyReleased_gui(GtkWidget *widget, GdkEventKey *event, gpointer data)
781 {
782 ShareBrowser *sb = (ShareBrowser *)data;
783 gint count = gtk_tree_selection_count_selected_rows(sb->fileSelection);
784
785 if (count > 0 && (event->keyval == GDK_Menu || (event->keyval == GDK_F10 && event->state & GDK_SHIFT_MASK)))
786 sb->popupFileMenu_gui();
787 else if (count == 1 && (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter))
788 sb->fileViewSelected_gui();
789
790 return FALSE;
791 }
792
onDirButtonReleased_gui(GtkWidget * widget,GdkEventButton * event,gpointer data)793 gboolean ShareBrowser::onDirButtonReleased_gui(GtkWidget *widget, GdkEventButton *event, gpointer data)
794 {
795 ShareBrowser *sb = (ShareBrowser *)data;
796 GtkTreeIter iter;
797 gpointer ptr;
798
799 if (!gtk_tree_selection_get_selected(sb->dirSelection, NULL, &iter))
800 return FALSE;
801
802 if (!sb->isFull()) sb->viewPartial_gui();
803
804 if (event->button == 1 && sb->oldType == GDK_2BUTTON_PRESS)
805 {
806 GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(sb->dirStore), &iter);
807 if (gtk_tree_view_row_expanded(sb->dirView.get(), path))
808 gtk_tree_view_collapse_row(sb->dirView.get(), path);
809 else
810 gtk_tree_view_expand_row(sb->dirView.get(), path, FALSE);
811 gtk_tree_path_free(path);
812 }
813 else if (event->button == 1 && event->type == GDK_BUTTON_RELEASE)
814 {
815 ptr = sb->dirView.getValue<gpointer>(&iter, "DL Dir");
816 sb->updateFiles_gui((DirectoryListing::Directory *)ptr);
817 }
818 else if (event->button == 3 && event->type == GDK_BUTTON_RELEASE)
819 {
820 ptr = sb->dirView.getValue<gpointer>(&iter, "DL Dir");
821 sb->updateFiles_gui((DirectoryListing::Directory *)ptr);
822 sb->popupDirMenu_gui();
823 }
824
825 return FALSE;
826 }
827
onDirKeyReleased_gui(GtkWidget * widget,GdkEventKey * event,gpointer data)828 gboolean ShareBrowser::onDirKeyReleased_gui(GtkWidget *widget, GdkEventKey *event, gpointer data)
829 {
830 ShareBrowser *sb = (ShareBrowser *)data;
831 GtkTreeIter iter;
832 gpointer ptr;
833
834 if (!gtk_tree_selection_get_selected(sb->dirSelection, NULL, &iter))
835 return FALSE;
836
837 if (!sb->isFull()) sb->viewPartial_gui();
838
839 if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter || event->keyval == GDK_Right || event->keyval == GDK_Left)
840 {
841 GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(sb->dirStore), &iter);
842 if (gtk_tree_view_row_expanded(sb->dirView.get(), path))
843 gtk_tree_view_collapse_row(sb->dirView.get(), path);
844 else
845 gtk_tree_view_expand_row(sb->dirView.get(), path, FALSE);
846 gtk_tree_path_free(path);
847 }
848 else if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up ||
849 event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
850 {
851 ptr = sb->dirView.getValue<gpointer>(&iter, "DL Dir");
852 sb->updateFiles_gui((DirectoryListing::Directory *)ptr);
853 }
854 else if (event->keyval == GDK_Menu || (event->keyval == GDK_F10 && event->state & GDK_SHIFT_MASK))
855 {
856 ptr = sb->dirView.getValue<gpointer>(&iter, "DL Dir");
857 sb->updateFiles_gui((DirectoryListing::Directory *)ptr);
858 sb->popupDirMenu_gui();
859 }
860
861 return FALSE;
862 }
863
onMatchButtonClicked_gui(GtkWidget * widget,gpointer data)864 void ShareBrowser::onMatchButtonClicked_gui(GtkWidget *widget, gpointer data)
865 {
866 typedef Func0<ShareBrowser> F0;
867 F0 *f0 = new F0((ShareBrowser*)data, &ShareBrowser::matchQueue_client);
868 WulforManager::get()->dispatchClientFunc(f0);
869 }
870
onFindButtonClicked_gui(GtkWidget * widget,gpointer data)871 void ShareBrowser::onFindButtonClicked_gui(GtkWidget *widget, gpointer data)
872 {
873 ShareBrowser *sb = (ShareBrowser *)data;
874
875 gtk_widget_grab_focus(GTK_WIDGET(sb->getWidget("findEntry")));
876 gint response = gtk_dialog_run(GTK_DIALOG(sb->getWidget("findDialog")));
877
878 // Fix crash, if the dialog gets programmatically destroyed.
879 if (response == GTK_RESPONSE_NONE)
880 return;
881
882 gtk_widget_hide(sb->getWidget("findDialog"));
883
884 if (response == GTK_RESPONSE_OK)
885 {
886 string text = gtk_entry_get_text(GTK_ENTRY(sb->getWidget("findEntry")));
887 if (!text.empty())
888 {
889 sb->search = text;
890 sb->skipHits = 0;
891 sb->find_gui();
892 }
893 else
894 {
895 sb->setStatus_gui("mainStatus", _("No matches"));
896 }
897 }
898 }
899
onNextButtonClicked_gui(GtkWidget * widget,gpointer data)900 void ShareBrowser::onNextButtonClicked_gui(GtkWidget *widget, gpointer data)
901 {
902 ShareBrowser *sb = (ShareBrowser *)data;
903 if (!sb->search.empty())
904 sb->find_gui();
905 else
906 sb->setStatus_gui("mainStatus", _("No search text entered"));
907 }
908
onDownloadClicked_gui(GtkMenuItem * item,gpointer data)909 void ShareBrowser::onDownloadClicked_gui(GtkMenuItem *item, gpointer data)
910 {
911 ShareBrowser *sb = (ShareBrowser *)data;
912 sb->downloadSelectedFiles_gui(Text::fromUtf8(SETTING(DOWNLOAD_DIRECTORY)));
913 }
914
onDownloadToClicked_gui(GtkMenuItem * item,gpointer data)915 void ShareBrowser::onDownloadToClicked_gui(GtkMenuItem *item, gpointer data)
916 {
917 ShareBrowser *sb = (ShareBrowser *)data;
918
919 gint response = gtk_dialog_run(GTK_DIALOG(sb->getWidget("dirChooserDialog")));
920
921 // Fix crash, if the dialog gets programmatically destroyed.
922 if (response == GTK_RESPONSE_NONE)
923 return;
924
925 gtk_widget_hide(sb->getWidget("dirChooserDialog"));
926
927 if (response == GTK_RESPONSE_OK)
928 {
929 gchar *temp = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(sb->getWidget("dirChooserDialog")));
930 if (temp)
931 {
932 string path = Text::toUtf8(temp);
933 g_free(temp);
934 if (path[path.length() - 1] != PATH_SEPARATOR)
935 path += PATH_SEPARATOR;
936
937 sb->downloadSelectedFiles_gui(path);
938 }
939 }
940 }
941
onDownloadFavoriteClicked_gui(GtkMenuItem * item,gpointer data)942 void ShareBrowser::onDownloadFavoriteClicked_gui(GtkMenuItem *item, gpointer data)
943 {
944 ShareBrowser *sb = (ShareBrowser *)data;
945 string target = string((gchar *)g_object_get_data(G_OBJECT(item), "fav"));
946 sb->downloadSelectedFiles_gui(target);
947 }
948
onDownloadDirClicked_gui(GtkMenuItem * item,gpointer data)949 void ShareBrowser::onDownloadDirClicked_gui(GtkMenuItem *item, gpointer data)
950 {
951 ShareBrowser *sb = (ShareBrowser *)data;
952 sb->downloadSelectedDirs_gui(Text::fromUtf8(SETTING(DOWNLOAD_DIRECTORY)));
953 }
954
onDownloadDirToClicked_gui(GtkMenuItem * item,gpointer data)955 void ShareBrowser::onDownloadDirToClicked_gui(GtkMenuItem *item, gpointer data)
956 {
957 ShareBrowser *sb = (ShareBrowser *)data;
958
959 gint response = gtk_dialog_run(GTK_DIALOG(sb->getWidget("dirChooserDialog")));
960
961 // Fix crash, if the dialog gets programmatically destroyed.
962 if (response == GTK_RESPONSE_NONE)
963 return;
964
965 gtk_widget_hide(sb->getWidget("dirChooserDialog"));
966
967 if (response == GTK_RESPONSE_OK)
968 {
969 gchar *temp = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(sb->getWidget("dirChooserDialog")));
970 if (temp)
971 {
972 string path = Text::toUtf8(temp);
973 g_free(temp);
974 if (path[path.length() - 1] != PATH_SEPARATOR)
975 path += PATH_SEPARATOR;
976
977 sb->downloadSelectedDirs_gui(path);
978 }
979 }
980 }
981
onDownloadFavoriteDirClicked_gui(GtkMenuItem * item,gpointer data)982 void ShareBrowser::onDownloadFavoriteDirClicked_gui(GtkMenuItem *item, gpointer data)
983 {
984 ShareBrowser *sb = (ShareBrowser *)data;
985 string target = string((gchar *)g_object_get_data(G_OBJECT(item), "fav"));
986 sb->downloadSelectedDirs_gui(target);
987 }
988
onSearchAlternatesClicked_gui(GtkMenuItem * item,gpointer data)989 void ShareBrowser::onSearchAlternatesClicked_gui(GtkMenuItem *item, gpointer data)
990 {
991 ShareBrowser *sb = (ShareBrowser *)data;
992 GtkTreeIter iter;
993 GtkTreePath *path;
994 string fileOrder;
995 Search *s;
996 DirectoryListing::File *file;
997 GList *list = gtk_tree_selection_get_selected_rows(sb->fileSelection, NULL);
998
999 for (GList *i = list; i; i = i->next)
1000 {
1001 path = (GtkTreePath *)i->data;
1002 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(sb->fileStore), &iter, path))
1003 {
1004 fileOrder = sb->fileView.getString(&iter, "File Order");
1005
1006 if (fileOrder[0] == 'f')
1007 {
1008 file = sb->fileView.getValue<gpointer, DirectoryListing::File *>(&iter, "DL File");
1009 s = WulforManager::get()->getMainWindow()->addSearch_gui();
1010 s->putValue_gui(file->getTTH().toBase32(), 0, SearchManager::SIZE_DONTCARE, SearchManager::TYPE_TTH);
1011 }
1012 }
1013 gtk_tree_path_free(path);
1014 }
1015 g_list_free(list);
1016 }
1017
onCopyMagnetClicked_gui(GtkMenuItem * item,gpointer data)1018 void ShareBrowser::onCopyMagnetClicked_gui(GtkMenuItem* item, gpointer data)
1019 {
1020 ShareBrowser *sb = (ShareBrowser *)data;
1021 GtkTreeIter iter;
1022 GtkTreePath *path;
1023 int64_t size;
1024 string magnets, magnet, filename, tth;
1025 GList *list = gtk_tree_selection_get_selected_rows(sb->fileSelection, NULL);
1026
1027 for (GList *i = list; i; i = i->next)
1028 {
1029 path = (GtkTreePath *)i->data;
1030 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(sb->fileStore), &iter, path))
1031 {
1032 filename = sb->fileView.getString(&iter, _("Filename"));
1033 size = sb->fileView.getValue<int64_t>(&iter, "Size Order");
1034 tth = sb->fileView.getString(&iter, _("TTH"));
1035 magnet = WulforUtil::makeMagnet(filename, size, tth);
1036
1037 if (!magnet.empty())
1038 {
1039 if (!magnets.empty())
1040 magnets += '\n';
1041 magnets += magnet;
1042 }
1043 }
1044 gtk_tree_path_free(path);
1045 }
1046 g_list_free(list);
1047
1048 if (!magnets.empty())
1049 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), magnets.c_str(), magnets.length());
1050 }
1051
onCopyPictureClicked_gui(GtkMenuItem * item,gpointer data)1052 void ShareBrowser::onCopyPictureClicked_gui(GtkMenuItem* item, gpointer data)
1053 {
1054 ShareBrowser *sb = (ShareBrowser *)data;
1055 GtkTreeIter iter;
1056 GtkTreePath *path;
1057 int64_t size;
1058 string magnets, magnet, filename, tth;
1059 GList *list = gtk_tree_selection_get_selected_rows(sb->fileSelection, NULL);
1060
1061 for (GList *i = list; i; i = i->next)
1062 {
1063 path = (GtkTreePath *)i->data;
1064 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(sb->fileStore), &iter, path))
1065 {
1066 filename = sb->fileView.getString(&iter, _("Filename"));
1067 size = sb->fileView.getValue<int64_t>(&iter, "Size Order");
1068 tth = sb->fileView.getString(&iter, _("TTH"));
1069 magnet = WulforUtil::makeMagnet(filename, size, tth);
1070
1071 if (!magnet.empty())
1072 {
1073 magnet = "[img]" + magnet + "[/img]";
1074 if (!magnets.empty())
1075 magnets += '\n';
1076 magnets += magnet;
1077 }
1078 }
1079 gtk_tree_path_free(path);
1080 }
1081 g_list_free(list);
1082
1083 if (!magnets.empty())
1084 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), magnets.c_str(), magnets.length());
1085 }
1086
downloadFile_client(DirectoryListing::File * file,string target)1087 void ShareBrowser::downloadFile_client(DirectoryListing::File *file, string target)
1088 {
1089 try
1090 {
1091 listing.download(file, target, FALSE, FALSE);
1092 }
1093 catch (const Exception& e)
1094 {
1095 typedef Func2<ShareBrowser, string, string> F2;
1096 F2 *func = new F2(this, &ShareBrowser::setStatus_gui, "mainStatus", e.getError());
1097 WulforManager::get()->dispatchGuiFunc(func);
1098 }
1099 }
1100
downloadDir_client(DirectoryListing::Directory * dir,string target)1101 void ShareBrowser::downloadDir_client(DirectoryListing::Directory *dir, string target)
1102 {
1103 try
1104 {
1105 listing.download(dir, target, FALSE);
1106 }
1107 catch (const Exception& e)
1108 {
1109 typedef Func2<ShareBrowser, string, string> F2;
1110 F2 *func = new F2(this, &ShareBrowser::setStatus_gui, "mainStatus", e.getError());
1111 WulforManager::get()->dispatchGuiFunc(func);
1112 }
1113 }
1114
matchQueue_client()1115 void ShareBrowser::matchQueue_client()
1116 {
1117 int matched = QueueManager::getInstance()->matchListing(listing);
1118 string message = _("Matched ") + Util::toString(matched) + _(" files");
1119
1120 typedef Func2<ShareBrowser, string, string> F2;
1121 F2 *f = new F2(this, &ShareBrowser::setStatus_gui, "mainStatus", message);
1122 WulforManager::get()->dispatchGuiFunc(f);
1123 }
onDirGet(GtkMenuItem * item,gpointer data)1124 void ShareBrowser::onDirGet(GtkMenuItem* item, gpointer data)
1125 {
1126 ShareBrowser *sb=(ShareBrowser*)data;
1127 GList *list = gtk_tree_selection_get_selected_rows(sb->fileSelection, NULL);
1128 GtkTreePath *path;
1129 GtkTreeIter iter;
1130 string name,fullpath;
1131 DirectoryListing::File *filed;
1132
1133 for (GList *i = list;i;i=i->next)
1134 {
1135 path = (GtkTreePath *)i->data;
1136 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(sb->fileStore), &iter, path))
1137 {
1138 filed = sb->fileView.getValue<gpointer, DirectoryListing::File *>(&iter, "DL File");
1139
1140 ItemInfo* ii= new ItemInfo(filed);
1141 if(ii->type == ItemInfo::FILE)
1142 {
1143 if(!ii->file->getAdls())return;
1144 DirectoryListing::Directory *dir=ii->file->getParent();
1145 while( dir && (dir != sb->listing.getRoot()))
1146 {
1147 fullpath=dir->getName()+PATH_SEPARATOR+fullpath;
1148 dir=dir->getParent();
1149 }
1150 }
1151 else if(ii->type == ItemInfo::DIRECTORY)
1152 {
1153 if(!(ii->dir->getAdls()) && (ii->dir->getParent() != sb->listing.getRoot()))
1154 return;
1155 fullpath = Text::toT(((DirectoryListing::AdlDirectory*)ii->dir)->getFullPath());
1156 }
1157 }
1158 }
1159 sb->openDir_gui(fullpath);
1160 }
1161
compareItems(ItemInfo * a,ItemInfo * b,int col)1162 int ShareBrowser::ItemInfo::compareItems(ItemInfo* a, ItemInfo* b, int col) {
1163 if(a->type == DIRECTORY) {
1164 if(b->type == DIRECTORY) {
1165 switch(col) {
1166 case COLUMN_EXACTSIZE: return compare(a->dir->getTotalSize(), b->dir->getTotalSize());
1167 case COLUMN_SIZE: return compare(a->dir->getTotalSize(), b->dir->getTotalSize());
1168 default: break; //strcmp(a->columns[col].c_str(), b->columns[col].c_str());
1169 }
1170 } else {
1171 return -1;
1172 }
1173 } else if(b->type == DIRECTORY) {
1174 return 1;
1175 } else {
1176 switch(col) {
1177 case COLUMN_EXACTSIZE: return compare(a->file->getSize(), b->file->getSize());
1178 case COLUMN_SIZE: return compare(a->file->getSize(), b->file->getSize());
1179 default: break;// strcmp(a->columns[col].c_str(), b->columns[col].c_str());
1180 }
1181 }
1182
1183 return -1;
1184 }
1185
loadXML(string txt)1186 void ShareBrowser::loadXML(string txt)
1187 {
1188 typedef Func1<ShareBrowser,string> F1;
1189 F1 *func = new F1(this,&ShareBrowser::load,txt);
1190 WulforManager::get()->dispatchGuiFunc(func);
1191 }
1192
load(string xml)1193 void ShareBrowser::load(string xml)
1194 {
1195 // Set name of root entry to user nick.
1196 listing.getRoot()->setName(nick);
1197
1198 GtkTreeIter iter;
1199 DirectoryListing::Directory *dirList;
1200 string path,path2;
1201 GtkTreePath *treepath;
1202 if (gtk_tree_selection_get_selected(dirSelection, NULL, &iter))
1203 {
1204 dirList = (DirectoryListing::Directory *)dirView.getValue<gpointer>(&iter,"DL Dir");
1205 path2 = dirList->getName();
1206 treepath = gtk_tree_path_copy(gtk_tree_model_get_path (GTK_TREE_MODEL(dirStore), gtk_tree_iter_copy(&iter)));
1207
1208 //path = QueueManager::getInstance()->getListPath(listing.getUser()) + ".xml";
1209 path = Util::getListPath() + nick + user->getCID().toBase32() + ".xml.bz2";
1210 if(File::getSize(path) != -1) {
1211 // load the cached list.
1212 listing.updateXML(File(path, File::READ, File::OPEN).read());
1213 }
1214 auto base = listing.updateXML(xml);
1215 //listing.save(path);
1216 ADLSearchManager::getInstance()->matchListing(listing);
1217 gtk_tree_store_clear(dirStore);
1218 gtk_list_store_clear(fileStore);
1219 buildDirs_gui(listing.getRoot(),NULL);
1220 gtk_tree_view_expand_to_path(dirView.get(), treepath);
1221 gtk_tree_view_scroll_to_cell(dirView.get(),treepath,NULL,FALSE,0,0);
1222 gtk_tree_selection_select_path(dirSelection,treepath);
1223 updateFiles_gui(dirList);
1224 }
1225 }
1226
viewPartial_gui()1227 void ShareBrowser::viewPartial_gui()
1228 {
1229 GtkTreeIter iter;
1230 DirectoryListing::Directory *dirList;
1231 if (gtk_tree_selection_get_selected(dirSelection, NULL, &iter))
1232 {
1233 dirList = (DirectoryListing::Directory *)dirView.getValue<gpointer>(&iter,"DL Dir");
1234 typedef Func1<ShareBrowser, DirectoryListing::Directory*> F1;
1235 F1 *func = new F1(this,&ShareBrowser::downloadChangedDir,dirList);
1236 WulforManager::get()->dispatchClientFunc(func);
1237 }
1238 }
1239
1240
downloadChangedDir(DirectoryListing::Directory * d)1241 void ShareBrowser::downloadChangedDir(DirectoryListing::Directory* d) {
1242 if(!d->getComplete()) {
1243 dcdebug("Directory %s incomplete, downloading...\n", d->getName().c_str());
1244 if(listing.getUser().user->isOnline()) {
1245 try {
1246 QueueManager::getInstance()->addList(listing.getUser(), QueueItem::FLAG_PARTIAL_LIST, listing.getPath(d));
1247 } catch(const QueueException& e) { }
1248 } else {
1249 setStatus_gui("mainStatus","User went offline");
1250 }
1251 }
1252 }
1253 /*Many code from orginal DC++*/
1254