diff --git a/glade/merge_dialog.glade b/glade/merge_dialog.glade new file mode 100644 index 000000000..ed2b83270 --- /dev/null +++ b/glade/merge_dialog.glade @@ -0,0 +1,56 @@ + + + + + + 5 + Deluge Merge Tracker Lists + GTK_WIN_POS_CENTER_ALWAYS + 200 + 50 + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK + 2 + + + True + Torrent already detected in Deluge, would you like to merge the tracker lists? + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK + GTK_BUTTONBOX_END + + + True + gtk-cancel + True + 0 + + + + + True + gtk-ok + True + 1 + + + 1 + + + + + False + GTK_PACK_END + + + + + + diff --git a/src/core.py b/src/core.py index dab1e0854..16c79ff6e 100644 --- a/src/core.py +++ b/src/core.py @@ -309,11 +309,19 @@ class Manager: def dump_torrent_file_info(self, torrent): return deluge_core.dump_file_info(torrent) + # Dump trackers from torrent file + def dump_trackers(self, torrent): + return deluge_core.dump_trackers(torrent) + # Torrent addition and removal functions def add_torrent(self, filename, save_dir, compact): self.add_torrent_ns(filename, save_dir, compact) return self.sync() # Syncing will create a new torrent in the core, and return it's ID + + # When duplicate torrent error, use to find duplicate when merging tracker lists + def test_duplicate(self, torrent, unique_id): + return deluge_core.test_duplicate(torrent, unique_id) def remove_torrent(self, unique_ID, data_also, torrent_also): temp = self.unique_IDs[unique_ID] diff --git a/src/deluge_core.cpp b/src/deluge_core.cpp index 401f2d05f..3d1f9a2c1 100644 --- a/src/deluge_core.cpp +++ b/src/deluge_core.cpp @@ -170,7 +170,6 @@ long get_torrent_index(torrent_handle &handle) RAISE_INT(DelugeError, "Handle not found."); } - long get_index_from_unique_ID(long unique_ID) { @@ -181,7 +180,7 @@ long get_index_from_unique_ID(long unique_ID) RAISE_INT(DelugeError, "No such unique_ID."); } -torrent_info internal_dump_file_info(std::string const& torrent_name) +torrent_info internal_get_torrent_info(std::string const& torrent_name) { std::ifstream in(torrent_name.c_str(), std::ios_base::binary); in.unsetf(std::ios_base::skipws); @@ -534,7 +533,7 @@ static PyObject *torrent_dump_file_info(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "s", &name)) return NULL; - torrent_info t = internal_dump_file_info(name); + torrent_info t = internal_get_torrent_info(name); PyObject *file_info; long file_index = 0; @@ -557,6 +556,24 @@ static PyObject *torrent_dump_file_info(PyObject *self, PyObject *args) return ret; } +static PyObject *torrent_dump_trackers(PyObject *self, PyObject *args) +{ + const char *name; + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + + torrent_info t = internal_get_torrent_info(name); + std::string trackerslist; + { + for (std::vector::const_iterator i = t.trackers().begin(); + i != t.trackers().end(); ++i) + { + trackerslist = trackerslist + i->url +"\n"; + } + } + return Py_BuildValue("s",trackerslist.c_str()); +} + static PyObject *torrent_add_torrent(PyObject *self, PyObject *args) { const char *name, *save_dir; @@ -583,6 +600,22 @@ static PyObject *torrent_add_torrent(PyObject *self, PyObject *args) { RAISE_PTR(DuplicateTorrentError, "libtorrent reports this is a duplicate torrent"); } } +static PyObject *torrent_test_duplicate(PyObject *self, PyObject *args) +{ + const char *name; + python_long unique_ID; + if (!PyArg_ParseTuple(args, "si", &name, &unique_ID)) + return NULL; + + long index = get_index_from_unique_ID(unique_ID); + if (PyErr_Occurred()) + return NULL; + + torrent_info t = internal_get_torrent_info(name); + return Py_BuildValue("b", t.info_hash() == M_torrents->at(index).handle.info_hash()); + +} + static PyObject *torrent_move_storage(PyObject *self, PyObject *args) { const char *move_dir; @@ -1511,49 +1544,51 @@ static PyObject *torrent_set_priv(PyObject *self, PyObject *args) static PyMethodDef deluge_core_methods[] = { - {"pe_settings", torrent_pe_settings, METH_VARARGS, "."}, - {"pre_init", torrent_pre_init, METH_VARARGS, "."}, - {"init", torrent_init, METH_VARARGS, "."}, - {"quit", torrent_quit, METH_VARARGS, "."}, - {"save_fastresume", torrent_save_fastresume, METH_VARARGS, "."}, - {"set_max_half_open", torrent_set_max_half_open, METH_VARARGS, "."}, - {"set_download_rate_limit", torrent_set_download_rate_limit, METH_VARARGS, "."}, - {"set_upload_rate_limit", torrent_set_upload_rate_limit, METH_VARARGS, "."}, - {"set_listen_on", torrent_set_listen_on, METH_VARARGS, "."}, - {"is_listening", torrent_is_listening, METH_VARARGS, "."}, - {"listening_port", torrent_listening_port, METH_VARARGS, "."}, - {"set_max_uploads", torrent_set_max_uploads, METH_VARARGS, "."}, - {"set_max_connections", torrent_set_max_connections, METH_VARARGS, "."}, - {"add_torrent", torrent_add_torrent, METH_VARARGS, "."}, - {"move_storage", torrent_move_storage, METH_VARARGS, "."}, - {"remove_torrent", torrent_remove_torrent, METH_VARARGS, "."}, - {"get_num_torrents", torrent_get_num_torrents, METH_VARARGS, "."}, - {"reannounce", torrent_reannounce, METH_VARARGS, "."}, - {"pause", torrent_pause, METH_VARARGS, "."}, - {"resume", torrent_resume, METH_VARARGS, "."}, - {"get_torrent_state", torrent_get_torrent_state, METH_VARARGS, "."}, - {"pop_event", torrent_pop_event, METH_VARARGS, "."}, - {"get_session_info", torrent_get_session_info, METH_VARARGS, "."}, - {"get_peer_info", torrent_get_peer_info, METH_VARARGS, "."}, - {"get_file_info", torrent_get_file_info, METH_VARARGS, "."}, - {"dump_file_info", torrent_dump_file_info, METH_VARARGS, "."}, - {"constants", torrent_constants, METH_VARARGS, "."}, - {"start_DHT", torrent_start_DHT, METH_VARARGS, "."}, - {"stop_DHT", torrent_stop_DHT, METH_VARARGS, "."}, - {"get_DHT_info", torrent_get_DHT_info, METH_VARARGS, "."}, - {"create_torrent", torrent_create_torrent, METH_VARARGS, "."}, - {"reset_IP_filter", torrent_reset_IP_filter, METH_VARARGS, "."}, - {"add_range_to_IP_filter", torrent_add_range_to_IP_filter, METH_VARARGS, "."}, - {"use_upnp", torrent_use_upnp, METH_VARARGS, "."}, - {"use_natpmp", torrent_use_natpmp, METH_VARARGS, "."}, - {"use_utpex", torrent_use_utpex, METH_VARARGS, "."}, - {"set_ratio", torrent_set_ratio, METH_VARARGS, "."}, - {"proxy_settings", torrent_proxy_settings, METH_VARARGS, "."}, - {"get_trackers", torrent_get_trackers, METH_VARARGS, "."}, - {"replace_trackers", torrent_replace_trackers, METH_VARARGS, "."}, - {"set_flp", torrent_set_flp, METH_VARARGS, "."}, - {"prioritize_files", torrent_prioritize_files, METH_VARARGS, "."}, - {"set_priv", torrent_set_priv, METH_VARARGS, "."}, + {"pe_settings", torrent_pe_settings, METH_VARARGS, "."}, + {"pre_init", torrent_pre_init, METH_VARARGS, "."}, + {"init", torrent_init, METH_VARARGS, "."}, + {"quit", torrent_quit, METH_VARARGS, "."}, + {"save_fastresume", torrent_save_fastresume, METH_VARARGS, "."}, + {"set_max_half_open", torrent_set_max_half_open, METH_VARARGS, "."}, + {"set_download_rate_limit", torrent_set_download_rate_limit, METH_VARARGS, "."}, + {"set_upload_rate_limit", torrent_set_upload_rate_limit, METH_VARARGS, "."}, + {"set_listen_on", torrent_set_listen_on, METH_VARARGS, "."}, + {"is_listening", torrent_is_listening, METH_VARARGS, "."}, + {"listening_port", torrent_listening_port, METH_VARARGS, "."}, + {"set_max_uploads", torrent_set_max_uploads, METH_VARARGS, "."}, + {"set_max_connections", torrent_set_max_connections, METH_VARARGS, "."}, + {"add_torrent", torrent_add_torrent, METH_VARARGS, "."}, + {"move_storage", torrent_move_storage, METH_VARARGS, "."}, + {"remove_torrent", torrent_remove_torrent, METH_VARARGS, "."}, + {"get_num_torrents", torrent_get_num_torrents, METH_VARARGS, "."}, + {"reannounce", torrent_reannounce, METH_VARARGS, "."}, + {"pause", torrent_pause, METH_VARARGS, "."}, + {"resume", torrent_resume, METH_VARARGS, "."}, + {"get_torrent_state", torrent_get_torrent_state, METH_VARARGS, "."}, + {"pop_event", torrent_pop_event, METH_VARARGS, "."}, + {"get_session_info", torrent_get_session_info, METH_VARARGS, "."}, + {"get_peer_info", torrent_get_peer_info, METH_VARARGS, "."}, + {"get_file_info", torrent_get_file_info, METH_VARARGS, "."}, + {"dump_file_info", torrent_dump_file_info, METH_VARARGS, "."}, + {"constants", torrent_constants, METH_VARARGS, "."}, + {"start_DHT", torrent_start_DHT, METH_VARARGS, "."}, + {"stop_DHT", torrent_stop_DHT, METH_VARARGS, "."}, + {"get_DHT_info", torrent_get_DHT_info, METH_VARARGS, "."}, + {"create_torrent", torrent_create_torrent, METH_VARARGS, "."}, + {"reset_IP_filter", torrent_reset_IP_filter, METH_VARARGS, "."}, + {"add_range_to_IP_filter", torrent_add_range_to_IP_filter, METH_VARARGS, "."}, + {"use_upnp", torrent_use_upnp, METH_VARARGS, "."}, + {"use_natpmp", torrent_use_natpmp, METH_VARARGS, "."}, + {"use_utpex", torrent_use_utpex, METH_VARARGS, "."}, + {"set_ratio", torrent_set_ratio, METH_VARARGS, "."}, + {"proxy_settings", torrent_proxy_settings, METH_VARARGS, "."}, + {"get_trackers", torrent_get_trackers, METH_VARARGS, "."}, + {"dump_trackers", torrent_dump_trackers, METH_VARARGS, "."}, + {"replace_trackers", torrent_replace_trackers, METH_VARARGS, "."}, + {"set_flp", torrent_set_flp, METH_VARARGS, "."}, + {"prioritize_files", torrent_prioritize_files, METH_VARARGS, "."}, + {"set_priv", torrent_set_priv, METH_VARARGS, "."}, + {"test_duplicate", torrent_test_duplicate, METH_VARARGS, "."}, {NULL} }; diff --git a/src/dialogs.py b/src/dialogs.py index aeaa71083..cec540b66 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -201,6 +201,20 @@ class PreferencesDlg: elif widget == self.glade.get_widget('chk_lock_tray'): self.glade.get_widget('txt_tray_passwd').set_sensitive(value) +class MergeDlg: + def __init__(self): + self.glade = gtk.glade.XML(common.get_glade_file("merge_dialog.glade"), + domain='deluge') + self.dialog = self.glade.get_widget("merge_dialog") + self.dialog.set_icon_from_file(common.get_pixmap("deluge32.png")) + + def show(self): + self.dialog.show() + r = self.dialog.run() + self.dialog.hide() + + return r + class FilesDlg: def __init__(self, dumped_torrent): self.glade = gtk.glade.XML(common.get_glade_file("files_dialog.glade"), diff --git a/src/interface.py b/src/interface.py index 88187602d..7427c3acd 100644 --- a/src/interface.py +++ b/src/interface.py @@ -1108,7 +1108,23 @@ class DelugeGTK: print "InvalidEncodingError", e dialogs.show_popup_warning(self.window, _("An error occured while trying to add the torrent. It's possible your .torrent file is corrupted.")) except core.DuplicateTorrentError, e: - dialogs.show_popup_warning(self.window, _("The torrent you've added seems to already be in Deluge.")) + for unique_id in self.manager.unique_IDs: + is_duplicate = self.manager.test_duplicate(torrent, unique_id) + if is_duplicate: + break + if is_duplicate: + merge_dialog = dialogs.MergeDlg() + if merge_dialog.show() == 1: + new_trackers_as_list = self.manager.dump_trackers(torrent).replace(' ','').splitlines(True) + original_trackers_as_list = self.manager.get_trackers(unique_id).replace(' ','').splitlines(True) + for index in xrange(len(new_trackers_as_list)): + if original_trackers_as_list.count(new_trackers_as_list[index]) == 0: + original_trackers_as_list.append(new_trackers_as_list[index]) + merged_trackers_as_string = ''.join([original_trackers_as_list[index] for \ + index in xrange(len(original_trackers_as_list))]) + self.manager.replace_trackers(unique_id, merged_trackers_as_string) + else: + dialogs.show_popup_warning(self.window, _("Unknown duplicate torrent error.")) except core.InsufficientFreeSpaceError, e: nice_need = common.fsize(e.needed_space) nice_free = common.fsize(e.free_space)