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 _
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.__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):
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 > row.activatable:active { box-shadow: none; }
/* OptionsBox */
#OptionsBox > row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; }
#OptionsBox > row:last-child { border-bottom: 0px}
#OptionsBox > row.activatable:active { box-shadow: none; }
#OptionsBox > row { padding: 10px 20px 10px 10px; }
#OptionsBox > row:not(.activatable) label { color: @insensitive_fg_color }
/* SettingsBox */
#SettingsBox > row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; }
#SettingsBox > row:last-child { border-bottom: 0px}
#SettingsBox > row.activatable:active { box-shadow: none; }
#SettingsBox > row { padding: 10px 20px 10px 10px; }
#SettingsBox > row:not(.activatable) label { color: @insensitive_fg_color }
/* GenericOption */
/* GenericSetting */
#SubDescription { color: @insensitive_fg_color;}
#GenericOptionBox { margin-left: 30px; }
#GenericOptionBox > label { padding-right: 3px; }
#GenericSettingBox { margin-left: 30px; }
#GenericSettingBox > label { padding-right: 3px; }
/* Generic Popover Menu with Buttons */
.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.connection import Connection
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.dialogs import PassphraseDialog
from gajim.options_dialog import OptionsDialog
from gajim.options_dialog import OptionsBox
from gajim.gtk.settings import SettingsDialog
from gajim.gtk.settings import SettingsBox
from gajim.gtk.dialogs import ConfirmationDialog
from gajim.gtk.dialogs import ConfirmationDialogDoubleRadio
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.util import get_icon_name
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):
@ -67,7 +66,7 @@ class AccountsWindow(Gtk.ApplicationWindow):
accounts = app.config.get_per('accounts')
accounts.sort()
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)
self._ui.account_list.add(account_item)
account_item.set_activatable()
@ -135,14 +134,14 @@ class AccountsWindow(Gtk.ApplicationWindow):
page = self._ui.stack.get_child_by_name('connection')
if page is None:
return
page.listbox.get_option('proxy').update_values()
page.listbox.get_setting('proxy').update_values()
def check_relogin(self):
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')
if options != self.need_relogin[account]:
self.need_relogin[account] = options
if settings != self.need_relogin[account]:
self.need_relogin[account] = settings
if active:
self.relog(account)
break
@ -180,17 +179,17 @@ class AccountsWindow(Gtk.ApplicationWindow):
on_response_yes=lambda *args: relog(account))
@staticmethod
def get_relogin_options(account):
def get_relogin_settings(account):
if account == app.ZEROCONF_ACC_NAME:
options = ['zeroconf_first_name', 'zeroconf_last_name',
'zeroconf_jabber_id', 'zeroconf_email']
settings = ['zeroconf_first_name', 'zeroconf_last_name',
'zeroconf_jabber_id', 'zeroconf_email']
else:
options = ['client_cert', 'proxy', 'resource',
'use_custom_host', 'custom_host', 'custom_port']
settings = ['client_cert', 'proxy', 'resource',
'use_custom_host', 'custom_host', 'custom_port']
values = []
for option in options:
values.append(app.config.get_per('accounts', account, option))
for setting in settings:
values.append(app.config.get_per('accounts', account, setting))
return values
def on_remove_account(self, button, account):
@ -248,7 +247,7 @@ class AccountsWindow(Gtk.ApplicationWindow):
account_item.set_activatable()
self._ui.account_list.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):
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,
spacing=12)
self.options = PreferencesPage()
self.settings = PreferencesPage()
self.parent = parent
self.account = None
@ -383,8 +382,8 @@ class Preferences(Gtk.Box):
pass
def on_row_activated(self):
self.options.update_states()
self.parent.set_page(self.options, 'pref')
self.settings.update_states()
self.parent.set_page(self.settings, 'pref')
def update(self):
pass
@ -396,9 +395,9 @@ class Account(Gtk.Box):
spacing=12)
self.account = account
if account == app.ZEROCONF_ACC_NAME:
self.options = ZeroConfPage(account, parent)
self.settings = ZeroConfPage(account, parent)
else:
self.options = AccountPage(account, parent)
self.settings = AccountPage(account, parent)
self.parent = parent
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.'))
def on_row_activated(self):
self.options.update_states()
self.parent.set_page(self.options, 'account')
self.settings.update_states()
self.parent.set_page(self.settings, 'account')
def update(self):
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)
class GenericOptionPage(Gtk.Box):
def __init__(self, account, parent, options):
class GenericSettingPage(Gtk.Box):
def __init__(self, account, parent, settings):
Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=12)
self.account = account
self.parent = parent
@ -447,13 +446,13 @@ class GenericOptionPage(Gtk.Box):
if not isinstance(self, (AccountPage, PreferencesPage, ZeroConfPage)):
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_vexpand(False)
self.listbox.set_valign(Gtk.Align.END)
for option in options:
self.listbox.add_option(option)
for setting in settings:
self.listbox.add_setting(setting)
self.listbox.update_states()
self.pack_end(self.listbox, True, True, 0)
@ -471,7 +470,7 @@ class GenericOptionPage(Gtk.Box):
self.listbox.update_states()
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):
account_label = app.get_account_label(self.account)
@ -495,9 +494,9 @@ class GenericOptionPage(Gtk.Box):
def update(self):
pass
def set_page(self, options, name):
options.update_states()
self.get_toplevel().set_page(options, name)
def set_page(self, settings, name):
settings.update_states()
self.get_toplevel().set_page(settings, name)
def _add_top_buttons(self, parent):
# 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)
class PreferencesPage(GenericOptionPage):
class PreferencesPage(GenericSettingPage):
def __init__(self):
options = [
Option(OptionKind.SWITCH, _('Merge Accounts'),
OptionType.ACTION, 'merge'),
settings = [
Setting(SettingKind.SWITCH, _('Merge Accounts'),
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):
general = partial(
@ -579,152 +578,150 @@ class AccountPage(GenericOptionPage):
connection = partial(
self.set_page, ConnectionPage(account, self), 'connection')
options = [
Option(OptionKind.ENTRY, _('Label'),
OptionType.ACCOUNT_CONFIG, 'account_label',
callback=self._on_account_name_change),
settings = [
Setting(SettingKind.ENTRY, _('Label'),
SettingType.ACCOUNT_CONFIG, 'account_label',
callback=self._on_account_name_change),
Option(OptionKind.LOGIN, _('Login'), OptionType.DIALOG,
props={'dialog': LoginDialog}),
Setting(SettingKind.LOGIN, _('Login'), SettingType.DIALOG,
props={'dialog': LoginDialog}),
Option(OptionKind.ACTION, _('Profile'), OptionType.ACTION,
'-profile', props={'action_args': account}),
Setting(SettingKind.ACTION, _('Profile'), SettingType.ACTION,
'-profile', props={'action_args': account}),
Option(OptionKind.CALLBACK, _('General'),
name='general', props={'callback': general}),
Setting(SettingKind.CALLBACK, _('General'),
name='general', props={'callback': general}),
Option(OptionKind.CALLBACK, _('Connection'),
name='connection', props={'callback': connection}),
Setting(SettingKind.CALLBACK, _('Connection'),
name='connection', props={'callback': connection}),
Option(OptionKind.ACTION, _('Import Contacts'), OptionType.ACTION,
'-import-contacts', props={'action_args': account}),
Setting(SettingKind.ACTION, _('Import Contacts'), SettingType.ACTION,
'-import-contacts', props={'action_args': account}),
Option(OptionKind.DIALOG, _('Client Certificate'),
OptionType.DIALOG, props={'dialog': CertificateDialog}),
Setting(SettingKind.DIALOG, _('Client Certificate'),
SettingType.DIALOG, props={'dialog': CertificateDialog}),
]
GenericOptionPage.__init__(self, account, parent, options)
GenericSettingPage.__init__(self, account, parent, settings)
self._add_top_buttons(parent)
def _on_account_name_change(self, account_name, *args):
self.parent.update_accounts()
class GeneralPage(GenericOptionPage):
class GeneralPage(GenericSettingPage):
def __init__(self, account, parent=None):
options = [
Option(OptionKind.SWITCH, _('Connect on startup'),
OptionType.ACCOUNT_CONFIG, 'autoconnect'),
settings = [
Setting(SettingKind.SWITCH, _('Connect on startup'),
SettingType.ACCOUNT_CONFIG, 'autoconnect'),
Option(OptionKind.SWITCH, _('Reconnect when connection is lost'),
OptionType.ACCOUNT_CONFIG, 'autoreconnect'),
Setting(SettingKind.SWITCH, _('Reconnect when connection is lost'),
SettingType.ACCOUNT_CONFIG, 'autoreconnect'),
Option(OptionKind.SWITCH, _('Save conversations for all contacts'),
OptionType.ACCOUNT_CONFIG, 'no_log_for',
desc=_('Store conversations on the harddrive')),
Setting(SettingKind.SWITCH, _('Save conversations for all contacts'),
SettingType.ACCOUNT_CONFIG, 'no_log_for',
desc=_('Store conversations on the harddrive')),
Option(OptionKind.SWITCH, _('Server Message Archive'),
OptionType.ACCOUNT_CONFIG, 'sync_logs_with_server',
desc=_('Messages get stored on the server.\n'
'The archive is used to sync messages\n'
'between multiple devices.\n'
'XEP-0313')),
Setting(SettingKind.SWITCH, _('Server Message Archive'),
SettingType.ACCOUNT_CONFIG, 'sync_logs_with_server',
desc=_('Messages get stored on the server. '
'The archive is used to sync messages '
'between multiple devices. (XEP-0313)')),
Option(OptionKind.SWITCH, _('Global Status'),
OptionType.ACCOUNT_CONFIG, 'sync_with_global_status',
desc=_('Synchronise the status of all accounts')),
Setting(SettingKind.SWITCH, _('Global Status'),
SettingType.ACCOUNT_CONFIG, 'sync_with_global_status',
desc=_('Synchronise the status of all accounts')),
Option(OptionKind.SWITCH, _('Message Carbons'),
OptionType.ACCOUNT_CONFIG, 'enable_message_carbons',
desc=_('All your other online devices get copies\n'
'of sent and received messages.\n'
'XEP-0280')),
Setting(SettingKind.SWITCH, _('Message Carbons'),
SettingType.ACCOUNT_CONFIG, 'enable_message_carbons',
desc=_('All your other online devices get copies '
'of sent and received messages. XEP-0280')),
Option(OptionKind.SWITCH, _('Use file transfer proxies'),
OptionType.ACCOUNT_CONFIG, 'use_ft_proxies'),
Setting(SettingKind.SWITCH, _('Use file transfer 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):
options = [
Option(OptionKind.SWITCH, 'HTTP_PROXY',
OptionType.ACCOUNT_CONFIG, 'use_env_http_proxy',
desc=_('Use environment variable')),
settings = [
Setting(SettingKind.SWITCH, 'HTTP_PROXY',
SettingType.ACCOUNT_CONFIG, 'use_env_http_proxy',
desc=_('Use environment variable')),
Option(OptionKind.PROXY, _('Proxy'),
OptionType.ACCOUNT_CONFIG, 'proxy', name='proxy'),
Setting(SettingKind.PROXY, _('Proxy'),
SettingType.ACCOUNT_CONFIG, 'proxy', name='proxy'),
Option(OptionKind.SWITCH, _('Warn on insecure connection'),
OptionType.ACCOUNT_CONFIG,
'warn_when_insecure_ssl_connection'),
Setting(SettingKind.SWITCH, _('Warn on insecure connection'),
SettingType.ACCOUNT_CONFIG,
'warn_when_insecure_ssl_connection'),
Option(OptionKind.SWITCH, _('Send keep-alive packets'),
OptionType.ACCOUNT_CONFIG, 'keep_alives_enabled'),
Setting(SettingKind.SWITCH, _('Send keep-alive packets'),
SettingType.ACCOUNT_CONFIG, 'keep_alives_enabled'),
Option(OptionKind.HOSTNAME, _('Hostname'), OptionType.DIALOG,
desc=_('Manually set the hostname for the server'),
props={'dialog': CutstomHostnameDialog}),
Setting(SettingKind.HOSTNAME, _('Hostname'), SettingType.DIALOG,
desc=_('Manually set the hostname for the server'),
props={'dialog': CutstomHostnameDialog}),
Option(OptionKind.ENTRY, _('Resource'),
OptionType.ACCOUNT_CONFIG, 'resource'),
Setting(SettingKind.ENTRY, _('Resource'),
SettingType.ACCOUNT_CONFIG, 'resource'),
Option(OptionKind.PRIORITY, _('Priority'),
OptionType.DIALOG, props={'dialog': PriorityDialog}),
Setting(SettingKind.PRIORITY, _('Priority'),
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):
options = [
Option(OptionKind.DIALOG, _('Profile'),
OptionType.DIALOG, props={'dialog': ZeroconfProfileDialog}),
settings = [
Setting(SettingKind.DIALOG, _('Profile'),
SettingType.DIALOG, props={'dialog': ZeroconfProfileDialog}),
Option(OptionKind.SWITCH, _('Connect on startup'),
OptionType.ACCOUNT_CONFIG, 'autoconnect',
desc=_('Use environment variable')),
Setting(SettingKind.SWITCH, _('Connect on startup'),
SettingType.ACCOUNT_CONFIG, 'autoconnect',
desc=_('Use environment variable')),
Option(OptionKind.SWITCH, _('Save conversations for all contacts'),
OptionType.ACCOUNT_CONFIG, 'no_log_for',
desc=_('Store conversations on the harddrive')),
Setting(SettingKind.SWITCH, _('Save conversations for all contacts'),
SettingType.ACCOUNT_CONFIG, 'no_log_for',
desc=_('Store conversations on the harddrive')),
Option(OptionKind.SWITCH, _('Global Status'),
OptionType.ACCOUNT_CONFIG, 'sync_with_global_status',
desc=_('Synchronize the status of all accounts')),
Setting(SettingKind.SWITCH, _('Global Status'),
SettingType.ACCOUNT_CONFIG, 'sync_with_global_status',
desc=_('Synchronize the status of all accounts')),
]
GenericOptionPage.__init__(self, account, parent, options)
GenericSettingPage.__init__(self, account, parent, settings)
self._add_top_buttons(None)
class ZeroconfProfileDialog(OptionsDialog):
class ZeroconfProfileDialog(SettingsDialog):
def __init__(self, account, parent):
options = [
Option(OptionKind.ENTRY, _('First Name'),
OptionType.ACCOUNT_CONFIG, 'zeroconf_first_name'),
settings = [
Setting(SettingKind.ENTRY, _('First Name'),
SettingType.ACCOUNT_CONFIG, 'zeroconf_first_name'),
Option(OptionKind.ENTRY, _('Last Name'),
OptionType.ACCOUNT_CONFIG, 'zeroconf_last_name'),
Setting(SettingKind.ENTRY, _('Last Name'),
SettingType.ACCOUNT_CONFIG, 'zeroconf_last_name'),
Option(OptionKind.ENTRY, _('Jabber ID'),
OptionType.ACCOUNT_CONFIG, 'zeroconf_jabber_id'),
Setting(SettingKind.ENTRY, _('Jabber ID'),
SettingType.ACCOUNT_CONFIG, 'zeroconf_jabber_id'),
Option(OptionKind.ENTRY, _('Email'),
OptionType.ACCOUNT_CONFIG, 'zeroconf_email'),
Setting(SettingKind.ENTRY, _('Email'),
SettingType.ACCOUNT_CONFIG, 'zeroconf_email'),
]
OptionsDialog.__init__(self, parent, _('Profile'),
Gtk.DialogFlags.MODAL, options, account)
SettingsDialog.__init__(self, parent, _('Profile'),
Gtk.DialogFlags.MODAL, settings, account)
class PriorityDialog(OptionsDialog):
class PriorityDialog(SettingsDialog):
def __init__(self, account, parent):
neg_priority = app.config.get('enable_negative_priority')
@ -733,18 +730,18 @@ class PriorityDialog(OptionsDialog):
else:
range_ = (0, 127)
options = [
Option(OptionKind.SWITCH, _('Adjust to status'),
OptionType.ACCOUNT_CONFIG, 'adjust_priority_with_status',
'adjust'),
settings = [
Setting(SettingKind.SWITCH, _('Adjust to status'),
SettingType.ACCOUNT_CONFIG, 'adjust_priority_with_status',
'adjust'),
Option(OptionKind.SPIN, _('Priority'),
OptionType.ACCOUNT_CONFIG, 'priority',
enabledif=('adjust', False), props={'range_': range_}),
Setting(SettingKind.SPIN, _('Priority'),
SettingType.ACCOUNT_CONFIG, 'priority',
enabledif=('adjust', False), props={'range_': range_}),
]
OptionsDialog.__init__(self, parent, _('Priority'),
Gtk.DialogFlags.MODAL, options, account)
SettingsDialog.__init__(self, parent, _('Priority'),
Gtk.DialogFlags.MODAL, settings, account)
self.connect('destroy', self.on_destroy)
@ -757,60 +754,60 @@ class PriorityDialog(OptionsDialog):
app.connections[self.account].change_status(show, status)
class CutstomHostnameDialog(OptionsDialog):
class CutstomHostnameDialog(SettingsDialog):
def __init__(self, account, parent):
options = [
Option(OptionKind.SWITCH, _('Enable'),
OptionType.ACCOUNT_CONFIG, 'use_custom_host', name='custom'),
settings = [
Setting(SettingKind.SWITCH, _('Enable'),
SettingType.ACCOUNT_CONFIG, 'use_custom_host', name='custom'),
Option(OptionKind.ENTRY, _('Hostname'),
OptionType.ACCOUNT_CONFIG, 'custom_host',
enabledif=('custom', True)),
Setting(SettingKind.ENTRY, _('Hostname'),
SettingType.ACCOUNT_CONFIG, 'custom_host',
enabledif=('custom', True)),
Option(OptionKind.ENTRY, _('Port'),
OptionType.ACCOUNT_CONFIG, 'custom_port',
enabledif=('custom', True)),
Setting(SettingKind.ENTRY, _('Port'),
SettingType.ACCOUNT_CONFIG, 'custom_port',
enabledif=('custom', True)),
]
OptionsDialog.__init__(self, parent, _('Connection Options'),
Gtk.DialogFlags.MODAL, options, account)
SettingsDialog.__init__(self, parent, _('Connection Settings'),
Gtk.DialogFlags.MODAL, settings, account)
class CertificateDialog(OptionsDialog):
class CertificateDialog(SettingsDialog):
def __init__(self, account, parent):
options = [
Option(OptionKind.FILECHOOSER, _('Client Certificate'),
OptionType.ACCOUNT_CONFIG, 'client_cert',
props={'filefilter': (_('PKCS12 Files'), '*.p12')}),
Settings = [
Setting(SettingKind.FILECHOOSER, _('Client Certificate'),
SettingType.ACCOUNT_CONFIG, 'client_cert',
props={'filefilter': (_('PKCS12 Files'), '*.p12')}),
Option(OptionKind.SWITCH, _('Encrypted Certificate'),
OptionType.ACCOUNT_CONFIG, 'client_cert_encrypted'),
Setting(SettingKind.SWITCH, _('Encrypted Certificate'),
SettingType.ACCOUNT_CONFIG, 'client_cert_encrypted'),
]
OptionsDialog.__init__(self, parent, _('Certificate Options'),
Gtk.DialogFlags.MODAL, options, account)
SettingsDialog.__init__(self, parent, _('Certificate Settings'),
Gtk.DialogFlags.MODAL, Settings, account)
class LoginDialog(OptionsDialog):
class LoginDialog(SettingsDialog):
def __init__(self, account, parent):
options = [
Option(OptionKind.ENTRY, _('Password'),
OptionType.ACCOUNT_CONFIG, 'password', name='password',
enabledif=('savepass', True)),
settings = [
Setting(SettingKind.ENTRY, _('Password'),
SettingType.ACCOUNT_CONFIG, 'password', name='password',
enabledif=('savepass', True)),
Option(OptionKind.SWITCH, _('Save Password'),
OptionType.ACCOUNT_CONFIG, 'savepass', name='savepass'),
Setting(SettingKind.SWITCH, _('Save Password'),
SettingType.ACCOUNT_CONFIG, 'savepass', name='savepass'),
Option(OptionKind.CHANGEPASSWORD, _('Change Password'),
OptionType.DIALOG, callback=self.on_password_change,
props={'dialog': None}),
Setting(SettingKind.CHANGEPASSWORD, _('Change Password'),
SettingType.DIALOG, callback=self.on_password_change,
props={'dialog': None}),
]
OptionsDialog.__init__(self, parent, _('Login Options'),
Gtk.DialogFlags.MODAL, options, account)
SettingsDialog.__init__(self, parent, _('Login Settings'),
Gtk.DialogFlags.MODAL, settings, account)
self.connect('destroy', self.on_destroy)

View File

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