gajim3/gajim/gtk/preferences.py

1057 lines
34 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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')