# -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 Andrew Resch # # This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with # the additional special exception to link portions of this program with the OpenSSL library. # See LICENSE for more details. # import logging import os.path import gtk from twisted.internet import defer import deluge.component as component from deluge.common import is_url, resource_filename from deluge.configmanager import ConfigManager from deluge.ui.client import client from deluge.ui.gtkui.common import get_deluge_icon log = logging.getLogger(__name__) class EditTrackersDialog: def __init__(self, torrent_id, parent=None): self.torrent_id = torrent_id self.builder = gtk.Builder() self.gtkui_config = ConfigManager("gtkui.conf") # Main dialog self.builder.add_from_file(resource_filename( "deluge.ui.gtkui", os.path.join("glade", "edit_trackers.ui") )) # add tracker dialog self.builder.add_from_file(resource_filename( "deluge.ui.gtkui", os.path.join("glade", "edit_trackers.add.ui") )) # edit tracker dialog self.builder.add_from_file(resource_filename( "deluge.ui.gtkui", os.path.join("glade", "edit_trackers.edit.ui") )) self.dialog = self.builder.get_object("edit_trackers_dialog") self.treeview = self.builder.get_object("tracker_treeview") self.add_tracker_dialog = self.builder.get_object("add_tracker_dialog") self.add_tracker_dialog.set_transient_for(self.dialog) self.edit_tracker_entry = self.builder.get_object("edit_tracker_entry") self.edit_tracker_entry.set_transient_for(self.dialog) self.dialog.set_icon(get_deluge_icon()) self.load_edit_trackers_dialog_state() if parent is not None: self.dialog.set_transient_for(parent) # Connect the signals self.builder.connect_signals({ "on_button_up_clicked": self.on_button_up_clicked, "on_button_add_clicked": self.on_button_add_clicked, "on_button_edit_clicked": self.on_button_edit_clicked, "on_button_edit_cancel_clicked": self.on_button_edit_cancel_clicked, "on_button_edit_ok_clicked": self.on_button_edit_ok_clicked, "on_button_remove_clicked": self.on_button_remove_clicked, "on_button_down_clicked": self.on_button_down_clicked, "on_button_add_ok_clicked": self.on_button_add_ok_clicked, "on_button_add_cancel_clicked": self.on_button_add_cancel_clicked, "on_edit_trackers_dialog_configure_event": self.on_edit_trackers_dialog_configure_event }) # Create a liststore for tier, url self.liststore = gtk.ListStore(int, str) # Create the columns self.treeview.append_column( gtk.TreeViewColumn(_("Tier"), gtk.CellRendererText(), text=0)) self.treeview.append_column( gtk.TreeViewColumn(_("Tracker"), gtk.CellRendererText(), text=1)) self.treeview.set_model(self.liststore) self.liststore.set_sort_column_id(0, gtk.SORT_ASCENDING) self.dialog.connect("delete-event", self._on_delete_event) self.dialog.connect("response", self._on_response) def run(self): # Make sure we have a torrent_id.. if not just return if self.torrent_id is None: return # Get the trackers for this torrent session = component.get("SessionProxy") session.get_torrent_status( self.torrent_id, ["trackers"] ).addCallback(self._on_get_torrent_status) client.force_call() self.deferred = defer.Deferred() return self.deferred def __del__(self): del self.gtkui_config def load_edit_trackers_dialog_state(self): w = self.gtkui_config["edit_trackers_dialog_width"] h = self.gtkui_config["edit_trackers_dialog_height"] if w is not None and h is not None: self.dialog.resize(w, h) def on_edit_trackers_dialog_configure_event(self, widget, event): self.gtkui_config["edit_trackers_dialog_width"] = event.width self.gtkui_config["edit_trackers_dialog_height"] = event.height def _on_delete_event(self, widget, event): self.deferred.callback(gtk.RESPONSE_DELETE_EVENT) self.dialog.destroy() def _on_response(self, widget, response): if response == 1: self.trackers = [] def each(model, path, iter, data): tracker = {} tracker["tier"] = model.get_value(iter, 0) tracker["url"] = model.get_value(iter, 1) self.trackers.append(tracker) self.liststore.foreach(each, None) if self.old_trackers != self.trackers: # Set the torrens trackers client.core.set_torrent_trackers(self.torrent_id, self.trackers) self.deferred.callback(gtk.RESPONSE_OK) else: self.deferred.callback(gtk.RESPONSE_CANCEL) else: self.deferred.callback(gtk.RESPONSE_CANCEL) self.dialog.destroy() def _on_get_torrent_status(self, status): """Display trackers dialog""" self.old_trackers = list(status["trackers"]) for tracker in self.old_trackers: self.add_tracker(tracker["tier"], tracker["url"]) self.treeview.set_cursor((0)) self.dialog.show() def add_tracker(self, tier, url): """Adds a tracker to the list""" self.liststore.append([tier, url]) def get_selected(self): """Returns the selected tracker""" return self.treeview.get_selection().get_selected()[1] def on_button_add_clicked(self, widget): log.debug("on_button_add_clicked") # Show the add tracker dialog self.add_tracker_dialog.show() self.builder.get_object("textview_trackers").grab_focus() def on_button_remove_clicked(self, widget): log.debug("on_button_remove_clicked") selected = self.get_selected() if selected is not None: self.liststore.remove(selected) def on_button_edit_clicked(self, widget): """edits an existing tracker""" log.debug("on_button_edit_clicked") selected = self.get_selected() if selected: tracker = self.liststore.get_value(selected, 1) self.builder.get_object("entry_edit_tracker").set_text(tracker) self.edit_tracker_entry.show() self.edit_tracker_entry.grab_focus() self.dialog.set_sensitive(False) def on_button_edit_cancel_clicked(self, widget): log.debug("on_button_edit_cancel_clicked") self.dialog.set_sensitive(True) self.edit_tracker_entry.hide() def on_button_edit_ok_clicked(self, widget): log.debug("on_button_edit_ok_clicked") selected = self.get_selected() tracker = self.builder.get_object("entry_edit_tracker").get_text() self.liststore.set_value(selected, 1, tracker) self.dialog.set_sensitive(True) self.edit_tracker_entry.hide() def on_button_up_clicked(self, widget): log.debug("on_button_up_clicked") selected = self.get_selected() num_rows = self.liststore.iter_n_children(None) if selected is not None and num_rows > 1: tier = self.liststore.get_value(selected, 0) if not tier > 0: return new_tier = tier - 1 # Now change the tier for this tracker self.liststore.set_value(selected, 0, new_tier) def on_button_down_clicked(self, widget): log.debug("on_button_down_clicked") selected = self.get_selected() num_rows = self.liststore.iter_n_children(None) if selected is not None and num_rows > 1: tier = self.liststore.get_value(selected, 0) new_tier = tier + 1 # Now change the tier for this tracker self.liststore.set_value(selected, 0, new_tier) def on_button_add_ok_clicked(self, widget): log.debug("on_button_add_ok_clicked") # Create a list of trackers from the textview widget textview = self.builder.get_object("textview_trackers") 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 is_url(l): trackers.append(l) for tracker in trackers: # Figure out what tier number to use.. it's going to be the highest+1 # Also check for duplicates # Check if there are any entries duplicate = False highest_tier = -1 for row in self.liststore: tier = row[0] if tier > highest_tier: highest_tier = tier if tracker == row[1]: duplicate = True break # If not a duplicate, then add it to the list if not duplicate: # Add the tracker to the list self.add_tracker(highest_tier + 1, tracker) # Clear the entry widget and hide the dialog textview.get_buffer().set_text("") self.add_tracker_dialog.hide() def on_button_add_cancel_clicked(self, widget): log.debug("on_button_add_cancel_clicked") # Clear the entry widget and hide the dialog b = gtk.TextBuffer() self.builder.get_object("textview_trackers").set_buffer(b) self.add_tracker_dialog.hide()