gajim3/gajim/gtk/preferences.py

1057 lines
34 KiB
Python
Raw Permalink Normal View History

# 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/>.
import logging
import sys
from gi.repository import Gtk
from gi.repository import Gdk
from gajim.common import app
from gajim.common import configpaths
from gajim.common import helpers
from gajim.common.const import THRESHOLD_OPTIONS
from gajim.common.nec import NetworkEvent
from gajim.common.i18n import _
from gajim.common.helpers import open_file
from gajim.common.multimedia_helpers import AudioInputManager
from gajim.common.multimedia_helpers import AudioOutputManager
from gajim.common.multimedia_helpers import VideoInputManager
from gajim.chat_control_base import ChatControlBase
from .const import Setting
from .const import SettingKind
from .const import SettingType
from .const import ControlType
from .emoji_chooser import emoji_chooser
from .settings import SettingsBox
from .settings import SettingsDialog
from .sidebar_switcher import SideBarSwitcher
from .video_preview import VideoPreview
from .util import get_available_iconsets
from .util import open_window
from .util import get_app_window
from .util import get_builder
if app.is_installed('GSPELL'):
from gi.repository import Gspell # pylint: disable=ungrouped-imports
log = logging.getLogger('gajim.gui.preferences')
class Preferences(Gtk.ApplicationWindow):
def __init__(self):
Gtk.ApplicationWindow.__init__(self)
self.set_application(app.app)
self.set_position(Gtk.WindowPosition.CENTER)
self.set_show_menubar(False)
self.set_name('PreferencesWindow')
self.set_default_size(900, 650)
self.set_resizable(True)
self.set_title(_('Preferences'))
self._ui = get_builder('preferences.ui')
self._video_preview = None
self._prefs = {}
side_bar_switcher = SideBarSwitcher()
side_bar_switcher.set_stack(self._ui.stack)
self._ui.grid.attach(side_bar_switcher, 0, 0, 1, 1)
self.add(self._ui.grid)
self._check_emoji_theme()
prefs = [
('window_behaviour', WindowBehaviour),
('contact_list', ContactList),
('chats', Chats),
('group_chats', GroupChats),
('visual_notifications', VisualNotifications),
('sounds', Sounds),
('status_message', StatusMessage),
('automatic_status', AutomaticStatus),
('themes', Themes),
('emoji', Emoji),
('status_icon', StatusIcon),
('server', Server),
('audio', Audio),
('video', Video),
('miscellaneous', Miscellaneous),
('advanced', Advanced),
]
self._add_prefs(prefs)
self._add_video_preview()
self._ui.audio_video_info_bar.set_revealed(not app.is_installed('AV'))
self.connect('key-press-event', self._on_key_press)
self._ui.connect_signals(self)
self.show_all()
if sys.platform not in ('win32', 'darwin'):
self._ui.emoji.hide()
def get_ui(self):
return self._ui
def _add_prefs(self, prefs):
for ui_name, klass in prefs:
pref_box = getattr(self._ui, ui_name)
if ui_name == 'video' and sys.platform == 'win32':
continue
pref = klass(self)
pref_box.add(pref)
self._prefs[ui_name] = pref
def _add_video_preview(self):
if sys.platform == 'win32':
return
self._video_preview = VideoPreview()
self._ui.video.add(self._video_preview.widget)
def _on_key_press(self, _widget, event):
if event.keyval == Gdk.KEY_Escape:
self.destroy()
def get_video_preview(self):
return self._video_preview
@staticmethod
def _on_features_clicked(_widget, _response):
open_window('Features')
def update_theme_list(self):
self._prefs['themes'].update_theme_list()
def update_proxy_list(self):
self._prefs['miscellaneous'].update_proxy_list()
@staticmethod
def get_all_controls():
for ctrl in app.interface.msg_win_mgr.get_controls():
yield ctrl
for account in app.connections:
for ctrl in app.interface.minimized_controls[account].values():
yield ctrl
@staticmethod
def get_all_muc_controls():
for ctrl in app.interface.msg_win_mgr.get_controls(
ControlType.GROUPCHAT):
yield ctrl
for account in app.connections:
for ctrl in app.interface.minimized_controls[account].values():
yield ctrl
@staticmethod
def _check_emoji_theme():
# Ensure selected emoji theme is valid
emoji_themes = helpers.get_available_emoticon_themes()
settings_theme = app.settings.get('emoticons_theme')
if settings_theme not in emoji_themes:
app.settings.set('emoticons_theme', 'font')
class PreferenceBox(SettingsBox):
def __init__(self, settings):
SettingsBox.__init__(self, None)
self.get_style_context().add_class('settings-border')
self.set_selection_mode(Gtk.SelectionMode.NONE)
self.set_vexpand(False)
self.set_valign(Gtk.Align.END)
for setting in settings:
self.add_setting(setting)
self.update_states()
class WindowBehaviour(PreferenceBox):
def __init__(self, *args):
win_layout_items = {
'never': _('Detached contact list with detached chats'),
'always': _('Detached contact list with single chat'),
'always_with_roster': _('Single window for everything'),
'peracct': _('Detached contact list with chats grouped by account'),
'pertype': _('Detached contact list with chats grouped by type'),
}
roster_on_startup_items = {
'always': _('Always'),
'never': _('Never'),
'last_state': _('Restore last state'),
}
tab_position_items = {
'top': _('Top'),
'bottom': _('Bottom'),
'left': _('Left'),
'Right': _('Right'),
}
settings = [
Setting(SettingKind.POPOVER,
_('Window Layout'),
SettingType.CONFIG,
'one_message_window',
props={'entries': win_layout_items},
callback=self._on_win_layout_changed),
Setting(SettingKind.POPOVER,
_('Contact List on Startup'),
SettingType.CONFIG,
'show_roster_on_startup',
props={'entries': roster_on_startup_items},
desc=_('Show contact list when starting Gajim')),
Setting(SettingKind.SWITCH,
_('Quit on Close'),
SettingType.CONFIG,
'quit_on_roster_x_button',
desc=_('Quit when closing contact list')),
Setting(SettingKind.POPOVER,
_('Tab Position'),
SettingType.CONFIG,
'tabs_position',
props={'entries': tab_position_items},
desc=_('Placement of chat window tabs'),
callback=self._on_win_layout_changed),
]
PreferenceBox.__init__(self, settings)
@staticmethod
def _on_win_layout_changed(*args):
app.interface.msg_win_mgr.reconfig()
class ContactList(PreferenceBox):
def __init__(self, *args):
settings = [
Setting(SettingKind.SWITCH,
_('Merge Accounts'),
SettingType.CONFIG,
'mergeaccounts',
callback=self._on_merge_accounts),
Setting(SettingKind.SWITCH,
_('Enable Metacontacts'),
SettingType.CONFIG,
'metacontacts_enabled'),
Setting(SettingKind.SWITCH,
_('Show Avatars'),
SettingType.CONFIG,
'show_avatars_in_roster',
callback=self._on_show_avatar_in_roster_changed),
Setting(SettingKind.SWITCH,
_('Show Status Message'),
SettingType.CONFIG,
'show_status_msgs_in_roster',
callback=self._on_show_status_in_roster),
Setting(SettingKind.SWITCH,
_('Sort Contacts by Status'),
SettingType.CONFIG,
'sort_by_show_in_roster',
callback=self._on_sort_by_show_in_roster),
Setting(SettingKind.SWITCH,
_('Show Mood'),
SettingType.CONFIG,
'show_mood_in_roster'),
Setting(SettingKind.SWITCH,
_('Show Activity'),
SettingType.CONFIG,
'show_activity_in_roster'),
Setting(SettingKind.SWITCH,
_('Show Tune'),
SettingType.CONFIG,
'show_tunes_in_roster'),
Setting(SettingKind.SWITCH,
_('Show Location'),
SettingType.CONFIG,
'show_location_in_roster'),
]
PreferenceBox.__init__(self, settings)
@staticmethod
def _on_merge_accounts(*args):
app.app.activate_action('merge')
@staticmethod
def _on_show_avatar_in_roster_changed(*args):
app.interface.roster.setup_and_draw_roster()
@staticmethod
def _on_show_status_in_roster(*args):
app.interface.roster.setup_and_draw_roster()
controls = get_app_window('Preferences').get_all_muc_controls()
for ctrl in controls:
ctrl.roster.draw_contacts()
@staticmethod
def _on_sort_by_show_in_roster(*args):
app.interface.roster.setup_and_draw_roster()
class Chats(PreferenceBox):
def __init__(self, *args):
speller_desc = None
if not app.is_installed('GSPELL'):
speller_desc = _('Needs gspell to be installed')
settings = [
Setting(SettingKind.SWITCH,
_('Spell Checking'),
SettingType.CONFIG,
'use_speller',
desc=speller_desc,
enabled_func=self._speller_available,
callback=self._on_use_speller),
Setting(SettingKind.SWITCH,
_('Message Receipts (✔)'),
SettingType.CONFIG,
'positive_184_ack',
desc=_('Add a checkmark to received messages')),
Setting(SettingKind.SWITCH,
_('XHTML Formatting'),
SettingType.CONFIG,
'show_xhtml',
desc=_('Render XHTML styles (colors, etc.) of incoming '
'messages')),
Setting(SettingKind.SWITCH,
_('Show Send Message Button'),
SettingType.CONFIG,
'show_send_message_button'),
Setting(SettingKind.SWITCH,
_('Show Status Message'),
SettingType.CONFIG,
'print_status_in_chats'),
Setting(SettingKind.SWITCH,
_('Show Chat State In Tabs'),
SettingType.CONFIG,
'show_chatstate_in_tabs',
desc=_('Show the contacts chat state (e.g. typing) in '
'the chats tab')),
Setting(SettingKind.SWITCH,
_('Show Chat State In Banner'),
SettingType.CONFIG,
'show_chatstate_in_banner',
desc=_('Show the contacts chat state (e.g. typing) in '
'the chats tabs banner')),
Setting(SettingKind.SWITCH,
_('Display Chat State In Contact List'),
SettingType.CONFIG,
'show_chatstate_in_roster',
desc=_('Show the contacts chat state (e.g. typing) in '
'the contact list')),
]
PreferenceBox.__init__(self, settings)
@staticmethod
def _speller_available():
return app.is_installed('GSPELL')
@staticmethod
def _on_use_speller(value, *args):
if not value:
return
lang = app.settings.get('speller_language')
gspell_lang = Gspell.language_lookup(lang)
if gspell_lang is None:
gspell_lang = Gspell.language_get_default()
app.settings.set('speller_language', gspell_lang.get_code())
for ctrl in get_app_window('Preferences').get_all_controls():
if isinstance(ctrl, ChatControlBase):
ctrl.set_speller()
class GroupChats(PreferenceBox):
def __init__(self, *args):
settings = [
Setting(SettingKind.SWITCH,
_('Show Subject'),
SettingType.CONFIG,
'show_subject_on_join'),
Setting(SettingKind.SWITCH,
_('Sort Contacts by Status'),
SettingType.CONFIG,
'sort_by_show_in_muc',
callback=self._on_sort_by_show_in_muc),
Setting(SettingKind.POPOVER,
_('Default Sync Threshold'),
SettingType.CONFIG,
'gc_sync_threshold_public_default',
desc=_('Default for new public group chats'),
props={'entries': THRESHOLD_OPTIONS}),
Setting(SettingKind.SWITCH,
_('Direct Messages'),
SettingType.CONFIG,
'muc_prefer_direct_msg',
desc=_('Prefer direct messages in private group chats ')),
Setting(SettingKind.SWITCH,
_('Show Joined / Left'),
SettingType.CONFIG,
'gc_print_join_left_default',
desc=_('Default for new group chats'),
props={'button-text':_('Reset'),
'button-tooltip': _('Reset all group chats to the '
'current default value'),
'button-style': 'destructive-action',
'button-callback': self._reset_join_left}),
Setting(SettingKind.SWITCH,
_('Show Status Changes'),
SettingType.CONFIG,
'gc_print_status_default',
desc=_('Default for new group chats'),
props={'button-text':_('Reset'),
'button-tooltip': _('Reset all group chats to the '
'current default value'),
'button-style': 'destructive-action',
'button-callback': self._reset_print_status}),
]
PreferenceBox.__init__(self, settings)
@staticmethod
def _on_sort_by_show_in_muc(*args):
for ctrl in get_app_window('Preferences').get_all_muc_controls():
ctrl.roster.invalidate_sort()
@staticmethod
def _reset_join_left(button):
button.set_sensitive(False)
app.settings.set_group_chat_settings('print_join_left', None)
@staticmethod
def _reset_print_status(button):
button.set_sensitive(False)
app.settings.set_group_chat_settings('print_status', None)
class VisualNotifications(PreferenceBox):
def __init__(self, *args):
trayicon_items = {
'never': _('Hide icon'),
'on_event': _('Only show for pending events'),
'always': _('Always show icon'),
}
settings = [
Setting(SettingKind.POPOVER,
_('Notification Area Icon'),
SettingType.CONFIG,
'trayicon',
props={'entries': trayicon_items},
callback=self._on_trayicon),
Setting(SettingKind.SWITCH,
_('Open Events'),
SettingType.CONFIG,
'autopopup',
desc=_('Open events instead of showing a notification '
'in the contact list')),
Setting(SettingKind.NOTIFICATIONS,
_('Show Notifications'),
SettingType.DIALOG,
props={'dialog': NotificationsDialog}),
]
PreferenceBox.__init__(self, settings)
@staticmethod
def _on_trayicon(value, *args):
if value == 'never':
app.interface.hide_systray()
elif value == 'on_event':
app.interface.show_systray()
else:
app.interface.show_systray()
class NotificationsDialog(SettingsDialog):
def __init__(self, account, parent):
settings = [
Setting(SettingKind.SWITCH,
_('Show Notifications'),
SettingType.CONFIG,
'show_notifications'),
Setting(SettingKind.SWITCH,
_('Notifications When Away'),
SettingType.CONFIG,
'autopopupaway',
desc=_('Show notifications even if you are Away, '
'Busy, etc.'),
bind='show_notifications'),
]
SettingsDialog.__init__(self, parent, _('Notifications'),
Gtk.DialogFlags.MODAL, settings, account)
class Sounds(PreferenceBox):
def __init__(self, *args):
settings = [
Setting(SettingKind.SWITCH,
_('Play Sounds'),
SettingType.CONFIG,
'sounds_on',
desc=_('Play sounds to notify about events'),
props={'button-icon-name': 'preferences-system-symbolic',
'button-callback': self._on_manage_sounds}),
Setting(SettingKind.SWITCH,
_('Sounds When Away'),
SettingType.CONFIG,
'sounddnd',
desc=_('Play sounds even when you are Away, Busy, etc.'),
bind='sounds_on'),
]
PreferenceBox.__init__(self, settings)
def _on_manage_sounds(self, *args):
open_window('ManageSounds', transient_for=self.get_toplevel())
class StatusMessage(PreferenceBox):
def __init__(self, *args):
settings = [
Setting(SettingKind.SWITCH,
_('Sign In'),
SettingType.CONFIG,
'ask_online_status'),
Setting(SettingKind.SWITCH,
_('Sign Out'),
SettingType.CONFIG,
'ask_offline_status'),
Setting(SettingKind.SWITCH,
_('Status Change'),
SettingType.CONFIG,
'always_ask_for_status_message'),
]
PreferenceBox.__init__(self, settings)
class AutomaticStatus(PreferenceBox):
def __init__(self, *args):
settings = [
Setting(SettingKind.AUTO_AWAY,
_('Auto Away'),
SettingType.DIALOG,
desc=_('Change your status to \'Away\' after a certain '
'amount of time'),
props={'dialog': AutoAwayDialog}),
Setting(SettingKind.AUTO_EXTENDED_AWAY,
_('Auto Not Available'),
SettingType.DIALOG,
desc=_('Change your status to \'Not Available\' after a '
'certain amount of time'),
props={'dialog': AutoExtendedAwayDialog}),
]
PreferenceBox.__init__(self, settings)
@staticmethod
def _get_auto_away():
return app.settings.get('autoaway')
@staticmethod
def _get_auto_xa():
return app.settings.get('autoxa')
class AutoAwayDialog(SettingsDialog):
def __init__(self, account, parent):
settings = [
Setting(SettingKind.SWITCH,
_('Auto Away'),
SettingType.CONFIG,
'autoaway'),
Setting(SettingKind.SPIN,
_('Time Until Away'),
SettingType.CONFIG,
'autoawaytime',
desc=_('Minutes until your status gets changed'),
props={'range_': (1, 720)},
bind='autoaway'),
Setting(SettingKind.ENTRY,
_('Status Message'),
SettingType.CONFIG,
'autoaway_message',
bind='autoaway'),
]
SettingsDialog.__init__(self, parent, _('Auto Away Settings'),
Gtk.DialogFlags.MODAL, settings, account)
class AutoExtendedAwayDialog(SettingsDialog):
def __init__(self, account, parent):
settings = [
Setting(SettingKind.SWITCH,
_('Auto Not Available'),
SettingType.CONFIG,
'autoxa'),
Setting(SettingKind.SPIN,
_('Time Until Not Available'),
SettingType.CONFIG,
'autoxatime',
desc=_('Minutes until your status gets changed'),
props={'range_': (1, 720)},
bind='autoxa'),
Setting(SettingKind.ENTRY,
_('Status Message'),
SettingType.CONFIG,
'autoxa_message',
bind='autoxa'),
]
SettingsDialog.__init__(self, parent, _('Auto Extended Away Settings'),
Gtk.DialogFlags.MODAL, settings, account)
class Themes(PreferenceBox):
def __init__(self, *args):
theme_items = self._get_theme_items()
dark_theme_items = {
0: _('Disabled'),
1: _('Enabled'),
2: _('System'),
}
settings = [
Setting(SettingKind.POPOVER,
_('Dark Theme'),
SettingType.CONFIG,
'dark_theme',
props={'entries': dark_theme_items},
callback=self._on_dark_theme),
Setting(SettingKind.POPOVER,
_('Theme'),
SettingType.CONFIG,
'roster_theme',
name='roster_theme',
props={'entries': theme_items,
'button-icon-name': 'preferences-system-symbolic',
'button-callback': self._on_edit_themes},
callback=self._on_theme_changed),
]
PreferenceBox.__init__(self, settings)
@staticmethod
def _get_theme_items():
theme_items = ['default']
for settings_theme in app.css_config.themes:
theme_items.append(settings_theme)
return theme_items
def update_theme_list(self):
self.get_setting('roster_theme').update_entries(self._get_theme_items())
def _on_edit_themes(self, *args):
open_window('Themes', transient=self.get_toplevel())
@staticmethod
def _on_theme_changed(value, *args):
app.css_config.change_theme(value)
app.nec.push_incoming_event(NetworkEvent('theme-update'))
app.nec.push_incoming_event(NetworkEvent('style-changed'))
app.interface.roster.repaint_themed_widgets()
app.interface.roster.change_roster_style(None)
@staticmethod
def _on_dark_theme(value, *args):
app.css_config.set_dark_theme(int(value))
app.nec.push_incoming_event(NetworkEvent('style-changed'))
class Emoji(PreferenceBox):
def __init__(self, *args):
if sys.platform not in ('win32', 'darwin'):
PreferenceBox.__init__(self, [])
return
emoji_themes_items = []
for theme in helpers.get_available_emoticon_themes():
emoji_themes_items.append(theme)
settings = [
Setting(SettingKind.POPOVER,
_('Emoji Theme'),
SettingType.CONFIG,
'emoticons_theme',
desc=_('Choose from various emoji styles'),
props={'entries': emoji_themes_items},
callback=self._on_emoticons_theme)
]
PreferenceBox.__init__(self, settings)
def _on_emoticons_theme(self, *args):
emoji_chooser.load()
self._toggle_emoticons()
@staticmethod
def _toggle_emoticons():
controls = get_app_window('Preferences').get_all_controls()
for ctrl in controls:
ctrl.toggle_emoticons()
class StatusIcon(PreferenceBox):
def __init__(self, *args):
iconset_items = []
for _index, iconset_name in enumerate(get_available_iconsets()):
iconset_items.append(iconset_name)
settings = [
Setting(SettingKind.POPOVER,
_('Status Icon Set'),
SettingType.CONFIG,
'iconset',
props={'entries': iconset_items},
callback=self._on_iconset_changed),
Setting(SettingKind.SWITCH,
_('Use Transport Icons'),
SettingType.CONFIG,
'use_transports_iconsets',
desc=_('Display protocol-specific status icons '
'(ICQ, ..)')),
]
PreferenceBox.__init__(self, settings)
@staticmethod
def _on_iconset_changed(*args):
app.interface.roster.update_icons()
class Server(PreferenceBox):
def __init__(self, *args):
settings = [
Setting(SettingKind.USE_STUN_SERVER,
_('Use STUN Server'),
SettingType.DIALOG,
desc=_('Helps to establish calls through firewalls'),
props={'dialog': StunServerDialog}),
]
PreferenceBox.__init__(self, settings)
self.set_sensitive(app.is_installed('AV'))
class StunServerDialog(SettingsDialog):
def __init__(self, account, parent):
settings = [
Setting(SettingKind.SWITCH,
_('Use STUN Server'),
SettingType.CONFIG,
'use_stun_server'),
Setting(SettingKind.ENTRY,
_('STUN Server'),
SettingType.CONFIG,
'stun_server',
bind='use_stun_server')
]
SettingsDialog.__init__(self, parent, _('STUN Server Settings'),
Gtk.DialogFlags.MODAL, settings, account)
class Audio(PreferenceBox):
def __init__(self, *args):
deps_installed = app.is_installed('AV')
audio_input_devices = {}
audio_output_devices = {}
if deps_installed:
audio_input_devices = AudioInputManager().get_devices()
audio_output_devices = AudioOutputManager().get_devices()
audio_input_items = self._create_av_combo_items(audio_input_devices)
audio_output_items = self._create_av_combo_items(audio_output_devices)
settings = [
Setting(SettingKind.POPOVER,
_('Audio Input Device'),
SettingType.CONFIG,
'audio_input_device',
desc=_('Select your audio input (e.g. microphone)'),
props={'entries': audio_input_items}),
Setting(SettingKind.POPOVER,
_('Audio Output Device'),
SettingType.CONFIG,
'audio_output_device',
desc=_('Select an audio output (e.g. speakers, '
'headphones)'),
props={'entries': audio_output_items}),
]
PreferenceBox.__init__(self, settings)
self.set_sensitive(deps_installed)
@staticmethod
def _create_av_combo_items(items_dict):
items = enumerate(sorted(
items_dict.items(),
key=lambda x: '' if x[1].startswith('auto') else x[0].lower()))
combo_items = {}
for _index, (name, value) in items:
combo_items[value] = name
return combo_items
class Video(PreferenceBox):
def __init__(self, *args):
deps_installed = app.is_installed('AV')
video_input_devices = {}
if deps_installed:
video_input_devices = VideoInputManager().get_devices()
video_input_items = self._create_av_combo_items(video_input_devices)
video_framerates = {
'': _('Default'),
'15/1': '15 fps',
'10/1': '10 fps',
'5/1': '5 fps',
'5/2': '2.5 fps',
}
video_sizes = {
'': _('Default'),
'800x600': '800x600',
'640x480': '640x480',
'320x240': '320x240',
}
settings = [
Setting(SettingKind.POPOVER,
_('Video Input Device'),
SettingType.CONFIG,
'video_input_device',
props={'entries': video_input_items},
desc=_('Select your video input device (e.g. webcam, '
'screen capture)'),
callback=self._on_video_input_changed),
Setting(SettingKind.POPOVER,
_('Video Framerate'),
SettingType.CONFIG,
'video_framerate',
props={'entries': video_framerates}),
Setting(SettingKind.POPOVER,
_('Video Resolution'),
SettingType.CONFIG,
'video_size',
props={'entries': video_sizes}),
Setting(SettingKind.SWITCH,
_('Show My Video Stream'),
SettingType.CONFIG,
'video_see_self',
desc=_('Show your own video stream in calls')),
Setting(SettingKind.SWITCH,
_('Live Preview'),
SettingType.VALUE,
desc=_('Show a live preview to test your video source'),
callback=self._toggle_live_preview),
]
PreferenceBox.__init__(self, settings)
self.set_sensitive(deps_installed)
@staticmethod
def _on_video_input_changed(value, *args):
preview = get_app_window('Preferences').get_video_preview()
if preview is None or not preview.is_active:
# changed signal gets triggered when we fill the combobox
return
preview.refresh()
@staticmethod
def _toggle_live_preview(value, *args):
preview = get_app_window('Preferences').get_video_preview()
preview.toggle_preview(value)
@staticmethod
def _create_av_combo_items(items_dict):
items = enumerate(sorted(
items_dict.items(),
key=lambda x: '' if x[1].startswith('auto') else x[0].lower()))
combo_items = {}
for _index, (name, value) in items:
combo_items[value] = name
return combo_items
class Miscellaneous(PreferenceBox):
def __init__(self, pref_window):
self._hints_list = [
'start_chat',
]
settings = [
Setting(SettingKind.POPOVER,
_('Global Proxy'),
SettingType.CONFIG,
'global_proxy',
name='global_proxy',
props={'entries': self._get_proxies(),
'default-text': _('System'),
'button-icon-name': 'preferences-system-symbolic',
'button-callback': self._on_proxy_edit}),
Setting(SettingKind.SWITCH,
_('Use System Keyring'),
SettingType.CONFIG,
'use_keyring',
desc=_('Use your systems keyring to store passwords')),
]
if sys.platform in ('win32', 'darwin'):
settings.append(
Setting(SettingKind.SWITCH,
_('Check For Updates'),
SettingType.CONFIG,
'check_for_update',
desc=_('Check for Gajim updates periodically')))
PreferenceBox.__init__(self, settings)
reset_button = pref_window.get_ui().reset_button
reset_button.connect('clicked', self._on_reset_hints)
reset_button.set_sensitive(self._check_hints_reset)
@staticmethod
def _get_proxies():
return {proxy: proxy for proxy in app.settings.get_proxies()}
@staticmethod
def _on_proxy_edit(*args):
open_window('ManageProxies')
def update_proxy_list(self):
self.get_setting('global_proxy').update_entries(self._get_proxies())
def _check_hints_reset(self):
for hint in self._hints_list:
if app.settings.get('show_help_%s' % hint) is False:
return True
return False
def _on_reset_hints(self, button):
for hint in self._hints_list:
app.settings.set('show_help_%s' % hint, True)
button.set_sensitive(False)
class Advanced(PreferenceBox):
def __init__(self, pref_window):
settings = [
Setting(SettingKind.SWITCH,
_('Debug Logging'),
SettingType.VALUE,
app.get_debug_mode(),
props={'button-icon-name': 'folder-symbolic',
'button-callback': self._on_open_debug_logs},
callback=self._on_debug_logging),
]
PreferenceBox.__init__(self, settings)
pref_window.get_ui().ace_button.connect(
'clicked', self._on_advanced_config_editor)
@staticmethod
def _on_debug_logging(value, *args):
app.set_debug_mode(value)
@staticmethod
def _on_open_debug_logs(*args):
open_file(configpaths.get('DEBUG'))
@staticmethod
def _on_advanced_config_editor(*args):
open_window('AdvancedConfig')