diff --git a/deluge/core/core.py b/deluge/core/core.py index 60128b471..29b43f363 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -19,6 +19,7 @@ from urlparse import urljoin import twisted.web.client import twisted.web.error +from twisted.internet import reactor, task import deluge.common import deluge.component as component @@ -186,36 +187,69 @@ class Core(component.Component): return self.new_release return False + def _add_torrent_file(self, filename, filedump, options, save_state=True): + """Adds a torrent file to the session. + + Args: + filename (str): The filename of the torrent. + filedump (str): A base64 encoded string of torrent file contents. + options (dict): The options to apply to the torrent upon adding. + save_state (bool): If the state should be saved after adding the file. + + Returns: + str: The torrent ID or None. + + """ + try: + filedump = base64.decodestring(filedump) + except Exception as ex: + log.error("There was an error decoding the filedump string: %s", ex) + + try: + torrent_id = self.torrentmanager.add( + filedump=filedump, options=options, filename=filename, save_state=save_state + ) + except RuntimeError as ex: + log.error("There was an error adding the torrent file %s: %s", filename, ex) + torrent_id = None + return torrent_id + # Exported Methods @export def add_torrent_file(self, filename, filedump, options): """Adds a torrent file to the session. Args: - filename (str): the filename of the torrent - filedump (str): A base64 encoded string of the torrent file contents - options (dict): The options to apply to the torrent on add + filename (str): The filename of the torrent. + filedump (str): A base64 encoded string of the torrent file contents. + options (dict): The options to apply to the torrent upon adding. Returns: - str: The torrent_id or None + str: The torrent_id or None. """ - try: - filedump = base64.decodestring(filedump) - except Exception as ex: - log.error("There was an error decoding the filedump string!") - log.exception(ex) + return self._add_torrent_file(filename, filedump, options) - try: - torrent_id = self.torrentmanager.add( - filedump=filedump, options=options, filename=filename - ) - except Exception as ex: - log.error("There was an error adding the torrent file %s", filename) - log.exception(ex) - torrent_id = None + @export + def add_torrent_files(self, torrent_files): + """Adds multiple torrent files to the session. - return torrent_id + Args: + torrent_files (list of tuples): Torrent files as tuple of (filename, filedump, options). + + Returns: + Deferred + + """ + def add_torrents(): + torrent_ids = [] + count = len(torrent_files) + for idx, torrent in enumerate(torrent_files): + torrent_id = self._add_torrent_file(torrent[0], torrent[1], + torrent[2], save_state=idx == (count - 1)) + torrent_ids.append(torrent_id) + return torrent_ids + return task.deferLater(reactor, 0, add_torrents) @export def add_torrent_url(self, url, options, headers=None): diff --git a/deluge/ui/gtkui/addtorrentdialog.py b/deluge/ui/gtkui/addtorrentdialog.py index a8f64f552..3bf1e7e31 100644 --- a/deluge/ui/gtkui/addtorrentdialog.py +++ b/deluge/ui/gtkui/addtorrentdialog.py @@ -182,6 +182,7 @@ class AddTorrentDialog(component.Component): def add_from_files(self, filenames): new_row = None + already_added = 0 for filename in filenames: # Get the torrent data from the torrent file @@ -193,12 +194,7 @@ class AddTorrentDialog(component.Component): continue if info.info_hash in self.files: - log.debug("Trying to add a duplicate torrent!") - ErrorDialog( - _("Duplicate Torrent"), - _("You cannot add the same torrent twice."), - self.dialog - ).run() + already_added += 1 continue new_row = self.torrent_liststore.append([info.info_hash, info.name, filename]) @@ -213,6 +209,16 @@ class AddTorrentDialog(component.Component): if not row and new_row: self.listview_torrents.get_selection().select_iter(new_row) + self.builder.get_object("label_torrent_count").set_text("Torrents (%d)" % len(self.torrent_liststore)) + + if already_added: + log.debug("Tried to add %d duplicate torrents!", already_added) + ErrorDialog( + _("Duplicate Torrent(s)"), + _("You cannot add the same torrent twice. %d torrents were already added." % already_added), + self.dialog + ).run() + def add_from_magnets(self, uris): new_row = None @@ -712,11 +718,16 @@ class AddTorrentDialog(component.Component): def _on_button_add_clicked(self, widget): log.debug("_on_button_add_clicked") - # Save the options for selected torrent prior to adding + self.add_torrents() + self.hide() + + def add_torrents(self): (model, row) = self.listview_torrents.get_selection().get_selected() if row is not None: self.save_torrent_options(row) + torrents_to_add = [] + row = self.torrent_liststore.get_iter_first() while row is not None: torrent_id = self.torrent_liststore.get_value(row, 0) @@ -734,14 +745,14 @@ class AddTorrentDialog(component.Component): del options["file_priorities"] client.core.add_torrent_magnet(filename, options) else: - client.core.add_torrent_file( - os.path.split(filename)[-1], - base64.encodestring(self.infos[torrent_id]), - options - ) - + torrents_to_add.append((os.path.split(filename)[-1], + base64.encodestring(self.infos[torrent_id]), + options)) row = self.torrent_liststore.iter_next(row) - self.hide() + + def on_torrents_added(torrent_ids): + log.info("Added %d torrents", len(torrent_ids)) + client.core.add_torrent_files(torrents_to_add).addCallback(on_torrents_added) def _on_button_apply_clicked(self, widget): log.debug("_on_button_apply_clicked") diff --git a/deluge/ui/gtkui/glade/add_torrent_dialog.ui b/deluge/ui/gtkui/glade/add_torrent_dialog.ui index 7c2878139..cc20975d2 100644 --- a/deluge/ui/gtkui/glade/add_torrent_dialog.ui +++ b/deluge/ui/gtkui/glade/add_torrent_dialog.ui @@ -288,7 +288,7 @@ - + True False Torrents