gajim-plural/gajim/gtk/settings.py

656 lines
21 KiB
Python
Raw Normal View History

# Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com>
#
# This file is part of Gajim.
#
# Gajim is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation; version 3 only.
#
# Gajim 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 Gajim. If not, see <http://www.gnu.org/licenses/>.
from gi.repository import Gtk
from gi.repository import GLib
from gi.repository import Gdk
from gi.repository import GObject
from gi.repository import Pango
2017-08-15 19:12:30 +02:00
from gajim.common import app
from gajim.common import passwords
from gajim.common.i18n import _
2017-08-15 19:12:30 +02:00
from gajim.common.exceptions import GajimGeneralException
from gajim import gtkgui_helpers
from gajim.gtk.dialogs import ChangePasswordDialog
2018-10-28 23:19:24 +01:00
from gajim.gtk.util import get_image_button
2019-04-20 14:43:07 +02:00
from gajim.gtk.util import MaxWidthComboBoxText
from gajim.gtk.const import SettingKind
from gajim.gtk.const import SettingType
2017-08-15 19:12:30 +02:00
class SettingsDialog(Gtk.ApplicationWindow):
def __init__(self, parent, title, flags, settings, account,
extend=None):
2017-08-15 19:12:30 +02:00
Gtk.ApplicationWindow.__init__(self)
self.set_application(app.app)
self.set_show_menubar(False)
self.set_title(title)
self.set_transient_for(parent)
self.set_resizable(False)
self.set_default_size(250, -1)
self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
self.account = account
if flags == Gtk.DialogFlags.MODAL:
self.set_modal(True)
elif flags == Gtk.DialogFlags.DESTROY_WITH_PARENT:
self.set_destroy_with_parent(True)
self.listbox = SettingsBox(account, extend)
2017-08-15 19:12:30 +02:00
self.listbox.set_hexpand(True)
self.listbox.set_selection_mode(Gtk.SelectionMode.NONE)
for setting in settings:
self.listbox.add_setting(setting)
2017-08-15 19:12:30 +02:00
self.listbox.update_states()
self.add(self.listbox)
self.show_all()
self.listbox.connect('row-activated', self.on_row_activated)
2017-09-29 02:43:29 +02:00
self.connect('key-press-event', self.on_key_press)
2019-05-09 17:54:33 +02:00
def on_key_press(self, _widget, event):
2017-09-29 02:43:29 +02:00
if event.keyval == Gdk.KEY_Escape:
self.destroy()
2017-08-15 19:12:30 +02:00
@staticmethod
2019-05-09 17:54:33 +02:00
def on_row_activated(_listbox, row):
row.on_row_activated()
2017-08-15 19:12:30 +02:00
def get_setting(self, name):
return self.listbox.get_setting(name)
2017-08-15 19:12:30 +02:00
class SettingsBox(Gtk.ListBox):
def __init__(self, account, extend=None):
2017-08-15 19:12:30 +02:00
Gtk.ListBox.__init__(self)
self.get_style_context().add_class('settings-box')
2017-08-15 19:12:30 +02:00
self.account = account
self.named_settings = {}
2017-08-15 19:12:30 +02:00
self.map = {
SettingKind.SWITCH: SwitchSetting,
SettingKind.SPIN: SpinSetting,
SettingKind.DIALOG: DialogSetting,
SettingKind.ENTRY: EntrySetting,
SettingKind.ACTION: ActionSetting,
SettingKind.LOGIN: LoginSetting,
SettingKind.FILECHOOSER: FileChooserSetting,
SettingKind.CALLBACK: CallbackSetting,
SettingKind.PROXY: ProxyComboSetting,
SettingKind.PRIORITY: PrioritySetting,
SettingKind.HOSTNAME: CutstomHostnameSetting,
SettingKind.CHANGEPASSWORD: ChangePasswordSetting,
2019-04-20 14:19:22 +02:00
SettingKind.COMBO: ComboSetting,
2019-04-20 19:54:48 +02:00
SettingKind.CHATSTATE_COMBO: ChatstateComboSetting,
2017-08-15 19:12:30 +02:00
}
if extend is not None:
for setting, callback in extend:
self.map[setting] = callback
def add_setting(self, setting):
if not isinstance(setting, Gtk.ListBoxRow):
if setting.props is not None:
listitem = self.map[setting.kind](
self.account, *setting[1:-1], **setting.props)
else:
listitem = self.map[setting.kind](self.account, *setting[1:-1])
listitem.connect('notify::setting-value', self.on_setting_changed)
if setting.name is not None:
self.named_settings[setting.name] = listitem
2017-08-15 19:12:30 +02:00
self.add(listitem)
def get_setting(self, name):
return self.named_settings[name]
2017-08-15 19:12:30 +02:00
def update_states(self):
values = []
values.append((None, None))
for row in self.get_children():
name = row.name
2017-08-15 19:12:30 +02:00
if name is None:
continue
value = row.get_property('setting-value')
2017-08-15 19:12:30 +02:00
values.append((name, value))
for name, value in values:
for row in self.get_children():
row.update_activatable(name, value)
2017-08-15 19:12:30 +02:00
def on_setting_changed(self, widget, *args):
value = widget.get_property('setting-value')
2017-08-15 19:12:30 +02:00
for row in self.get_children():
row.update_activatable(widget.name, value)
2017-08-15 19:12:30 +02:00
class GenericSetting(Gtk.ListBoxRow):
2017-08-15 19:12:30 +02:00
def __init__(self, account, label, type_, value,
name, callback, data, desc, enabledif, enabled_func):
Gtk.ListBoxRow.__init__(self)
self._grid = Gtk.Grid()
self._grid.set_size_request(-1, 30)
self._grid.set_column_spacing(12)
2017-08-15 19:12:30 +02:00
self.callback = callback
self.type_ = type_
self.value = value
self.data = data
self.label = label
self.account = account
self.name = name
self.enabledif = enabledif
self.enabled_func = enabled_func
self.setting_value = self.get_value()
2017-08-15 19:12:30 +02:00
description_box = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0)
description_box.set_valign(Gtk.Align.CENTER)
settingtext = Gtk.Label(label=label)
settingtext.set_hexpand(True)
settingtext.set_halign(Gtk.Align.START)
settingtext.set_valign(Gtk.Align.CENTER)
settingtext.set_vexpand(True)
description_box.add(settingtext)
2017-08-15 19:12:30 +02:00
if desc is not None:
description = Gtk.Label(label=desc)
description.set_name('SubDescription')
description.set_hexpand(True)
description.set_halign(Gtk.Align.START)
description.set_valign(Gtk.Align.CENTER)
description.set_xalign(0)
description.set_line_wrap(True)
description.set_line_wrap_mode(Pango.WrapMode.WORD)
description.set_max_width_chars(50)
2017-08-15 19:12:30 +02:00
description_box.add(description)
self._grid.add(description_box)
2017-08-15 19:12:30 +02:00
self.setting_box = Gtk.Box(spacing=6)
self.setting_box.set_size_request(200, -1)
self.setting_box.set_valign(Gtk.Align.CENTER)
self.setting_box.set_name('GenericSettingBox')
self._grid.add(self.setting_box)
self.add(self._grid)
2017-08-15 19:12:30 +02:00
def do_get_property(self, prop):
if prop.name == 'setting-value':
return self.setting_value
2018-09-18 10:14:04 +02:00
raise AttributeError('unknown property %s' % prop.name)
2017-08-15 19:12:30 +02:00
def do_set_property(self, prop, value):
if prop.name == 'setting-value':
self.setting_value = value
2017-08-15 19:12:30 +02:00
else:
raise AttributeError('unknown property %s' % prop.name)
def get_value(self):
return self.__get_value(self.type_, self.value, self.account)
@staticmethod
def __get_value(type_, value, account):
if value is None:
2019-05-09 17:54:33 +02:00
return None
if type_ == SettingType.VALUE:
2017-08-15 19:12:30 +02:00
return value
2018-09-18 10:14:04 +02:00
if type_ == SettingType.CONFIG:
2017-08-15 19:12:30 +02:00
return app.config.get(value)
2018-09-18 10:14:04 +02:00
if type_ == SettingType.ACCOUNT_CONFIG:
2017-08-15 19:12:30 +02:00
if value == 'password':
return passwords.get_password(account)
2018-09-18 10:14:04 +02:00
if value == 'no_log_for':
2017-08-15 19:12:30 +02:00
no_log = app.config.get_per(
'accounts', account, 'no_log_for').split()
return account not in no_log
2018-09-18 10:14:04 +02:00
return app.config.get_per('accounts', account, value)
if type_ == SettingType.ACTION:
2017-08-15 19:12:30 +02:00
if value.startswith('-'):
return account + value
return value
2018-09-18 10:14:04 +02:00
raise ValueError('Wrong SettingType?')
2017-08-15 19:12:30 +02:00
def set_value(self, state):
if self.type_ == SettingType.CONFIG:
2017-08-15 19:12:30 +02:00
app.config.set(self.value, state)
if self.type_ == SettingType.ACCOUNT_CONFIG:
2017-08-15 19:12:30 +02:00
if self.value == 'password':
passwords.save_password(self.account, state)
if self.value == 'no_log_for':
self.set_no_log_for(self.account, state)
else:
app.config.set_per('accounts', self.account, self.value, state)
if self.callback is not None:
self.callback(state, self.data)
self.set_property('setting-value', state)
2017-08-15 19:12:30 +02:00
@staticmethod
2018-04-09 00:35:27 +02:00
def set_no_log_for(account, state):
2017-08-15 19:12:30 +02:00
no_log = app.config.get_per('accounts', account, 'no_log_for').split()
2018-04-09 00:35:27 +02:00
if state and account in no_log:
2017-08-15 19:12:30 +02:00
no_log.remove(account)
2018-04-09 00:35:27 +02:00
elif not state and account not in no_log:
2017-08-15 19:12:30 +02:00
no_log.append(account)
app.config.set_per('accounts', account, 'no_log_for', ' '.join(no_log))
def on_row_activated(self):
raise NotImplementedError
def update_activatable(self, name, value):
enabled_func_value = True
if self.enabled_func is not None:
enabled_func_value = self.enabled_func()
enabledif_value = True
if self.enabledif is not None and self.enabledif[0] == name:
enabledif_value = (name, value) == self.enabledif
self.set_activatable(enabled_func_value and enabledif_value)
self.set_sensitive(enabled_func_value and enabledif_value)
2017-08-15 19:12:30 +02:00
class SwitchSetting(GenericSetting):
2017-08-15 19:12:30 +02:00
__gproperties__ = {
"setting-value": (bool, 'Switch Value', '', False,
2019-05-09 17:54:33 +02:00
GObject.ParamFlags.READWRITE),}
2017-08-15 19:12:30 +02:00
def __init__(self, *args):
GenericSetting.__init__(self, *args)
2017-08-15 19:12:30 +02:00
self.switch = Gtk.Switch()
if self.type_ == SettingType.ACTION:
self.switch.set_action_name('app.%s' % self.setting_value)
state = app.app.get_action_state(self.setting_value)
self.switch.set_active(state.get_boolean())
else:
self.switch.set_active(self.setting_value)
2017-08-15 19:12:30 +02:00
self.switch.connect('notify::active', self.on_switch)
self.switch.set_hexpand(True)
self.switch.set_halign(Gtk.Align.END)
self.switch.set_valign(Gtk.Align.CENTER)
self.setting_box.add(self.switch)
2017-08-15 19:12:30 +02:00
self.show_all()
def on_row_activated(self):
state = self.switch.get_active()
self.switch.set_active(not state)
def on_switch(self, switch, *args):
value = switch.get_active()
self.set_value(value)
class EntrySetting(GenericSetting):
2017-08-15 19:12:30 +02:00
__gproperties__ = {
"setting-value": (str, 'Entry Value', '', '',
2019-05-09 17:54:33 +02:00
GObject.ParamFlags.READWRITE),}
2017-08-15 19:12:30 +02:00
def __init__(self, *args):
GenericSetting.__init__(self, *args)
2017-08-15 19:12:30 +02:00
self.entry = Gtk.Entry()
self.entry.set_text(str(self.setting_value))
2017-08-15 19:12:30 +02:00
self.entry.connect('notify::text', self.on_text_change)
self.entry.set_valign(Gtk.Align.CENTER)
self.entry.set_alignment(1)
2017-08-15 19:12:30 +02:00
if self.value == 'password':
self.entry.set_invisible_char('*')
self.entry.set_visibility(False)
self.setting_box.pack_end(self.entry, True, True, 0)
2017-08-15 19:12:30 +02:00
self.show_all()
def on_text_change(self, *args):
text = self.entry.get_text()
self.set_value(text)
def on_row_activated(self):
self.entry.grab_focus()
class DialogSetting(GenericSetting):
2017-08-15 19:12:30 +02:00
__gproperties__ = {
"setting-value": (str, 'Dummy', '', '',
2019-05-09 17:54:33 +02:00
GObject.ParamFlags.READWRITE),}
2017-08-15 19:12:30 +02:00
def __init__(self, *args, dialog):
GenericSetting.__init__(self, *args)
2017-08-15 19:12:30 +02:00
self.dialog = dialog
self.setting_value = Gtk.Label()
self.setting_value.set_text(self.get_setting_value())
self.setting_value.set_halign(Gtk.Align.END)
self.setting_box.pack_start(self.setting_value, True, True, 0)
2017-08-15 19:12:30 +02:00
self.show_all()
def show_dialog(self, parent):
if self.dialog:
dialog = self.dialog(self.account, parent)
dialog.connect('destroy', self.on_destroy)
def on_destroy(self, *args):
self.setting_value.set_text(self.get_setting_value())
2017-08-15 19:12:30 +02:00
def get_setting_value(self):
self.setting_value.hide()
2017-08-15 19:12:30 +02:00
return ''
def on_row_activated(self):
self.show_dialog(self.get_toplevel())
class SpinSetting(GenericSetting):
2017-08-15 19:12:30 +02:00
__gproperties__ = {
"setting-value": (int, 'Priority', '', -128, 127, 0,
2019-05-09 17:54:33 +02:00
GObject.ParamFlags.READWRITE),}
2017-08-15 19:12:30 +02:00
def __init__(self, *args, range_):
GenericSetting.__init__(self, *args)
2017-08-15 19:12:30 +02:00
lower, upper = range_
adjustment = Gtk.Adjustment(value=0,
lower=lower,
upper=upper,
step_increment=1,
page_increment=10,
page_size=0)
2017-08-15 19:12:30 +02:00
self.spin = Gtk.SpinButton()
self.spin.set_adjustment(adjustment)
self.spin.set_numeric(True)
self.spin.set_update_policy(Gtk.SpinButtonUpdatePolicy.IF_VALID)
self.spin.set_value(self.setting_value)
2017-08-15 19:12:30 +02:00
self.spin.set_halign(Gtk.Align.END)
self.spin.set_valign(Gtk.Align.CENTER)
self.spin.connect('notify::value', self.on_value_change)
self.setting_box.pack_start(self.spin, True, True, 0)
2017-08-15 19:12:30 +02:00
self.show_all()
def on_row_activated(self):
self.spin.grab_focus()
def on_value_change(self, spin, *args):
value = spin.get_value_as_int()
self.set_value(value)
class FileChooserSetting(GenericSetting):
2017-08-15 19:12:30 +02:00
__gproperties__ = {
"setting-value": (str, 'Certificate Path', '', '',
2019-05-09 17:54:33 +02:00
GObject.ParamFlags.READWRITE),}
2017-08-15 19:12:30 +02:00
def __init__(self, *args, filefilter):
GenericSetting.__init__(self, *args)
2017-08-15 19:12:30 +02:00
2018-11-18 21:31:58 +01:00
button = Gtk.FileChooserButton(title=self.label,
action=Gtk.FileChooserAction.OPEN)
2017-08-15 19:12:30 +02:00
button.set_halign(Gtk.Align.END)
# GTK Bug: The FileChooserButton expands without limit
# get the label and use set_max_wide_chars()
label = button.get_children()[0].get_children()[0].get_children()[1]
label.set_max_width_chars(20)
if filefilter:
name, pattern = filefilter
filter_ = Gtk.FileFilter()
filter_.set_name(name)
filter_.add_pattern(pattern)
button.add_filter(filter_)
button.set_filter(filter_)
filter_ = Gtk.FileFilter()
filter_.set_name(_('All files'))
filter_.add_pattern('*')
button.add_filter(filter_)
if self.setting_value:
button.set_filename(self.setting_value)
2017-08-15 19:12:30 +02:00
button.connect('selection-changed', self.on_select)
2018-10-28 23:19:24 +01:00
clear_button = get_image_button(
2018-01-11 15:12:07 +01:00
'edit-clear-all-symbolic', _('Clear File'))
2017-08-15 19:12:30 +02:00
clear_button.connect('clicked', lambda *args: button.unselect_all())
self.setting_box.pack_start(button, True, True, 0)
self.setting_box.pack_start(clear_button, False, False, 0)
2017-08-15 19:12:30 +02:00
self.show_all()
def on_select(self, filechooser):
self.set_value(filechooser.get_filename() or '')
def on_row_activated(self):
pass
class CallbackSetting(GenericSetting):
2017-08-15 19:12:30 +02:00
__gproperties__ = {
"setting-value": (str, 'Dummy', '', '',
2019-05-09 17:54:33 +02:00
GObject.ParamFlags.READWRITE),}
2017-08-15 19:12:30 +02:00
def __init__(self, *args, callback):
GenericSetting.__init__(self, *args)
2017-08-15 19:12:30 +02:00
self.callback = callback
self.show_all()
def on_row_activated(self):
self.callback()
class ActionSetting(GenericSetting):
2017-08-15 19:12:30 +02:00
__gproperties__ = {
"setting-value": (str, 'Dummy', '', '',
2019-05-09 17:54:33 +02:00
GObject.ParamFlags.READWRITE),}
2017-08-15 19:12:30 +02:00
def __init__(self, *args, account):
GenericSetting.__init__(self, *args)
action_name = '%s%s' % (account, self.value)
self.action = gtkgui_helpers.get_action(action_name)
self.variant = GLib.Variant.new_string(account)
2017-08-15 19:12:30 +02:00
self.on_enable()
self.show_all()
self.action.connect('notify::enabled', self.on_enable)
def on_enable(self, *args):
self.set_sensitive(self.action.get_enabled())
def on_row_activated(self):
self.action.activate(self.variant)
class LoginSetting(DialogSetting):
2017-08-15 19:12:30 +02:00
def __init__(self, *args, **kwargs):
DialogSetting.__init__(self, *args, **kwargs)
self.setting_value.set_selectable(True)
2017-08-15 19:12:30 +02:00
def get_setting_value(self):
2017-08-15 19:12:30 +02:00
jid = app.get_jid_from_account(self.account)
return jid
def update_activatable(self, name, value):
super().update_activatable(name, value)
2017-08-15 19:12:30 +02:00
anonym = app.config.get_per('accounts', self.account, 'anonymous_auth')
self.set_activatable(not anonym)
2017-08-15 19:12:30 +02:00
2019-04-20 14:19:22 +02:00
class ComboSetting(GenericSetting):
__gproperties__ = {
"setting-value": (str, 'Proxy', '', '',
2019-05-09 17:54:33 +02:00
GObject.ParamFlags.READWRITE),}
2019-04-20 14:19:22 +02:00
def __init__(self, *args, combo_items):
GenericSetting.__init__(self, *args)
2019-04-20 14:43:07 +02:00
self.combo = MaxWidthComboBoxText()
2019-04-20 14:19:22 +02:00
self.combo.set_valign(Gtk.Align.CENTER)
text_renderer = self.combo.get_cells()[0]
text_renderer.set_property('ellipsize', Pango.EllipsizeMode.END)
for index, value in enumerate(combo_items):
2019-04-20 14:43:07 +02:00
if isinstance(value, tuple):
value, label = value
self.combo.append(value, _(label))
else:
self.combo.append(value, value)
2019-04-20 14:19:22 +02:00
if value == self.setting_value or index == 0:
self.combo.set_active(index)
self.combo.connect('changed', self.on_value_change)
self.setting_box.pack_start(self.combo, True, True, 0)
self.show_all()
def on_value_change(self, combo):
self.set_value(combo.get_active_id())
2019-04-20 19:54:48 +02:00
class ChatstateComboSetting(ComboSetting):
def on_value_change(self, combo):
self.set_value(combo.get_active_id())
if 'muc' in self.value:
app.config.del_all_per('rooms', 'send_chatstate')
else:
app.config.del_all_per('contacts', 'send_chatstate')
class ProxyComboSetting(GenericSetting):
2017-08-15 19:12:30 +02:00
__gproperties__ = {
"setting-value": (str, 'Proxy', '', '',
2019-05-09 17:54:33 +02:00
GObject.ParamFlags.READWRITE),}
2017-08-15 19:12:30 +02:00
def __init__(self, *args):
GenericSetting.__init__(self, *args)
2017-08-15 19:12:30 +02:00
2019-04-20 14:43:07 +02:00
self.combo = MaxWidthComboBoxText()
2017-08-15 19:12:30 +02:00
self.combo.set_valign(Gtk.Align.CENTER)
2019-04-20 14:43:07 +02:00
text_renderer = self.combo.get_cells()[0]
text_renderer.set_property('ellipsize', Pango.EllipsizeMode.END)
2017-08-15 19:12:30 +02:00
self._signal_id = None
self.update_values()
2018-10-28 23:19:24 +01:00
button = get_image_button(
2018-01-11 15:12:07 +01:00
'preferences-system-symbolic', _('Manage Proxies'))
2017-08-15 19:12:30 +02:00
button.set_action_name('app.manage-proxies')
button.set_valign(Gtk.Align.CENTER)
self.setting_box.pack_start(self.combo, True, True, 0)
self.setting_box.pack_start(button, False, True, 0)
2017-08-15 19:12:30 +02:00
self.show_all()
def _block_signal(self, state):
if state:
if self._signal_id is None:
return
self.combo.disconnect(self._signal_id)
else:
self._signal_id = self.combo.connect('changed',
self.on_value_change)
self.combo.emit('changed')
2017-08-15 19:12:30 +02:00
def update_values(self):
self._block_signal(True)
2017-08-15 19:12:30 +02:00
proxies = app.config.get_per('proxies')
proxies.insert(0, _('No Proxy'))
2017-08-15 19:12:30 +02:00
self.combo.remove_all()
for index, value in enumerate(proxies):
self.combo.insert_text(-1, value)
if value == self.setting_value or index == 0:
2017-08-15 19:12:30 +02:00
self.combo.set_active(index)
self._block_signal(False)
2017-08-15 19:12:30 +02:00
def on_value_change(self, combo):
if combo.get_active() == 0:
self.set_value('')
else:
self.set_value(combo.get_active_text())
2017-08-15 19:12:30 +02:00
def on_row_activated(self):
pass
class PrioritySetting(DialogSetting):
2017-08-15 19:12:30 +02:00
def __init__(self, *args, **kwargs):
DialogSetting.__init__(self, *args, **kwargs)
2017-08-15 19:12:30 +02:00
def get_setting_value(self):
2017-08-15 19:12:30 +02:00
adjust = app.config.get_per(
'accounts', self.account, 'adjust_priority_with_status')
if adjust:
return _('Adjust to Status')
priority = app.config.get_per('accounts', self.account, 'priority')
return str(priority)
class CutstomHostnameSetting(DialogSetting):
2017-08-15 19:12:30 +02:00
def __init__(self, *args, **kwargs):
DialogSetting.__init__(self, *args, **kwargs)
2017-08-15 19:12:30 +02:00
def get_setting_value(self):
2017-08-15 19:12:30 +02:00
custom = app.config.get_per('accounts', self.account, 'use_custom_host')
return _('On') if custom else _('Off')
class ChangePasswordSetting(DialogSetting):
2017-08-15 19:12:30 +02:00
def __init__(self, *args, **kwargs):
DialogSetting.__init__(self, *args, **kwargs)
2017-08-15 19:12:30 +02:00
def show_dialog(self, parent):
try:
self.change_dialog = ChangePasswordDialog(
2017-08-15 19:12:30 +02:00
self.account, self.on_changed, parent)
except GajimGeneralException:
return
self.change_dialog.set_modal(True)
2017-08-15 19:12:30 +02:00
def on_changed(self, new_password):
self.set_value(new_password)
2017-08-15 19:12:30 +02:00
def update_activatable(self, name, value):
2017-08-15 19:12:30 +02:00
activatable = False
if self.account in app.connections:
con = app.connections[self.account]
activatable = con.is_connected and con.register_supported
self.set_activatable(activatable)