Updates to the QueuedTorrents dialog stuff.
Updates to StatusBar.
This commit is contained in:
parent
3c78e41fc2
commit
35fe99eee3
6
TODO
6
TODO
|
@ -22,7 +22,5 @@
|
||||||
* Add a health indication to the statusbar
|
* Add a health indication to the statusbar
|
||||||
* Add sidebar for labels and other things.. Plugins should be able to add their
|
* Add sidebar for labels and other things.. Plugins should be able to add their
|
||||||
own section to this.
|
own section to this.
|
||||||
* Have the dbus interface queue up torrents if we're not connected to a host.
|
* Finish queuedtorrents dialog
|
||||||
Once connected it should prompt the user if they would like to add the
|
* Update statusbar to use new statusbaritems
|
||||||
queued torrents. Maybe add an indicator to the status bar that their are
|
|
||||||
queued torrents.
|
|
||||||
|
|
|
@ -341,7 +341,8 @@ class TorrentManager:
|
||||||
"""Force a tracker reannounce"""
|
"""Force a tracker reannounce"""
|
||||||
try:
|
try:
|
||||||
self.torrents[torrent_id].handle.force_reannounce()
|
self.torrents[torrent_id].handle.force_reannounce()
|
||||||
except:
|
except Exception, e:
|
||||||
|
log.debug("Unable to force reannounce: %s", e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -52,9 +52,7 @@ from deluge.log import LOG as log
|
||||||
|
|
||||||
class DbusInterface(dbus.service.Object, component.Component):
|
class DbusInterface(dbus.service.Object, component.Component):
|
||||||
def __init__(self, args, path="/org/deluge_torrent/Deluge"):
|
def __init__(self, args, path="/org/deluge_torrent/Deluge"):
|
||||||
component.Component.__init__(self, "DbusInterface", ["StatusBar"])
|
component.Component.__init__(self, "DbusInterface")
|
||||||
self.queue = []
|
|
||||||
self.widgets = None
|
|
||||||
# Check to see if the daemon is already running and if not, start it
|
# Check to see if the daemon is already running and if not, start it
|
||||||
bus = dbus.SessionBus()
|
bus = dbus.SessionBus()
|
||||||
obj = bus.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus")
|
obj = bus.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus")
|
||||||
|
@ -89,58 +87,6 @@ class DbusInterface(dbus.service.Object, component.Component):
|
||||||
bus=dbus.SessionBus())
|
bus=dbus.SessionBus())
|
||||||
dbus.service.Object.__init__(self, bus_name, path)
|
dbus.service.Object.__init__(self, bus_name, path)
|
||||||
|
|
||||||
def start(self):
|
|
||||||
"""Called when we connect to a host"""
|
|
||||||
log.debug("DbusInterface start..")
|
|
||||||
if len(self.queue) == 0:
|
|
||||||
return
|
|
||||||
# Make sure status bar info is showing
|
|
||||||
self.widgets = None
|
|
||||||
self.update_status_bar()
|
|
||||||
|
|
||||||
def add_to_queue(self, torrents):
|
|
||||||
"""Adds the list of torrents to the queue"""
|
|
||||||
# Add to the queue while removing duplicates
|
|
||||||
self.queue = list(set(self.queue + torrents))
|
|
||||||
|
|
||||||
# Update the status bar
|
|
||||||
self.update_status_bar()
|
|
||||||
|
|
||||||
def update_status_bar(self):
|
|
||||||
"""Attempts to update status bar"""
|
|
||||||
# If there are no queued torrents.. remove statusbar widgets and return
|
|
||||||
if len(self.queue) == 0:
|
|
||||||
if self.widgets != None:
|
|
||||||
for widget in self.widgets:
|
|
||||||
component.get("StatusBar").remove(widget)
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
|
||||||
statusbar = component.get("StatusBar")
|
|
||||||
except Exception, e:
|
|
||||||
# The statusbar hasn't been loaded yet, so we'll add a timer to
|
|
||||||
# update it later.
|
|
||||||
gobject.timeout_add(100, self.update_status_bar)
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Set the label text for statusbar
|
|
||||||
if len(self.queue) > 1:
|
|
||||||
label = str(len(self.queue)) + _(" Torrents Queued")
|
|
||||||
else:
|
|
||||||
label = str(len(self.queue)) + _(" Torrent Queued")
|
|
||||||
|
|
||||||
# Add the statusbar items if needed, or just modify the label if they
|
|
||||||
# have already been added.
|
|
||||||
if self.widgets == None:
|
|
||||||
self.widgets = component.get("StatusBar").add_item(
|
|
||||||
stock=gtk.STOCK_SORT_DESCENDING,
|
|
||||||
text=label)
|
|
||||||
else:
|
|
||||||
self.widgets[1].set_text(label)
|
|
||||||
|
|
||||||
# We return False so the timer stops
|
|
||||||
return False
|
|
||||||
|
|
||||||
@dbus.service.method("org.deluge_torrent.Deluge", in_signature="as")
|
@dbus.service.method("org.deluge_torrent.Deluge", in_signature="as")
|
||||||
def process_args(self, args):
|
def process_args(self, args):
|
||||||
"""Process arguments sent to already running Deluge"""
|
"""Process arguments sent to already running Deluge"""
|
||||||
|
@ -153,7 +99,7 @@ class DbusInterface(dbus.service.Object, component.Component):
|
||||||
if not client.connected():
|
if not client.connected():
|
||||||
# We're not connected so add these to the queue
|
# We're not connected so add these to the queue
|
||||||
log.debug("Not connected to host.. Adding to queue.")
|
log.debug("Not connected to host.. Adding to queue.")
|
||||||
self.add_to_queue(args)
|
component.get("QueuedTorrents").add_to_queue(args)
|
||||||
return
|
return
|
||||||
|
|
||||||
for arg in args:
|
for arg in args:
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
<?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 Wed Nov 14 03:28:00 2007 -->
|
<!--Generated with glade3 3.4.0 on Sat Nov 17 02:37:49 2007 -->
|
||||||
<glade-interface>
|
<glade-interface>
|
||||||
<widget class="GtkDialog" id="queued_torrents_dialog">
|
<widget class="GtkDialog" id="queued_torrents_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>
|
||||||
<property name="border_width">5</property>
|
<property name="border_width">5</property>
|
||||||
|
<property name="title" translatable="yes">Queued Torrents</property>
|
||||||
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
|
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
|
||||||
|
<property name="default_width">450</property>
|
||||||
|
<property name="default_height">300</property>
|
||||||
<property name="destroy_with_parent">True</property>
|
<property name="destroy_with_parent">True</property>
|
||||||
<property name="icon">.</property>
|
|
||||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||||
|
<property name="has_separator">False</property>
|
||||||
<child internal-child="vbox">
|
<child internal-child="vbox">
|
||||||
<widget class="GtkVBox" id="dialog-vbox1">
|
<widget class="GtkVBox" id="dialog-vbox1">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -23,7 +26,7 @@
|
||||||
<widget class="GtkHBox" id="hbox1">
|
<widget class="GtkHBox" id="hbox1">
|
||||||
<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">5</property>
|
<property name="spacing">10</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkImage" id="image1">
|
<widget class="GtkImage" id="image1">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -39,6 +42,8 @@
|
||||||
<widget class="GtkLabel" id="label1">
|
<widget class="GtkLabel" id="label1">
|
||||||
<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="xalign">0.05000000074505806</property>
|
||||||
|
<property name="ypad">10</property>
|
||||||
<property name="label" translatable="yes"><big><b>Add Queued Torrents</b></big></property>
|
<property name="label" translatable="yes"><big><b>Add Queued Torrents</b></big></property>
|
||||||
<property name="use_markup">True</property>
|
<property name="use_markup">True</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -63,11 +68,11 @@
|
||||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||||
<property name="shadow_type">GTK_SHADOW_IN</property>
|
<property name="shadow_type">GTK_SHADOW_IN</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkTreeView" id="treeview1">
|
<widget class="GtkTreeView" id="treeview">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">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="headers_clickable">True</property>
|
<property name="headers_visible">False</property>
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -114,20 +119,6 @@
|
||||||
<property name="position">2</property>
|
<property name="position">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<widget class="GtkExpander" id="expander1">
|
|
||||||
<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>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkAlignment" id="alignment1">
|
|
||||||
<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="left_padding">11</property>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkVBox" id="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>
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkCheckButton" id="chk_autoadd">
|
<widget class="GtkCheckButton" id="chk_autoadd">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -140,24 +131,6 @@
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">False</property>
|
<property name="fill">False</property>
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
<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">Options</property>
|
|
||||||
</widget>
|
|
||||||
<packing>
|
|
||||||
<property name="type">label_item</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
<packing>
|
|
||||||
<property name="position">3</property>
|
<property name="position">3</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
@ -172,21 +145,26 @@
|
||||||
<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="layout_style">GTK_BUTTONBOX_END</property>
|
<property name="layout_style">GTK_BUTTONBOX_END</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkButton" id="button_cancel">
|
<widget class="GtkButton" id="button_close">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_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="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="label" translatable="yes">gtk-close</property>
|
||||||
<property name="use_stock">True</property>
|
<property name="use_stock">True</property>
|
||||||
<property name="response_id">0</property>
|
<property name="response_id">0</property>
|
||||||
<signal name="clicked" handler="on_button_cancel_clicked"/>
|
<signal name="clicked" handler="on_button_close_clicked"/>
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkButton" id="button_add">
|
<widget class="GtkButton" id="button_add">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
<property name="sensitive">False</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
|
<property name="has_focus">True</property>
|
||||||
|
<property name="is_focus">True</property>
|
||||||
|
<property name="can_default">True</property>
|
||||||
|
<property name="has_default">True</property>
|
||||||
<property name="receives_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="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-add</property>
|
<property name="label" translatable="yes">gtk-add</property>
|
||||||
|
|
|
@ -52,6 +52,7 @@ from connectionmanager import ConnectionManager
|
||||||
from signals import Signals
|
from signals import Signals
|
||||||
from pluginmanager import PluginManager
|
from pluginmanager import PluginManager
|
||||||
from dbusinterface import DbusInterface
|
from dbusinterface import DbusInterface
|
||||||
|
from queuedtorrents import QueuedTorrents
|
||||||
from deluge.configmanager import ConfigManager
|
from deluge.configmanager import ConfigManager
|
||||||
from deluge.log import LOG as log
|
from deluge.log import LOG as log
|
||||||
import deluge.configmanager
|
import deluge.configmanager
|
||||||
|
@ -87,10 +88,6 @@ DEFAULT_PREFS = {
|
||||||
|
|
||||||
class GtkUI:
|
class GtkUI:
|
||||||
def __init__(self, args):
|
def __init__(self, args):
|
||||||
# Start the Dbus Interface before anything else.. Just in case we are
|
|
||||||
# already running.
|
|
||||||
self.dbusinterface = DbusInterface(args)
|
|
||||||
|
|
||||||
# Initialize gettext
|
# Initialize gettext
|
||||||
locale.setlocale(locale.LC_MESSAGES, '')
|
locale.setlocale(locale.LC_MESSAGES, '')
|
||||||
locale.bindtextdomain("deluge",
|
locale.bindtextdomain("deluge",
|
||||||
|
@ -108,6 +105,11 @@ class GtkUI:
|
||||||
# Make sure gtkui.conf has at least the defaults set
|
# Make sure gtkui.conf has at least the defaults set
|
||||||
config = ConfigManager("gtkui.conf", DEFAULT_PREFS)
|
config = ConfigManager("gtkui.conf", DEFAULT_PREFS)
|
||||||
|
|
||||||
|
# Start the Dbus Interface before anything else.. Just in case we are
|
||||||
|
# already running.
|
||||||
|
self.queuedtorrents = QueuedTorrents()
|
||||||
|
self.dbusinterface = DbusInterface(args)
|
||||||
|
|
||||||
# We make sure that the UI components start once we get a core URI
|
# We make sure that the UI components start once we get a core URI
|
||||||
client.connect_on_new_core(component.start)
|
client.connect_on_new_core(component.start)
|
||||||
client.connect_on_no_core(component.stop)
|
client.connect_on_no_core(component.stop)
|
||||||
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
#
|
||||||
|
# queuedtorrents.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2007 Andrew Resch ('andar') <andrewresch@gmail.com>
|
||||||
|
#
|
||||||
|
# Deluge is free software.
|
||||||
|
#
|
||||||
|
# You may redistribute it and/or modify it under the terms of the
|
||||||
|
# GNU General Public License, as published by the Free Software
|
||||||
|
# Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# deluge is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with deluge. If not, write to:
|
||||||
|
# The Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor
|
||||||
|
# Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# In addition, as a special exception, the copyright holders give
|
||||||
|
# permission to link the code of portions of this program with the OpenSSL
|
||||||
|
# library.
|
||||||
|
# You must obey the GNU General Public License in all respects for all of
|
||||||
|
# the code used other than OpenSSL. If you modify file(s) with this
|
||||||
|
# exception, you may extend this exception to your version of the file(s),
|
||||||
|
# but you are not obligated to do so. If you do not wish to do so, delete
|
||||||
|
# this exception statement from your version. If you delete this exception
|
||||||
|
# statement from all source files in the program, then also delete it here.
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
import gtk, gtk.glade
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
import deluge.ui.component as component
|
||||||
|
import deluge.ui.client as client
|
||||||
|
import deluge.common
|
||||||
|
from deluge.log import LOG as log
|
||||||
|
|
||||||
|
class QueuedTorrents(component.Component):
|
||||||
|
def __init__(self):
|
||||||
|
component.Component.__init__(self, "QueuedTorrents", ["StatusBar"])
|
||||||
|
self.queue = []
|
||||||
|
self.status_item = None
|
||||||
|
|
||||||
|
self.glade = gtk.glade.XML(
|
||||||
|
pkg_resources.resource_filename("deluge.ui.gtkui",
|
||||||
|
"glade/queuedtorrents.glade"))
|
||||||
|
|
||||||
|
self.dialog = self.glade.get_widget("queued_torrents_dialog")
|
||||||
|
self.dialog.set_icon(deluge.common.get_logo(32))
|
||||||
|
|
||||||
|
self.glade.signal_autoconnect({
|
||||||
|
"on_button_remove_clicked": self.on_button_remove_clicked,
|
||||||
|
"on_button_clear_clicked": self.on_button_clear_clicked,
|
||||||
|
"on_button_close_clicked": self.on_button_close_clicked,
|
||||||
|
"on_button_add_clicked": self.on_button_add_clicked
|
||||||
|
})
|
||||||
|
|
||||||
|
self.treeview = self.glade.get_widget("treeview")
|
||||||
|
self.treeview.append_column(
|
||||||
|
gtk.TreeViewColumn(_("Torrent"), gtk.CellRendererText(), text=0))
|
||||||
|
|
||||||
|
self.liststore = gtk.ListStore(str, str)
|
||||||
|
self.treeview.set_model(self.liststore)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.dialog.set_transient_for(component.get("MainWindow").window)
|
||||||
|
self.dialog.show()
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
if len(self.queue) == 0:
|
||||||
|
return
|
||||||
|
# Make sure status bar info is showing
|
||||||
|
self.status_item = None
|
||||||
|
self.update_status_bar()
|
||||||
|
# We only want the add button sensitive if we're connected to a host
|
||||||
|
self.glade.get_widget("button_add").set_sensitive(True)
|
||||||
|
self.run()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
# We only want the add button sensitive if we're connected to a host
|
||||||
|
self.glade.get_widget("button_add").set_sensitive(False)
|
||||||
|
|
||||||
|
def add_to_queue(self, torrents):
|
||||||
|
"""Adds the list of torrents to the queue"""
|
||||||
|
# Add to the queue while removing duplicates
|
||||||
|
self.queue = list(set(self.queue + torrents))
|
||||||
|
|
||||||
|
# Update the liststore
|
||||||
|
self.liststore.clear()
|
||||||
|
for torrent in self.queue:
|
||||||
|
self.liststore.append([os.path.split(torrent)[1], torrent])
|
||||||
|
|
||||||
|
# Update the status bar
|
||||||
|
self.update_status_bar()
|
||||||
|
|
||||||
|
def update_status_bar(self):
|
||||||
|
"""Attempts to update status bar"""
|
||||||
|
# If there are no queued torrents.. remove statusbar widgets and return
|
||||||
|
if len(self.queue) == 0:
|
||||||
|
if self.status_item != None:
|
||||||
|
component.get("StatusBar").remove_item(self.status_item)
|
||||||
|
self.status_item = None
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
statusbar = component.get("StatusBar")
|
||||||
|
except Exception, e:
|
||||||
|
# The statusbar hasn't been loaded yet, so we'll add a timer to
|
||||||
|
# update it later.
|
||||||
|
gobject.timeout_add(100, self.update_status_bar)
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Set the label text for statusbar
|
||||||
|
if len(self.queue) > 1:
|
||||||
|
label = str(len(self.queue)) + _(" Torrents Queued")
|
||||||
|
else:
|
||||||
|
label = str(len(self.queue)) + _(" Torrent Queued")
|
||||||
|
|
||||||
|
# Add the statusbar items if needed, or just modify the label if they
|
||||||
|
# have already been added.
|
||||||
|
if self.status_item == None:
|
||||||
|
self.status_item = component.get("StatusBar").add_item(
|
||||||
|
stock=gtk.STOCK_SORT_DESCENDING,
|
||||||
|
text=label,
|
||||||
|
callback=self.on_statusbar_click)
|
||||||
|
else:
|
||||||
|
self.status_item.set_text(label)
|
||||||
|
|
||||||
|
# We return False so the timer stops
|
||||||
|
return False
|
||||||
|
|
||||||
|
def on_statusbar_click(self, widget, event):
|
||||||
|
log.debug("on_statusbar_click")
|
||||||
|
self.run()
|
||||||
|
|
||||||
|
def on_button_remove_clicked(self, widget):
|
||||||
|
selected = self.treeview.get_selection().get_selected()[1]
|
||||||
|
if selected != None:
|
||||||
|
path = self.liststore.get_value(selected, 1)
|
||||||
|
self.liststore.remove(selected)
|
||||||
|
self.queue.remove(path)
|
||||||
|
self.update_status_bar()
|
||||||
|
|
||||||
|
def on_button_clear_clicked(self, widget):
|
||||||
|
self.liststore.clear()
|
||||||
|
self.update_status_bar()
|
||||||
|
|
||||||
|
def on_button_close_clicked(self, widget):
|
||||||
|
self.dialog.hide()
|
||||||
|
|
||||||
|
def on_button_add_clicked(self, widget):
|
||||||
|
# Add all the torrents in the liststore
|
||||||
|
def add_torrent(model, path, iter, data):
|
||||||
|
torrent_path = model.get_value(iter, 1)
|
||||||
|
client.add_torrent_file([torrent_path])
|
||||||
|
|
||||||
|
self.liststore.foreach(add_torrent, None)
|
||||||
|
del self.queue[:]
|
||||||
|
self.dialog.hide()
|
||||||
|
self.update_status_bar()
|
|
@ -38,6 +38,57 @@ import deluge.common
|
||||||
import deluge.ui.client as client
|
import deluge.ui.client as client
|
||||||
from deluge.log import LOG as log
|
from deluge.log import LOG as log
|
||||||
|
|
||||||
|
class StatusBarItem:
|
||||||
|
def __init__(self, image=None, stock=None, text=None, callback=None):
|
||||||
|
self._widgets = []
|
||||||
|
self._ebox = gtk.EventBox()
|
||||||
|
self._hbox = gtk.HBox()
|
||||||
|
self._image = gtk.Image()
|
||||||
|
self._label = gtk.Label()
|
||||||
|
self._hbox.add(self._image)
|
||||||
|
self._hbox.add(self._label)
|
||||||
|
self._ebox.add(self._hbox)
|
||||||
|
|
||||||
|
# Add image from file or stock
|
||||||
|
if image != None or stock != None:
|
||||||
|
if image != None:
|
||||||
|
self.set_image_from_file(image)
|
||||||
|
if stock != None:
|
||||||
|
self.set_image_from_stock(stock)
|
||||||
|
|
||||||
|
# Add text
|
||||||
|
if text != None:
|
||||||
|
self.set_text(text)
|
||||||
|
|
||||||
|
if callback != None:
|
||||||
|
self.set_callback(callback)
|
||||||
|
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
def set_callback(self, callback):
|
||||||
|
self._ebox.connect("button-press-event", callback)
|
||||||
|
|
||||||
|
def show_all(self):
|
||||||
|
self._ebox.show()
|
||||||
|
self._hbox.show()
|
||||||
|
self._image.show()
|
||||||
|
self._label.show()
|
||||||
|
|
||||||
|
def set_image_from_file(self, image):
|
||||||
|
self._image.set_from_file(image)
|
||||||
|
|
||||||
|
def set_image_from_stock(self, stock):
|
||||||
|
self._image.set_from_stock(stock, gtk.ICON_SIZE_MENU)
|
||||||
|
|
||||||
|
def set_text(self, text):
|
||||||
|
self._label.set_text(text)
|
||||||
|
|
||||||
|
def get_widgets(self):
|
||||||
|
return self._widgets()
|
||||||
|
|
||||||
|
def get_eventbox(self):
|
||||||
|
return self._ebox
|
||||||
|
|
||||||
class StatusBar(component.Component):
|
class StatusBar(component.Component):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
component.Component.__init__(self, "StatusBar")
|
component.Component.__init__(self, "StatusBar")
|
||||||
|
@ -90,37 +141,17 @@ class StatusBar(component.Component):
|
||||||
self.hbox.pack_start(label, expand=False, fill=False)
|
self.hbox.pack_start(label, expand=False, fill=False)
|
||||||
self.statusbar.show_all()
|
self.statusbar.show_all()
|
||||||
|
|
||||||
def add_item(self, image=None, stock=None, text=None):
|
def add_item(self, image=None, stock=None, text=None, callback=None):
|
||||||
"""Adds an item to the status bar"""
|
"""Adds an item to the status bar"""
|
||||||
# The return tuple.. we return whatever widgets we add
|
# The return tuple.. we return whatever widgets we add
|
||||||
ret = []
|
item = StatusBarItem(image, stock, text, callback)
|
||||||
# Add image from file or stock
|
self.hbox.pack_start(item.get_eventbox(), expand=False, fill=False)
|
||||||
if image != None or stock != None:
|
return item
|
||||||
_image = gtk.Image()
|
|
||||||
if image != None:
|
|
||||||
_image.set_from_file(image)
|
|
||||||
if stock != None:
|
|
||||||
_image.set_from_stock(stock, gtk.ICON_SIZE_MENU)
|
|
||||||
self.hbox.pack_start(_image, expand=False, fill=False)
|
|
||||||
ret.append(_image)
|
|
||||||
|
|
||||||
# Add text
|
def remove_item(self, item):
|
||||||
if text != None:
|
|
||||||
label = gtk.Label(text)
|
|
||||||
self.hbox.pack_start(label, expand=False, fill=False)
|
|
||||||
ret.append(label)
|
|
||||||
|
|
||||||
# Show the widgets
|
|
||||||
for widget in ret:
|
|
||||||
widget.show()
|
|
||||||
|
|
||||||
# Return the widgets
|
|
||||||
return tuple(ret)
|
|
||||||
|
|
||||||
def remove_item(self, widget):
|
|
||||||
"""Removes an item from the statusbar"""
|
"""Removes an item from the statusbar"""
|
||||||
try:
|
try:
|
||||||
self.hbox.remove(widget)
|
self.hbox.remove(item.get_eventbox())
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
log.debug("Unable to remove widget: %s", e)
|
log.debug("Unable to remove widget: %s", e)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue