Skip to content
Snippets Groups Projects
config.py 180 KiB
Newer Older
roidelapluie's avatar
roidelapluie committed
# -*- coding:utf-8 -*-
roidelapluie's avatar
roidelapluie committed
## src/config.py
Yann Leboulanger's avatar
Yann Leboulanger committed
##
roidelapluie's avatar
roidelapluie committed
## Copyright (C) 2003-2005 Vincent Hanquez <tab AT snarc.org>
Dicson's avatar
Dicson committed
## Copyright (C) 2003-2014 Yann Leboulanger <asterix AT lagaule.org>
roidelapluie's avatar
roidelapluie committed
## Copyright (C) 2005 Alex Podaras <bigpod AT gmail.com>
roidelapluie's avatar
roidelapluie committed
##                    Stéphan Kochen <stephan AT kochen.nl>
roidelapluie's avatar
roidelapluie committed
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
##                         Nikos Kouremenos <kourem AT gmail.com>
roidelapluie's avatar
roidelapluie committed
## Copyright (C) 2006 Junglecow J <junglecow AT gmail.com>
roidelapluie's avatar
roidelapluie committed
## Copyright (C) 2006-2007 Travis Shirk <travis AT pobox.com>
##                         Stefan Bethge <stefan AT lanpartei.de>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2007 James Newton <redshodan AT gmail.com>
##                    Julien Pivotto <roidelapluie AT gmail.com>
## Copyright (C) 2007-2008 Stephan Erb <steve-e AT h3c.de>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
Yann Leboulanger's avatar
Yann Leboulanger committed
##
Yann Leboulanger's avatar
Yann Leboulanger committed
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
Yann Leboulanger's avatar
Yann Leboulanger committed
## it under the terms of the GNU General Public License as published
Yann Leboulanger's avatar
Yann Leboulanger committed
## by the Free Software Foundation; version 3 only.
Yann Leboulanger's avatar
Yann Leboulanger committed
##
Yann Leboulanger's avatar
Yann Leboulanger committed
## Gajim is distributed in the hope that it will be useful,
Yann Leboulanger's avatar
Yann Leboulanger committed
## but WITHOUT ANY WARRANTY; without even the implied warranty of
roidelapluie's avatar
roidelapluie committed
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Yann Leboulanger's avatar
Yann Leboulanger committed
## GNU General Public License for more details.
##
Yann Leboulanger's avatar
Yann Leboulanger committed
## You should have received a copy of the GNU General Public License
roidelapluie's avatar
roidelapluie committed
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
Yann Leboulanger's avatar
Yann Leboulanger committed
##
Yann Leboulanger's avatar
Yann Leboulanger committed

import gtk
Yann Leboulanger's avatar
Yann Leboulanger committed
import os, sys
import common.config
from common.i18n import Q_
import gtkgui_helpers
import cell_renderer_image
nicfit's avatar
nicfit committed
import message_control
import chat_control
import dataforms_widget
import profile_window
nkour's avatar
nkour committed

try:
    import gtkspell
    HAS_GTK_SPELL = True
nkour's avatar
nkour committed

from common import helpers
from common import gajim
Yann Leboulanger's avatar
Yann Leboulanger committed
from common import connection
from common import passwords
from common.zeroconf import connection_zeroconf
from common import dataforms
from common import gpg
Yann Leboulanger's avatar
Yann Leboulanger committed
from common import ged
    from common.multimedia_helpers import AudioInputManager, AudioOutputManager
    from common.multimedia_helpers import VideoInputManager, VideoOutputManager
    HAS_GST = True
except ImportError:
from common.exceptions import GajimGeneralException
from common.connection_handlers_events import InformationEvent
#---------- PreferencesWindow class -------------#
class PreferencesWindow:
    """
    Class for Preferences window
    """

    def on_preferences_window_destroy(self, widget):
        """
        Close window
        """
        del gajim.interface.instances['preferences']

    def on_close_button_clicked(self, widget):
        self.window.destroy()

    def __init__(self):
        """
        Initialize Preferences window
        """
        self.xml = gtkgui_helpers.get_gtk_builder('preferences_window.ui')
        self.window = self.xml.get_object('preferences_window')
        self.window.set_transient_for(gajim.interface.roster.window)
        self.notebook = self.xml.get_object('preferences_notebook')
        self.one_window_type_combobox =\
                self.xml.get_object('one_window_type_combobox')
        self.iconset_combobox = self.xml.get_object('iconset_combobox')
        self.notify_on_signin_checkbutton = self.xml.get_object(
                'notify_on_signin_checkbutton')
        self.notify_on_signout_checkbutton = self.xml.get_object(
                'notify_on_signout_checkbutton')
        self.auto_popup_away_checkbutton = self.xml.get_object(
                'auto_popup_away_checkbutton')
        self.sound_dnd_checkbutton = self.xml.get_object('sound_dnd_checkbutton')
        self.auto_away_checkbutton = self.xml.get_object('auto_away_checkbutton')
        self.auto_away_time_spinbutton = self.xml.get_object(
                'auto_away_time_spinbutton')
        self.auto_away_message_entry = self.xml.get_object(
                'auto_away_message_entry')
        self.auto_xa_checkbutton = self.xml.get_object('auto_xa_checkbutton')
        self.auto_xa_time_spinbutton = self.xml.get_object(
                'auto_xa_time_spinbutton')
        self.auto_xa_message_entry = self.xml.get_object('auto_xa_message_entry')

        ### General tab ###
        # Display avatars in roster
        st = gajim.config.get('show_avatars_in_roster')
        self.xml.get_object('show_avatars_in_roster_checkbutton'). \
                set_active(st)

        # Display status msg under contact name in roster
        st = gajim.config.get('show_status_msgs_in_roster')
        self.xml.get_object('show_status_msgs_in_roster_checkbutton'). \
                set_active( st)

        # Display PEP in roster
        st1 = gajim.config.get('show_mood_in_roster')
        st2 = gajim.config.get('show_activity_in_roster')
        st3 = gajim.config.get('show_tunes_in_roster')
        st4 = gajim.config.get('show_location_in_roster')
        w = self.xml.get_object('show_pep_in_roster_checkbutton')
        if st1 == st2 == st3 == st4:
            w.set_active(st1)
        else:
            w.set_inconsistent(True)

        # Sort contacts by show
        st = gajim.config.get('sort_by_show_in_roster')
        self.xml.get_object('sort_by_show_in_roster_checkbutton').set_active(st)
        st = gajim.config.get('sort_by_show_in_muc')
        self.xml.get_object('sort_by_show_in_muc_checkbutton').set_active(st)

        # emoticons
        emoticons_combobox = self.xml.get_object('emoticons_combobox')
        emoticons_list = os.listdir(os.path.join(gajim.DATA_DIR, 'emoticons'))
        # user themes
        if os.path.isdir(gajim.MY_EMOTS_PATH):
            emoticons_list += os.listdir(gajim.MY_EMOTS_PATH)
        renderer_text = gtk.CellRendererText()
        emoticons_combobox.pack_start(renderer_text, True)
        emoticons_combobox.add_attribute(renderer_text, 'text', 0)
        model = gtk.ListStore(str)
        emoticons_combobox.set_model(model)
        l = []
        for dir_ in emoticons_list:
            if not os.path.isdir(os.path.join(gajim.DATA_DIR, 'emoticons', dir_)) \
            and not os.path.isdir(os.path.join(gajim.MY_EMOTS_PATH, dir_)) :
                continue
            if dir_ != '.svn':
                l.append(dir_)
        l.append(_('Disabled'))
        for i in xrange(len(l)):
            model.append([l[i]])
            if gajim.config.get('emoticons_theme') == l[i]:
                emoticons_combobox.set_active(i)
        if not gajim.config.get('emoticons_theme'):
            emoticons_combobox.set_active(len(l)-1)

        # Set default for single window type
        choices = common.config.opt_one_window_types
        type_ = gajim.config.get('one_message_window')
        if type_ in choices:
            self.one_window_type_combobox.set_active(choices.index(type_))
        else:
            self.one_window_type_combobox.set_active(0)

        # Show roster on startup
        show_roster_combobox = self.xml.get_object('show_roster_on_startup')
        choices = common.config.opt_show_roster_on_startup
        type_ = gajim.config.get('show_roster_on_startup')
        if type_ in choices:
            show_roster_combobox.set_active(choices.index(type_))
        else:
            show_roster_combobox.set_active(0)

        # Compact View
        st = gajim.config.get('compact_view')
        self.xml.get_object('compact_view_checkbutton').set_active(st)

        # Ignore XHTML
        st = gajim.config.get('ignore_incoming_xhtml')
        self.xml.get_object('xhtml_checkbutton').set_active(st)

        # use speller
        if HAS_GTK_SPELL:
            st = gajim.config.get('use_speller')
            self.xml.get_object('speller_checkbutton').set_active(st)
        else:
            self.xml.get_object('speller_checkbutton').set_sensitive(False)

        # XEP-0184 positive ack
        st = gajim.config.get('positive_184_ack')
        self.xml.get_object('positive_184_ack_checkbutton').set_active(st)

        ### Style tab ###
        # Themes
        theme_combobox = self.xml.get_object('theme_combobox')
        cell = gtk.CellRendererText()
        theme_combobox.pack_start(cell, True)
        theme_combobox.add_attribute(cell, 'text', 0)
        self.update_theme_list()

        # iconset
        iconsets_list = os.listdir(os.path.join(gajim.DATA_DIR, 'iconsets'))
        if os.path.isdir(gajim.MY_ICONSETS_PATH):
            iconsets_list += os.listdir(gajim.MY_ICONSETS_PATH)
        # new model, image in 0, string in 1
        model = gtk.ListStore(gtk.Image, str)
        renderer_image = cell_renderer_image.CellRendererImage(0, 0)
        renderer_text = gtk.CellRendererText()
        renderer_text.set_property('xpad', 5)
        self.iconset_combobox.pack_start(renderer_image, expand = False)
        self.iconset_combobox.pack_start(renderer_text, expand = True)
        self.iconset_combobox.set_attributes(renderer_text, text = 1)
        self.iconset_combobox.add_attribute(renderer_image, 'image', 0)
        self.iconset_combobox.set_model(model)
        l = []
        for dir in iconsets_list:
            if not os.path.isdir(os.path.join(gajim.DATA_DIR, 'iconsets', dir)) \
            and not os.path.isdir(os.path.join(gajim.MY_ICONSETS_PATH, dir)):
                continue
            if dir != '.svn' and dir != 'transports':
                l.append(dir)
        if l.count == 0:
            l.append(' ')
        for i in xrange(len(l)):
            preview = gtk.Image()
            files = []
            files.append(os.path.join(helpers.get_iconset_path(l[i]), '16x16',
                    'online.png'))
            files.append(os.path.join(helpers.get_iconset_path(l[i]), '16x16',
                    'online.gif'))
            for file_ in files:
                if os.path.exists(file_):
                    preview.set_from_file(file_)
            model.append([preview, l[i]])
            if gajim.config.get('iconset') == l[i]:
                self.iconset_combobox.set_active(i)

        # Use transports iconsets
        st = gajim.config.get('use_transports_iconsets')
        self.xml.get_object('transports_iconsets_checkbutton').set_active(st)

        # Color widgets
        self.draw_color_widgets()

        # Font for messages
        font = gajim.config.get('conversation_font')
        # try to set default font for the current desktop env
        fontbutton = self.xml.get_object('conversation_fontbutton')
        if font == '':
            fontbutton.set_sensitive(False)
            self.xml.get_object('default_chat_font').set_active(True)
        else:
            fontbutton.set_font_name(font)

        ### Personal Events tab ###
        # outgoing send chat state notifications
        st = gajim.config.get('outgoing_chat_state_notifications')
        combo = self.xml.get_object('outgoing_chat_states_combobox')
        if st == 'all':
            combo.set_active(0)
        elif st == 'composing_only':
            combo.set_active(1)
        else: # disabled
            combo.set_active(2)

        # displayed send chat state notifications
        st = gajim.config.get('displayed_chat_state_notifications')
        combo = self.xml.get_object('displayed_chat_states_combobox')
        if st == 'all':
            combo.set_active(0)
        elif st == 'composing_only':
            combo.set_active(1)
        else: # disabled
            combo.set_active(2)


        ### Notifications tab ###
        # On new event
        on_event_combobox = self.xml.get_object('on_event_combobox')
        if gajim.config.get('autopopup'):
            on_event_combobox.set_active(0)
        elif gajim.config.get('notify_on_new_message'):
            on_event_combobox.set_active(1)
        else:
            on_event_combobox.set_active(2)

        # notify on online statuses
        st = gajim.config.get('notify_on_signin')
        self.notify_on_signin_checkbutton.set_active(st)

        # notify on offline statuses
        st = gajim.config.get('notify_on_signout')
        self.notify_on_signout_checkbutton.set_active(st)

        # autopopupaway
        st = gajim.config.get('autopopupaway')
        self.auto_popup_away_checkbutton.set_active(st)

        # sounddnd
        st = gajim.config.get('sounddnd')
        self.sound_dnd_checkbutton.set_active(st)

        # Systray
        systray_combobox = self.xml.get_object('systray_combobox')
        if gajim.config.get('trayicon') == 'never':
            systray_combobox.set_active(0)
        elif gajim.config.get('trayicon') == 'on_event':
            systray_combobox.set_active(1)
        else:
            systray_combobox.set_active(2)

        # sounds
        if gajim.config.get('sounds_on'):
            self.xml.get_object('play_sounds_checkbutton').set_active(True)
        else:
            self.xml.get_object('manage_sounds_button').set_sensitive(False)

        # Notify user of new gmail e-mail messages,
        # make checkbox sensitive if user has a gtalk account
        frame_gmail = self.xml.get_object('frame_gmail')
        notify_gmail_checkbutton = self.xml.get_object('notify_gmail_checkbutton')
        notify_gmail_extra_checkbutton = self.xml.get_object(
                'notify_gmail_extra_checkbutton')

        for account in gajim.config.get_per('accounts'):
            jid = gajim.get_jid_from_account(account)
            if gajim.get_server_from_jid(jid) in gajim.gmail_domains:
                frame_gmail.set_sensitive(True)
                st = gajim.config.get('notify_on_new_gmail_email')
                notify_gmail_checkbutton.set_active(st)
                st = gajim.config.get('notify_on_new_gmail_email_extra')
                notify_gmail_extra_checkbutton.set_active(st)
                break

        #### Status tab ###
        # Autoaway
        st = gajim.config.get('autoaway')
        self.auto_away_checkbutton.set_active(st)

        # Autoawaytime
        st = gajim.config.get('autoawaytime')
        self.auto_away_time_spinbutton.set_value(st)
        self.auto_away_time_spinbutton.set_sensitive(gajim.config.get('autoaway'))

        # autoaway message
        st = gajim.config.get('autoaway_message')
        self.auto_away_message_entry.set_text(st)
        self.auto_away_message_entry.set_sensitive(gajim.config.get('autoaway'))

        # Autoxa
        st = gajim.config.get('autoxa')
        self.auto_xa_checkbutton.set_active(st)

        # Autoxatime
        st = gajim.config.get('autoxatime')
        self.auto_xa_time_spinbutton.set_value(st)
        self.auto_xa_time_spinbutton.set_sensitive(gajim.config.get('autoxa'))

        # autoxa message
        st = gajim.config.get('autoxa_message')
        self.auto_xa_message_entry.set_text(st)
        self.auto_xa_message_entry.set_sensitive(gajim.config.get('autoxa'))

        from common import sleepy
        if not sleepy.SUPPORTED:
            self.xml.get_object('autoaway_table').set_sensitive(False)

        # ask_status when online / offline
        st = gajim.config.get('ask_online_status')
        self.xml.get_object('prompt_online_status_message_checkbutton').\
                set_active(st)
        st = gajim.config.get('ask_offline_status')
        self.xml.get_object('prompt_offline_status_message_checkbutton').\
                set_active(st)

        # Default Status messages
        self.default_msg_tree = self.xml.get_object('default_msg_treeview')
        col2 = self.default_msg_tree.rc_get_style().bg[gtk.STATE_ACTIVE].\
        # (status, translated_status, message, enabled)
        model = gtk.ListStore(str, str, str, bool)
        self.default_msg_tree.set_model(model)
        col = gtk.TreeViewColumn(_('Status'))
        col.set_resizable(True)
        self.default_msg_tree.append_column(col)
        renderer = gtk.CellRendererText()
        col.pack_start(renderer, False)
        col.set_attributes(renderer, text = 1)
        col = gtk.TreeViewColumn(_('Default Message'))
        col.set_resizable(True)
        self.default_msg_tree.append_column(col)
        renderer = gtk.CellRendererText()
        col.pack_start(renderer, True)
        col.set_attributes(renderer, text = 2)
        renderer.connect('edited', self.on_default_msg_cell_edited)
        renderer.set_property('editable', True)
        renderer.set_property('cell-background', col2)
        col = gtk.TreeViewColumn(_('Enabled'))
        col.set_resizable(True)
        self.default_msg_tree.append_column(col)
        renderer = gtk.CellRendererToggle()
        col.pack_start(renderer, False)
        col.set_attributes(renderer, active = 3)
        renderer.set_property('activatable', True)
        renderer.connect('toggled', self.default_msg_toggled_cb)
        self.fill_default_msg_treeview()

        # Status messages
        self.msg_tree = self.xml.get_object('msg_treeview')
        model = gtk.ListStore(str, str, str, str, str, str, str)
        self.msg_tree.set_model(model)
        col = gtk.TreeViewColumn('name')
        self.msg_tree.append_column(col)
        renderer = gtk.CellRendererText()
        col.pack_start(renderer, True)
        col.set_attributes(renderer, text = 0)
        renderer.connect('edited', self.on_msg_cell_edited)
        renderer.set_property('editable', True)
        self.fill_msg_treeview()
        buf = self.xml.get_object('msg_textview').get_buffer()
        buf.connect('changed', self.on_msg_textview_changed)

        ### Audio / Video tab ###
        def create_av_combobox(opt_name, device_dict, config_name=None,
        key=None):
            combobox = self.xml.get_object(opt_name + '_combobox')
            cell = gtk.CellRendererText()
            cell.set_property('ellipsize', pango.ELLIPSIZE_END)
            cell.set_property('ellipsize-set', True)
            combobox.pack_start(cell, True)
            combobox.add_attribute(cell, 'text', 0)
            model = gtk.ListStore(str, str)
            combobox.set_model(model)
            if config_name:
                config = gajim.config.get(config_name)
            else:
                config = gajim.config.get(opt_name + '_device')
            for index, (name, value) in enumerate(sorted(device_dict.\
            iteritems(), key=key)):
                model.append((name, value))
                    combobox.set_active(index)

        if HAS_GST:
            create_av_combobox('audio_input', AudioInputManager().get_devices())
            create_av_combobox('audio_output', AudioOutputManager().get_devices(
                ))
            create_av_combobox('video_input', VideoInputManager().get_devices())
            create_av_combobox('video_output', VideoOutputManager().get_devices(
                ))

            create_av_combobox('video_framerate', {_('Default'): '',
                '15fps': '15/1', '10fps': '10/1', '5fps': '5/1',
                '2.5fps': '5/2'}, 'video_framerate', key=lambda x: -1 if \
                not x[1] else float(x[0][:-3]))
            create_av_combobox('video_size', {_('Default'): '',
                '800x600': '800x600', '640x480': '640x480',
                '320x240': '320x240'}, 'video_size', key=lambda x: -1 if \
                not x[1] else int(x[0][:3]))
            st = gajim.config.get('video_see_self')
            self.xml.get_object('video_see_self_checkbutton').set_active(st)
        else:
            for opt_name in ('audio_input', 'audio_output', 'video_input',
            'video_output', 'video_framerate', 'video_size'):
                combobox = self.xml.get_object(opt_name + '_combobox')
                combobox.set_sensitive(False)

        # STUN
        cb = self.xml.get_object('stun_checkbutton')
        st = gajim.config.get('use_stun_server')
        cb.set_active(st)

        entry = self.xml.get_object('stun_server_entry')
        entry.set_text(gajim.config.get('stun_server'))
        if not st:
            entry.set_sensitive(False)

        ### Advanced tab ###
        # open links with
        if os.name == 'nt':
            applications_frame = self.xml.get_object('applications_frame')
            applications_frame.set_no_show_all(True)
            applications_frame.hide()
        else:
            self.applications_combobox = self.xml.get_object(
                    'applications_combobox')
            self.xml.get_object('custom_apps_frame').hide()
            self.xml.get_object('custom_apps_frame').set_no_show_all(True)

            if gajim.config.get('autodetect_browser_mailer'):
                self.applications_combobox.set_active(0)
                self.xml.get_object('custom_apps_frame').show()

            self.xml.get_object('custom_browser_entry').set_text(
                    gajim.config.get('custombrowser'))
            self.xml.get_object('custom_mail_client_entry').set_text(
                    gajim.config.get('custommailapp'))
            self.xml.get_object('custom_file_manager_entry').set_text(
                    gajim.config.get('custom_file_manager'))

        # log status changes of contacts
        st = gajim.config.get('log_contact_status_changes')
        self.xml.get_object('log_show_changes_checkbutton').set_active(st)

        # log encrypted chat sessions
        w = self.xml.get_object('log_encrypted_chats_checkbutton')
        st = self.get_per_account_option('log_encrypted_sessions')
        if st == 'mixed':
            w.set_inconsistent(True)
        else:
            w.set_active(st)

        # send os info
        w = self.xml.get_object('send_os_info_checkbutton')
        st = self.get_per_account_option('send_os_info')
        if st == 'mixed':
            w.set_inconsistent(True)
        else:
            w.set_active(st)

        # send absolute time info
        w = self.xml.get_object('send_time_info_checkbutton')
        st = self.get_per_account_option('send_time_info')
        if st == 'mixed':
            w.set_inconsistent(True)
        else:
            w.set_active(st)

        # send idle time
        w = self.xml.get_object('send_idle_time_checkbutton')
        st = self.get_per_account_option('send_idle_time')
        if st == 'mixed':
            w.set_inconsistent(True)
        else:
            w.set_active(st)

        # check if gajm is default
        st = gajim.config.get('check_if_gajim_is_default')
        self.xml.get_object('check_default_client_checkbutton').set_active(st)

        # Ignore messages from unknown contacts
        w = self.xml.get_object('ignore_events_from_unknown_contacts_checkbutton')
        st = self.get_per_account_option('ignore_unknown_contacts')
        if st == 'mixed':
            w.set_inconsistent(True)
        else:
            w.set_active(st)

        self.xml.connect_signals(self)

        self.msg_tree.get_model().connect('row-changed',
                                self.on_msg_treemodel_row_changed)
        self.msg_tree.get_model().connect('row-deleted',
                                self.on_msg_treemodel_row_deleted)
        self.default_msg_tree.get_model().connect('row-changed',
                                self.on_default_msg_treemodel_row_changed)

        self.theme_preferences = None
        self.sounds_preferences = None

        self.notebook.set_current_page(0)
        self.xml.get_object('close_button').grab_focus()

        self.window.show_all()
        gtkgui_helpers.possibly_move_window_in_current_desktop(self.window)

    def on_preferences_notebook_switch_page(self, widget, page, page_num):
        gobject.idle_add(self.xml.get_object('close_button').grab_focus)

    def on_preferences_window_key_press_event(self, widget, event):
        if event.keyval == gtk.keysyms.Escape:
            self.window.hide()

    def get_per_account_option(self, opt):
        """
        Return the value of the option opt if it's the same in all accounts else
        returns "mixed"
        """
        if len(gajim.connections) == 0:
            # a non existant key return default value
            return gajim.config.get_per('accounts', '__default__', opt)
        val = None
        for account in gajim.connections:
            v = gajim.config.get_per('accounts', account, opt)
            if val is None:
                val = v
            elif val != v:
                return 'mixed'
        return val

    def on_checkbutton_toggled(self, widget, config_name,
    change_sensitivity_widgets=None):
        gajim.config.set(config_name, widget.get_active())
        if change_sensitivity_widgets:
            for w in change_sensitivity_widgets:
                w.set_sensitive(widget.get_active())

    def on_per_account_checkbutton_toggled(self, widget, config_name,
    change_sensitivity_widgets=None):
        for account in gajim.connections:
            gajim.config.set_per('accounts', account, config_name,
                    widget.get_active())
        if change_sensitivity_widgets:
            for w in change_sensitivity_widgets:
                w.set_sensitive(widget.get_active())

    def _get_all_controls(self):
        for ctrl in gajim.interface.msg_win_mgr.get_controls():
            yield ctrl
        for account in gajim.connections:
            for ctrl in gajim.interface.minimized_controls[account].values():
                yield ctrl

    def _get_all_muc_controls(self):
        for ctrl in gajim.interface.msg_win_mgr.get_controls(
        message_control.TYPE_GC):
            yield ctrl
        for account in gajim.connections:
            for ctrl in gajim.interface.minimized_controls[account].values():
                yield ctrl

    def on_sort_by_show_in_roster_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'sort_by_show_in_roster')
        gajim.interface.roster.setup_and_draw_roster()

    def on_sort_by_show_in_muc_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'sort_by_show_in_muc')
        # Redraw groupchats
        for ctrl in self._get_all_muc_controls():
            ctrl.draw_roster()

    def on_show_avatars_in_roster_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'show_avatars_in_roster')
        gajim.interface.roster.setup_and_draw_roster()
        # Redraw groupchats (in an ugly way)
        for ctrl in self._get_all_muc_controls():
            ctrl.draw_roster()

    def on_show_status_msgs_in_roster_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'show_status_msgs_in_roster')
        gajim.interface.roster.setup_and_draw_roster()
        for ctrl in self._get_all_muc_controls():
            ctrl.update_ui()

    def on_show_pep_in_roster_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'show_mood_in_roster')
        self.on_checkbutton_toggled(widget, 'show_activity_in_roster')
        self.on_checkbutton_toggled(widget, 'show_tunes_in_roster')
        self.on_checkbutton_toggled(widget, 'show_location_in_roster')
        gajim.interface.roster.setup_and_draw_roster()

    def on_emoticons_combobox_changed(self, widget):
        active = widget.get_active()
        model = widget.get_model()
        emot_theme = model[active][0].decode('utf-8')
        if emot_theme == _('Disabled'):
            gajim.config.set('emoticons_theme', '')
        else:
            gajim.config.set('emoticons_theme', emot_theme)

        gajim.interface.init_emoticons(need_reload = True)
        gajim.interface.make_regexps()
        self.toggle_emoticons()

    def toggle_emoticons(self):
        """
        Update emoticons state in Opened Chat Windows
        """
        for ctrl in self._get_all_controls():
            ctrl.toggle_emoticons()

    def on_one_window_type_combo_changed(self, widget):
        active = widget.get_active()
        config_type = common.config.opt_one_window_types[active]
        gajim.config.set('one_message_window', config_type)
        gajim.interface.msg_win_mgr.reconfig()

    def on_show_roster_on_startup_changed(self, widget):
        active = widget.get_active()
        config_type = common.config.opt_show_roster_on_startup[active]
        gajim.config.set('show_roster_on_startup', config_type)

    def on_compact_view_checkbutton_toggled(self, widget):
        active = widget.get_active()
        for ctrl in self._get_all_controls():
            ctrl.chat_buttons_set_visible(active)
        gajim.config.set('compact_view', active)

    def on_xhtml_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'ignore_incoming_xhtml')
        helpers.update_optional_features()

    def apply_speller(self):
        for ctrl in self._get_all_controls():
            if isinstance(ctrl, chat_control.ChatControlBase):
                try:
                    spell_obj = gtkspell.get_from_text_view(ctrl.msg_textview)
                except (TypeError, RuntimeError, OSError):
                    spell_obj = None

                if not spell_obj:
                    ctrl.set_speller()

    def remove_speller(self):
        for ctrl in self._get_all_controls():
            if isinstance(ctrl, chat_control.ChatControlBase):
                try:
                    spell_obj = gtkspell.get_from_text_view(ctrl.msg_textview)
                except (TypeError, RuntimeError):
                    spell_obj = None
                if spell_obj:
                    spell_obj.detach()

    def on_speller_checkbutton_toggled(self, widget):
        active = widget.get_active()
        gajim.config.set('use_speller', active)
        if active:
            lang = gajim.config.get('speller_language')
            if not lang:
                lang = gajim.LANG
            tv = gtk.TextView()
            try:
                gtkspell.Spell(tv, lang)
            except (TypeError, RuntimeError, OSError):
                dialogs.ErrorDialog(
                        _('Dictionary for lang %s not available') % lang,
                        _('You have to install %s dictionary to use spellchecking, or '
                        'choose another language by setting the speller_language option.'
                        ) % lang)
                gajim.config.set('use_speller', False)
                widget.set_active(False)
            else:
                gajim.config.set('speller_language', lang)
                self.apply_speller()
        else:
            self.remove_speller()

    def on_positive_184_ack_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'positive_184_ack')

    def on_theme_combobox_changed(self, widget):
        model = widget.get_model()
        active = widget.get_active()
        config_theme = model[active][0].decode('utf-8').replace(' ', '_')

        gajim.config.set('roster_theme', config_theme)

        # begin repainting themed widgets throughout
        gajim.interface.roster.repaint_themed_widgets()
        gajim.interface.roster.change_roster_style(None)

    def update_theme_list(self):
        theme_combobox = self.xml.get_object('theme_combobox')
        model = gtk.ListStore(str)
        theme_combobox.set_model(model)
        i = 0
        for config_theme in gajim.config.get_per('themes'):
            theme = config_theme.replace('_', ' ')
            model.append([theme])
            if gajim.config.get('roster_theme') == config_theme:
                theme_combobox.set_active(i)
            i += 1

    def on_manage_theme_button_clicked(self, widget):
        if self.theme_preferences is None:
            self.theme_preferences = dialogs.GajimThemesWindow()
        else:
            self.theme_preferences.window.present()
            self.theme_preferences.select_active_theme()

    def on_iconset_combobox_changed(self, widget):
        model = widget.get_model()
        active = widget.get_active()
        icon_string = model[active][1].decode('utf-8')
        gajim.config.set('iconset', icon_string)
        gtkgui_helpers.reload_jabber_state_images()

    def on_transports_iconsets_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'use_transports_iconsets')
        gtkgui_helpers.reload_jabber_state_images()

    def on_outgoing_chat_states_combobox_changed(self, widget):
        active = widget.get_active()
        old_value = gajim.config.get('outgoing_chat_state_notifications')
        if active == 0: # all
            gajim.config.set('outgoing_chat_state_notifications', 'all')
        elif active == 1: # only composing
            gajim.config.set('outgoing_chat_state_notifications', 'composing_only')
        else: # disabled
            gajim.config.set('outgoing_chat_state_notifications', 'disabled')
        new_value = gajim.config.get('outgoing_chat_state_notifications')
        if 'disabled' in (old_value, new_value):
            # we changed from disabled to sth else or vice versa
            helpers.update_optional_features()

    def on_displayed_chat_states_combobox_changed(self, widget):
        active = widget.get_active()
        if active == 0: # all
            gajim.config.set('displayed_chat_state_notifications', 'all')
        elif active == 1: # only composing
            gajim.config.set('displayed_chat_state_notifications',
                    'composing_only')
        else: # disabled
            gajim.config.set('displayed_chat_state_notifications', 'disabled')

    def on_ignore_events_from_unknown_contacts_checkbutton_toggled(self, widget):
        widget.set_inconsistent(False)
        self.on_per_account_checkbutton_toggled(widget, 'ignore_unknown_contacts')

    def on_on_event_combobox_changed(self, widget):
        active = widget.get_active()
        if active == 0:
            gajim.config.set('autopopup', True)
            gajim.config.set('notify_on_new_message', False)
        elif active == 1:
            gajim.config.set('autopopup', False)
            gajim.config.set('notify_on_new_message', True)
        else:
            gajim.config.set('autopopup', False)
            gajim.config.set('notify_on_new_message', False)

    def on_notify_on_signin_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'notify_on_signin')

    def on_notify_on_signout_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'notify_on_signout')

    def on_auto_popup_away_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'autopopupaway')

    def on_sound_dnd_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'sounddnd')

    def on_systray_combobox_changed(self, widget):
        active = widget.get_active()
        if active == 0:
            gajim.config.set('trayicon', 'never')
            gajim.interface.systray_enabled = False
            gajim.interface.systray.hide_icon()
        elif active == 1:
            gajim.config.set('trayicon', 'on_event')
            gajim.interface.systray_enabled = True
            gajim.interface.systray.show_icon()
        else:
            gajim.config.set('trayicon', 'always')
            gajim.interface.systray_enabled = True
            gajim.interface.systray.show_icon()

    def on_play_sounds_checkbutton_toggled(self, widget):
        self.on_checkbutton_toggled(widget, 'sounds_on',
                [self.xml.get_object('manage_sounds_button')])

    def on_manage_sounds_button_clicked(self, widget):
        if self.sounds_preferences is None:
            self.sounds_preferences = ManageSoundsWindow()
        else:
            self.sounds_preferences.window.present()

    def update_text_tags(self):
        """
        Update color tags in opened chat windows
        """
        for ctrl in self._get_all_controls():
            ctrl.update_tags()

    def on_preference_widget_color_set(self, widget, text):
        color = widget.get_color()
        color_string = gtkgui_helpers.make_color_string(color)
        gajim.config.set(text, color_string)
        self.update_text_tags()

    def on_preference_widget_font_set(self, widget, text):
        if widget:
            font = widget.get_font_name()
        else:
            font = ''
        gajim.config.set(text, font)
        self.update_text_font()

    def update_text_font(self):
        """
        Update text font in opened chat windows
        """
        for ctrl in self._get_all_controls():
            ctrl.update_font()

    def on_incoming_nick_colorbutton_color_set(self, widget):
        self.on_preference_widget_color_set(widget, 'inmsgcolor')

    def on_outgoing_nick_colorbutton_color_set(self, widget):
        self.on_preference_widget_color_set(widget, 'outmsgcolor')

    def on_incoming_msg_colorbutton_color_set(self, widget):
        self.on_preference_widget_color_set(widget, 'inmsgtxtcolor')

    def on_outgoing_msg_colorbutton_color_set(self, widget):
        self.on_preference_widget_color_set(widget, 'outmsgtxtcolor')

    def on_url_msg_colorbutton_color_set(self, widget):
        self.on_preference_widget_color_set(widget, 'urlmsgcolor')

    def on_status_msg_colorbutton_color_set(self, widget):
        self.on_preference_widget_color_set(widget, 'statusmsgcolor')

    def on_muc_highlight_colorbutton_color_set(self, widget):
        self.on_preference_widget_color_set(widget, 'markedmsgcolor')

    def on_conversation_fontbutton_font_set(self, widget):
        self.on_preference_widget_font_set(widget, 'conversation_font')

    def on_default_chat_font_toggled(self, widget):
        font_widget = self.xml.get_object('conversation_fontbutton')
        if widget.get_active():
            font_widget.set_sensitive(False)
            font_widget = None
        else:
            font_widget.set_sensitive(True)
        self.on_preference_widget_font_set(font_widget, 'conversation_font')

    def draw_color_widgets(self):
        col_to_widget = {'inmsgcolor': 'incoming_nick_colorbutton',
                        'outmsgcolor': 'outgoing_nick_colorbutton',
                        'inmsgtxtcolor': ['incoming_msg_colorbutton',
                                'incoming_msg_checkbutton'],
                        'outmsgtxtcolor': ['outgoing_msg_colorbutton',
                                'outgoing_msg_checkbutton'],
                        'statusmsgcolor': 'status_msg_colorbutton',
                        'urlmsgcolor': 'url_msg_colorbutton',
                        'markedmsgcolor': 'muc_highlight_colorbutton'}
        for c in col_to_widget:
            col = gajim.config.get(c)
            if col:
                if isinstance(col_to_widget[c], list):
                    self.xml.get_object(col_to_widget[c][0]).set_color(
                            gtk.gdk.color_parse(col))
                    self.xml.get_object(col_to_widget[c][0]).set_sensitive(True)
                    self.xml.get_object(col_to_widget[c][1]).set_active(True)
                else:
                    self.xml.get_object(col_to_widget[c]).set_color(
                            gtk.gdk.color_parse(col))
            else:
                if isinstance(col_to_widget[c], list):
                    self.xml.get_object(col_to_widget[c][0]).set_color(
                            gtk.gdk.color_parse('#000000'))
                    self.xml.get_object(col_to_widget[c][0]).set_sensitive(False)
                    self.xml.get_object(col_to_widget[c][1]).set_active(False)
                else:
                    self.xml.get_object(col_to_widget[c]).set_color(
                            gtk.gdk.color_parse('#000000'))

    def on_reset_colors_button_clicked(self, widget):
        col_to_widget = {'inmsgcolor': 'incoming_nick_colorbutton',
                        'outmsgcolor': 'outgoing_nick_colorbutton',
                        'inmsgtxtcolor': 'incoming_msg_colorbutton',
                        'outmsgtxtcolor': 'outgoing_msg_colorbutton',
                        'statusmsgcolor': 'status_msg_colorbutton',
                        'urlmsgcolor': 'url_msg_colorbutton',
                        'markedmsgcolor': 'muc_highlight_colorbutton'}
        for c in col_to_widget:
            gajim.config.set(c, gajim.interface.default_colors[c])
        self.draw_color_widgets()

        self.update_text_tags()

    def _set_color(self, state, widget_name, option):
        """
        Set color value in prefs and update the UI
        """
        if state:
            color = self.xml.get_object(widget_name).get_color()
            color_string = gtkgui_helpers.make_color_string(color)
        else:
            color_string = ''
        gajim.config.set(option, color_string)

    def on_incoming_msg_checkbutton_toggled(self, widget):
        state = widget.get_active()
        self.xml.get_object('incoming_msg_colorbutton').set_sensitive(state)
        self._set_color(state, 'incoming_msg_colorbutton', 'inmsgtxtcolor')