Refactor OptionsDialog

- Rename Option to Setting, it fits better
- Settings inherit from Gtk.ListBoxRow
This commit is contained in:
Philipp Hörist 2019-04-20 12:56:00 +02:00
parent cc3750711d
commit c343746430
6 changed files with 409 additions and 374 deletions

View File

@ -3,36 +3,9 @@ from collections import namedtuple
from gajim.common.i18n import _ from gajim.common.i18n import _
Option = namedtuple('Option', 'kind label type value name callback data desc enabledif props')
Option.__new__.__defaults__ = (None,) * len(Option._fields) # type: ignore
EncryptionData = namedtuple('EncryptionData', 'additional_data') EncryptionData = namedtuple('EncryptionData', 'additional_data')
EncryptionData.__new__.__defaults__ = (None,) # type: ignore EncryptionData.__new__.__defaults__ = (None,) # type: ignore
@unique
class OptionKind(IntEnum):
ENTRY = 0
SWITCH = 1
SPIN = 2
ACTION = 3
LOGIN = 4
DIALOG = 5
CALLBACK = 6
PROXY = 7
HOSTNAME = 8
PRIORITY = 9
FILECHOOSER = 10
CHANGEPASSWORD = 11
@unique
class OptionType(IntEnum):
ACCOUNT_CONFIG = 0
CONFIG = 1
VALUE = 2
ACTION = 3
DIALOG = 4
class AvatarSize(IntEnum): class AvatarSize(IntEnum):
TAB = 16 TAB = 16

View File

@ -83,17 +83,17 @@ popover#EmoticonPopover { padding: 5px; background-color: @theme_unfocused_base_
#FeaturesInfoGrid > list > label { padding:10px; color: @insensitive_fg_color; font-weight: bold; } #FeaturesInfoGrid > list > label { padding:10px; color: @insensitive_fg_color; font-weight: bold; }
#FeaturesInfoGrid > list > row.activatable:active { box-shadow: none; } #FeaturesInfoGrid > list > row.activatable:active { box-shadow: none; }
/* OptionsBox */ /* SettingsBox */
#OptionsBox > row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; } #SettingsBox > row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; }
#OptionsBox > row:last-child { border-bottom: 0px} #SettingsBox > row:last-child { border-bottom: 0px}
#OptionsBox > row.activatable:active { box-shadow: none; } #SettingsBox > row.activatable:active { box-shadow: none; }
#OptionsBox > row { padding: 10px 20px 10px 10px; } #SettingsBox > row { padding: 10px 20px 10px 10px; }
#OptionsBox > row:not(.activatable) label { color: @insensitive_fg_color } #SettingsBox > row:not(.activatable) label { color: @insensitive_fg_color }
/* GenericOption */ /* GenericSetting */
#SubDescription { color: @insensitive_fg_color;} #SubDescription { color: @insensitive_fg_color;}
#GenericOptionBox { margin-left: 30px; } #GenericSettingBox { margin-left: 30px; }
#GenericOptionBox > label { padding-right: 3px; } #GenericSettingBox > label { padding-right: 3px; }
/* Generic Popover Menu with Buttons */ /* Generic Popover Menu with Buttons */
.PopoverButtonListbox { padding-left: 0px; padding-right: 0px; } .PopoverButtonListbox { padding-left: 0px; padding-right: 0px; }

View File

@ -25,16 +25,12 @@ from gajim.common import ged
from gajim.common.i18n import _ from gajim.common.i18n import _
from gajim.common.connection import Connection from gajim.common.connection import Connection
from gajim.common.zeroconf.connection_zeroconf import ConnectionZeroconf from gajim.common.zeroconf.connection_zeroconf import ConnectionZeroconf
from gajim.common.const import Option
from gajim.common.const import OptionKind
from gajim.common.const import OptionType
from gajim import gui_menu_builder from gajim import gui_menu_builder
from gajim.dialogs import PassphraseDialog from gajim.dialogs import PassphraseDialog
from gajim.options_dialog import OptionsDialog from gajim.gtk.settings import SettingsDialog
from gajim.options_dialog import OptionsBox from gajim.gtk.settings import SettingsBox
from gajim.gtk.dialogs import ConfirmationDialog from gajim.gtk.dialogs import ConfirmationDialog
from gajim.gtk.dialogs import ConfirmationDialogDoubleRadio from gajim.gtk.dialogs import ConfirmationDialogDoubleRadio
from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import ErrorDialog
@ -43,6 +39,9 @@ from gajim.gtk.dialogs import DialogButton
from gajim.gtk.dialogs import NewConfirmationDialog from gajim.gtk.dialogs import NewConfirmationDialog
from gajim.gtk.util import get_icon_name from gajim.gtk.util import get_icon_name
from gajim.gtk.util import get_builder from gajim.gtk.util import get_builder
from gajim.gtk.const import Setting
from gajim.gtk.const import SettingKind
from gajim.gtk.const import SettingType
class AccountsWindow(Gtk.ApplicationWindow): class AccountsWindow(Gtk.ApplicationWindow):
@ -67,7 +66,7 @@ class AccountsWindow(Gtk.ApplicationWindow):
accounts = app.config.get_per('accounts') accounts = app.config.get_per('accounts')
accounts.sort() accounts.sort()
for account in accounts: for account in accounts:
self.need_relogin[account] = self.get_relogin_options(account) self.need_relogin[account] = self.get_relogin_settings(account)
account_item = Account(account, self) account_item = Account(account, self)
self._ui.account_list.add(account_item) self._ui.account_list.add(account_item)
account_item.set_activatable() account_item.set_activatable()
@ -135,14 +134,14 @@ class AccountsWindow(Gtk.ApplicationWindow):
page = self._ui.stack.get_child_by_name('connection') page = self._ui.stack.get_child_by_name('connection')
if page is None: if page is None:
return return
page.listbox.get_option('proxy').update_values() page.listbox.get_setting('proxy').update_values()
def check_relogin(self): def check_relogin(self):
for account in self.need_relogin: for account in self.need_relogin:
options = self.get_relogin_options(account) settings = self.get_relogin_settings(account)
active = app.config.get_per('accounts', account, 'active') active = app.config.get_per('accounts', account, 'active')
if options != self.need_relogin[account]: if settings != self.need_relogin[account]:
self.need_relogin[account] = options self.need_relogin[account] = settings
if active: if active:
self.relog(account) self.relog(account)
break break
@ -180,17 +179,17 @@ class AccountsWindow(Gtk.ApplicationWindow):
on_response_yes=lambda *args: relog(account)) on_response_yes=lambda *args: relog(account))
@staticmethod @staticmethod
def get_relogin_options(account): def get_relogin_settings(account):
if account == app.ZEROCONF_ACC_NAME: if account == app.ZEROCONF_ACC_NAME:
options = ['zeroconf_first_name', 'zeroconf_last_name', settings = ['zeroconf_first_name', 'zeroconf_last_name',
'zeroconf_jabber_id', 'zeroconf_email'] 'zeroconf_jabber_id', 'zeroconf_email']
else: else:
options = ['client_cert', 'proxy', 'resource', settings = ['client_cert', 'proxy', 'resource',
'use_custom_host', 'custom_host', 'custom_port'] 'use_custom_host', 'custom_host', 'custom_port']
values = [] values = []
for option in options: for setting in settings:
values.append(app.config.get_per('accounts', account, option)) values.append(app.config.get_per('accounts', account, setting))
return values return values
def on_remove_account(self, button, account): def on_remove_account(self, button, account):
@ -248,7 +247,7 @@ class AccountsWindow(Gtk.ApplicationWindow):
account_item.set_activatable() account_item.set_activatable()
self._ui.account_list.show_all() self._ui.account_list.show_all()
self._ui.stack.show_all() self._ui.stack.show_all()
self.need_relogin[account] = self.get_relogin_options(account) self.need_relogin[account] = self.get_relogin_settings(account)
def select_account(self, account): def select_account(self, account):
for row in self._ui.account_list.get_children(): for row in self._ui.account_list.get_children():
@ -365,7 +364,7 @@ class Preferences(Gtk.Box):
Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL,
spacing=12) spacing=12)
self.options = PreferencesPage() self.settings = PreferencesPage()
self.parent = parent self.parent = parent
self.account = None self.account = None
@ -383,8 +382,8 @@ class Preferences(Gtk.Box):
pass pass
def on_row_activated(self): def on_row_activated(self):
self.options.update_states() self.settings.update_states()
self.parent.set_page(self.options, 'pref') self.parent.set_page(self.settings, 'pref')
def update(self): def update(self):
pass pass
@ -396,9 +395,9 @@ class Account(Gtk.Box):
spacing=12) spacing=12)
self.account = account self.account = account
if account == app.ZEROCONF_ACC_NAME: if account == app.ZEROCONF_ACC_NAME:
self.options = ZeroConfPage(account, parent) self.settings = ZeroConfPage(account, parent)
else: else:
self.options = AccountPage(account, parent) self.settings = AccountPage(account, parent)
self.parent = parent self.parent = parent
self.label = Gtk.Label(label=app.get_account_label(account)) self.label = Gtk.Label(label=app.get_account_label(account))
@ -421,8 +420,8 @@ class Account(Gtk.Box):
_('Please check if Avahi or Bonjour is installed.')) _('Please check if Avahi or Bonjour is installed.'))
def on_row_activated(self): def on_row_activated(self):
self.options.update_states() self.settings.update_states()
self.parent.set_page(self.options, 'account') self.parent.set_page(self.settings, 'account')
def update(self): def update(self):
self.label.set_text(app.get_account_label(self.account)) self.label.set_text(app.get_account_label(self.account))
@ -434,8 +433,8 @@ class Account(Gtk.Box):
self.image.set_from_icon_name(icon, Gtk.IconSize.MENU) self.image.set_from_icon_name(icon, Gtk.IconSize.MENU)
class GenericOptionPage(Gtk.Box): class GenericSettingPage(Gtk.Box):
def __init__(self, account, parent, options): def __init__(self, account, parent, settings):
Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=12) Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=12)
self.account = account self.account = account
self.parent = parent self.parent = parent
@ -447,13 +446,13 @@ class GenericOptionPage(Gtk.Box):
if not isinstance(self, (AccountPage, PreferencesPage, ZeroConfPage)): if not isinstance(self, (AccountPage, PreferencesPage, ZeroConfPage)):
self.pack_start(button, False, True, 0) self.pack_start(button, False, True, 0)
self.listbox = OptionsBox(account) self.listbox = SettingsBox(account)
self.listbox.set_selection_mode(Gtk.SelectionMode.NONE) self.listbox.set_selection_mode(Gtk.SelectionMode.NONE)
self.listbox.set_vexpand(False) self.listbox.set_vexpand(False)
self.listbox.set_valign(Gtk.Align.END) self.listbox.set_valign(Gtk.Align.END)
for option in options: for setting in settings:
self.listbox.add_option(option) self.listbox.add_setting(setting)
self.listbox.update_states() self.listbox.update_states()
self.pack_end(self.listbox, True, True, 0) self.pack_end(self.listbox, True, True, 0)
@ -471,7 +470,7 @@ class GenericOptionPage(Gtk.Box):
self.listbox.update_states() self.listbox.update_states()
def on_row_activated(self, listbox, row): def on_row_activated(self, listbox, row):
row.get_child().on_row_activated() row.on_row_activated()
def set_entry_text(self, toggle, update=False): def set_entry_text(self, toggle, update=False):
account_label = app.get_account_label(self.account) account_label = app.get_account_label(self.account)
@ -495,9 +494,9 @@ class GenericOptionPage(Gtk.Box):
def update(self): def update(self):
pass pass
def set_page(self, options, name): def set_page(self, settings, name):
options.update_states() settings.update_states()
self.get_toplevel().set_page(options, name) self.get_toplevel().set_page(settings, name)
def _add_top_buttons(self, parent): def _add_top_buttons(self, parent):
# This adds the Account enable switch and the back button # This adds the Account enable switch and the back button
@ -560,18 +559,18 @@ class GenericOptionPage(Gtk.Box):
app.config.set_per('accounts', account, 'active', state) app.config.set_per('accounts', account, 'active', state)
class PreferencesPage(GenericOptionPage): class PreferencesPage(GenericSettingPage):
def __init__(self): def __init__(self):
options = [ settings = [
Option(OptionKind.SWITCH, _('Merge Accounts'), Setting(SettingKind.SWITCH, _('Merge Accounts'),
OptionType.ACTION, 'merge'), SettingType.ACTION, 'merge'),
] ]
GenericOptionPage.__init__(self, None, None, options) GenericSettingPage.__init__(self, None, None, settings)
class AccountPage(GenericOptionPage): class AccountPage(GenericSettingPage):
def __init__(self, account, parent=None): def __init__(self, account, parent=None):
general = partial( general = partial(
@ -579,152 +578,150 @@ class AccountPage(GenericOptionPage):
connection = partial( connection = partial(
self.set_page, ConnectionPage(account, self), 'connection') self.set_page, ConnectionPage(account, self), 'connection')
options = [ settings = [
Option(OptionKind.ENTRY, _('Label'), Setting(SettingKind.ENTRY, _('Label'),
OptionType.ACCOUNT_CONFIG, 'account_label', SettingType.ACCOUNT_CONFIG, 'account_label',
callback=self._on_account_name_change), callback=self._on_account_name_change),
Option(OptionKind.LOGIN, _('Login'), OptionType.DIALOG, Setting(SettingKind.LOGIN, _('Login'), SettingType.DIALOG,
props={'dialog': LoginDialog}), props={'dialog': LoginDialog}),
Option(OptionKind.ACTION, _('Profile'), OptionType.ACTION, Setting(SettingKind.ACTION, _('Profile'), SettingType.ACTION,
'-profile', props={'action_args': account}), '-profile', props={'action_args': account}),
Option(OptionKind.CALLBACK, _('General'), Setting(SettingKind.CALLBACK, _('General'),
name='general', props={'callback': general}), name='general', props={'callback': general}),
Option(OptionKind.CALLBACK, _('Connection'), Setting(SettingKind.CALLBACK, _('Connection'),
name='connection', props={'callback': connection}), name='connection', props={'callback': connection}),
Option(OptionKind.ACTION, _('Import Contacts'), OptionType.ACTION, Setting(SettingKind.ACTION, _('Import Contacts'), SettingType.ACTION,
'-import-contacts', props={'action_args': account}), '-import-contacts', props={'action_args': account}),
Option(OptionKind.DIALOG, _('Client Certificate'), Setting(SettingKind.DIALOG, _('Client Certificate'),
OptionType.DIALOG, props={'dialog': CertificateDialog}), SettingType.DIALOG, props={'dialog': CertificateDialog}),
] ]
GenericOptionPage.__init__(self, account, parent, options) GenericSettingPage.__init__(self, account, parent, settings)
self._add_top_buttons(parent) self._add_top_buttons(parent)
def _on_account_name_change(self, account_name, *args): def _on_account_name_change(self, account_name, *args):
self.parent.update_accounts() self.parent.update_accounts()
class GeneralPage(GenericOptionPage): class GeneralPage(GenericSettingPage):
def __init__(self, account, parent=None): def __init__(self, account, parent=None):
options = [ settings = [
Option(OptionKind.SWITCH, _('Connect on startup'), Setting(SettingKind.SWITCH, _('Connect on startup'),
OptionType.ACCOUNT_CONFIG, 'autoconnect'), SettingType.ACCOUNT_CONFIG, 'autoconnect'),
Option(OptionKind.SWITCH, _('Reconnect when connection is lost'), Setting(SettingKind.SWITCH, _('Reconnect when connection is lost'),
OptionType.ACCOUNT_CONFIG, 'autoreconnect'), SettingType.ACCOUNT_CONFIG, 'autoreconnect'),
Option(OptionKind.SWITCH, _('Save conversations for all contacts'), Setting(SettingKind.SWITCH, _('Save conversations for all contacts'),
OptionType.ACCOUNT_CONFIG, 'no_log_for', SettingType.ACCOUNT_CONFIG, 'no_log_for',
desc=_('Store conversations on the harddrive')), desc=_('Store conversations on the harddrive')),
Option(OptionKind.SWITCH, _('Server Message Archive'), Setting(SettingKind.SWITCH, _('Server Message Archive'),
OptionType.ACCOUNT_CONFIG, 'sync_logs_with_server', SettingType.ACCOUNT_CONFIG, 'sync_logs_with_server',
desc=_('Messages get stored on the server.\n' desc=_('Messages get stored on the server. '
'The archive is used to sync messages\n' 'The archive is used to sync messages '
'between multiple devices.\n' 'between multiple devices. (XEP-0313)')),
'XEP-0313')),
Option(OptionKind.SWITCH, _('Global Status'), Setting(SettingKind.SWITCH, _('Global Status'),
OptionType.ACCOUNT_CONFIG, 'sync_with_global_status', SettingType.ACCOUNT_CONFIG, 'sync_with_global_status',
desc=_('Synchronise the status of all accounts')), desc=_('Synchronise the status of all accounts')),
Option(OptionKind.SWITCH, _('Message Carbons'), Setting(SettingKind.SWITCH, _('Message Carbons'),
OptionType.ACCOUNT_CONFIG, 'enable_message_carbons', SettingType.ACCOUNT_CONFIG, 'enable_message_carbons',
desc=_('All your other online devices get copies\n' desc=_('All your other online devices get copies '
'of sent and received messages.\n' 'of sent and received messages. XEP-0280')),
'XEP-0280')),
Option(OptionKind.SWITCH, _('Use file transfer proxies'), Setting(SettingKind.SWITCH, _('Use file transfer proxies'),
OptionType.ACCOUNT_CONFIG, 'use_ft_proxies'), SettingType.ACCOUNT_CONFIG, 'use_ft_proxies'),
] ]
GenericOptionPage.__init__(self, account, parent, options) GenericSettingPage.__init__(self, account, parent, settings)
class ConnectionPage(GenericOptionPage): class ConnectionPage(GenericSettingPage):
def __init__(self, account, parent=None): def __init__(self, account, parent=None):
options = [ settings = [
Option(OptionKind.SWITCH, 'HTTP_PROXY', Setting(SettingKind.SWITCH, 'HTTP_PROXY',
OptionType.ACCOUNT_CONFIG, 'use_env_http_proxy', SettingType.ACCOUNT_CONFIG, 'use_env_http_proxy',
desc=_('Use environment variable')), desc=_('Use environment variable')),
Option(OptionKind.PROXY, _('Proxy'), Setting(SettingKind.PROXY, _('Proxy'),
OptionType.ACCOUNT_CONFIG, 'proxy', name='proxy'), SettingType.ACCOUNT_CONFIG, 'proxy', name='proxy'),
Option(OptionKind.SWITCH, _('Warn on insecure connection'), Setting(SettingKind.SWITCH, _('Warn on insecure connection'),
OptionType.ACCOUNT_CONFIG, SettingType.ACCOUNT_CONFIG,
'warn_when_insecure_ssl_connection'), 'warn_when_insecure_ssl_connection'),
Option(OptionKind.SWITCH, _('Send keep-alive packets'), Setting(SettingKind.SWITCH, _('Send keep-alive packets'),
OptionType.ACCOUNT_CONFIG, 'keep_alives_enabled'), SettingType.ACCOUNT_CONFIG, 'keep_alives_enabled'),
Option(OptionKind.HOSTNAME, _('Hostname'), OptionType.DIALOG, Setting(SettingKind.HOSTNAME, _('Hostname'), SettingType.DIALOG,
desc=_('Manually set the hostname for the server'), desc=_('Manually set the hostname for the server'),
props={'dialog': CutstomHostnameDialog}), props={'dialog': CutstomHostnameDialog}),
Option(OptionKind.ENTRY, _('Resource'), Setting(SettingKind.ENTRY, _('Resource'),
OptionType.ACCOUNT_CONFIG, 'resource'), SettingType.ACCOUNT_CONFIG, 'resource'),
Option(OptionKind.PRIORITY, _('Priority'), Setting(SettingKind.PRIORITY, _('Priority'),
OptionType.DIALOG, props={'dialog': PriorityDialog}), SettingType.DIALOG, props={'dialog': PriorityDialog}),
] ]
GenericOptionPage.__init__(self, account, parent, options) GenericSettingPage.__init__(self, account, parent, settings)
class ZeroConfPage(GenericOptionPage): class ZeroConfPage(GenericSettingPage):
def __init__(self, account, parent=None): def __init__(self, account, parent=None):
options = [ settings = [
Option(OptionKind.DIALOG, _('Profile'), Setting(SettingKind.DIALOG, _('Profile'),
OptionType.DIALOG, props={'dialog': ZeroconfProfileDialog}), SettingType.DIALOG, props={'dialog': ZeroconfProfileDialog}),
Option(OptionKind.SWITCH, _('Connect on startup'), Setting(SettingKind.SWITCH, _('Connect on startup'),
OptionType.ACCOUNT_CONFIG, 'autoconnect', SettingType.ACCOUNT_CONFIG, 'autoconnect',
desc=_('Use environment variable')), desc=_('Use environment variable')),
Option(OptionKind.SWITCH, _('Save conversations for all contacts'), Setting(SettingKind.SWITCH, _('Save conversations for all contacts'),
OptionType.ACCOUNT_CONFIG, 'no_log_for', SettingType.ACCOUNT_CONFIG, 'no_log_for',
desc=_('Store conversations on the harddrive')), desc=_('Store conversations on the harddrive')),
Option(OptionKind.SWITCH, _('Global Status'), Setting(SettingKind.SWITCH, _('Global Status'),
OptionType.ACCOUNT_CONFIG, 'sync_with_global_status', SettingType.ACCOUNT_CONFIG, 'sync_with_global_status',
desc=_('Synchronize the status of all accounts')), desc=_('Synchronize the status of all accounts')),
] ]
GenericOptionPage.__init__(self, account, parent, options) GenericSettingPage.__init__(self, account, parent, settings)
self._add_top_buttons(None) self._add_top_buttons(None)
class ZeroconfProfileDialog(OptionsDialog): class ZeroconfProfileDialog(SettingsDialog):
def __init__(self, account, parent): def __init__(self, account, parent):
options = [ settings = [
Option(OptionKind.ENTRY, _('First Name'), Setting(SettingKind.ENTRY, _('First Name'),
OptionType.ACCOUNT_CONFIG, 'zeroconf_first_name'), SettingType.ACCOUNT_CONFIG, 'zeroconf_first_name'),
Option(OptionKind.ENTRY, _('Last Name'), Setting(SettingKind.ENTRY, _('Last Name'),
OptionType.ACCOUNT_CONFIG, 'zeroconf_last_name'), SettingType.ACCOUNT_CONFIG, 'zeroconf_last_name'),
Option(OptionKind.ENTRY, _('Jabber ID'), Setting(SettingKind.ENTRY, _('Jabber ID'),
OptionType.ACCOUNT_CONFIG, 'zeroconf_jabber_id'), SettingType.ACCOUNT_CONFIG, 'zeroconf_jabber_id'),
Option(OptionKind.ENTRY, _('Email'), Setting(SettingKind.ENTRY, _('Email'),
OptionType.ACCOUNT_CONFIG, 'zeroconf_email'), SettingType.ACCOUNT_CONFIG, 'zeroconf_email'),
] ]
OptionsDialog.__init__(self, parent, _('Profile'), SettingsDialog.__init__(self, parent, _('Profile'),
Gtk.DialogFlags.MODAL, options, account) Gtk.DialogFlags.MODAL, settings, account)
class PriorityDialog(OptionsDialog): class PriorityDialog(SettingsDialog):
def __init__(self, account, parent): def __init__(self, account, parent):
neg_priority = app.config.get('enable_negative_priority') neg_priority = app.config.get('enable_negative_priority')
@ -733,18 +730,18 @@ class PriorityDialog(OptionsDialog):
else: else:
range_ = (0, 127) range_ = (0, 127)
options = [ settings = [
Option(OptionKind.SWITCH, _('Adjust to status'), Setting(SettingKind.SWITCH, _('Adjust to status'),
OptionType.ACCOUNT_CONFIG, 'adjust_priority_with_status', SettingType.ACCOUNT_CONFIG, 'adjust_priority_with_status',
'adjust'), 'adjust'),
Option(OptionKind.SPIN, _('Priority'), Setting(SettingKind.SPIN, _('Priority'),
OptionType.ACCOUNT_CONFIG, 'priority', SettingType.ACCOUNT_CONFIG, 'priority',
enabledif=('adjust', False), props={'range_': range_}), enabledif=('adjust', False), props={'range_': range_}),
] ]
OptionsDialog.__init__(self, parent, _('Priority'), SettingsDialog.__init__(self, parent, _('Priority'),
Gtk.DialogFlags.MODAL, options, account) Gtk.DialogFlags.MODAL, settings, account)
self.connect('destroy', self.on_destroy) self.connect('destroy', self.on_destroy)
@ -757,60 +754,60 @@ class PriorityDialog(OptionsDialog):
app.connections[self.account].change_status(show, status) app.connections[self.account].change_status(show, status)
class CutstomHostnameDialog(OptionsDialog): class CutstomHostnameDialog(SettingsDialog):
def __init__(self, account, parent): def __init__(self, account, parent):
options = [ settings = [
Option(OptionKind.SWITCH, _('Enable'), Setting(SettingKind.SWITCH, _('Enable'),
OptionType.ACCOUNT_CONFIG, 'use_custom_host', name='custom'), SettingType.ACCOUNT_CONFIG, 'use_custom_host', name='custom'),
Option(OptionKind.ENTRY, _('Hostname'), Setting(SettingKind.ENTRY, _('Hostname'),
OptionType.ACCOUNT_CONFIG, 'custom_host', SettingType.ACCOUNT_CONFIG, 'custom_host',
enabledif=('custom', True)), enabledif=('custom', True)),
Option(OptionKind.ENTRY, _('Port'), Setting(SettingKind.ENTRY, _('Port'),
OptionType.ACCOUNT_CONFIG, 'custom_port', SettingType.ACCOUNT_CONFIG, 'custom_port',
enabledif=('custom', True)), enabledif=('custom', True)),
] ]
OptionsDialog.__init__(self, parent, _('Connection Options'), SettingsDialog.__init__(self, parent, _('Connection Settings'),
Gtk.DialogFlags.MODAL, options, account) Gtk.DialogFlags.MODAL, settings, account)
class CertificateDialog(OptionsDialog): class CertificateDialog(SettingsDialog):
def __init__(self, account, parent): def __init__(self, account, parent):
options = [ Settings = [
Option(OptionKind.FILECHOOSER, _('Client Certificate'), Setting(SettingKind.FILECHOOSER, _('Client Certificate'),
OptionType.ACCOUNT_CONFIG, 'client_cert', SettingType.ACCOUNT_CONFIG, 'client_cert',
props={'filefilter': (_('PKCS12 Files'), '*.p12')}), props={'filefilter': (_('PKCS12 Files'), '*.p12')}),
Option(OptionKind.SWITCH, _('Encrypted Certificate'), Setting(SettingKind.SWITCH, _('Encrypted Certificate'),
OptionType.ACCOUNT_CONFIG, 'client_cert_encrypted'), SettingType.ACCOUNT_CONFIG, 'client_cert_encrypted'),
] ]
OptionsDialog.__init__(self, parent, _('Certificate Options'), SettingsDialog.__init__(self, parent, _('Certificate Settings'),
Gtk.DialogFlags.MODAL, options, account) Gtk.DialogFlags.MODAL, Settings, account)
class LoginDialog(OptionsDialog): class LoginDialog(SettingsDialog):
def __init__(self, account, parent): def __init__(self, account, parent):
options = [ settings = [
Option(OptionKind.ENTRY, _('Password'), Setting(SettingKind.ENTRY, _('Password'),
OptionType.ACCOUNT_CONFIG, 'password', name='password', SettingType.ACCOUNT_CONFIG, 'password', name='password',
enabledif=('savepass', True)), enabledif=('savepass', True)),
Option(OptionKind.SWITCH, _('Save Password'), Setting(SettingKind.SWITCH, _('Save Password'),
OptionType.ACCOUNT_CONFIG, 'savepass', name='savepass'), SettingType.ACCOUNT_CONFIG, 'savepass', name='savepass'),
Option(OptionKind.CHANGEPASSWORD, _('Change Password'), Setting(SettingKind.CHANGEPASSWORD, _('Change Password'),
OptionType.DIALOG, callback=self.on_password_change, SettingType.DIALOG, callback=self.on_password_change,
props={'dialog': None}), props={'dialog': None}),
] ]
OptionsDialog.__init__(self, parent, _('Login Options'), SettingsDialog.__init__(self, parent, _('Login Settings'),
Gtk.DialogFlags.MODAL, options, account) Gtk.DialogFlags.MODAL, settings, account)
self.connect('destroy', self.on_destroy) self.connect('destroy', self.on_destroy)

View File

@ -21,6 +21,9 @@ from enum import unique
Filter = namedtuple('Filter', 'name pattern default') Filter = namedtuple('Filter', 'name pattern default')
Setting = namedtuple('Setting', 'kind label type value name callback data desc enabledif props')
Setting.__new__.__defaults__ = (None,) * len(Setting._fields) # type: ignore
@unique @unique
class Theme(IntEnum): class Theme(IntEnum):
NOT_DARK = 0 NOT_DARK = 0
@ -36,3 +39,28 @@ class GajimIconSet(Enum):
JABBERBULB = 'jabberbulb' JABBERBULB = 'jabberbulb'
SUN = 'sun' SUN = 'sun'
WROOP = 'wroop' WROOP = 'wroop'
@unique
class SettingKind(IntEnum):
ENTRY = 0
SWITCH = 1
SPIN = 2
ACTION = 3
LOGIN = 4
DIALOG = 5
CALLBACK = 6
PROXY = 7
HOSTNAME = 8
PRIORITY = 9
FILECHOOSER = 10
CHANGEPASSWORD = 11
@unique
class SettingType(IntEnum):
ACCOUNT_CONFIG = 0
CONFIG = 1
VALUE = 2
ACTION = 3
DIALOG = 4

View File

@ -1,16 +1,41 @@
from gi.repository import Gtk, GLib, Gdk, GObject # 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
from gajim.common import app from gajim.common import app
from gajim.common import passwords from gajim.common import passwords
from gajim.common.i18n import _ from gajim.common.i18n import _
from gajim import gtkgui_helpers
from gajim.common.const import OptionKind, OptionType
from gajim.common.exceptions import GajimGeneralException from gajim.common.exceptions import GajimGeneralException
from gajim import gtkgui_helpers
from gajim.gtk.dialogs import ChangePasswordDialog from gajim.gtk.dialogs import ChangePasswordDialog
from gajim.gtk.util import get_image_button from gajim.gtk.util import get_image_button
from gajim.gtk.const import SettingKind
from gajim.gtk.const import SettingType
class OptionsDialog(Gtk.ApplicationWindow): class SettingsDialog(Gtk.ApplicationWindow):
def __init__(self, parent, title, flags, options, account, def __init__(self, parent, title, flags, settings, account,
extend=None): extend=None):
Gtk.ApplicationWindow.__init__(self) Gtk.ApplicationWindow.__init__(self)
self.set_application(app.app) self.set_application(app.app)
@ -26,12 +51,12 @@ class OptionsDialog(Gtk.ApplicationWindow):
elif flags == Gtk.DialogFlags.DESTROY_WITH_PARENT: elif flags == Gtk.DialogFlags.DESTROY_WITH_PARENT:
self.set_destroy_with_parent(True) self.set_destroy_with_parent(True)
self.listbox = OptionsBox(account, extend) self.listbox = SettingsBox(account, extend)
self.listbox.set_hexpand(True) self.listbox.set_hexpand(True)
self.listbox.set_selection_mode(Gtk.SelectionMode.NONE) self.listbox.set_selection_mode(Gtk.SelectionMode.NONE)
for option in options: for setting in settings:
self.listbox.add_option(option) self.listbox.add_setting(setting)
self.listbox.update_states() self.listbox.update_states()
self.add(self.listbox) self.add(self.listbox)
@ -46,78 +71,81 @@ class OptionsDialog(Gtk.ApplicationWindow):
@staticmethod @staticmethod
def on_row_activated(listbox, row): def on_row_activated(listbox, row):
row.get_child().on_row_activated() row.on_row_activated()
def get_option(self, name): def get_setting(self, name):
return self.listbox.get_option(name) return self.listbox.get_setting(name)
class OptionsBox(Gtk.ListBox): class SettingsBox(Gtk.ListBox):
def __init__(self, account, extend=None): def __init__(self, account, extend=None):
Gtk.ListBox.__init__(self) Gtk.ListBox.__init__(self)
self.set_name('OptionsBox') self.set_name('SettingsBox')
self.account = account self.account = account
self.named_options = {} self.named_settings = {}
self.map = { self.map = {
OptionKind.SWITCH: SwitchOption, SettingKind.SWITCH: SwitchSetting,
OptionKind.SPIN: SpinOption, SettingKind.SPIN: SpinSetting,
OptionKind.DIALOG: DialogOption, SettingKind.DIALOG: DialogSetting,
OptionKind.ENTRY: EntryOption, SettingKind.ENTRY: EntrySetting,
OptionKind.ACTION: ActionOption, SettingKind.ACTION: ActionSetting,
OptionKind.LOGIN: LoginOption, SettingKind.LOGIN: LoginSetting,
OptionKind.FILECHOOSER: FileChooserOption, SettingKind.FILECHOOSER: FileChooserSetting,
OptionKind.CALLBACK: CallbackOption, SettingKind.CALLBACK: CallbackSetting,
OptionKind.PROXY: ProxyComboOption, SettingKind.PROXY: ProxyComboSetting,
OptionKind.PRIORITY: PriorityOption, SettingKind.PRIORITY: PrioritySetting,
OptionKind.HOSTNAME: CutstomHostnameOption, SettingKind.HOSTNAME: CutstomHostnameSetting,
OptionKind.CHANGEPASSWORD: ChangePasswordOption, SettingKind.CHANGEPASSWORD: ChangePasswordSetting,
} }
if extend is not None: if extend is not None:
for option, callback in extend: for setting, callback in extend:
self.map[option] = callback self.map[setting] = callback
def add_option(self, option): def add_setting(self, setting):
if option.props is not None: if not isinstance(setting, Gtk.ListBoxRow):
listitem = self.map[option.kind]( if setting.props is not None:
self.account, *option[1:-1], **option.props) listitem = self.map[setting.kind](
self.account, *setting[1:-1], **setting.props)
else: else:
listitem = self.map[option.kind](self.account, *option[1:-1]) listitem = self.map[setting.kind](self.account, *setting[1:-1])
listitem.connect('notify::option-value', self.on_option_changed) listitem.connect('notify::setting-value', self.on_setting_changed)
if option.name is not None: if setting.name is not None:
self.named_options[option.name] = listitem self.named_settings[setting.name] = listitem
self.add(listitem) self.add(listitem)
def get_option(self, name): def get_setting(self, name):
return self.named_options[name] return self.named_settings[name]
def update_states(self): def update_states(self):
values = [] values = []
values.append((None, None)) values.append((None, None))
for row in self.get_children(): for row in self.get_children():
name = row.get_child().name name = row.name
if name is None: if name is None:
continue continue
value = row.get_child().get_property('option-value') value = row.get_property('setting-value')
values.append((name, value)) values.append((name, value))
for name, value in values: for name, value in values:
for row in self.get_children(): for row in self.get_children():
row.get_child().set_activatable(name, value) row.update_activatable(name, value)
def on_option_changed(self, widget, *args): def on_setting_changed(self, widget, *args):
value = widget.get_property('option-value') value = widget.get_property('setting-value')
for row in self.get_children(): for row in self.get_children():
row.get_child().set_activatable(widget.name, value) row.update_activatable(widget.name, value)
class GenericOption(Gtk.Grid): class GenericSetting(Gtk.ListBoxRow):
def __init__(self, account, label, type_, value, def __init__(self, account, label, type_, value,
name, callback, data, desc, enabledif): name, callback, data, desc, enabledif):
Gtk.Grid.__init__(self) Gtk.ListBoxRow.__init__(self)
self.set_column_spacing(12) self._grid = Gtk.Grid()
self.set_size_request(-1, 25) self._grid.set_size_request(-1, 30)
self._grid.set_column_spacing(12)
self.callback = callback self.callback = callback
self.type_ = type_ self.type_ = type_
self.value = value self.value = value
@ -126,18 +154,18 @@ class GenericOption(Gtk.Grid):
self.account = account self.account = account
self.name = name self.name = name
self.enabledif = enabledif self.enabledif = enabledif
self.option_value = self.get_value() self.setting_value = self.get_value()
description_box = Gtk.Box( description_box = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=0) orientation=Gtk.Orientation.VERTICAL, spacing=0)
description_box.set_valign(Gtk.Align.CENTER) description_box.set_valign(Gtk.Align.CENTER)
optiontext = Gtk.Label(label=label) settingtext = Gtk.Label(label=label)
optiontext.set_hexpand(True) settingtext.set_hexpand(True)
optiontext.set_halign(Gtk.Align.START) settingtext.set_halign(Gtk.Align.START)
optiontext.set_valign(Gtk.Align.CENTER) settingtext.set_valign(Gtk.Align.CENTER)
optiontext.set_vexpand(True) settingtext.set_vexpand(True)
description_box.add(optiontext) description_box.add(settingtext)
if desc is not None: if desc is not None:
description = Gtk.Label(label=desc) description = Gtk.Label(label=desc)
@ -145,24 +173,29 @@ class GenericOption(Gtk.Grid):
description.set_hexpand(True) description.set_hexpand(True)
description.set_halign(Gtk.Align.START) description.set_halign(Gtk.Align.START)
description.set_valign(Gtk.Align.CENTER) 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(40)
description_box.add(description) description_box.add(description)
self.add(description_box) self._grid.add(description_box)
self.option_box = Gtk.Box(spacing=6) self.setting_box = Gtk.Box(spacing=6)
self.option_box.set_size_request(200, -1) self.setting_box.set_size_request(200, -1)
self.option_box.set_valign(Gtk.Align.CENTER) self.setting_box.set_valign(Gtk.Align.CENTER)
self.option_box.set_name('GenericOptionBox') self.setting_box.set_name('GenericSettingBox')
self.add(self.option_box) self._grid.add(self.setting_box)
self.add(self._grid)
def do_get_property(self, prop): def do_get_property(self, prop):
if prop.name == 'option-value': if prop.name == 'setting-value':
return self.option_value return self.setting_value
raise AttributeError('unknown property %s' % prop.name) raise AttributeError('unknown property %s' % prop.name)
def do_set_property(self, prop, value): def do_set_property(self, prop, value):
if prop.name == 'option-value': if prop.name == 'setting-value':
self.option_value = value self.setting_value = value
else: else:
raise AttributeError('unknown property %s' % prop.name) raise AttributeError('unknown property %s' % prop.name)
@ -173,13 +206,13 @@ class GenericOption(Gtk.Grid):
def __get_value(type_, value, account): def __get_value(type_, value, account):
if value is None: if value is None:
return return
if type_ == OptionType.VALUE: if type_ == SettingType.VALUE:
return value return value
if type_ == OptionType.CONFIG: if type_ == SettingType.CONFIG:
return app.config.get(value) return app.config.get(value)
if type_ == OptionType.ACCOUNT_CONFIG: if type_ == SettingType.ACCOUNT_CONFIG:
if value == 'password': if value == 'password':
return passwords.get_password(account) return passwords.get_password(account)
if value == 'no_log_for': if value == 'no_log_for':
@ -188,17 +221,17 @@ class GenericOption(Gtk.Grid):
return account not in no_log return account not in no_log
return app.config.get_per('accounts', account, value) return app.config.get_per('accounts', account, value)
if type_ == OptionType.ACTION: if type_ == SettingType.ACTION:
if value.startswith('-'): if value.startswith('-'):
return account + value return account + value
return value return value
raise ValueError('Wrong OptionType?') raise ValueError('Wrong SettingType?')
def set_value(self, state): def set_value(self, state):
if self.type_ == OptionType.CONFIG: if self.type_ == SettingType.CONFIG:
app.config.set(self.value, state) app.config.set(self.value, state)
if self.type_ == OptionType.ACCOUNT_CONFIG: if self.type_ == SettingType.ACCOUNT_CONFIG:
if self.value == 'password': if self.value == 'password':
passwords.save_password(self.account, state) passwords.save_password(self.account, state)
if self.value == 'no_log_for': if self.value == 'no_log_for':
@ -209,7 +242,7 @@ class GenericOption(Gtk.Grid):
if self.callback is not None: if self.callback is not None:
self.callback(state, self.data) self.callback(state, self.data)
self.set_property('option-value', state) self.set_property('setting-value', state)
@staticmethod @staticmethod
def set_no_log_for(account, state): def set_no_log_for(account, state):
@ -223,36 +256,36 @@ class GenericOption(Gtk.Grid):
def on_row_activated(self): def on_row_activated(self):
raise NotImplementedError raise NotImplementedError
def set_activatable(self, name, value): def update_activatable(self, name, value):
if self.enabledif is None or self.enabledif[0] != name: if self.enabledif is None or self.enabledif[0] != name:
return return
activatable = (name, value) == self.enabledif activatable = (name, value) == self.enabledif
self.get_parent().set_activatable(activatable) self.set_activatable(activatable)
self.set_sensitive(activatable) self.set_sensitive(activatable)
class SwitchOption(GenericOption): class SwitchSetting(GenericSetting):
__gproperties__ = { __gproperties__ = {
"option-value": (bool, 'Switch Value', '', False, "setting-value": (bool, 'Switch Value', '', False,
GObject.ParamFlags.READWRITE),} GObject.ParamFlags.READWRITE),}
def __init__(self, *args): def __init__(self, *args):
GenericOption.__init__(self, *args) GenericSetting.__init__(self, *args)
self.switch = Gtk.Switch() self.switch = Gtk.Switch()
if self.type_ == OptionType.ACTION: if self.type_ == SettingType.ACTION:
self.switch.set_action_name('app.%s' % self.option_value) self.switch.set_action_name('app.%s' % self.setting_value)
state = app.app.get_action_state(self.option_value) state = app.app.get_action_state(self.setting_value)
self.switch.set_active(state.get_boolean()) self.switch.set_active(state.get_boolean())
else: else:
self.switch.set_active(self.option_value) self.switch.set_active(self.setting_value)
self.switch.connect('notify::active', self.on_switch) self.switch.connect('notify::active', self.on_switch)
self.switch.set_hexpand(True) self.switch.set_hexpand(True)
self.switch.set_halign(Gtk.Align.END) self.switch.set_halign(Gtk.Align.END)
self.switch.set_valign(Gtk.Align.CENTER) self.switch.set_valign(Gtk.Align.CENTER)
self.option_box.add(self.switch) self.setting_box.add(self.switch)
self.show_all() self.show_all()
@ -265,17 +298,17 @@ class SwitchOption(GenericOption):
self.set_value(value) self.set_value(value)
class EntryOption(GenericOption): class EntrySetting(GenericSetting):
__gproperties__ = { __gproperties__ = {
"option-value": (str, 'Entry Value', '', '', "setting-value": (str, 'Entry Value', '', '',
GObject.ParamFlags.READWRITE),} GObject.ParamFlags.READWRITE),}
def __init__(self, *args): def __init__(self, *args):
GenericOption.__init__(self, *args) GenericSetting.__init__(self, *args)
self.entry = Gtk.Entry() self.entry = Gtk.Entry()
self.entry.set_text(str(self.option_value)) self.entry.set_text(str(self.setting_value))
self.entry.connect('notify::text', self.on_text_change) self.entry.connect('notify::text', self.on_text_change)
self.entry.set_valign(Gtk.Align.CENTER) self.entry.set_valign(Gtk.Align.CENTER)
self.entry.set_alignment(1) self.entry.set_alignment(1)
@ -284,7 +317,7 @@ class EntryOption(GenericOption):
self.entry.set_invisible_char('*') self.entry.set_invisible_char('*')
self.entry.set_visibility(False) self.entry.set_visibility(False)
self.option_box.pack_end(self.entry, True, True, 0) self.setting_box.pack_end(self.entry, True, True, 0)
self.show_all() self.show_all()
@ -296,20 +329,20 @@ class EntryOption(GenericOption):
self.entry.grab_focus() self.entry.grab_focus()
class DialogOption(GenericOption): class DialogSetting(GenericSetting):
__gproperties__ = { __gproperties__ = {
"option-value": (str, 'Dummy', '', '', "setting-value": (str, 'Dummy', '', '',
GObject.ParamFlags.READWRITE),} GObject.ParamFlags.READWRITE),}
def __init__(self, *args, dialog): def __init__(self, *args, dialog):
GenericOption.__init__(self, *args) GenericSetting.__init__(self, *args)
self.dialog = dialog self.dialog = dialog
self.option_value = Gtk.Label() self.setting_value = Gtk.Label()
self.option_value.set_text(self.get_option_value()) self.setting_value.set_text(self.get_setting_value())
self.option_value.set_halign(Gtk.Align.END) self.setting_value.set_halign(Gtk.Align.END)
self.option_box.pack_start(self.option_value, True, True, 0) self.setting_box.pack_start(self.setting_value, True, True, 0)
self.show_all() self.show_all()
@ -319,38 +352,43 @@ class DialogOption(GenericOption):
dialog.connect('destroy', self.on_destroy) dialog.connect('destroy', self.on_destroy)
def on_destroy(self, *args): def on_destroy(self, *args):
self.option_value.set_text(self.get_option_value()) self.setting_value.set_text(self.get_setting_value())
def get_option_value(self): def get_setting_value(self):
self.option_value.hide() self.setting_value.hide()
return '' return ''
def on_row_activated(self): def on_row_activated(self):
self.show_dialog(self.get_toplevel()) self.show_dialog(self.get_toplevel())
class SpinOption(GenericOption): class SpinSetting(GenericSetting):
__gproperties__ = { __gproperties__ = {
"option-value": (int, 'Priority', '', -128, 127, 0, "setting-value": (int, 'Priority', '', -128, 127, 0,
GObject.ParamFlags.READWRITE),} GObject.ParamFlags.READWRITE),}
def __init__(self, *args, range_): def __init__(self, *args, range_):
GenericOption.__init__(self, *args) GenericSetting.__init__(self, *args)
lower, upper = range_ lower, upper = range_
adjustment = Gtk.Adjustment(0, lower, upper, 1, 10, 0) adjustment = Gtk.Adjustment(value=0,
lower=lower,
upper=upper,
step_increment=1,
page_increment=10,
page_size=0)
self.spin = Gtk.SpinButton() self.spin = Gtk.SpinButton()
self.spin.set_adjustment(adjustment) self.spin.set_adjustment(adjustment)
self.spin.set_numeric(True) self.spin.set_numeric(True)
self.spin.set_update_policy(Gtk.SpinButtonUpdatePolicy.IF_VALID) self.spin.set_update_policy(Gtk.SpinButtonUpdatePolicy.IF_VALID)
self.spin.set_value(self.option_value) self.spin.set_value(self.setting_value)
self.spin.set_halign(Gtk.Align.END) self.spin.set_halign(Gtk.Align.END)
self.spin.set_valign(Gtk.Align.CENTER) self.spin.set_valign(Gtk.Align.CENTER)
self.spin.connect('notify::value', self.on_value_change) self.spin.connect('notify::value', self.on_value_change)
self.option_box.pack_start(self.spin, True, True, 0) self.setting_box.pack_start(self.spin, True, True, 0)
self.show_all() self.show_all()
@ -362,14 +400,14 @@ class SpinOption(GenericOption):
self.set_value(value) self.set_value(value)
class FileChooserOption(GenericOption): class FileChooserSetting(GenericSetting):
__gproperties__ = { __gproperties__ = {
"option-value": (str, 'Certificate Path', '', '', "setting-value": (str, 'Certificate Path', '', '',
GObject.ParamFlags.READWRITE),} GObject.ParamFlags.READWRITE),}
def __init__(self, *args, filefilter): def __init__(self, *args, filefilter):
GenericOption.__init__(self, *args) GenericSetting.__init__(self, *args)
button = Gtk.FileChooserButton(title=self.label, button = Gtk.FileChooserButton(title=self.label,
action=Gtk.FileChooserAction.OPEN) action=Gtk.FileChooserAction.OPEN)
@ -393,15 +431,15 @@ class FileChooserOption(GenericOption):
filter_.add_pattern('*') filter_.add_pattern('*')
button.add_filter(filter_) button.add_filter(filter_)
if self.option_value: if self.setting_value:
button.set_filename(self.option_value) button.set_filename(self.setting_value)
button.connect('selection-changed', self.on_select) button.connect('selection-changed', self.on_select)
clear_button = get_image_button( clear_button = get_image_button(
'edit-clear-all-symbolic', _('Clear File')) 'edit-clear-all-symbolic', _('Clear File'))
clear_button.connect('clicked', lambda *args: button.unselect_all()) clear_button.connect('clicked', lambda *args: button.unselect_all())
self.option_box.pack_start(button, True, True, 0) self.setting_box.pack_start(button, True, True, 0)
self.option_box.pack_start(clear_button, False, False, 0) self.setting_box.pack_start(clear_button, False, False, 0)
self.show_all() self.show_all()
@ -412,14 +450,14 @@ class FileChooserOption(GenericOption):
pass pass
class CallbackOption(GenericOption): class CallbackSetting(GenericSetting):
__gproperties__ = { __gproperties__ = {
"option-value": (str, 'Dummy', '', '', "setting-value": (str, 'Dummy', '', '',
GObject.ParamFlags.READWRITE),} GObject.ParamFlags.READWRITE),}
def __init__(self, *args, callback): def __init__(self, *args, callback):
GenericOption.__init__(self, *args) GenericSetting.__init__(self, *args)
self.callback = callback self.callback = callback
self.show_all() self.show_all()
@ -427,15 +465,15 @@ class CallbackOption(GenericOption):
self.callback() self.callback()
class ActionOption(GenericOption): class ActionSetting(GenericSetting):
__gproperties__ = { __gproperties__ = {
"option-value": (str, 'Dummy', '', '', "setting-value": (str, 'Dummy', '', '',
GObject.ParamFlags.READWRITE),} GObject.ParamFlags.READWRITE),}
def __init__(self, *args, action_args): def __init__(self, *args, action_args):
GenericOption.__init__(self, *args) GenericSetting.__init__(self, *args)
self.action = gtkgui_helpers.get_action(self.option_value) self.action = gtkgui_helpers.get_action(self.setting_value)
self.variant = GLib.Variant.new_string(action_args) self.variant = GLib.Variant.new_string(action_args)
self.on_enable() self.on_enable()
@ -449,29 +487,29 @@ class ActionOption(GenericOption):
self.action.activate(self.variant) self.action.activate(self.variant)
class LoginOption(DialogOption): class LoginSetting(DialogSetting):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
DialogOption.__init__(self, *args, **kwargs) DialogSetting.__init__(self, *args, **kwargs)
self.option_value.set_selectable(True) self.setting_value.set_selectable(True)
def get_option_value(self): def get_setting_value(self):
jid = app.get_jid_from_account(self.account) jid = app.get_jid_from_account(self.account)
return jid return jid
def set_activatable(self, name, value): def update_activatable(self, name, value):
DialogOption.set_activatable(self, name, value) super().update_activatable(name, value)
anonym = app.config.get_per('accounts', self.account, 'anonymous_auth') anonym = app.config.get_per('accounts', self.account, 'anonymous_auth')
self.get_parent().set_activatable(not anonym) self.set_activatable(not anonym)
class ProxyComboOption(GenericOption): class ProxyComboSetting(GenericSetting):
__gproperties__ = { __gproperties__ = {
"option-value": (str, 'Proxy', '', '', "setting-value": (str, 'Proxy', '', '',
GObject.ParamFlags.READWRITE),} GObject.ParamFlags.READWRITE),}
def __init__(self, *args): def __init__(self, *args):
GenericOption.__init__(self, *args) GenericSetting.__init__(self, *args)
self.combo = Gtk.ComboBoxText() self.combo = Gtk.ComboBoxText()
self.combo.set_valign(Gtk.Align.CENTER) self.combo.set_valign(Gtk.Align.CENTER)
@ -484,8 +522,8 @@ class ProxyComboOption(GenericOption):
button.set_action_name('app.manage-proxies') button.set_action_name('app.manage-proxies')
button.set_valign(Gtk.Align.CENTER) button.set_valign(Gtk.Align.CENTER)
self.option_box.pack_start(self.combo, True, True, 0) self.setting_box.pack_start(self.combo, True, True, 0)
self.option_box.pack_start(button, False, True, 0) self.setting_box.pack_start(button, False, True, 0)
self.show_all() self.show_all()
def _block_signal(self, state): def _block_signal(self, state):
@ -505,7 +543,7 @@ class ProxyComboOption(GenericOption):
self.combo.remove_all() self.combo.remove_all()
for index, value in enumerate(proxies): for index, value in enumerate(proxies):
self.combo.insert_text(-1, value) self.combo.insert_text(-1, value)
if value == self.option_value or index == 0: if value == self.setting_value or index == 0:
self.combo.set_active(index) self.combo.set_active(index)
self._block_signal(False) self._block_signal(False)
@ -519,11 +557,11 @@ class ProxyComboOption(GenericOption):
pass pass
class PriorityOption(DialogOption): class PrioritySetting(DialogSetting):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
DialogOption.__init__(self, *args, **kwargs) DialogSetting.__init__(self, *args, **kwargs)
def get_option_value(self): def get_setting_value(self):
adjust = app.config.get_per( adjust = app.config.get_per(
'accounts', self.account, 'adjust_priority_with_status') 'accounts', self.account, 'adjust_priority_with_status')
if adjust: if adjust:
@ -533,18 +571,18 @@ class PriorityOption(DialogOption):
return str(priority) return str(priority)
class CutstomHostnameOption(DialogOption): class CutstomHostnameSetting(DialogSetting):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
DialogOption.__init__(self, *args, **kwargs) DialogSetting.__init__(self, *args, **kwargs)
def get_option_value(self): def get_setting_value(self):
custom = app.config.get_per('accounts', self.account, 'use_custom_host') custom = app.config.get_per('accounts', self.account, 'use_custom_host')
return _('On') if custom else _('Off') return _('On') if custom else _('Off')
class ChangePasswordOption(DialogOption): class ChangePasswordSetting(DialogSetting):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
DialogOption.__init__(self, *args, **kwargs) DialogSetting.__init__(self, *args, **kwargs)
def show_dialog(self, parent): def show_dialog(self, parent):
try: try:
@ -557,9 +595,9 @@ class ChangePasswordOption(DialogOption):
def on_changed(self, new_password): def on_changed(self, new_password):
self.set_value(new_password) self.set_value(new_password)
def set_activatable(self, name, value): def update_activatable(self, name, value):
activatable = False activatable = False
if self.account in app.connections: if self.account in app.connections:
con = app.connections[self.account] con = app.connections[self.account]
activatable = con.connected >= 2 and con.register_supported activatable = con.connected >= 2 and con.register_supported
self.get_parent().set_activatable(activatable) self.set_activatable(activatable)

View File

@ -22,17 +22,16 @@ from gi.repository import GLib
from gajim.common import app from gajim.common import app
from gajim.common import ged from gajim.common import ged
from gajim.common.i18n import _ from gajim.common.i18n import _
from gajim.common.const import Option
from gajim.common.const import OptionKind
from gajim.common.const import OptionType
from gajim.common.const import StyleAttr from gajim.common.const import StyleAttr
from gajim.gtk import util from gajim.gtk import util
from gajim.gtk.util import get_builder from gajim.gtk.util import get_builder
from gajim.gtk.util import get_image_button from gajim.gtk.util import get_image_button
from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import ErrorDialog
from gajim.gtk.settings import SettingsDialog
from gajim.options_dialog import OptionsDialog from gajim.gtk.const import Setting
from gajim.gtk.const import SettingKind
from gajim.gtk.const import SettingType
UNDECLARED = 'http://www.gajim.org/xmlns/undeclared' UNDECLARED = 'http://www.gajim.org/xmlns/undeclared'
@ -191,29 +190,29 @@ class XMLConsoleWindow(Gtk.Window):
self.filter_dialog.present() self.filter_dialog.present()
return return
options = [ options = [
Option(OptionKind.SWITCH, 'Presence', Setting(SettingKind.SWITCH, 'Presence',
OptionType.VALUE, self.presence, SettingType.VALUE, self.presence,
callback=self.on_option, data='presence'), callback=self.on_option, data='presence'),
Option(OptionKind.SWITCH, 'Message', Setting(SettingKind.SWITCH, 'Message',
OptionType.VALUE, self.message, SettingType.VALUE, self.message,
callback=self.on_option, data='message'), callback=self.on_option, data='message'),
Option(OptionKind.SWITCH, 'Iq', OptionType.VALUE, self.iq, Setting(SettingKind.SWITCH, 'Iq', SettingType.VALUE, self.iq,
callback=self.on_option, data='iq'), callback=self.on_option, data='iq'),
Option(OptionKind.SWITCH, 'Stream\nManagement', Setting(SettingKind.SWITCH, 'Stream\nManagement',
OptionType.VALUE, self.stream, SettingType.VALUE, self.stream,
callback=self.on_option, data='stream'), callback=self.on_option, data='stream'),
Option(OptionKind.SWITCH, 'In', OptionType.VALUE, self.incoming, Setting(SettingKind.SWITCH, 'In', SettingType.VALUE, self.incoming,
callback=self.on_option, data='incoming'), callback=self.on_option, data='incoming'),
Option(OptionKind.SWITCH, 'Out', OptionType.VALUE, self.outgoing, Setting(SettingKind.SWITCH, 'Out', SettingType.VALUE, self.outgoing,
callback=self.on_option, data='outgoing'), callback=self.on_option, data='outgoing'),
] ]
self.filter_dialog = OptionsDialog(self, 'Filter', self.filter_dialog = SettingsDialog(self, 'Filter',
Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.DialogFlags.DESTROY_WITH_PARENT,
options, self.account) options, self.account)
self.filter_dialog.connect('destroy', self.on_filter_destroyed) self.filter_dialog.connect('destroy', self.on_filter_destroyed)