From 000b3ad5933e286a2a28ca1762d49893bfc3de7c Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Wed, 15 Jun 2011 18:41:24 +0200 Subject: [PATCH] first version of Triggers plugin --- plugins/triggers/__init__.py | 1 + plugins/triggers/config_dialog.ui | 900 ++++++++++++++++++++++++++++++ plugins/triggers/manifest.ini | 7 + plugins/triggers/triggers.py | 637 +++++++++++++++++++++ 4 files changed, 1545 insertions(+) create mode 100644 plugins/triggers/__init__.py create mode 100644 plugins/triggers/config_dialog.ui create mode 100644 plugins/triggers/manifest.ini create mode 100644 plugins/triggers/triggers.py diff --git a/plugins/triggers/__init__.py b/plugins/triggers/__init__.py new file mode 100644 index 000000000..4f8d9f87b --- /dev/null +++ b/plugins/triggers/__init__.py @@ -0,0 +1 @@ +from triggers import Triggers diff --git a/plugins/triggers/config_dialog.ui b/plugins/triggers/config_dialog.ui new file mode 100644 index 000000000..68a53be20 --- /dev/null +++ b/plugins/triggers/config_dialog.ui @@ -0,0 +1,900 @@ + + + + + + + + + + + + contact(s) + + + group(s) + + + everybody + + + + + + + + + + + Receive a Message + + + + + 6 + Advanced Notifications Control + Advanced Notifications Control + False + True + + + True + 12 + vertical + 12 + + + True + vertical + 5 + + + 90 + True + True + never + automatic + in + + + True + True + + + + + + False + False + 0 + + + + + True + 1 + 212 + + + True + + + True + 10 + + + gtk-new + True + True + True + False + True + + + + False + False + 0 + + + + + gtk-go-up + True + True + True + False + True + + + + False + False + 1 + + + + + gtk-go-down + True + True + True + False + True + + + + False + False + 2 + + + + + gtk-delete + True + True + True + False + True + + + + False + False + 3 + + + + + False + 0 + + + + + + + False + False + 1 + + + + + 0 + + + + + True + vertical + 5 + + + True + <b>Conditions</b> + True + + + False + False + 0 + + + + + True + vertical + 5 + + + True + 5 + + + True + When + True + + + False + False + 0 + + + + + True + liststore2 + + + + + 0 + + + + + False + False + 1 + + + + + 0 + + + + + True + 5 + + + True + for + True + + + False + False + 0 + + + + + True + liststore1 + + + + + 0 + + + + + False + 1 + + + + + True + True + True + + + + 2 + + + + + 1 + + + + + True + + + True + when I'm in + True + + + False + False + 0 + + + + + True + 3 + + + All statuses + True + True + False + True + True + + + + False + False + 0 + + + + + One or more special statuses... + True + True + False + True + True + all_status_rb + + + False + False + 1 + + + + + Online / Free For Chat + True + True + False + True + True + True + + + + False + False + 2 + + + + + Away + True + True + False + True + True + True + + + + False + False + 3 + + + + + Not Available + True + True + False + True + True + True + + + + False + False + 4 + + + + + Busy + True + True + False + True + True + True + + + + False + False + 5 + + + + + Invisible + True + True + False + True + True + True + + + + False + False + 6 + + + + + 1 + + + + + 2 + + + + + True + + + True + and I + True + + + False + False + 0 + + + + + Have + True + True + False + True + True + + + + False + False + 1 + + + + + Don't have + True + True + False + True + True + + + + False + False + 2 + + + + + True + a window/tab opened with that contact + True + + + False + False + 3 + + + + + 3 + + + + + 1 + + + + + True + <b>Actions</b> + True + + + False + False + 2 + + + + + True + 0 + none + + + True + 6 + + + _Inform me with a popup window + True + True + False + True + True + + + + False + False + 0 + + + + + _Disable existing popup window + True + True + False + True + True + + + + False + False + 1 + + + + + + + True + 0 + none + + + True + 6 + 12 + + + True + vertical + 6 + + + True + 6 + True + + + Play a sound + True + True + False + True + True + + + + 0 + + + + + True + False + 6 + + + True + True + + + + 0 + + + + + ... + True + True + False + True + + + + False + False + 1 + + + + + True + True + False + + + + True + gtk-media-play + + + + + False + False + 2 + + + + + 1 + + + + + False + False + 0 + + + + + _Disable existing sound for this event + True + True + False + True + True + + + + False + False + 1 + + + + + + + + + True + <b>Sounds</b> + True + + + + + + + 3 + + + + + True + 6 + + + _Open chat window with user + True + True + False + True + True + + + + False + False + 0 + + + + + _Disable auto opening chat window + True + True + False + True + True + + + + False + False + 1 + + + + + 4 + + + + + True + True + True + + + True + vertical + 5 + + + True + 6 + + + Launch a command + True + True + False + True + True + + + + False + 0 + + + + + True + False + True + + + + 1 + + + + + False + False + 0 + + + + + True + 6 + + + _Show event in notification area + True + True + False + True + True + + + + False + False + 0 + + + + + _Disable showing event in notification area + True + True + False + True + True + + + + False + False + 1 + + + + + 1 + + + + + True + 6 + + + _Show event in roster + True + True + False + True + True + + + + False + False + 0 + + + + + _Disable showing event in roster + True + True + False + True + True + + + + False + False + 1 + + + + + 2 + + + + + _Activate window manager's UrgencyHint to make chat window in taskbar flash + True + False + True + True + True + + + + False + False + 3 + + + + + _Deactivate window manager's UrgencyHint + True + False + True + True + True + + + + False + False + 4 + + + + + + + True + Advanced Actions + + + + + 5 + + + + + 1 + + + + + + diff --git a/plugins/triggers/manifest.ini b/plugins/triggers/manifest.ini new file mode 100644 index 000000000..79e85f38c --- /dev/null +++ b/plugins/triggers/manifest.ini @@ -0,0 +1,7 @@ +[info] +name: Triggers +short_name: triggers +version: 0.0.1 +description: Configure Gajim's behaviour for each contact +authors: Yann Leboulanger +homepage: http://trac.gajim.org/wiki/ diff --git a/plugins/triggers/triggers.py b/plugins/triggers/triggers.py new file mode 100644 index 000000000..5c968516e --- /dev/null +++ b/plugins/triggers/triggers.py @@ -0,0 +1,637 @@ +# -*- coding: utf-8 -*- +# +## plugins/triggers/triggers.py +## +## Copyright (C) 2011 Yann Leboulanger +## +## 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 . +## + +import gtk +import sys + +from common import gajim +from plugins import GajimPlugin +from plugins.helpers import log_calls, log +from plugins.gui import GajimPluginConfigDialog +from common import i18n +from common import ged +from common import helpers + + +class Triggers(GajimPlugin): + + @log_calls('TriggersPlugin') + def init(self): + self.config_dialog = TriggersPluginConfigDialog(self) + self.config_default_values = {} + + self.events_handlers = {'notification' : (ged.PREGUI, self._nec_notif), + 'decrypted-message-received': (ged.PREGUI2, + self._nec_decrypted_message_received)} + + def _check_rule_recipients(self, obj, rule): + rule_recipients = [t.strip() for t in rule['recipients'].split(',')] + if rule['recipient_type'] == 'contact' and obj.jid not in \ + rule_recipients: + return False + contact_groups = gajim.contacts.get_first_contact_from_jid( + obj.conn.name, obj.jid).groups + group_found = False + for group in contact_groups: + if group in rule_recipients: + group_found = True + break + if rule['recipient_type'] == 'group' and not group_found: + return False + + return True + + def _check_rule_status(self, obj, rule): + rule_statuses = rule['status'].split() + our_status = gajim.SHOW_LIST[obj.conn.connected] + if rule['status'] != 'all' and our_status not in rule_statuses: + return False + + return True + + def _check_rule_tab_opened(self, obj, rule): + if rule['tab_opened'] == 'both': + return True + tab_opened = False + if gajim.interface.msg_win_mgr.get_control(obj.jid, obj.conn.name): + tab_opened = True + if tab_opened and rule['tab_opened'] == 'no': + return False + elif not tab_opened and rule['tab_opened'] == 'yes': + return False + + return True + + def check_rule_apply_notif(self, obj, rule): + # Check notification type + notif_type = '' + if obj.notif_type == 'msg': + notif_type = 'message_received' + if notif_type != rule['event']: + return False + + # notification type is ok. Now check recipient + if not self._check_rule_recipients(obj, rule): + return False + + # recipient is ok. Now check our status + if not self._check_rule_status(obj, rule): + return False + + # our_status is ok. Now check opened chat window + if not self._check_rule_tab_opened(obj, rule): + return False + + # All is ok + return True + + def check_rule_apply_decrypted_msg(self, obj, rule): + # Check notification type + if rule['event'] != 'message_received': + return False + + # notification type is ok. Now check recipient + if not self._check_rule_recipients(obj, rule): + return False + + # recipient is ok. Now check our status + if not self._check_rule_status(obj, rule): + return False + + # our_status is ok. Now check opened chat window + if not self._check_rule_tab_opened(obj, rule): + return False + + # All is ok + return True + + def apply_rule(self, obj, rule): + if rule['sound'] == 'no': + obj.do_sound = False + elif rule['sound'] == 'yes': + obj.do_sound = True + obj.sound_event = '' + obj.sound_file = rule['sound_file'] + + if rule['popup'] == 'no': + obj.do_popup = False + elif rule['popup'] == 'yes': + obj.do_popup = True + + if rule['run_command']: + obj.do_command = True + obj.command = rule['command'] + else: + obj.do_command = False + + if rule['systray'] == 'no': + obj.show_in_notification_area = False + elif rule['systray'] == 'yes': + obj.show_in_notification_area = True + + if rule['roster'] == 'no': + obj.show_in_roster = False + elif rule['roster'] == 'yes': + obj.show_in_roster = True + +# if rule['urgency_hint'] == 'no': +# ?? not in obj actions +# elif rule['urgency_hint'] == 'yes': + + def _nec_notif(self, obj): + # check rules in order + rules_num = [int(i) for i in self.config.keys()] + rules_num.sort() + for num in rules_num: + if self.check_rule_apply_notif(obj, self.config[str(num)]): + self.apply_rule(obj, self.config[str(num)]) + # Should we stop after first valid rule ? + # break + + def _nec_decrypted_message_received(self, obj): + rules_num = [int(i) for i in self.config.keys()] + rules_num.sort() + for num in rules_num: + rule = self.config[str(num)] + if self.check_rule_apply_decrypted_msg(obj, rule): + if rule['auto_open'] == 'no': + obj.popup = False + elif rule['auto_open'] == 'yes': + obj.popup = True + + +class TriggersPluginConfigDialog(GajimPluginConfigDialog): + events_list = ['message_received']#, 'contact_connected', + #'contact_disconnected', 'contact_change_status', 'gc_msg_highlight', + #'gc_msg'] + recipient_types_list = ['contact', 'group', 'all'] + config_options = ['event', 'recipient_type', 'recipients', 'status', + 'tab_opened', 'sound', 'sound_file', 'popup', 'auto_open', + 'run_command', 'command', 'systray', 'roster', 'urgency_hint'] + + def init(self): + self.GTK_BUILDER_FILE_PATH = self.plugin.local_file_path( + 'config_dialog.ui') + self.xml = gtk.Builder() + self.xml.add_objects_from_file(self.GTK_BUILDER_FILE_PATH, + ['vbox', 'liststore1', 'liststore2']) + vbox = self.xml.get_object('vbox') + self.child.pack_start(vbox) + + self.xml.connect_signals(self) + self.connect('hide', self.on_hide) + + def on_run(self): + # fill window + for w in ('conditions_treeview', 'config_vbox', 'event_combobox', + 'recipient_type_combobox', 'recipient_list_entry', 'delete_button', + 'status_hbox', 'use_sound_cb', 'disable_sound_cb', 'use_popup_cb', + 'disable_popup_cb', 'use_auto_open_cb', 'disable_auto_open_cb', + 'use_systray_cb', 'disable_systray_cb', 'use_roster_cb', + 'disable_roster_cb', 'tab_opened_cb', 'not_tab_opened_cb', + 'sound_entry', 'sound_file_hbox', 'up_button', 'down_button', + 'run_command_cb', 'command_entry', 'use_urgency_hint_cb', + 'disable_urgency_hint_cb'): + self.__dict__[w] = self.xml.get_object(w) + + self.config = {} + for n in self.plugin.config: + self.config[int(n)] = self.plugin.config[n] + + # Contains status checkboxes + childs = self.status_hbox.get_children() + + self.all_status_rb = childs[0] + self.special_status_rb = childs[1] + self.online_cb = childs[2] + self.away_cb = childs[3] + self.xa_cb = childs[4] + self.dnd_cb = childs[5] + self.invisible_cb = childs[6] + + if not self.conditions_treeview.get_column(0): + # window never opened + model = gtk.ListStore(int, str) + model.set_sort_column_id(0, gtk.SORT_ASCENDING) + self.conditions_treeview.set_model(model) + + # means number + col = gtk.TreeViewColumn(_('#')) + self.conditions_treeview.append_column(col) + renderer = gtk.CellRendererText() + col.pack_start(renderer, expand=False) + col.set_attributes(renderer, text=0) + + col = gtk.TreeViewColumn(_('Condition')) + self.conditions_treeview.append_column(col) + renderer = gtk.CellRendererText() + col.pack_start(renderer, expand=True) + col.set_attributes(renderer, text=1) + else: + model = self.conditions_treeview.get_model() + + model.clear() + + # Fill conditions_treeview + num = 0 + while num in self.config: + iter_ = model.append((num, '')) + path = model.get_path(iter_) + self.conditions_treeview.set_cursor(path) + self.active_num = num + self.initiate_rule_state() + self.set_treeview_string() + num += 1 + + # No rule selected at init time + self.conditions_treeview.get_selection().unselect_all() + self.active_num = -1 + self.config_vbox.set_sensitive(False) + self.delete_button.set_sensitive(False) + self.down_button.set_sensitive(False) + self.up_button.set_sensitive(False) + + def initiate_rule_state(self): + """ + Set values for all widgets + """ + if self.active_num < 0: + return + # event + value = self.config[self.active_num]['event'] + if value: + self.event_combobox.set_active(self.events_list.index(value)) + else: + self.event_combobox.set_active(-1) + # recipient_type + value = self.config[self.active_num]['recipient_type'] + if value: + self.recipient_type_combobox.set_active( + self.recipient_types_list.index(value)) + else: + self.recipient_type_combobox.set_active(-1) + # recipient + value = self.config[self.active_num]['recipients'] + if not value: + value = '' + self.recipient_list_entry.set_text(value) + # status + value = self.config[self.active_num]['status'] + if value == 'all': + self.all_status_rb.set_active(True) + else: + self.special_status_rb.set_active(True) + values = value.split() + for v in ('online', 'away', 'xa', 'dnd', 'invisible'): + if v in values: + self.__dict__[v + '_cb'].set_active(True) + else: + self.__dict__[v + '_cb'].set_active(False) + self.on_status_radiobutton_toggled(self.all_status_rb) + + # tab_opened + value = self.config[self.active_num]['tab_opened'] + self.tab_opened_cb.set_active(True) + self.not_tab_opened_cb.set_active(True) + if value == 'no': + self.tab_opened_cb.set_active(False) + elif value == 'yes': + self.not_tab_opened_cb.set_active(False) + + # sound_file + value = self.config[self.active_num]['sound_file'] + self.sound_entry.set_text(value) + + # sound, popup, auto_open, systray, roster + for option in ('sound', 'popup', 'auto_open', 'systray', 'roster', + 'urgency_hint'): + value = self.config[self.active_num][option] + if value == 'yes': + self.__dict__['use_' + option + '_cb'].set_active(True) + else: + self.__dict__['use_' + option + '_cb'].set_active(False) + if value == 'no': + self.__dict__['disable_' + option + '_cb'].set_active(True) + else: + self.__dict__['disable_' + option + '_cb'].set_active(False) + + # run_command + value = self.config[self.active_num]['run_command'] + self.run_command_cb.set_active(value) + + # command + value = self.config[self.active_num]['command'] + self.command_entry.set_text(value) + + def set_treeview_string(self): + (model, iter_) = self.conditions_treeview.get_selection().get_selected() + if not iter_: + return + event = self.event_combobox.get_active_text() + recipient_type = self.recipient_type_combobox.get_active_text() + recipient = '' + if recipient_type != 'everybody': + recipient = self.recipient_list_entry.get_text() + if self.all_status_rb.get_active(): + status = '' + else: + status = _('when I am ') + for st in ('online', 'away', 'xa', 'dnd', 'invisible'): + if self.__dict__[st + '_cb'].get_active(): + status += helpers.get_uf_show(st) + ' ' + model[iter_][1] = "When %s for %s %s %s" % (event, recipient_type, + recipient, status) + + def on_conditions_treeview_cursor_changed(self, widget): + (model, iter_) = widget.get_selection().get_selected() + if not iter_: + self.active_num = '' + return + self.active_num = model[iter_][0] + if self.active_num == '0': + self.up_button.set_sensitive(False) + else: + self.up_button.set_sensitive(True) + max = self.conditions_treeview.get_model().iter_n_children(None) + if self.active_num == max - 1: + self.down_button.set_sensitive(False) + else: + self.down_button.set_sensitive(True) + self.initiate_rule_state() + self.config_vbox.set_sensitive(True) + self.delete_button.set_sensitive(True) + + def on_new_button_clicked(self, widget): + model = self.conditions_treeview.get_model() + num = self.conditions_treeview.get_model().iter_n_children(None) + self.config[num] = {'event': '', 'recipient_type': 'all', + 'recipients': '', 'status': 'all', 'tab_opened': 'both', + 'sound': '', 'sound_file': '', 'popup': '', 'auto_open': '', + 'run_command': False, 'command': '', 'systray': '', 'roster': '', + 'urgency_hint': False} + iter_ = model.append((num, '')) + path = model.get_path(iter_) + self.conditions_treeview.set_cursor(path) + self.active_num = num + self.set_treeview_string() + self.config_vbox.set_sensitive(True) + + def on_delete_button_clicked(self, widget): + (model, iter_) = self.conditions_treeview.get_selection().get_selected() + if not iter_: + return + # up all others + iter2 = model.iter_next(iter_) + num = self.active_num + while iter2: + num = model[iter2][0] + model[iter2][0] = num - 1 + self.config[num-1] = self.config[num].copy() + iter2 = model.iter_next(iter2) + model.remove(iter_) + del self.config[num] + self.active_num = '' + self.config_vbox.set_sensitive(False) + self.delete_button.set_sensitive(False) + self.up_button.set_sensitive(False) + self.down_button.set_sensitive(False) + + def on_up_button_clicked(self, widget): + (model, iter_) = self.conditions_treeview.get_selection().get_selected() + if not iter_: + return + conf = self.config[self.active_num].copy() + self.config[self.active_num] = self.config[self.active_num - 1] + self.config[self.active_num - 1] = conf + + model[iter_][0] =self.active_num - 1 + # get previous iter + path = model.get_path(iter_) + iter_ = model.get_iter((path[0] - 1,)) + model[iter_][0] = self.active_num + self.on_conditions_treeview_cursor_changed(self.conditions_treeview) + + def on_down_button_clicked(self, widget): + (model, iter_) = self.conditions_treeview.get_selection().get_selected() + if not iter_: + return + conf = self.config[self.active_num].copy() + self.config[self.active_num] = self.config[self.active_num + 1] + self.config[self.active_num + 1] = conf + + model[iter_][0] = self.active_num + 1 + iter_ = model.iter_next(iter_) + model[iter_][0] = self.active_num + self.on_conditions_treeview_cursor_changed(self.conditions_treeview) + + def on_event_combobox_changed(self, widget): + if self.active_num < 0: + return + active = self.event_combobox.get_active() + if active == -1: + event = '' + else: + event = self.events_list[active] + self.config[self.active_num]['event'] = event + self.set_treeview_string() + + def on_recipient_type_combobox_changed(self, widget): + if self.active_num < 0: + return + recipient_type = self.recipient_types_list[ + self.recipient_type_combobox.get_active()] + self.config[self.active_num]['recipient_type'] = recipient_type + if recipient_type == 'all': + self.recipient_list_entry.hide() + else: + self.recipient_list_entry.show() + self.set_treeview_string() + + def on_recipient_list_entry_changed(self, widget): + if self.active_num < 0: + return + recipients = widget.get_text().decode('utf-8') + #TODO: do some check + self.config[self.active_num]['recipients'] = recipients + self.set_treeview_string() + + def set_status_config(self): + if self.active_num < 0: + return + status = '' + for st in ('online', 'away', 'xa', 'dnd', 'invisible'): + if self.__dict__[st + '_cb'].get_active(): + status += st + ' ' + if status: + status = status[:-1] + self.config[self.active_num]['status'] = status + self.set_treeview_string() + + def on_status_radiobutton_toggled(self, widget): + if self.active_num < 0: + return + if self.all_status_rb.get_active(): + self.config[self.active_num]['status'] = 'all' + # 'All status' clicked + for st in ('online', 'away', 'xa', 'dnd', 'invisible'): + self.__dict__[st + '_cb'].hide() + + self.special_status_rb.show() + else: + self.set_status_config() + # 'special status' clicked + for st in ('online', 'away', 'xa', 'dnd', 'invisible'): + self.__dict__[st + '_cb'].show() + + self.special_status_rb.hide() + self.set_treeview_string() + + def on_status_cb_toggled(self, widget): + if self.active_num < 0: + return + self.set_status_config() + + # tab_opened OR (not xor) not_tab_opened must be active + def on_tab_opened_cb_toggled(self, widget): + if self.active_num < 0: + return + if self.tab_opened_cb.get_active(): + if self.not_tab_opened_cb.get_active(): + self.config[self.active_num]['tab_opened'] = 'both' + else: + self.config[self.active_num]['tab_opened'] = 'yes' + else: + self.not_tab_opened_cb.set_active(True) + self.config[self.active_num]['tab_opened'] = 'no' + + def on_not_tab_opened_cb_toggled(self, widget): + if self.active_num < 0: + return + if self.not_tab_opened_cb.get_active(): + if self.tab_opened_cb.get_active(): + self.config[self.active_num]['tab_opened'] = 'both' + else: + self.config[self.active_num]['tab_opened'] = 'no' + else: + self.tab_opened_cb.set_active(True) + self.config[self.active_num]['tab_opened'] = 'yes' + + def on_use_it_toggled(self, widget, oposite_widget, option): + if widget.get_active(): + if oposite_widget.get_active(): + oposite_widget.set_active(False) + self.config[self.active_num][option] = 'yes' + elif oposite_widget.get_active(): + self.config[self.active_num][option] = 'no' + else: + self.config[self.active_num][option] = '' + + def on_disable_it_toggled(self, widget, oposite_widget, option): + if widget.get_active(): + if oposite_widget.get_active(): + oposite_widget.set_active(False) + self.config[self.active_num][option] = 'no' + elif oposite_widget.get_active(): + self.config[self.active_num][option] = 'yes' + else: + self.config[self.active_num][option] = '' + + def on_use_sound_cb_toggled(self, widget): + self.on_use_it_toggled(widget, self.disable_sound_cb, 'sound') + if widget.get_active(): + self.sound_file_hbox.set_sensitive(True) + else: + self.sound_file_hbox.set_sensitive(False) + + def on_browse_for_sounds_button_clicked(self, widget, data=None): + if self.active_num < 0: + return + + def on_ok(widget, path_to_snd_file): + dialog.destroy() + if not path_to_snd_file: + path_to_snd_file = '' + self.config[self.active_num]['sound_file'] = path_to_snd_file + self.sound_entry.set_text(path_to_snd_file) + + path_to_snd_file = self.sound_entry.get_text().decode('utf-8') + path_to_snd_file = os.path.join(os.getcwd(), path_to_snd_file) + dialog = SoundChooserDialog(path_to_snd_file, on_ok) + + def on_play_button_clicked(self, widget): + helpers.play_sound_file(self.sound_entry.get_text().decode('utf-8')) + + def on_disable_sound_cb_toggled(self, widget): + self.on_disable_it_toggled(widget, self.use_sound_cb, 'sound') + + def on_sound_entry_changed(self, widget): + self.config[self.active_num]['sound_file'] = widget.get_text().\ + decode('utf-8') + + def on_use_popup_cb_toggled(self, widget): + self.on_use_it_toggled(widget, self.disable_popup_cb, 'popup') + + def on_disable_popup_cb_toggled(self, widget): + self.on_disable_it_toggled(widget, self.use_popup_cb, 'popup') + + def on_use_auto_open_cb_toggled(self, widget): + self.on_use_it_toggled(widget, self.disable_auto_open_cb, 'auto_open') + + def on_disable_auto_open_cb_toggled(self, widget): + self.on_disable_it_toggled(widget, self.use_auto_open_cb, 'auto_open') + + def on_run_command_cb_toggled(self, widget): + self.config[self.active_num]['run_command'] = widget.get_active() + if widget.get_active(): + self.command_entry.set_sensitive(True) + else: + self.command_entry.set_sensitive(False) + + def on_command_entry_changed(self, widget): + self.config[self.active_num]['command'] = widget.get_text().\ + decode('utf-8') + + def on_use_systray_cb_toggled(self, widget): + self.on_use_it_toggled(widget, self.disable_systray_cb, 'systray') + + def on_disable_systray_cb_toggled(self, widget): + self.on_disable_it_toggled(widget, self.use_systray_cb, 'systray') + + def on_use_roster_cb_toggled(self, widget): + self.on_use_it_toggled(widget, self.disable_roster_cb, 'roster') + + def on_disable_roster_cb_toggled(self, widget): + self.on_disable_it_toggled(widget, self.use_roster_cb, 'roster') + + def on_use_urgency_hint_cb_toggled(self, widget): + self.on_use_it_toggled(widget, self.disable_urgency_hint_cb, + 'uregency_hint') + + def on_disable_urgency_hint_cb_toggled(self, widget): + self.on_disable_it_toggled(widget, self.use_urgency_hint_cb, + 'uregency_hint') + + def on_hide(self, widget): + # save config + for n in self.plugin.config: + del self.plugin.config[n] + for n in self.config: + self.plugin.config[str(n)] = self.config[n]