diff --git a/ChangeLog b/ChangeLog index c8a2b6f6b..dc3533db5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,3 +10,4 @@ Deluge 1.1.0 - "" (In Development) * Sorting # column will place downloaders above seeds * Remove dependency on libtorrent for add torrent dialog * Allow adding multiple trackers at once in the edit tracker dialog + * Implement #28 Create Torrent Dialog diff --git a/deluge/core/core.py b/deluge/core/core.py index cf8e0bf03..e4c4e948b 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -645,7 +645,41 @@ class Core( """Returns the size of the file or folder 'path' and -1 if the path is unaccessible (non-existent or insufficient privs)""" return deluge.common.get_path_size(path) - + + def export_create_torrent(self, path, tracker, piece_length, comment, target, + url_list, private, created_by, httpseeds, add_to_session): + + log.debug("creating torrent..") + threading.Thread(target=_create_torrent_thread, + args=( + path, + tracker, + piece_length, + comment, + target, + url_list, + private, + created_by, + httpseeds, + add_to_session)).start() + + def _create_torrent_thread(self, path, tracker, piece_length, comment, target, + url_list, private, created_by, httpseeds, add_to_session): + import deluge.metafile + deluge.metafile.make_meta_file( + path, + tracker, + piece_length, + comment=comment, + target=target, + url_list=url_list, + private=private, + created_by=created_by, + httpseeds=httpseeds) + log.debug("torrent created!") + if add_to_session: + self.export_add_torrent_file(os.path.split(target)[1], open(target, "rb").read(), None) + ## Queueing functions ## def export_queue_top(self, torrent_ids): log.debug("Attempting to queue %s to top", torrent_ids) diff --git a/deluge/metafile.py b/deluge/metafile.py index 98904434d..2b5620a58 100644 --- a/deluge/metafile.py +++ b/deluge/metafile.py @@ -72,11 +72,11 @@ def decode_from_filesystem(path): def dummy(v): pass -def make_meta_file(path, url, piece_len_exp, progress=dummy, +def make_meta_file(path, url, piece_length, progress=dummy, title=None, comment=None, safe=None, content_type=None, - target=None, url_list=None, name=None): + target=None, url_list=None, name=None, private=False, + created_by=None, httpseeds=None): data = {'announce': url.strip(), 'creation date': int(gmtime())} - piece_length = 2 ** piece_len_exp a, b = os.path.split(path) if not target: if b == '': @@ -85,7 +85,7 @@ def make_meta_file(path, url, piece_len_exp, progress=dummy, f = os.path.join(a, b + '.torrent') else: f = target - info = makeinfo(path, piece_length, progress, name, content_type) + info = makeinfo(path, piece_length, progress, name, content_type, private) #check_info(info) h = file(f, 'wb') @@ -99,6 +99,11 @@ def make_meta_file(path, url, piece_len_exp, progress=dummy, data['safe'] = safe if url_list: data['url-list'] = url_list + if created_by: + data['created by'] = created_by + if httpseeds: + data['httpseeds'] = httpseeds + h.write(bencode(data)) h.close() @@ -109,7 +114,7 @@ def calcsize(path): return total def makeinfo(path, piece_length, progress, name = None, - content_type = None): # HEREDAVE. If path is directory, + content_type = None, private=False): # HEREDAVE. If path is directory, # how do we assign content type? def to_utf8(name): if isinstance(name, unicode): @@ -130,6 +135,7 @@ def makeinfo(path, piece_length, progress, name = None, 'characters.' % name) return u.encode('utf-8') path = os.path.abspath(path) + piece_count = 0 if os.path.isdir(path): subs = subfiles(path) subs.sort() @@ -141,7 +147,8 @@ def makeinfo(path, piece_length, progress, name = None, totalhashed = 0 for p, f in subs: totalsize += os.path.getsize(f) - + num_pieces = totalsize / piece_length + for p, f in subs: pos = 0 size = os.path.getsize(f) @@ -155,6 +162,7 @@ def makeinfo(path, piece_length, progress, name = None, while pos < size: a = min(size - pos, piece_length - done) sh.update(h.read(a)) + piece_count += 1 done += a pos += a totalhashed += a @@ -163,7 +171,7 @@ def makeinfo(path, piece_length, progress, name = None, pieces.append(sh.digest()) done = 0 sh = sha() - progress(a) + progress(piece_count, num_pieces) h.close() if done > 0: pieces.append(sh.digest()) @@ -176,30 +184,33 @@ def makeinfo(path, piece_length, progress, name = None, return {'pieces': ''.join(pieces), 'piece length': piece_length, 'files': fs, - 'name': name} + 'name': name, + 'private': private} else: size = os.path.getsize(path) + num_pieces = size / piece_length pieces = [] p = 0 h = file(path, 'rb') while p < size: x = h.read(min(piece_length, size - p)) - if flag.isSet(): - return pieces.append(sha(x).digest()) + piece_count += 1 p += piece_length if p > size: p = size - progress(min(piece_length, size - p)) + progress(piece_count, num_pieces) h.close() if content_type is not None: return {'pieces': ''.join(pieces), 'piece length': piece_length, 'length': size, 'name': to_utf8(os.path.split(path)[1]), - 'content_type' : content_type } + 'content_type' : content_type, + 'private': private } return {'pieces': ''.join(pieces), 'piece length': piece_length, 'length': size, - 'name': to_utf8(os.path.split(path)[1])} + 'name': to_utf8(os.path.split(path)[1]), + 'private': private} def subfiles(d): r = [] diff --git a/deluge/ui/client.py b/deluge/ui/client.py index 69662a3f9..2f8300a9f 100644 --- a/deluge/ui/client.py +++ b/deluge/ui/client.py @@ -169,7 +169,7 @@ class BaseClient(object): "set_torrent_prioritize_first_last", "set_torrent_auto_managed", "set_torrent_stop_ratio", "set_torrent_stop_at_ratio", "set_torrent_remove_at_ratio", "set_torrent_move_on_completed", - "set_torrent_move_on_completed_path", "add_torrent_magnets"] + "set_torrent_move_on_completed_path", "add_torrent_magnets", "create_torrent"] def __init__(self): self.core = _core diff --git a/deluge/ui/gtkui/createtorrentdialog.py b/deluge/ui/gtkui/createtorrentdialog.py index 812980571..b27fbc1ef 100644 --- a/deluge/ui/gtkui/createtorrentdialog.py +++ b/deluge/ui/gtkui/createtorrentdialog.py @@ -33,67 +33,356 @@ import gtk import pkg_resources +import os.path +import gobject +from deluge.ui.client import aclient as client +import deluge.ui.gtkui.listview as listview import deluge.component as component import deluge.common from deluge.configmanager import ConfigManager from deluge.log import LOG as log class CreateTorrentDialog: - def __init__(self): - pass - def show(self): - self.config = ConfigManager("gtkui.conf") - glade = gtk.glade.XML( + self.glade = gtk.glade.XML( pkg_resources.resource_filename( "deluge.ui.gtkui", "glade/create_torrent_dialog.glade")) - - self.dialog = glade.get_widget("create_torrent_dialog") + + self.config = ConfigManager("gtkui.conf") + + self.dialog = self.glade.get_widget("create_torrent_dialog") self.dialog.set_transient_for(component.get("MainWindow").window) - - glade.signal_autoconnect({ + + self.glade.signal_autoconnect({ "on_button_file_clicked": self._on_button_file_clicked, "on_button_folder_clicked": self._on_button_folder_clicked, "on_button_remote_path_clicked": self._on_button_remote_path_clicked, "on_button_cancel_clicked": self._on_button_cancel_clicked, - "on_button_create_clicked": self._on_button_create_clicked, + "on_button_save_clicked": self._on_button_save_clicked, "on_button_up_clicked": self._on_button_up_clicked, "on_button_add_clicked": self._on_button_add_clicked, "on_button_remove_clicked": self._on_button_remove_clicked, "on_button_down_clicked": self._on_button_down_clicked }) + # path, icon, size + self.files_treestore = gtk.TreeStore(str, str, gobject.TYPE_UINT64) - self.dialog.show_all() + column = gtk.TreeViewColumn(_("Filename")) + render = gtk.CellRendererPixbuf() + column.pack_start(render, False) + column.add_attribute(render, "stock-id", 1) + render = gtk.CellRendererText() + column.pack_start(render, True) + column.add_attribute(render, "text", 0) + column.set_expand(True) + self.glade.get_widget("treeview_files").append_column(column) + + column = gtk.TreeViewColumn(_("Size")) + render = gtk.CellRendererText() + column.pack_start(render) + column.set_cell_data_func(render, listview.cell_data_size, 2) + self.glade.get_widget("treeview_files").append_column(column) + + self.glade.get_widget("treeview_files").set_model(self.files_treestore) + self.glade.get_widget("treeview_files").set_show_expanders(False) + + # tier, url + self.trackers_liststore = gtk.ListStore(int, str) + + self.glade.get_widget("tracker_treeview").append_column( + gtk.TreeViewColumn(_("Tier"), gtk.CellRendererText(), text=0)) + self.glade.get_widget("tracker_treeview").append_column( + gtk.TreeViewColumn(_("Tracker"), gtk.CellRendererText(), text=1)) + + self.glade.get_widget("tracker_treeview").set_model(self.trackers_liststore) + self.trackers_liststore.set_sort_column_id(0, gtk.SORT_ASCENDING) + if not client.is_localhost() and client.connected(): + self.glade.get_widget("button_remote_path").show() + else: + self.glade.get_widget("button_remote_path").hide() + + self.dialog.show() + + def adjust_piece_size(self): + """Adjusts the recommended piece based on the file/folder/path selected.""" + size = self.files_treestore[0][2] + model = self.glade.get_widget("combo_piece_size").get_model() + psize = 0 + for index,value in enumerate(model): + psize = int(value[0].split()[0]) * 1024 + pieces = size / psize + if pieces < 2048 or (index + 1) == len(model): + self.glade.get_widget("combo_piece_size").set_active(index) + break + def _on_button_file_clicked(self, widget): log.debug("_on_button_file_clicked") + # Setup the filechooserdialog + chooser = gtk.FileChooserDialog(_("Choose a file"), + self.dialog, + gtk.FILE_CHOOSER_ACTION_OPEN, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, + gtk.RESPONSE_OK)) + + chooser.set_transient_for(self.dialog) + chooser.set_select_multiple(False) + chooser.set_property("skip-taskbar-hint", True) + + # Run the dialog + response = chooser.run() + + if response == gtk.RESPONSE_OK: + result = chooser.get_filename() + else: + chooser.destroy() + return + + self.files_treestore.clear() + self.files_treestore.append(None, [result, gtk.STOCK_FILE, deluge.common.get_path_size(result)]) + self.adjust_piece_size() + chooser.destroy() def _on_button_folder_clicked(self, widget): log.debug("_on_button_folder_clicked") - + # Setup the filechooserdialog + chooser = gtk.FileChooserDialog(_("Choose a folder"), + self.dialog, + gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, + gtk.RESPONSE_OK)) + + chooser.set_transient_for(self.dialog) + chooser.set_select_multiple(False) + chooser.set_property("skip-taskbar-hint", True) + # Run the dialog + response = chooser.run() + + if response == gtk.RESPONSE_OK: + result = chooser.get_filename() + else: + chooser.destroy() + return + + self.files_treestore.clear() + + self.files_treestore.append(None, [result, gtk.STOCK_OPEN, deluge.common.get_path_size(result)]) + self.adjust_piece_size() + chooser.destroy() + def _on_button_remote_path_clicked(self, widget): log.debug("_on_button_remote_path_clicked") + dialog = self.glade.get_widget("remote_path_dialog") + entry = self.glade.get_widget("entry_path") + dialog.set_transient_for(self.dialog) + entry.set_text("/") + entry.grab_focus() + response = dialog.run() + + if response == gtk.RESPONSE_OK: + result = entry.get_text() + def _on_get_path_size(size): + log.debug("size: %s", size) + if size > 0: + self.files_treestore.clear() + self.files_treestore.append(None, [result, gtk.STOCK_NETWORK, size]) + self.adjust_piece_size() + client.get_path_size(_on_get_path_size, result) + client.force_call(True) + + dialog.destroy() def _on_button_cancel_clicked(self, widget): log.debug("_on_button_cancel_clicked") self.dialog.destroy() - def _on_button_create_clicked(self, widget): - log.debug("_on_button_create_clicked") + def _on_button_save_clicked(self, widget): + log.debug("_on_button_save_clicked") + if len(self.files_treestore) == 0: + return + + is_remote = self.files_treestore[0][1] == gtk.STOCK_NETWORK + if is_remote: + # This is a remote path + response = self.glade.get_widget("remote_save_dialog").run() + if response == gtk.RESPONSE_OK: + result = self.glade.get_widget("entry_save_path").get_text() + else: + return + else: + # Setup the filechooserdialog + chooser = gtk.FileChooserDialog(_("Save .torrent file"), + self.dialog, + gtk.FILE_CHOOSER_ACTION_SAVE, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, + gtk.RESPONSE_OK)) + + chooser.set_transient_for(self.dialog) + chooser.set_select_multiple(False) + chooser.set_property("skip-taskbar-hint", True) + + # Add .torrent and * file filters + file_filter = gtk.FileFilter() + file_filter.set_name(_("Torrent files")) + file_filter.add_pattern("*." + "torrent") + chooser.add_filter(file_filter) + file_filter = gtk.FileFilter() + file_filter.set_name(_("All files")) + file_filter.add_pattern("*") + chooser.add_filter(file_filter) + + # Run the dialog + response = chooser.run() + + if response == gtk.RESPONSE_OK: + result = chooser.get_filename() + else: + chooser.destroy() + return + + # Fix up torrent filename + if len(result) < 9: + result += ".torrent" + elif result[-8:] != ".torrent": + result += ".torrent" + + # Get the path + path = self.files_treestore[0][0] + # Get a list of trackers + trackers = [t[1] for t in self.trackers_liststore] + if len(trackers) == 0: + return + # Get a list of webseeds + webseeds = [] + b = self.glade.get_widget("textview_webseeds").get_buffer() + lines = b.get_text(b.get_start_iter(), b.get_end_iter()).strip().split("\n") + import deluge.common + for l in lines: + if deluge.common.is_url(l): + webseeds.append(l) + # Get the piece length in bytes + combo = self.glade.get_widget("combo_piece_size") + piece_length = int(combo.get_model()[combo.get_active()][0].split()[0]) * 1024 + num_pieces = self.files_treestore[0][2] / piece_length + + author = self.glade.get_widget("entry_author").get_text() + comment = self.glade.get_widget("entry_comments").get_text() + private = self.glade.get_widget("chk_private_flag").get_active() + add_to_session = self.glade.get_widget("chk_add_to_session").get_active() + + if is_remote: + client.create_torrent( + path, + trackers[0], + piece_length, + comment, + result, + trackers, + private, + author, + webseeds, + add_to_session) + + else: + # Setup progress dialog + self.glade.get_widget("progress_dialog").set_transient_for(component.get("MainWindow").window) + self.glade.get_widget("progress_dialog").show_all() + + import threading + threading.Thread(target=self.create_torrent, + args=( + path, + trackers[0], + piece_length, + self._on_create_torrent_progress, + comment, + result, + trackers, + private, + author, + webseeds, + add_to_session)).start() + + chooser.destroy() self.dialog.destroy() + + def create_torrent(self, path, tracker, piece_length, progress, comment, target, + url_list, private, created_by, httpseeds, add_to_session): + import deluge.metafile + deluge.metafile.make_meta_file( + path, + tracker, + piece_length, + progress=progress, + comment=comment, + target=target, + url_list=url_list, + private=private, + created_by=created_by, + httpseeds=httpseeds) + self.glade.get_widget("progress_dialog").hide_all() + if add_to_session: + client.add_torrent_files([target]) + + def _on_create_torrent_progress(self, value, num_pieces): + percent = float(value)/float(num_pieces) + pbar = self.glade.get_widget("progressbar") + pbar.set_text(_("%.2f%%") % (percent*100)) + if percent >= 0 and percent <= 1.0: + pbar.set_fraction(percent) def _on_button_up_clicked(self, widget): log.debug("_on_button_up_clicked") - + row = self.glade.get_widget("tracker_treeview").get_selection().get_selected()[1] + if self.trackers_liststore[row][0] == 0: + return + else: + self.trackers_liststore[row][0] -= 1 + + def _on_button_down_clicked(self, widget): + log.debug("_on_button_down_clicked") + row = self.glade.get_widget("tracker_treeview").get_selection().get_selected()[1] + self.trackers_liststore[row][0] += 1 + def _on_button_add_clicked(self, widget): log.debug("_on_button_add_clicked") + glade = gtk.glade.XML( + pkg_resources.resource_filename( + "deluge.ui.gtkui", + "glade/edit_trackers.glade")) + dialog = glade.get_widget("add_tracker_dialog") + dialog.set_transient_for(self.dialog) + textview = glade.get_widget("textview_trackers") + textview.get_buffer().set_text("") + textview.grab_focus() + response = dialog.run() + + if response == gtk.RESPONSE_OK: + # Create a list of trackers from the textview buffer + trackers = [] + b = textview.get_buffer() + lines = b.get_text(b.get_start_iter(), b.get_end_iter()).strip().split("\n") + for l in lines: + if deluge.common.is_url(l): + trackers.append(l) + + # We are going to add these trackers to the heighest tier + 1 + tier = 0 + for row in self.trackers_liststore: + if row[0] > tier: + tier = row[0] + + for tracker in trackers: + self.trackers_liststore.append([tier, tracker]) + + dialog.destroy() def _on_button_remove_clicked(self, widget): log.debug("_on_button_remove_clicked") - - def _on_button_down_clicked(self, widget): - log.debug("_on_button_down_clicked") + row = self.glade.get_widget("tracker_treeview").get_selection().get_selected()[1] + self.trackers_liststore.remove(row) + diff --git a/deluge/ui/gtkui/glade/create_torrent_dialog.glade b/deluge/ui/gtkui/glade/create_torrent_dialog.glade index c7504b0fd..9df3c7280 100644 --- a/deluge/ui/gtkui/glade/create_torrent_dialog.glade +++ b/deluge/ui/gtkui/glade/create_torrent_dialog.glade @@ -1,9 +1,8 @@ - + - 560 5 Create Torrent GTK_WIN_POS_CENTER_ON_PARENT @@ -82,10 +81,15 @@ True True + False True + + False + False + @@ -279,48 +283,31 @@ - + True - 2 - 2 - 5 - - - - - - True - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_IN - - - True - True - - - - - 1 - 2 - 2 - - + 5 True - 0 - 0 Comments: - GTK_FILL - + False + + + + + True + True + + + 1 + False + False 1 @@ -394,7 +381,7 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-go-up + gtk-go-up True 0 @@ -421,7 +408,7 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-remove + gtk-remove True 0 @@ -436,7 +423,7 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-go-down + gtk-go-down True 0 @@ -497,7 +484,7 @@ True GTK_RESIZE_QUEUE - + True True @@ -562,6 +549,11 @@ True + 32 KiB +64 KiB +128 KiB +256 KiB +512 KiB False @@ -655,20 +647,21 @@ True True True - gtk-cancel + gtk-cancel True 0 - + True True True gtk-save True 0 + 1 @@ -686,4 +679,333 @@ + + 462 + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Enter Remote Path + GTK_WIN_POS_CENTER_ON_PARENT + True + GDK_WINDOW_TYPE_HINT_DIALOG + False + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-network + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Remote Path</b> + True + + + False + False + 1 + + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Path: + + + False + False + + + + + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + 1 + + + + + False + False + 2 + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-cancel + True + -6 + + + + + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-ok + True + -5 + + + 1 + + + + + False + GTK_PACK_END + + + + + + + 5 + Creating Torrent + GTK_WIN_POS_CENTER_ON_PARENT + GDK_WINDOW_TYPE_HINT_DIALOG + False + + + True + 2 + + + 200 + True + + + + False + False + 1 + + + + + True + GTK_BUTTONBOX_END + + + False + GTK_PACK_END + + + + + + + 462 + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Save .torrent as + GTK_WIN_POS_CENTER_ON_PARENT + True + GDK_WINDOW_TYPE_HINT_DIALOG + False + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-network + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Save .torrent file</b> + True + + + False + False + 1 + + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Path: + + + False + False + + + + + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + 1 + + + + + False + False + 2 + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-cancel + True + -6 + + + + + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-ok + True + -5 + + + 1 + + + + + False + GTK_PACK_END + + + + + diff --git a/deluge/ui/gtkui/glade/edit_trackers.glade b/deluge/ui/gtkui/glade/edit_trackers.glade index c45d6b6f3..960a418f5 100644 --- a/deluge/ui/gtkui/glade/edit_trackers.glade +++ b/deluge/ui/gtkui/glade/edit_trackers.glade @@ -1,6 +1,6 @@ - + 400 @@ -343,7 +343,7 @@ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-cancel True - 0 + -6 @@ -357,7 +357,7 @@ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-ok True - 0 + -5