More changes related to automatic connections.

Auto-connecting on start of the gtk ui is now fully working.
Auto-staring localhost if needed is now also working.
Authentication failures now get passed correctly to the client implementation which will allow the user to enter username and/or password to complete authentication.
It's now possible to shutdown the daemon from the connection manager even if not on localhost, it just needs all required information to be present on the liststore.
This commit is contained in:
Pedro Algarvio 2011-04-30 07:42:06 +01:00
parent 63d0d0c69b
commit dd3f78bd36
7 changed files with 375 additions and 296 deletions

View File

@ -56,7 +56,7 @@ except ImportError:
import deluge.component as component
import deluge.configmanager
from deluge.core.authmanager import AUTH_LEVEL_NONE, AUTH_LEVEL_DEFAULT, AUTH_LEVEL_ADMIN
from deluge.error import DelugeError, NotAuthorizedError, __PassthroughError
from deluge.error import DelugeError, NotAuthorizedError, _PassthroughError
RPC_RESPONSE = 1
RPC_ERROR = 2
@ -266,7 +266,7 @@ class DelugeRPCProtocol(Protocol):
self.factory.authorized_sessions[self.transport.sessionno] = (ret, args[0])
self.factory.session_protocols[self.transport.sessionno] = self
except Exception, e:
if isinstance(e, __PassthroughError):
if isinstance(e, _PassthroughError):
self.sendData(
(RPC_EVENT_AUTH, request_id,
e.__class__.__name__,

View File

@ -448,7 +448,9 @@ class TorrentManager(component.Component):
# Set auto_managed to False because the torrent is paused
handle.auto_managed(False)
# Create a Torrent object
owner = state.owner if state else (owner if owner else component.get("RPCServer").get_session_user())
owner = state.owner if state else (
owner if owner else component.get("RPCServer").get_session_user()
)
account_exists = component.get("AuthManager").has_account(owner)
if not account_exists:
owner = 'localclient'

View File

@ -50,14 +50,23 @@ class InvalidTorrentError(DelugeError):
class InvalidPathError(DelugeError):
pass
class __PassthroughError(DelugeError):
class _PassthroughError(DelugeError):
def _get_message(self):
return self._message
def _set_message(self, message):
self._message = message
message = property(_get_message, _set_message)
del _get_message, _set_message
def __new__(cls, *args, **kwargs):
inst = super(__PassthroughError, cls).__new__(cls, *args, **kwargs)
inst = super(_PassthroughError, cls).__new__(cls, *args, **kwargs)
inst._args = args
inst._kwargs = kwargs
return inst
class NotAuthorizedError(__PassthroughError):
class NotAuthorizedError(_PassthroughError):
def __init__(self, current_level, required_level):
self.message = _(
"Auth level too low: %(current_level)s < %(required_level)s" %
@ -67,14 +76,7 @@ class NotAuthorizedError(__PassthroughError):
self.required_level = required_level
class __UsernameBasedPasstroughError(__PassthroughError):
def _get_message(self):
return self._message
def _set_message(self, message):
self._message = message
message = property(_get_message, _set_message)
del _get_message, _set_message
class _UsernameBasedPasstroughError(_PassthroughError):
def _get_username(self):
return self._username
@ -84,16 +86,16 @@ class __UsernameBasedPasstroughError(__PassthroughError):
del _get_username, _set_username
def __init__(self, message, username):
super(__UsernameBasedPasstroughError, self).__init__(message)
super(_UsernameBasedPasstroughError, self).__init__(message)
self.message = message
self.username = username
class BadLoginError(__UsernameBasedPasstroughError):
class BadLoginError(_UsernameBasedPasstroughError):
pass
class AuthenticationRequired(__UsernameBasedPasstroughError):
class AuthenticationRequired(_UsernameBasedPasstroughError):
pass
class AuthManagerError(__UsernameBasedPasstroughError):
class AuthManagerError(_UsernameBasedPasstroughError):
pass

View File

@ -421,7 +421,7 @@ class DaemonSSLProxy(DaemonProxy):
# Still log these errors
log.error(error_data.value.logable())
return error_data
if isinstance(error_data.value, error.__PassthroughError):
if isinstance(error_data.value, error._PassthroughError):
return error_data
except:
pass
@ -472,7 +472,7 @@ class DaemonSSLProxy(DaemonProxy):
self.login_deferred.callback(result)
def __on_login_fail(self, result):
log.debug("_on_login_fail(): %s", result)
log.debug("_on_login_fail(): %s", result.value)
self.login_deferred.errback(result)
def __on_auth_levels_mappings(self, result):
@ -529,12 +529,14 @@ class DaemonClassicProxy(DaemonProxy):
log.exception(e)
return defer.fail(e)
else:
return defer.maybeDeferred(m, *copy.deepcopy(args), **copy.deepcopy(kwargs))
return defer.maybeDeferred(
m, *copy.deepcopy(args), **copy.deepcopy(kwargs)
)
def register_event_handler(self, event, handler):
"""
Registers a handler function to be called when `:param:event` is received
from the daemon.
Registers a handler function to be called when `:param:event` is
received from the daemon.
:param event: the name of the event to handle
:type event: str
@ -604,37 +606,39 @@ class Client(object):
:returns: a Deferred object that will be called once the connection
has been established or fails
"""
self._daemon_proxy = DaemonSSLProxy(dict(self.__event_handlers))
self._daemon_proxy.set_disconnect_callback(self.__on_disconnect)
d = self._daemon_proxy.connect(host, port)
auth_deferred = defer.Deferred()
def on_connect_fail(reason):
self.disconnect()
auth_deferred.errback(reason)
return reason
def on_authenticate(result, daemon_info):
log.debug("Authentication sucessfull: %s", result)
return result
def on_authenticate_fail(reason):
log.debug("Failed to authenticate: %s", reason.value)
return reason
def on_connected(daemon_version):
log.debug("Client.connect.on_connected. Daemon version: %s",
daemon_version)
return daemon_version
def authenticate(daemon_version, username, password):
d = self._daemon_proxy.authenticate(username, password)
d.addCallback(on_authenticate, daemon_version)
d.addErrback(on_authenticate_fail)
return d
d.addCallback(on_connected)
d.addErrback(on_connect_fail)
if not skip_authentication:
def on_authenticate(result, daemon_info):
log.debug("Authentication sucessfull: %s", result)
auth_deferred.callback(daemon_info)
def on_authenticate_fail(reason):
log.debug("Failed to authenticate")
log.exception(reason)
auth_deferred.errback(reason)
def on_connected(daemon_version):
log.debug("Client.connect.on_connected. Daemon version: %s",
daemon_version)
d = self._daemon_proxy.authenticate(username, password)
d.addCallback(on_authenticate, daemon_version)
d.addErrback(on_authenticate_fail)
d.addCallback(on_connected)
return auth_deferred
d.addCallback(authenticate, username, password)
return d
def disconnect(self):

View File

@ -48,8 +48,7 @@ from deluge.ui.common import get_localhost_auth
from deluge.ui.client import client
import deluge.ui.client
from deluge.configmanager import ConfigManager
from deluge.error import AuthenticationRequired
from deluge.log import LOG as log
from deluge.error import AuthenticationRequired, BadLoginError
import dialogs
log = logging.getLogger(__name__)
@ -187,6 +186,9 @@ class ConnectionManager(component.Component):
# Connect the signals to the handlers
self.glade.signal_autoconnect(self)
self.hostlist.get_selection().connect(
"changed", self.on_hostlist_selection_changed
)
# Load any saved host entries
self.__load_hostlist()
@ -361,7 +363,9 @@ class ConnectionManager(component.Component):
"""
Set the widgets to show the correct options from the config.
"""
self.autoconnect_host_id = self.gtkui_config['autoconnect_host_id']
self.glade.get_widget("chk_autoconnect").set_active(
self.gtkui_config["autoconnect"]
)
self.glade.get_widget("chk_autostart").set_active(
self.gtkui_config["autostart_localhost"]
)
@ -389,25 +393,20 @@ class ConnectionManager(component.Component):
self.glade.get_widget("image_startdaemon").set_from_stock(
gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU)
self.glade.get_widget("label_startdaemon").set_text("_Start Daemon")
self.glade.get_widget("chk_autoconnect").set_sensitive(False)
model, row = self.hostlist.get_selection().get_selected()
if not row:
self.glade.get_widget("button_edithost").set_sensitive(False)
self.glade.get_widget("chk_autoconnect").set_sensitive(False)
return
self.glade.get_widget("button_edithost").set_sensitive(True)
self.glade.get_widget("chk_autoconnect").set_sensitive(True)
# Get some values about the selected host
status = model[row][HOSTLIST_COL_STATUS]
hostid = model[row][HOSTLIST_COL_ID]
host = model[row][HOSTLIST_COL_HOST]
self.glade.get_widget("chk_autoconnect").set_active(
hostid == self.gtkui_config["autoconnect_host_id"]
)
port = model[row][HOSTLIST_COL_PORT]
user = model[row][HOSTLIST_COL_USER]
passwd = model[row][HOSTLIST_COL_PASS]
log.debug("Status: %s", status)
# Check to see if we have a localhost entry selected
@ -445,8 +444,14 @@ class ConnectionManager(component.Component):
self.glade.get_widget("label_startdaemon").set_text(
_("_Start Daemon"))
if not localhost:
# An offline host
if client.connected() and (host, port, user) == client.connection_info():
# If we're connected, we can stop the dameon
self.glade.get_widget("button_startdaemon").set_sensitive(True)
elif user and passwd:
# In this case we also have all the info to shutdown the dameon
self.glade.get_widget("button_startdaemon").set_sensitive(True)
else:
# Can't stop non localhost daemons, specially without the necessary info
self.glade.get_widget("button_startdaemon").set_sensitive(False)
# Make sure label is displayed correctly using mnemonics
@ -493,16 +498,16 @@ class ConnectionManager(component.Component):
def __on_connected(self, daemon_info, host_id):
if self.gtkui_config["autoconnect"]:
self.gtkui_config["autoconnect_host_id"] = host_id
self.connection_manager.response(gtk.RESPONSE_OK)
component.start()
def __on_connected_failed(self, reason, host_id, host, port, user):
log.debug("Failed to connect: %s", reason)
if reason.check(AuthenticationRequired):
if reason.check(AuthenticationRequired, BadLoginError):
log.debug("PasswordRequired exception")
dialog = dialogs.AuthenticationDialog(reason.value.message,
reason.value.username)
dialog = dialogs.AuthenticationDialog(
reason.value.message, reason.value.username
)
def dialog_finished(response_id, host, port, user):
if response_id == gtk.RESPONSE_OK:
self.__connect(host_id, host, port,
@ -547,6 +552,7 @@ class ConnectionManager(component.Component):
time.sleep(0.5)
do_retry_connect(try_counter)
return result
def do_retry_connect(try_counter):
d = client.connect(host, port, user, password)
d.addCallback(self.__on_connected, host_id)
@ -657,9 +663,11 @@ class ConnectionManager(component.Component):
log.debug("on_button_startdaemon_clicked")
if self.liststore.iter_n_children(None) < 1:
# There is nothing in the list, so lets create a localhost entry
self.add_host(DEFAULT_HOST, DEFAULT_PORT)
self.add_host(DEFAULT_HOST, DEFAULT_PORT, *get_localhost_auth())
# ..and start the daemon.
self.start_daemon(DEFAULT_PORT, deluge.configmanager.get_config_dir())
self.start_daemon(
DEFAULT_PORT, deluge.configmanager.get_config_dir()
)
return
paths = self.hostlist.get_selection().get_selected_rows()[1]
@ -681,9 +689,10 @@ class ConnectionManager(component.Component):
def on_daemon_shutdown(d):
# Update display to show change
self.__update_list()
if client.connected() and client.connection_info() == (host, port, user):
client.daemon.shutdown().addCallback(on_daemon_shutdown)
else:
elif user and password:
# Create a new client instance
c = deluge.ui.client.Client()
def on_connect(d, c):
@ -712,44 +721,6 @@ class ConnectionManager(component.Component):
def on_askpassword_dialog_entry_activate(self, entry):
self.askpassword_dialog.response(gtk.RESPONSE_OK)
def on_hostlist_cursor_changed(self, widget):
paths = self.hostlist.get_selection().get_selected_rows()[1]
if len(paths) < 1:
self.glade.get_widget("chk_autoconnect").set_sensitive(False)
return
else:
self.glade.get_widget("chk_autoconnect").set_sensitive(True)
hostid = self.liststore[paths[0]][HOSTLIST_COL_ID]
self.glade.get_widget("chk_autoconnect").set_active(
hostid == self.gtkui_config["autoconnect_host_id"]
)
def on_chk_autoconnect_toggled(self, widget):
paths = self.hostlist.get_selection().get_selected_rows()[1]
if len(paths) < 1:
self.glade.get_widget("chk_autoconnect").set_sensitive(False)
self.glade.get_widget("chk_autostart").set_sensitive(False)
return
else:
self.glade.get_widget("chk_autoconnect").set_sensitive(True)
self.glade.get_widget("chk_autostart").set_sensitive(widget.get_active())
hostid = self.liststore[paths[0]][HOSTLIST_COL_ID]
if widget.get_active():
if self.autoconnect_host_id != hostid:
self.gtkui_config["autoconnect_host_id"] = hostid
self.autoconnect_host_id = hostid
self.gtkui_config.save()
return
if self.autoconnect_host_id == hostid:
self.gtkui_config["autoconnect_host_id"] = None
self.autoconnect_host_id = None
self.gtkui_config.save()
def __migrate_config_1_to_2(self, config):
localclient_username, localclient_password = get_localhost_auth()
if not localclient_username:

View File

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<glade-interface>
<!-- interface-requires gtk+ 2.6 -->
<!-- interface-requires gtk+ 2.22 -->
<!-- interface-naming-policy toplevel-contextual -->
<widget class="GtkDialog" id="addhost_dialog">
<property name="can_focus">False</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="title" translatable="yes">Add Host</property>
@ -13,16 +14,83 @@
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox3">
<property name="visible">True</property>
<property name="can_focus">False</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 internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area3">
<property name="visible">True</property>
<property name="can_focus">False</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">end</property>
<child>
<widget class="GtkButton" id="button_addhost_cancel">
<property name="label">gtk-cancel</property>
<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="use_action_appearance">False</property>
<property name="use_stock">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button_addhost_add">
<property name="label">gtk-add</property>
<property name="response_id">1</property>
<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="use_action_appearance">False</property>
<property name="use_stock">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button_addhost_save">
<property name="label">gtk-save</property>
<property name="response_id">2</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="can_focus">False</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="label3">
<property name="visible">True</property>
<property name="can_focus">False</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">Hostname:</property>
</widget>
@ -35,6 +103,7 @@
<child>
<widget class="GtkAlignment" id="alignment4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">1</property>
<child>
<widget class="GtkEntry" id="entry_hostname">
@ -42,16 +111,23 @@
<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="activates_default">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</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">Port:</property>
</widget>
@ -69,6 +145,10 @@
<property name="max_length">5</property>
<property name="width_chars">5</property>
<property name="xalign">1</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
<property name="adjustment">58846 0 65535 1 10 0</property>
<property name="climb_rate">1</property>
<property name="numeric">True</property>
@ -89,17 +169,23 @@
<child>
<widget class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<child>
<widget class="GtkAlignment" id="alignment3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">5</property>
<child>
<widget class="GtkEntry" id="entry_password">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="visibility">False</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</widget>
</child>
</widget>
@ -113,11 +199,16 @@
<child>
<widget class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">5</property>
<child>
<widget class="GtkEntry" id="entry_username">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</widget>
</child>
</widget>
@ -129,6 +220,7 @@
<child>
<widget class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Password:</property>
</widget>
<packing>
@ -140,6 +232,7 @@
<child>
<widget class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Username:</property>
</widget>
<packing>
@ -149,25 +242,46 @@
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</widget>
</child>
</widget>
<widget class="GtkDialog" id="askpassword_dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Password Required</property>
<property name="modal">True</property>
<property name="window_position">center-on-parent</property>
<property name="default_width">320</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">dialog</property>
<property name="skip_taskbar_hint">True</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area3">
<widget class="GtkHButtonBox" id="dialog-action_area5">
<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="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<widget class="GtkButton" id="button_addhost_cancel">
<property name="label">gtk-cancel</property>
<widget class="GtkButton" id="askpassword_dialog_connect_button">
<property name="label">gtk-connect</property>
<property name="response_id">1</property>
<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="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_askpassword_dialog_connect_button_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
@ -175,49 +289,61 @@
<property name="position">0</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<widget class="GtkButton" id="button_addhost_add">
<property name="label">gtk-add</property>
<property name="response_id">1</property>
<widget class="GtkImage" id="askpassword_dialog_image">
<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="use_stock">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-dialog-authentication</property>
<property name="icon-size">6</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button_addhost_save">
<property name="label">gtk-save</property>
<property name="response_id">2</property>
<widget class="GtkEntry" id="askpassword_dialog_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="visibility">False</property>
<property name="invisible_char">●</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
<signal name="activate" handler="on_askpassword_dialog_entry_activate"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
<widget class="GtkDialog" id="connection_manager">
<property name="can_focus">False</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>
@ -232,16 +358,33 @@
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox2">
<property name="visible">True</property>
<property name="can_focus">False</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 internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area2">
<property name="sensitive">False</property>
<property name="can_focus">False</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">end</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</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="can_focus">False</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-missing-image</property>
</widget>
@ -254,18 +397,21 @@
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</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">&lt;big&gt;&lt;b&gt;Connection Manager&lt;/b&gt;&lt;/big&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
<property name="position">1</property>
</packing>
@ -273,11 +419,13 @@
<child>
<widget class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="can_focus">False</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="GtkViewport" id="viewport1">
<property name="visible">True</property>
<property name="can_focus">False</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">queue</property>
<child>
@ -292,7 +440,6 @@
<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>
<signal name="cursor_changed" handler="on_hostlist_cursor_changed"/>
<signal name="row_activated" handler="on_hostlist_row_activated"/>
</widget>
</child>
@ -300,16 +447,20 @@
</child>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox3">
<property name="visible">True</property>
<property name="can_focus">False</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="GtkHButtonBox" id="hbuttonbox2">
<property name="visible">True</property>
<property name="can_focus">False</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">start</property>
<child>
@ -319,6 +470,7 @@
<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="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_button_addhost_clicked"/>
</widget>
@ -332,9 +484,9 @@
<widget class="GtkButton" id="button_edithost">
<property name="label">gtk-edit</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_button_edithost_clicked"/>
</widget>
@ -351,6 +503,7 @@
<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="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_button_removehost_clicked"/>
</widget>
@ -367,51 +520,44 @@
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button_refresh">
<property name="label">gtk-refresh</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_button_refresh_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button_startdaemon">
<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="use_action_appearance">False</property>
<signal name="clicked" handler="on_button_startdaemon_clicked"/>
<child>
<widget class="GtkHBox" id="hbox4">
<property name="visible">True</property>
<property name="can_focus">False</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="GtkImage" id="image_startdaemon">
<property name="visible">True</property>
<property name="can_focus">False</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-execute</property>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label_startdaemon">
<property name="visible">True</property>
<property name="can_focus">False</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">_Start local daemon</property>
<property name="use_underline">True</property>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
@ -425,6 +571,22 @@
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button_refresh">
<property name="label">gtk-refresh</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_button_refresh_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
@ -434,6 +596,8 @@
</child>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="padding">10</property>
<property name="position">2</property>
</packing>
@ -446,6 +610,7 @@
<child>
<widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="top_padding">5</property>
<property name="bottom_padding">5</property>
@ -454,6 +619,7 @@
<child>
<widget class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<property name="can_focus">False</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="GtkCheckButton" id="chk_autoconnect">
@ -462,31 +628,30 @@
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_chk_autoconnect_toggled"/>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment2">
<widget class="GtkCheckButton" id="chk_autostart">
<property name="label" translatable="yes">Automatically start localhost if needed</property>
<property name="visible">True</property>
<property name="left_padding">15</property>
<child>
<widget class="GtkCheckButton" id="chk_autostart">
<property name="label" translatable="yes">Automatically start localhost if needed</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_chk_autostart_toggled"/>
</widget>
</child>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_chk_autostart_toggled"/>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
@ -497,10 +662,13 @@
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_chk_donotshow_toggled"/>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
@ -511,6 +679,7 @@
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</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>
@ -521,12 +690,14 @@
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<widget class="GtkButton" id="button_close">
@ -535,6 +706,7 @@
<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="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_button_close_clicked"/>
</widget>
@ -550,6 +722,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_button_connect_clicked"/>
</widget>
@ -566,92 +739,6 @@
<property name="position">4</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area2">
<property name="sensitive">False</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">end</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</widget>
</child>
</widget>
<widget class="GtkDialog" id="askpassword_dialog">
<property name="border_width">5</property>
<property name="title" translatable="yes">Password Required</property>
<property name="modal">True</property>
<property name="window_position">center-on-parent</property>
<property name="default_width">320</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">dialog</property>
<property name="skip_taskbar_hint">True</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox5">
<property name="visible">True</property>
<property name="spacing">2</property>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<child>
<widget class="GtkImage" id="askpassword_dialog_image">
<property name="visible">True</property>
<property name="stock">gtk-dialog-authentication</property>
<property name="icon-size">6</property>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="askpassword_dialog_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="visibility">False</property>
<property name="invisible_char">●</property>
<signal name="activate" handler="on_askpassword_dialog_entry_activate"/>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area5">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<widget class="GtkButton" id="askpassword_dialog_connect_button">
<property name="label">gtk-connect</property>
<property name="response_id">1</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_askpassword_dialog_connect_button_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</widget>
</child>
</widget>

View File

@ -327,14 +327,30 @@ Please see the details below for more information."), details=traceback.format_e
def __start_non_classic(self):
# Autoconnect to a host
if self.config["autoconnect"]:
for host in self.connectionmanager.config["hosts"]:
if host[0] == self.config["autoconnect_host_id"]:
def update_connection_manager():
if not self.connectionmanager.running:
return
self.connectionmanager.glade.get_widget(
"button_refresh"
).emit("clicked")
def close_connection_manager():
if not self.connectionmanager.running:
return
self.connectionmanager.glade.get_widget(
"button_close"
).emit("clicked")
for host_config in self.connectionmanager.config["hosts"]:
hostid, host, port, user, passwd = host_config
if hostid == self.config["autoconnect_host_id"]:
try_connect = True
# Check to see if we need to start the localhost daemon
if self.config["autostart_localhost"] and host[1] in ("localhost", "127.0.0.1"):
log.debug("Autostarting localhost:%s", host[2])
if self.config["autostart_localhost"] and host in ("localhost", "127.0.0.1"):
log.debug("Autostarting localhost:%s", host)
try_connect = client.start_daemon(
host[2], deluge.configmanager.get_config_dir()
port, deluge.configmanager.get_config_dir()
)
log.debug("Localhost started: %s", try_connect)
if not try_connect:
@ -345,57 +361,54 @@ Please see the details below for more information."), details=traceback.format_e
"to see if there is an error.")
).run()
# def refresh_connection_manager_list():
# try:
# self.connectionmanager.glade.get_widget(
# "button_refresh"
# ).emit("clicked")
# except:
# pass
#
# reactor.callLatter(1, refresh_connection_manager_list)
def update_connection_manager():
if not self.connectionmanager.running:
return
self.connectionmanager.glade.get_widget(
"button_refresh"
).emit("clicked")
def close_connection_manager():
if not self.connectionmanager.running:
return
self.connectionmanager.glade.get_widget(
"button_close"
).emit("clicked")
# Daemon Started, let's update it's info
reactor.callLater(0.5, update_connection_manager)
def on_connect(connector):
print 'ON GTK UI CONNECT!!!!\n\n'
component.start()
reactor.callLater(0.5, update_connection_manager)
reactor.callLater(1, close_connection_manager)
reactor.callLater(0.2, update_connection_manager)
reactor.callLater(0.5, close_connection_manager)
def on_connect_fail(reason, try_counter,
host, port, user, passwd):
if not try_counter:
return
if reason.check(deluge.error.AuthenticationRequired,
deluge.error.BadLoginError):
log.debug("PasswordRequired exception")
dialog = dialogs.AuthenticationDialog(
reason.value.message, reason.value.username
)
def dialog_finished(response_id, host, port):
if response_id == gtk.RESPONSE_OK:
reactor.callLater(
0.5, do_connect, try_counter-1,
host, port, dialog.get_username(),
dialog.get_password())
dialog.run().addCallback(dialog_finished,
host, port)
return
def on_connect_fail(result, try_counter):
log.error("Connection to host failed..")
# We failed connecting to the daemon, but lets try again
if try_counter:
log.info("Retrying connection.. Retries left: "
"%s", try_counter)
try_counter -= 1
import time
time.sleep(0.5)
do_connect(try_counter)
reactor.callLater(0.5, update_connection_manager)
return result
log.info("Retrying connection.. Retries left: "
"%s", try_counter)
reactor.callLater(0.5, update_connection_manager)
reactor.callLater(0.5, do_connect, try_counter-1,
host, port, user, passwd)
def do_connect(try_counter):
d = client.connect(*host[1:])
def do_connect(try_counter, host, port, user, passwd):
log.debug("Trying to connect to %s@%s:%s",
user, host, port)
d = client.connect(host, port, user, passwd)
d.addCallback(on_connect)
d.addErrback(on_connect_fail, try_counter)
d.addErrback(on_connect_fail, try_counter,
host, port, user, passwd)
if try_connect:
do_connect(6)
reactor.callLater(
0.5, do_connect, 6, host, port, user, passwd
)
break
if self.config["show_connection_manager_on_start"]: