[GTK] Fix adding daemon accounts

Errors were raised when trying to add a new daemon account due to dialog
being destroyed before looking up widget values.

Fixed by saving widget values before destroying.

Refactored code to be simplified with a named tuple for the account
details instead of separate attributes and modernized the preferences
dialog creation and account saving by replacing callback functions.
This commit is contained in:
Calum Lind 2022-02-12 22:56:03 +00:00
parent 66b5a2fc40
commit af26fdfb37
No known key found for this signature in database
GPG Key ID: 90597A687B836BA3
2 changed files with 61 additions and 68 deletions

View File

@ -8,6 +8,8 @@
# pylint: disable=super-on-old-class # pylint: disable=super-on-old-class
from collections import namedtuple
from gi.repository import Gtk from gi.repository import Gtk
from twisted.internet import defer from twisted.internet import defer
@ -16,6 +18,8 @@ from deluge.common import windows_check
from .common import get_deluge_icon, get_pixbuf from .common import get_deluge_icon, get_pixbuf
Account = namedtuple('Account', 'username password authlevel')
class BaseDialog(Gtk.Dialog): class BaseDialog(Gtk.Dialog):
""" """
@ -273,21 +277,21 @@ class AccountDialog(BaseDialog):
parent, parent,
) )
self.levels_mapping = levels_mapping self.account = None
table = Gtk.Table(2, 3, False) table = Gtk.Table(2, 3, False)
self.username_label = Gtk.Label() username_label = Gtk.Label()
self.username_label.set_markup('<b>' + _('Username:') + '</b>') username_label.set_markup('<b>' + _('Username:') + '</b>')
self.username_label.set_alignment(1.0, 0.5) username_label.set_alignment(1.0, 0.5)
self.username_label.set_padding(5, 5) username_label.set_padding(5, 5)
self.username_entry = Gtk.Entry() self.username_entry = Gtk.Entry()
table.attach(self.username_label, 0, 1, 0, 1) table.attach(username_label, 0, 1, 0, 1)
table.attach(self.username_entry, 1, 2, 0, 1) table.attach(self.username_entry, 1, 2, 0, 1)
self.authlevel_label = Gtk.Label() authlevel_label = Gtk.Label()
self.authlevel_label.set_markup('<b>' + _('Authentication Level:') + '</b>') authlevel_label.set_markup('<b>' + _('Authentication Level:') + '</b>')
self.authlevel_label.set_alignment(1.0, 0.5) authlevel_label.set_alignment(1.0, 0.5)
self.authlevel_label.set_padding(5, 5) authlevel_label.set_padding(5, 5)
# combo_box_new_text is deprecated but no other pygtk alternative. # combo_box_new_text is deprecated but no other pygtk alternative.
self.authlevel_combo = Gtk.ComboBoxText() self.authlevel_combo = Gtk.ComboBoxText()
@ -302,16 +306,16 @@ class AccountDialog(BaseDialog):
if active_idx is not None: if active_idx is not None:
self.authlevel_combo.set_active(active_idx) self.authlevel_combo.set_active(active_idx)
table.attach(self.authlevel_label, 0, 1, 1, 2) table.attach(authlevel_label, 0, 1, 1, 2)
table.attach(self.authlevel_combo, 1, 2, 1, 2) table.attach(self.authlevel_combo, 1, 2, 1, 2)
self.password_label = Gtk.Label() password_label = Gtk.Label()
self.password_label.set_markup('<b>' + _('Password:') + '</b>') password_label.set_markup('<b>' + _('Password:') + '</b>')
self.password_label.set_alignment(1.0, 0.5) password_label.set_alignment(1.0, 0.5)
self.password_label.set_padding(5, 5) password_label.set_padding(5, 5)
self.password_entry = Gtk.Entry() self.password_entry = Gtk.Entry()
self.password_entry.set_visibility(False) self.password_entry.set_visibility(False)
table.attach(self.password_label, 0, 1, 2, 3) table.attach(password_label, 0, 1, 2, 3)
table.attach(self.password_entry, 1, 2, 2, 3) table.attach(self.password_entry, 1, 2, 2, 3)
self.vbox.pack_start(table, False, False, padding=5) self.vbox.pack_start(table, False, False, padding=5)
@ -324,18 +328,17 @@ class AccountDialog(BaseDialog):
if password: if password:
self.password_entry.set_text(username) self.password_entry.set_text(username)
self.show_all() self.vbox.show_all()
def get_username(self): def _on_response(self, widget, response):
return self.username_entry.get_text() if response == Gtk.ResponseType.OK:
self.account = Account(
def get_password(self): self.username_entry.get_text(),
return self.password_entry.get_text() self.password_entry.get_text(),
self.authlevel_combo.get_active_text(),
def get_authlevel(self): )
combobox = self.authlevel_combo self.destroy()
level = combobox.get_model()[combobox.get_active()][0] self.deferred.callback(response)
return level
class OtherDialog(BaseDialog): class OtherDialog(BaseDialog):

View File

@ -1329,58 +1329,48 @@ class Preferences(component.Component):
(model, itr) = treeselection.get_selected() (model, itr) = treeselection.get_selected()
if not itr: if not itr:
return return
username = model[itr][0] level = model[itr][1]
if username: if level:
self.builder.get_object('accounts_edit').set_sensitive(True) self.builder.get_object('accounts_edit').set_sensitive(True)
self.builder.get_object('accounts_delete').set_sensitive(True) self.builder.get_object('accounts_delete').set_sensitive(True)
else: else:
self.builder.get_object('accounts_edit').set_sensitive(False) self.builder.get_object('accounts_edit').set_sensitive(False)
self.builder.get_object('accounts_delete').set_sensitive(False) self.builder.get_object('accounts_delete').set_sensitive(False)
def on_accounts_add_clicked(self, widget): from deluge.decorators import maybe_coroutine
@maybe_coroutine
async def on_accounts_add_clicked(self, widget):
dialog = AccountDialog( dialog = AccountDialog(
levels_mapping=client.auth_levels_mapping, parent=self.pref_dialog levels_mapping=client.auth_levels_mapping, parent=self.pref_dialog
) )
response = await dialog.run()
if response != Gtk.ResponseType.OK:
return
def dialog_finished(response_id): account = dialog.account
username = dialog.get_username() try:
password = dialog.get_password() await client.core.create_account(*account)
authlevel = dialog.get_authlevel() except AuthManagerError as ex:
return ErrorDialog(
_('Error Adding Account'),
_('Authentication failed'),
parent=self.pref_dialog,
details=ex,
).run()
except Exception as ex:
return ErrorDialog(
_('Error Adding Account'),
_(f'An error occurred while adding account: {account}'),
parent=self.pref_dialog,
details=ex,
).run()
def add_ok(rv): self.accounts_liststore.set(
accounts_iter = self.accounts_liststore.append() self.accounts_liststore.append(),
self.accounts_liststore.set_value( [ACCOUNTS_USERNAME, ACCOUNTS_LEVEL, ACCOUNTS_PASSWORD],
accounts_iter, ACCOUNTS_USERNAME, username [account.username, account.authlevel, account.password],
) )
self.accounts_liststore.set_value(
accounts_iter, ACCOUNTS_LEVEL, authlevel
)
self.accounts_liststore.set_value(
accounts_iter, ACCOUNTS_PASSWORD, password
)
def add_fail(failure):
if failure.type == AuthManagerError:
ErrorDialog(
_('Error Adding Account'),
_('Authentication failed'),
parent=self.pref_dialog,
details=failure.getErrorMessage(),
).run()
else:
ErrorDialog(
_('Error Adding Account'),
_('An error occurred while adding account'),
parent=self.pref_dialog,
details=failure.getErrorMessage(),
).run()
if response_id == Gtk.ResponseType.OK:
client.core.create_account(username, password, authlevel).addCallback(
add_ok
).addErrback(add_fail)
dialog.run().addCallback(dialog_finished)
def on_accounts_edit_clicked(self, widget): def on_accounts_edit_clicked(self, widget):
(model, itr) = self.accounts_listview.get_selection().get_selected() (model, itr) = self.accounts_listview.get_selection().get_selected()