EditTrackerDialog now works.
Save trackers in torrent state. Load trackers on torrent add from state.
This commit is contained in:
parent
190d6d94ea
commit
6bced0fb8c
12
TODO
12
TODO
|
@ -2,20 +2,22 @@
|
||||||
* Queue plugin 'apply_queue' stuff.. Just finishing the queue plugin and it's
|
* Queue plugin 'apply_queue' stuff.. Just finishing the queue plugin and it's
|
||||||
intended functionality.
|
intended functionality.
|
||||||
* Figure out easy way for user-made plugins to add i18n support.
|
* Figure out easy way for user-made plugins to add i18n support.
|
||||||
* Change the menubar.py gtkui component to menus.py and add support for plugins
|
|
||||||
to add menuitems to the torrentmenu in an easy way.
|
|
||||||
* Restart daemon function
|
* Restart daemon function
|
||||||
* Docstrings!
|
* Docstrings!
|
||||||
* Implement caching in client.py
|
* Implement caching in client.py
|
||||||
* Create a new add torrent dialog
|
* Create a new add torrent dialog
|
||||||
* Create edit trackers dialog
|
|
||||||
* Implement open folder
|
* Implement open folder
|
||||||
* Maybe add pop-up menus to the status bar items
|
* Maybe add pop-up menus to the status bar items
|
||||||
* Address issue where torrents will redownload if the storage is moved outside
|
* Address issue where torrents will redownload if the storage is moved outside
|
||||||
of deluge.
|
of deluge.
|
||||||
* Hide open folder if not localhost
|
* Hide open folder if not localhost
|
||||||
* Modify sensitivity of torrent/tray menu based on connection state
|
|
||||||
* Add classic/normal mode to preferences
|
* Add classic/normal mode to preferences
|
||||||
* Implement 'Classic' mode
|
* Implement 'Classic' mode
|
||||||
* Add remove torrent dialog and ability to remove data
|
* Add remove torrent dialog and ability to remove data
|
||||||
|
* Tray tooltip
|
||||||
|
* Add DBUS to gtkui so we can add torrents to existing session
|
||||||
|
* Add LSD
|
||||||
|
* Add torrentfiles location config option
|
||||||
|
* Add autoload folder
|
||||||
|
* Add wizard
|
||||||
|
* Add a health indication to the statusbar
|
||||||
|
|
|
@ -388,6 +388,10 @@ class Core(
|
||||||
"""Forces a data recheck on torrent_id"""
|
"""Forces a data recheck on torrent_id"""
|
||||||
return self.torrents.force_recheck(torrent_id)
|
return self.torrents.force_recheck(torrent_id)
|
||||||
|
|
||||||
|
def export_set_torrent_trackers(self, torrent_id, trackers):
|
||||||
|
"""Sets a torrents tracker list. trackers will be [{"url", "tier"}]"""
|
||||||
|
return self.torrents.set_trackers(torrent_id, trackers)
|
||||||
|
|
||||||
# Signals
|
# Signals
|
||||||
def torrent_added(self, torrent_id):
|
def torrent_added(self, torrent_id):
|
||||||
"""Emitted when a new torrent is added to the core"""
|
"""Emitted when a new torrent is added to the core"""
|
||||||
|
|
|
@ -38,7 +38,8 @@ import deluge.common
|
||||||
class Torrent:
|
class Torrent:
|
||||||
"""Torrent holds information about torrents added to the libtorrent session.
|
"""Torrent holds information about torrents added to the libtorrent session.
|
||||||
"""
|
"""
|
||||||
def __init__(self, filename, handle, compact, save_path, total_uploaded=0):
|
def __init__(self, filename, handle, compact, save_path, total_uploaded=0,
|
||||||
|
trackers=None):
|
||||||
# Set the filename
|
# Set the filename
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
# Set the libtorrent handle
|
# Set the libtorrent handle
|
||||||
|
@ -53,6 +54,17 @@ class Torrent:
|
||||||
self.save_path = save_path
|
self.save_path = save_path
|
||||||
# The tracker status
|
# The tracker status
|
||||||
self.tracker_status = ""
|
self.tracker_status = ""
|
||||||
|
# Tracker list
|
||||||
|
if trackers == None:
|
||||||
|
self.trackers = []
|
||||||
|
# Create a list of trackers
|
||||||
|
for value in self.handle.trackers():
|
||||||
|
tracker = {}
|
||||||
|
tracker["url"] = value.url
|
||||||
|
tracker["tier"] = value.tier
|
||||||
|
self.trackers.append(tracker)
|
||||||
|
else:
|
||||||
|
self.trackers = trackers
|
||||||
|
|
||||||
def set_tracker_status(self, status):
|
def set_tracker_status(self, status):
|
||||||
"""Sets the tracker status"""
|
"""Sets the tracker status"""
|
||||||
|
@ -62,7 +74,8 @@ class Torrent:
|
||||||
"""Returns the state of this torrent for saving to the session state"""
|
"""Returns the state of this torrent for saving to the session state"""
|
||||||
status = self.handle.status()
|
status = self.handle.status()
|
||||||
return (self.torrent_id, self.filename, self.compact, status.paused,
|
return (self.torrent_id, self.filename, self.compact, status.paused,
|
||||||
self.save_path, self.total_uploaded + status.total_payload_upload)
|
self.save_path, self.total_uploaded + status.total_payload_upload,
|
||||||
|
self.trackers)
|
||||||
|
|
||||||
def get_eta(self):
|
def get_eta(self):
|
||||||
"""Returns the ETA in seconds for this torrent"""
|
"""Returns the ETA in seconds for this torrent"""
|
||||||
|
@ -161,6 +174,7 @@ class Torrent:
|
||||||
"eta": self.get_eta(),
|
"eta": self.get_eta(),
|
||||||
"ratio": self.get_ratio(),
|
"ratio": self.get_ratio(),
|
||||||
"tracker": status.current_tracker,
|
"tracker": status.current_tracker,
|
||||||
|
"trackers": self.trackers,
|
||||||
"tracker_status": self.tracker_status,
|
"tracker_status": self.tracker_status,
|
||||||
"save_path": self.save_path,
|
"save_path": self.save_path,
|
||||||
"files": self.get_files()
|
"files": self.get_files()
|
||||||
|
|
|
@ -48,13 +48,14 @@ from deluge.log import LOG as log
|
||||||
|
|
||||||
class TorrentState:
|
class TorrentState:
|
||||||
def __init__(self, torrent_id, filename, compact, paused, save_path,
|
def __init__(self, torrent_id, filename, compact, paused, save_path,
|
||||||
total_uploaded):
|
total_uploaded, trackers):
|
||||||
self.torrent_id = torrent_id
|
self.torrent_id = torrent_id
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.compact = compact
|
self.compact = compact
|
||||||
self.paused = paused
|
self.paused = paused
|
||||||
self.save_path = save_path
|
self.save_path = save_path
|
||||||
self.total_uploaded = total_uploaded
|
self.total_uploaded = total_uploaded
|
||||||
|
self.trackers = trackers
|
||||||
|
|
||||||
class TorrentManagerState:
|
class TorrentManagerState:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -121,7 +122,7 @@ class TorrentManager:
|
||||||
return self.torrents.keys()
|
return self.torrents.keys()
|
||||||
|
|
||||||
def add(self, filename, filedump=None, compact=None, paused=False,
|
def add(self, filename, filedump=None, compact=None, paused=False,
|
||||||
save_path=None, total_uploaded=0):
|
save_path=None, total_uploaded=0, trackers=None):
|
||||||
"""Add a torrent to the manager and returns it's torrent_id"""
|
"""Add a torrent to the manager and returns it's torrent_id"""
|
||||||
log.info("Adding torrent: %s", filename)
|
log.info("Adding torrent: %s", filename)
|
||||||
|
|
||||||
|
@ -174,7 +175,7 @@ class TorrentManager:
|
||||||
str(save_path),
|
str(save_path),
|
||||||
resume_data=fastresume,
|
resume_data=fastresume,
|
||||||
storage_mode=storage_mode,
|
storage_mode=storage_mode,
|
||||||
paused=paused)
|
paused=True)
|
||||||
except RuntimeError, e:
|
except RuntimeError, e:
|
||||||
log.warning("Error adding torrent: %s", e)
|
log.warning("Error adding torrent: %s", e)
|
||||||
|
|
||||||
|
@ -184,15 +185,23 @@ class TorrentManager:
|
||||||
|
|
||||||
# Create a Torrent object
|
# Create a Torrent object
|
||||||
torrent = Torrent(filename, handle, compact,
|
torrent = Torrent(filename, handle, compact,
|
||||||
save_path, total_uploaded)
|
save_path, total_uploaded, trackers)
|
||||||
|
|
||||||
# Add the torrent object to the dictionary
|
# Add the torrent object to the dictionary
|
||||||
self.torrents[torrent.torrent_id] = torrent
|
self.torrents[torrent.torrent_id] = torrent
|
||||||
|
|
||||||
|
# Set the trackers
|
||||||
|
if trackers != None:
|
||||||
|
self.set_trackers(str(handle.info_hash()), trackers)
|
||||||
|
|
||||||
# Set per-torrent limits
|
# Set per-torrent limits
|
||||||
handle.set_max_connections(self.max_connections)
|
handle.set_max_connections(self.max_connections)
|
||||||
handle.set_max_uploads(self.max_uploads)
|
handle.set_max_uploads(self.max_uploads)
|
||||||
|
|
||||||
|
# Resume the torrent if needed
|
||||||
|
if paused == False:
|
||||||
|
handle.resume()
|
||||||
|
|
||||||
# Save the torrent file
|
# Save the torrent file
|
||||||
self.save_torrent(filename, filedump)
|
self.save_torrent(filename, filedump)
|
||||||
|
|
||||||
|
@ -305,6 +314,27 @@ class TorrentManager:
|
||||||
|
|
||||||
return torrent_was_resumed
|
return torrent_was_resumed
|
||||||
|
|
||||||
|
def set_trackers(self, torrent_id, trackers):
|
||||||
|
"""Sets trackers"""
|
||||||
|
if trackers == [] or trackers == None:
|
||||||
|
return
|
||||||
|
log.debug("Setting trackers for %s", torrent_id)
|
||||||
|
tracker_list = []
|
||||||
|
|
||||||
|
for tracker in trackers:
|
||||||
|
new_entry = lt.announce_entry(tracker["url"])
|
||||||
|
new_entry.tier = tracker["tier"]
|
||||||
|
tracker_list.append(new_entry)
|
||||||
|
|
||||||
|
self.torrents[torrent_id].handle.replace_trackers(tracker_list)
|
||||||
|
# Print out the trackers
|
||||||
|
for t in self.torrents[torrent_id].handle.trackers():
|
||||||
|
log.debug("tier: %s tracker: %s", t.tier, t.url)
|
||||||
|
# Set the tracker list in the torrent object
|
||||||
|
self.torrents[torrent_id].trackers = trackers
|
||||||
|
# Force a reannounce
|
||||||
|
self.force_reannounce(torrent_id)
|
||||||
|
|
||||||
def force_reannounce(self, torrent_id):
|
def force_reannounce(self, torrent_id):
|
||||||
"""Force a tracker reannounce"""
|
"""Force a tracker reannounce"""
|
||||||
try:
|
try:
|
||||||
|
@ -381,7 +411,8 @@ class TorrentManager:
|
||||||
for torrent_state in state.torrents:
|
for torrent_state in state.torrents:
|
||||||
self.add(torrent_state.filename, compact=torrent_state.compact,
|
self.add(torrent_state.filename, compact=torrent_state.compact,
|
||||||
paused=torrent_state.paused, save_path=torrent_state.save_path,
|
paused=torrent_state.paused, save_path=torrent_state.save_path,
|
||||||
total_uploaded=torrent_state.total_uploaded)
|
total_uploaded=torrent_state.total_uploaded,
|
||||||
|
trackers=torrent_state.trackers)
|
||||||
|
|
||||||
def save_state(self):
|
def save_state(self):
|
||||||
"""Save the state of the TorrentManager to the torrents.state file"""
|
"""Save the state of the TorrentManager to the torrents.state file"""
|
||||||
|
|
|
@ -337,6 +337,13 @@ def force_recheck(torrent_ids):
|
||||||
except (AttributeError, socket.error):
|
except (AttributeError, socket.error):
|
||||||
set_core_uri(None)
|
set_core_uri(None)
|
||||||
|
|
||||||
|
def set_torrent_trackers(torrent_id, trackers):
|
||||||
|
"""Sets the torrents trackers"""
|
||||||
|
try:
|
||||||
|
get_core().set_torrent_trackers(torrent_id, trackers)
|
||||||
|
except (AttributeError, socket.error):
|
||||||
|
set_core_uri(None)
|
||||||
|
|
||||||
def open_url_in_browser(url):
|
def open_url_in_browser(url):
|
||||||
"""Opens link in the desktop's default browser"""
|
"""Opens link in the desktop's default browser"""
|
||||||
def start_browser():
|
def start_browser():
|
||||||
|
|
|
@ -41,11 +41,16 @@ from deluge.log import LOG as log
|
||||||
|
|
||||||
class EditTrackersDialog:
|
class EditTrackersDialog:
|
||||||
def __init__(self, torrent_id, parent=None):
|
def __init__(self, torrent_id, parent=None):
|
||||||
|
self.torrent_id = torrent_id
|
||||||
self.glade = gtk.glade.XML(
|
self.glade = gtk.glade.XML(
|
||||||
pkg_resources.resource_filename("deluge.ui.gtkui",
|
pkg_resources.resource_filename("deluge.ui.gtkui",
|
||||||
"glade/edit_trackers.glade"))
|
"glade/edit_trackers.glade"))
|
||||||
|
|
||||||
self.dialog = self.glade.get_widget("edit_trackers_dialog")
|
self.dialog = self.glade.get_widget("edit_trackers_dialog")
|
||||||
|
self.treeview = self.glade.get_widget("tracker_treeview")
|
||||||
|
self.add_tracker_dialog = self.glade.get_widget("add_tracker_dialog")
|
||||||
|
self.add_tracker_dialog.set_transient_for(self.dialog)
|
||||||
|
|
||||||
self.dialog.set_icon(deluge.common.get_logo(32))
|
self.dialog.set_icon(deluge.common.get_logo(32))
|
||||||
|
|
||||||
if parent != None:
|
if parent != None:
|
||||||
|
@ -58,21 +63,148 @@ class EditTrackersDialog:
|
||||||
"on_button_remove_clicked": self.on_button_remove_clicked,
|
"on_button_remove_clicked": self.on_button_remove_clicked,
|
||||||
"on_button_down_clicked": self.on_button_down_clicked,
|
"on_button_down_clicked": self.on_button_down_clicked,
|
||||||
"on_button_ok_clicked": self.on_button_ok_clicked,
|
"on_button_ok_clicked": self.on_button_ok_clicked,
|
||||||
"on_button_cancel_clicked": self.on_button_cancel_clicked
|
"on_button_cancel_clicked": self.on_button_cancel_clicked,
|
||||||
|
"on_button_add_ok_clicked": self.on_button_add_ok_clicked,
|
||||||
|
"on_button_add_cancel_clicked": self.on_button_add_cancel_clicked
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
# Make sure we have a torrent_id.. if not just return
|
||||||
|
if self.torrent_id == None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get the trackers for this torrent
|
||||||
|
trackers = client.get_torrent_status(self.torrent_id, ["trackers"])
|
||||||
|
for tracker in trackers["trackers"]:
|
||||||
|
self.add_tracker(tracker["tier"], tracker["url"])
|
||||||
|
|
||||||
self.dialog.show()
|
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_up_clicked(self, widget):
|
def on_button_up_clicked(self, widget):
|
||||||
log.debug("on_button_up_clicked")
|
log.debug("on_button_up_clicked")
|
||||||
|
selected = self.get_selected()
|
||||||
|
num_rows = self.liststore.iter_n_children(None)
|
||||||
|
if selected != None and num_rows > 1:
|
||||||
|
tier = self.liststore.get_value(selected, 0)
|
||||||
|
new_tier = tier - 1
|
||||||
|
# Return if the tier is already at the top
|
||||||
|
if tier == 0:
|
||||||
|
return
|
||||||
|
# Change the tier of the tracker we're surplanting
|
||||||
|
def change_tier(model, path, iter, data):
|
||||||
|
t = model.get_value(iter, 0)
|
||||||
|
if t == data:
|
||||||
|
model.set_value(iter, 0, data + 1)
|
||||||
|
self.liststore.foreach(change_tier, new_tier)
|
||||||
|
|
||||||
|
# Now change the tier for this tracker
|
||||||
|
self.liststore.set_value(selected, 0, new_tier)
|
||||||
|
|
||||||
def on_button_add_clicked(self, widget):
|
def on_button_add_clicked(self, widget):
|
||||||
log.debug("on_button_add_clicked")
|
log.debug("on_button_add_clicked")
|
||||||
|
# Show the add tracker dialog
|
||||||
|
self.add_tracker_dialog.show()
|
||||||
|
self.glade.get_widget("entry_tracker").grab_focus()
|
||||||
|
|
||||||
def on_button_remove_clicked(self, widget):
|
def on_button_remove_clicked(self, widget):
|
||||||
log.debug("on_button_remove_clicked")
|
log.debug("on_button_remove_clicked")
|
||||||
|
selected = self.get_selected()
|
||||||
|
if selected != None:
|
||||||
|
self.liststore.remove(selected)
|
||||||
|
|
||||||
def on_button_down_clicked(self, widget):
|
def on_button_down_clicked(self, widget):
|
||||||
log.debug("on_button_down_clicked")
|
log.debug("on_button_down_clicked")
|
||||||
|
selected = self.get_selected()
|
||||||
|
num_rows = self.liststore.iter_n_children(None)
|
||||||
|
if selected != None and num_rows > 1:
|
||||||
|
tier = self.liststore.get_value(selected, 0)
|
||||||
|
new_tier = tier + 1
|
||||||
|
# This tracker is on the bottom already
|
||||||
|
if new_tier == num_rows:
|
||||||
|
return
|
||||||
|
# Change the tier of the tracker we're surplanting
|
||||||
|
def change_tier(model, path, iter, data):
|
||||||
|
t = model.get_value(iter, 0)
|
||||||
|
if t == data:
|
||||||
|
model.set_value(iter, 0, data - 1)
|
||||||
|
self.liststore.foreach(change_tier, new_tier)
|
||||||
|
# Now change the tier for this tracker
|
||||||
|
self.liststore.set_value(selected, 0, new_tier)
|
||||||
|
|
||||||
def on_button_ok_clicked(self, widget):
|
def on_button_ok_clicked(self, widget):
|
||||||
log.debug("on_button_ok_clicked")
|
log.debug("on_button_ok_clicked")
|
||||||
|
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)
|
||||||
|
# Set the torrens trackers
|
||||||
|
client.set_torrent_trackers(self.torrent_id, self.trackers)
|
||||||
|
self.dialog.destroy()
|
||||||
|
|
||||||
def on_button_cancel_clicked(self, widget):
|
def on_button_cancel_clicked(self, widget):
|
||||||
log.debug("on_button_cancel_clicked")
|
log.debug("on_button_cancel_clicked")
|
||||||
|
self.dialog.destroy()
|
||||||
|
|
||||||
|
def on_button_add_ok_clicked(self, widget):
|
||||||
|
log.debug("on_button_add_ok_clicked")
|
||||||
|
tracker = self.glade.get_widget("entry_tracker").get_text()
|
||||||
|
if tracker[:7] != "http://" or tracker[:8] != "https://":
|
||||||
|
# Bad url.. lets prepend http://
|
||||||
|
tracker = "http://" + tracker
|
||||||
|
|
||||||
|
# Figure out what tier number to use.. it's going to be the highest+1
|
||||||
|
# Also check for duplicates
|
||||||
|
self.highest_tier = 0
|
||||||
|
self.duplicate = False
|
||||||
|
def tier_count(model, path, iter, data):
|
||||||
|
tier = model.get_value(iter, 0)
|
||||||
|
if tier > self.highest_tier:
|
||||||
|
self.highest_tier = tier
|
||||||
|
tracker = model.get_value(iter, 1)
|
||||||
|
if data == tracker:
|
||||||
|
# We already have this tracker in the list
|
||||||
|
self.duplicate = True
|
||||||
|
|
||||||
|
# Check if there are any entries
|
||||||
|
if self.liststore.iter_n_children(None) > 0:
|
||||||
|
self.liststore.foreach(tier_count, tracker)
|
||||||
|
else:
|
||||||
|
self.highest_tier = -1
|
||||||
|
|
||||||
|
# If not a duplicate, then add it to the list
|
||||||
|
if not self.duplicate:
|
||||||
|
# Add the tracker to the list
|
||||||
|
self.add_tracker(self.highest_tier + 1, tracker)
|
||||||
|
|
||||||
|
# Clear the entry widget and hide the dialog
|
||||||
|
self.glade.get_widget("entry_tracker").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
|
||||||
|
self.glade.get_widget("entry_tracker").set_text("")
|
||||||
|
self.add_tracker_dialog.hide()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||||
<!--Generated with glade3 3.4.0 on Sat Nov 10 03:18:41 2007 -->
|
<!--Generated with glade3 3.4.0 on Mon Nov 12 03:27:39 2007 -->
|
||||||
<glade-interface>
|
<glade-interface>
|
||||||
<widget class="GtkDialog" id="edit_trackers_dialog">
|
<widget class="GtkDialog" id="edit_trackers_dialog">
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
@ -70,20 +70,12 @@
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||||
|
<property name="shadow_type">GTK_SHADOW_IN</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkViewport" id="viewport3">
|
<widget class="GtkTreeView" id="tracker_treeview">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="resize_mode">GTK_RESIZE_QUEUE</property>
|
|
||||||
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkTreeView" id="tracker_treeview">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
|
||||||
<property name="headers_clickable">True</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -93,7 +85,7 @@
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="spacing">1</property>
|
<property name="spacing">1</property>
|
||||||
<property name="layout_style">GTK_BUTTONBOX_END</property>
|
<property name="layout_style">GTK_BUTTONBOX_CENTER</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkButton" id="button_up">
|
<widget class="GtkButton" id="button_up">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -160,8 +152,6 @@
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
@ -211,4 +201,152 @@
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="GtkDialog" id="add_tracker_dialog">
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="border_width">5</property>
|
||||||
|
<property name="title" translatable="yes">Add Tracker</property>
|
||||||
|
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
|
||||||
|
<property name="destroy_with_parent">True</property>
|
||||||
|
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||||
|
<property name="decorated">False</property>
|
||||||
|
<property name="has_separator">False</property>
|
||||||
|
<child internal-child="vbox">
|
||||||
|
<widget class="GtkVBox" id="dialog-vbox2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="spacing">2</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkVBox" id="vbox1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="spacing">5</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkHBox" id="hbox1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="spacing">5</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkImage" id="image1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="stock">gtk-add</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="label" translatable="yes"><b>Add Tracker</b></property>
|
||||||
|
<property name="use_markup">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkHSeparator" id="hseparator1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkHBox" id="hbox2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="spacing">5</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="label" translatable="yes">Tracker:</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkEntry" id="entry_tracker">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="has_focus">True</property>
|
||||||
|
<property name="is_focus">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="activates_default">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child internal-child="action_area">
|
||||||
|
<widget class="GtkHButtonBox" id="dialog-action_area2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="layout_style">GTK_BUTTONBOX_END</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkButton" id="button_add_cancel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="label" translatable="yes">gtk-cancel</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
<property name="response_id">0</property>
|
||||||
|
<signal name="clicked" handler="on_button_add_cancel_clicked"/>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkButton" id="button_add_ok">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="can_default">True</property>
|
||||||
|
<property name="has_default">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="label" translatable="yes">gtk-ok</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
<property name="response_id">0</property>
|
||||||
|
<signal name="clicked" handler="on_button_add_ok_clicked"/>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="pack_type">GTK_PACK_END</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
</glade-interface>
|
</glade-interface>
|
||||||
|
|
|
@ -184,7 +184,9 @@ class MenuBar(component.Component):
|
||||||
def on_menuitem_edittrackers_activate(self, data=None):
|
def on_menuitem_edittrackers_activate(self, data=None):
|
||||||
log.debug("on_menuitem_edittrackers_activate")
|
log.debug("on_menuitem_edittrackers_activate")
|
||||||
from edittrackersdialog import EditTrackersDialog
|
from edittrackersdialog import EditTrackersDialog
|
||||||
dialog = EditTrackersDialog(None, component.get("MainWindow").window)
|
dialog = EditTrackersDialog(
|
||||||
|
component.get("TorrentView").get_selected_torrent(),
|
||||||
|
component.get("MainWindow").window)
|
||||||
dialog.run()
|
dialog.run()
|
||||||
|
|
||||||
def on_menuitem_remove_activate(self, data=None):
|
def on_menuitem_remove_activate(self, data=None):
|
||||||
|
|
|
@ -272,6 +272,14 @@ class TorrentView(listview.ListView, component.Component):
|
||||||
break
|
break
|
||||||
row = self.liststore.iter_next(row)
|
row = self.liststore.iter_next(row)
|
||||||
|
|
||||||
|
def get_selected_torrent(self):
|
||||||
|
"""Returns a torrent_id or None. If multiple torrents are selected,
|
||||||
|
it will return the torrent_id of the first one."""
|
||||||
|
selected = self.get_selected_torrents()
|
||||||
|
if selected == None:
|
||||||
|
return selected
|
||||||
|
return selected[0]
|
||||||
|
|
||||||
def get_selected_torrents(self):
|
def get_selected_torrents(self):
|
||||||
"""Returns a list of selected torrents or None"""
|
"""Returns a list of selected torrents or None"""
|
||||||
torrent_ids = []
|
torrent_ids = []
|
||||||
|
|
Loading…
Reference in New Issue