[triggers] Refactor plugin

- Use new config dialog
- Add scrolledwindow in order to reduce dialog height
- Fix pylint errors
This commit is contained in:
Daniel Brötzmann
2020-05-06 09:06:58 +02:00
parent fcba4c8b07
commit 3624bf9d61
4 changed files with 1759 additions and 1749 deletions

File diff suppressed because it is too large Load Diff

590
triggers/gtk/config.py Normal file
View File

@@ -0,0 +1,590 @@
# Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com>
#
# This file is part of Gajim.
#
# Gajim is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation; version 3 only.
#
# Gajim is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
from pathlib import Path
from gi.repository import Gtk
from gi.repository import Gdk
from gajim.common import app
from gajim.common.helpers import get_uf_show
from gajim.common.helpers import play_sound_file
from gajim.plugins.plugins_i18n import _
from gajim.plugins.helpers import get_builder
EVENTS = {
'message_received': [],
'contact_connected': [
'use_systray_cb',
'disable_systray_cb',
'use_roster_cb',
'disable_roster_cb'
],
'contact_disconnected': [
'use_systray_cb',
'disable_systray_cb',
'use_roster_cb',
'disable_roster_cb'
],
'contact_status_change': [
'use_systray_cb',
'disable_systray_cb',
'use_roster_cb',
'disable_roster_cb'
]
}
RECIPIENT_TYPES = [
'contact',
'group',
'groupchat',
'all'
]
class ConfigDialog(Gtk.ApplicationWindow):
def __init__(self, plugin, transient):
Gtk.ApplicationWindow.__init__(self)
self.set_application(app.app)
self.set_show_menubar(False)
self.set_title(_('Triggers Configuration'))
self.set_transient_for(transient)
self.set_default_size(600, 700)
self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
self.set_modal(True)
self.set_destroy_with_parent(True)
ui_path = Path(__file__).parent
self._ui = get_builder(ui_path.resolve() / 'config.ui')
self._plugin = plugin
self.add(self._ui.box)
self.show_all()
self._active_num = ''
self._initialize()
self._ui.connect_signals(self)
self.connect('destroy', self._on_destroy)
def _on_destroy(self, *args):
for num in list(self._plugin.config.keys()):
del self._plugin.config[num]
for num in self._config:
self._plugin.config[str(num)] = self._config[num]
def _initialize(self):
# Fill window
for widget in (
'conditions_treeview', 'config_box', 'event_combobox',
'recipient_type_combobox', 'recipient_list_entry',
'delete_button', 'online_cb', 'away_cb', 'xa_cb', 'dnd_cb',
'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', 'has_focus_cb',
'not_has_focus_cb', 'filechooser', 'sound_file_box',
'up_button', 'down_button', 'run_command_cb',
'command_entry', 'one_shot_cb'):
self._ui.__dict__[widget] = self._ui.get_object(widget)
self._config = {}
for num in self._plugin.config:
self._config[int(num)] = self._plugin.config[num]
if not self._ui.conditions_treeview.get_column(0):
# Window never opened
model = Gtk.ListStore(int, str)
model.set_sort_column_id(0, Gtk.SortType.ASCENDING)
self._ui.conditions_treeview.set_model(model)
# '#' Means number
col = Gtk.TreeViewColumn(_('#'))
self._ui.conditions_treeview.append_column(col)
renderer = Gtk.CellRendererText()
col.pack_start(renderer, expand=False)
col.add_attribute(renderer, 'text', 0)
col = Gtk.TreeViewColumn(_('Condition'))
self._ui.conditions_treeview.append_column(col)
renderer = Gtk.CellRendererText()
col.pack_start(renderer, expand=True)
col.add_attribute(renderer, 'text', 1)
else:
model = self._ui.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._ui.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._ui.conditions_treeview.get_selection().unselect_all()
self._active_num = -1
self._ui.config_box.set_sensitive(False)
self._ui.delete_button.set_sensitive(False)
self._ui.down_button.set_sensitive(False)
self._ui.up_button.set_sensitive(False)
filter_ = Gtk.FileFilter()
filter_.set_name(_('All Files'))
filter_.add_pattern('*')
self._ui.filechooser.add_filter(filter_)
filter_ = Gtk.FileFilter()
filter_.set_name(_('Wav Sounds'))
filter_.add_pattern('*.wav')
self._ui.filechooser.add_filter(filter_)
self._ui.filechooser.set_filter(filter_)
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._ui.event_combobox.set_active(
list(EVENTS.keys()).index(value))
else:
self._ui.event_combobox.set_active(-1)
# recipient_type
value = self._config[self._active_num]['recipient_type']
if value:
self._ui.recipient_type_combobox.set_active(
RECIPIENT_TYPES.index(value))
else:
self._ui.recipient_type_combobox.set_active(-1)
# recipient
value = self._config[self._active_num]['recipients']
if not value:
value = ''
self._ui.recipient_list_entry.set_text(value)
# status
value = self._config[self._active_num]['status']
if value == 'all':
self._ui.all_status_rb.set_active(True)
else:
self._ui.special_status_rb.set_active(True)
values = value.split()
for val in ('online', 'away', 'xa', 'dnd'):
if val in values:
self._ui.__dict__[val + '_cb'].set_active(True)
else:
self._ui.__dict__[val + '_cb'].set_active(False)
self._on_status_radiobutton_toggled(self._ui.all_status_rb)
# tab_opened
value = self._config[self._active_num]['tab_opened']
self._ui.tab_opened_cb.set_active(True)
self._ui.not_tab_opened_cb.set_active(True)
if value == 'no':
self._ui.tab_opened_cb.set_active(False)
elif value == 'yes':
self._ui.not_tab_opened_cb.set_active(False)
# has_focus
if 'has_focus' not in self._config[self._active_num]:
self._config[self._active_num]['has_focus'] = 'both'
value = self._config[self._active_num]['has_focus']
self._ui.has_focus_cb.set_active(True)
self._ui.not_has_focus_cb.set_active(True)
if value == 'no':
self._ui.has_focus_cb.set_active(False)
elif value == 'yes':
self._ui.not_has_focus_cb.set_active(False)
# sound_file
value = self._config[self._active_num]['sound_file']
if value is None:
self._ui.filechooser.unselect_all()
else:
self._ui.filechooser.set_filename(value)
# sound, popup, auto_open, systray, roster
for option in ('sound', 'popup', 'auto_open', 'systray', 'roster'):
value = self._config[self._active_num][option]
if value == 'yes':
self._ui.__dict__['use_' + option + '_cb'].set_active(True)
else:
self._ui.__dict__['use_' + option + '_cb'].set_active(False)
if value == 'no':
self._ui.__dict__['disable_' + option + '_cb'].set_active(True)
else:
self._ui.__dict__['disable_' + option + '_cb'].set_active(False)
# run_command
value = self._config[self._active_num]['run_command']
self._ui.run_command_cb.set_active(value)
# command
value = self._config[self._active_num]['command']
self._ui.command_entry.set_text(value)
# one shot
if 'one_shot' in self._config[self._active_num]:
value = self._config[self._active_num]['one_shot']
else:
value = False
self._ui.one_shot_cb.set_active(value)
def _set_treeview_string(self):
selection = self._ui.conditions_treeview.get_selection()
(model, iter_) = selection.get_selected()
if not iter_:
return
ind = self._ui.event_combobox.get_active()
event = ''
if ind > -1:
event = self._ui.event_combobox.get_model()[ind][0]
ind = self._ui.recipient_type_combobox.get_active()
recipient_type = ''
if ind > -1:
recipient_type_model = self._ui.recipient_type_combobox.get_model()
recipient_type = recipient_type_model[ind][0]
recipient = ''
if recipient_type != 'everybody':
recipient = self._ui.recipient_list_entry.get_text()
if self._ui.all_status_rb.get_active():
status = ''
else:
status = _('and I am ')
for st in ('online', 'away', 'xa', 'dnd'):
if self._ui.__dict__[st + '_cb'].get_active():
status += get_uf_show(st) + ' '
model[iter_][1] = _('%(event)s (%(recipient_type)s) %(recipient)s '
'%(status)s') % {
'event': event,
'recipient_type': recipient_type,
'recipient': recipient,
'status': 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._ui.up_button.set_sensitive(False)
else:
self._ui.up_button.set_sensitive(True)
_max = widget.get_model().iter_n_children(None)
if self._active_num == _max - 1:
self._ui.down_button.set_sensitive(False)
else:
self._ui.down_button.set_sensitive(True)
self._initiate_rule_state()
self._ui.config_box.set_sensitive(True)
self._ui.delete_button.set_sensitive(True)
def _on_new_button_clicked(self, _widget):
model = self._ui.conditions_treeview.get_model()
num = self._ui.conditions_treeview.get_model().iter_n_children(None)
self._config[num] = {
'event': 'message_received',
'recipient_type': 'all',
'recipients': '',
'status': 'all',
'tab_opened': 'both',
'has_focus': 'both',
'sound': '',
'sound_file': '',
'popup': '',
'auto_open': '',
'run_command': False,
'command': '',
'systray': '',
'roster': '',
'one_shot': False,
}
iter_ = model.append((num, ''))
path = model.get_path(iter_)
self._ui.conditions_treeview.set_cursor(path)
self._active_num = num
self._set_treeview_string()
self._ui.config_box.set_sensitive(True)
def _on_delete_button_clicked(self, widget):
selection = self._ui.conditions_treeview.get_selection()
(model, iter_) = 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 = ''
widget.set_sensitive(False)
self._ui.up_button.set_sensitive(False)
self._ui.down_button.set_sensitive(False)
self._ui.config_box.set_sensitive(False)
def _on_up_button_clicked(self, _widget):
selection = self._ui.conditions_treeview.get_selection()
(model, iter_) = 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._ui.conditions_treeview)
def _on_down_button_clicked(self, _widget):
selection = self._ui.conditions_treeview.get_selection()
(model, iter_) = 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._ui.conditions_treeview)
def _on_event_combobox_changed(self, widget):
if self._active_num < 0:
return
active = widget.get_active()
if active == -1:
return
event = list(EVENTS.keys())[active]
self._config[self._active_num]['event'] = event
for widget in ('use_systray_cb', 'disable_systray_cb', 'use_roster_cb',
'disable_roster_cb'):
self._ui.__dict__[widget].set_sensitive(True)
for widget in EVENTS[event]:
self._ui.__dict__[widget].set_sensitive(False)
self._ui.__dict__[widget].set_state(False)
self._set_treeview_string()
def _on_recipient_type_combobox_changed(self, widget):
if self._active_num < 0:
return
recipient_type = RECIPIENT_TYPES[widget.get_active()]
self._config[self._active_num]['recipient_type'] = recipient_type
if recipient_type == 'all':
self._ui.recipient_list_entry.set_sensitive(False)
else:
self._ui.recipient_list_entry.set_sensitive(True)
self._set_treeview_string()
def _on_recipient_list_entry_changed(self, widget):
if self._active_num < 0:
return
recipients = widget.get_text()
# 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'):
if self._ui.__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._ui.all_status_rb.get_active():
self._ui.status_expander.set_expanded(False)
self._config[self._active_num]['status'] = 'all'
# 'All status' clicked
for st in ('online', 'away', 'xa', 'dnd'):
self._ui.__dict__[st + '_cb'].set_sensitive(False)
else:
self._ui.status_expander.set_expanded(True)
self._set_status_config()
# 'special status' clicked
for st in ('online', 'away', 'xa', 'dnd'):
self._ui.__dict__[st + '_cb'].set_sensitive(True)
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 widget.get_active():
self._ui.has_focus_cb.set_sensitive(True)
self._ui.not_has_focus_cb.set_sensitive(True)
if self._ui.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._ui.has_focus_cb.set_sensitive(False)
self._ui.not_has_focus_cb.set_sensitive(False)
self._ui.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 widget.get_active():
if self._ui.tab_opened_cb.get_active():
self._config[self._active_num]['tab_opened'] = 'both'
else:
self._config[self._active_num]['tab_opened'] = 'no'
else:
self._ui.tab_opened_cb.set_active(True)
self._config[self._active_num]['tab_opened'] = 'yes'
# has_focus OR (not xor) not_has_focus must be active
def _on_has_focus_cb_toggled(self, widget):
if self._active_num < 0:
return
if widget.get_active():
if self._ui.not_has_focus_cb.get_active():
self._config[self._active_num]['has_focus'] = 'both'
else:
self._config[self._active_num]['has_focus'] = 'yes'
else:
self._ui.not_has_focus_cb.set_active(True)
self._config[self._active_num]['has_focus'] = 'no'
def _on_not_has_focus_cb_toggled(self, widget):
if self._active_num < 0:
return
if widget.get_active():
if self._ui.has_focus_cb.get_active():
self._config[self._active_num]['has_focus'] = 'both'
else:
self._config[self._active_num]['has_focus'] = 'no'
else:
self._ui.has_focus_cb.set_active(True)
self._config[self._active_num]['has_focus'] = 'yes'
def _on_use_it_toggled(self, widget, opposite_widget, option):
if widget.get_active():
if opposite_widget.get_active():
opposite_widget.set_active(False)
self._config[self._active_num][option] = 'yes'
elif opposite_widget.get_active():
self._config[self._active_num][option] = 'no'
else:
self._config[self._active_num][option] = ''
def _on_disable_it_toggled(self, widget, opposite_widget, option):
if widget.get_active():
if opposite_widget.get_active():
opposite_widget.set_active(False)
self._config[self._active_num][option] = 'no'
elif opposite_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._ui.disable_sound_cb, 'sound')
if widget.get_active():
self._ui.sound_file_box.set_sensitive(True)
else:
self._ui.sound_file_box.set_sensitive(False)
def _on_sound_file_set(self, widget):
self._config[self._active_num]['sound_file'] = widget.get_filename()
def _on_play_button_clicked(self, _widget):
play_sound_file(self._ui.filechooser.get_filename())
def _on_disable_sound_cb_toggled(self, widget):
self._on_disable_it_toggled(widget, self._ui.use_sound_cb, 'sound')
def _on_use_popup_cb_toggled(self, widget):
self._on_use_it_toggled(widget, self._ui.disable_popup_cb, 'popup')
def _on_disable_popup_cb_toggled(self, widget):
self._on_disable_it_toggled(widget, self._ui.use_popup_cb, 'popup')
def _on_use_auto_open_cb_toggled(self, widget):
self._on_use_it_toggled(widget, self._ui.disable_auto_open_cb,
'auto_open')
def _on_disable_auto_open_cb_toggled(self, widget):
self._on_disable_it_toggled(widget, self._ui.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._ui.command_entry.set_sensitive(True)
else:
self._ui.command_entry.set_sensitive(False)
def _on_command_entry_changed(self, widget):
self._config[self._active_num]['command'] = widget.get_text()
def _on_use_systray_cb_toggled(self, widget):
self._on_use_it_toggled(widget, self._ui.disable_systray_cb, 'systray')
def _on_disable_systray_cb_toggled(self, widget):
self._on_disable_it_toggled(widget, self._ui.use_systray_cb, 'systray')
def _on_use_roster_cb_toggled(self, widget):
self._on_use_it_toggled(widget, self._ui.disable_roster_cb, 'roster')
def _on_disable_roster_cb_toggled(self, widget):
self._on_disable_it_toggled(widget, self._ui.use_roster_cb, 'roster')
def _on_one_shot_cb_toggled(self, widget):
self._config[self._active_num]['one_shot'] = widget.get_active()
self._ui.command_entry.set_sensitive(widget.get_active())

1108
triggers/gtk/config.ui Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,59 +1,45 @@
# -*- coding: utf-8 -*- # Copyright (C) 2011-2017 Yann Leboulanger <asterix AT lagaule.org>
#
# 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/>.
# #
## plugins/triggers/triggers.py
##
## Copyright (C) 2011-2017 Yann Leboulanger <asterix AT lagaule.org>
##
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## Gajim is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
from functools import partial
import os
from gi.repository import Gtk
from gajim.common import app from gajim.common import app
from gajim.common import ged from gajim.common import ged
from gajim.common import helpers
from gajim.plugins import GajimPlugin from gajim.plugins import GajimPlugin
from gajim.plugins.helpers import log_calls
from gajim.plugins.helpers import get_builder
from gajim.plugins.gui import GajimPluginConfigDialog
from gajim.plugins.plugins_i18n import _ from gajim.plugins.plugins_i18n import _
from gajim.gtk.filechoosers import NativeFileChooserDialog, Filter from triggers.gtk.config import ConfigDialog
class SoundChooserDialog(NativeFileChooserDialog):
_title = _('Choose Sound')
_filters = [Filter(_('All files'), '*', False),
Filter(_('WAV files'), '*.wav', True)]
class Triggers(GajimPlugin): class Triggers(GajimPlugin):
@log_calls('TriggersPlugin')
def init(self): def init(self):
self.description = _('Configure Gajim\'s behaviour with conditions for each contact') self.description = _('Configure Gajims behaviour with triggers '
self.config_dialog = TriggersPluginConfigDialog(self) 'for each contact')
self.config_dialog = partial(ConfigDialog, self)
self.config_default_values = {} self.config_default_values = {}
self.events_handlers = {'notification': (ged.PREGUI, self._nec_notif), self.events_handlers = {
'notification': (ged.PREGUI, self._on_notification),
'decrypted-message-received': (ged.PREGUI2, 'decrypted-message-received': (ged.PREGUI2,
self._nec_decrypted_message_received), self._on_message_received),
'gc-message-received': (ged.PREGUI2, self._nec_gc_message_received), 'gc-message-received': (ged.PREGUI2, self._on_gc_message_received),
'presence-received': (ged.PREGUI, self._nec_presence_received)} 'presence-received': (ged.PREGUI, self._on_presence_received),
}
def _check_rule_recipients(self, obj, rule): def _check_rule_recipients(self, obj, rule):
rule_recipients = [t.strip() for t in rule['recipients'].split(',')] rule_recipients = [t.strip() for t in rule['recipients'].split(',')]
@@ -61,11 +47,11 @@ class Triggers(GajimPlugin):
if obj.jid in rule_recipients: if obj.jid in rule_recipients:
return True return True
return False return False
if rule['recipient_type'] == 'contact' and obj.jid not in \ if (rule['recipient_type'] == 'contact' and obj.jid not in
rule_recipients: rule_recipients):
return False return False
contact = app.contacts.get_first_contact_from_jid(obj.conn.name, contact = app.contacts.get_first_contact_from_jid(
obj.jid) obj.conn.name, obj.jid)
if not contact: # PM? if not contact: # PM?
return False return False
contact_groups = contact.groups contact_groups = contact.groups
@@ -118,7 +104,7 @@ class Triggers(GajimPlugin):
return True return True
def check_rule_all(self, event, obj, rule): def _check_rule_all(self, event, obj, rule):
# Check notification type # Check notification type
if rule['event'] != event: if rule['event'] != event:
return False return False
@@ -142,7 +128,7 @@ class Triggers(GajimPlugin):
# All is ok # All is ok
return True return True
def check_rule_apply_notif(self, obj, rule): def _check_rule_apply_notification(self, obj, rule):
# Check notification type # Check notification type
notif_type = '' notif_type = ''
if obj.notif_type in ('msg', 'gc-msg'): if obj.notif_type in ('msg', 'gc-msg'):
@@ -155,21 +141,21 @@ class Triggers(GajimPlugin):
else: else:
notif_type = 'contact_status_change' notif_type = 'contact_status_change'
return self.check_rule_all(notif_type, obj, rule) return self._check_rule_all(notif_type, obj, rule)
def check_rule_apply_decrypted_msg(self, obj, rule): def _check_rule_apply_msg_received(self, obj, rule):
return self.check_rule_all('message_received', obj, rule) return self._check_rule_all('message_received', obj, rule)
def check_rule_apply_connected(self, obj, rule): def _check_rule_apply_connected(self, obj, rule):
return self.check_rule_all('contact_connected', obj, rule) return self._check_rule_all('contact_connected', obj, rule)
def check_rule_apply_disconnected(self, obj, rule): def _check_rule_apply_disconnected(self, obj, rule):
return self.check_rule_all('contact_disconnected', obj, rule) return self._check_rule_all('contact_disconnected', obj, rule)
def check_rule_apply_status_changed(self, obj, rule): def _check_rule_apply_status_changed(self, obj, rule):
return self.check_rule_all('contact_status_change', obj, rule) return self._check_rule_all('contact_status_change', obj, rule)
def apply_rule_notif(self, obj, rule): def _apply_rule_notification(self, obj, rule):
if rule['sound'] == 'no': if rule['sound'] == 'no':
obj.do_sound = False obj.do_sound = False
elif rule['sound'] == 'yes': elif rule['sound'] == 'yes':
@@ -198,23 +184,19 @@ class Triggers(GajimPlugin):
elif rule['roster'] == 'yes': elif rule['roster'] == 'yes':
obj.show_in_roster = True obj.show_in_roster = True
# if rule['urgency_hint'] == 'no': def _apply_rule_message_received(self, obj, rule):
# ?? not in obj actions
# elif rule['urgency_hint'] == 'yes':
def apply_rule_decrypted_message(self, obj, rule):
if rule['auto_open'] == 'no': if rule['auto_open'] == 'no':
obj.popup = False obj.popup = False
elif rule['auto_open'] == 'yes': elif rule['auto_open'] == 'yes':
obj.popup = True obj.popup = True
def apply_rule_presence(self, obj, rule): def _apply_rule_presence_received(self, obj, rule):
if rule['auto_open'] == 'no': if rule['auto_open'] == 'no':
obj.popup = False obj.popup = False
elif rule['auto_open'] == 'yes': elif rule['auto_open'] == 'yes':
obj.popup = True obj.popup = True
def _nec_all(self, obj, check_func, apply_func): def _check_all(self, obj, check_func, apply_func):
# check rules in order # check rules in order
rules_num = [int(i) for i in self.config.keys()] rules_num = [int(i) for i in self.config.keys()]
rules_num.sort() rules_num.sort()
@@ -231,7 +213,7 @@ class Triggers(GajimPlugin):
decal = 0 decal = 0
num = 0 num = 0
while str(num) in self.config: while str(num) in self.config:
if (num + decal) in to_remove: if num + decal in to_remove:
num2 = num num2 = num
while str(num2 + 1) in self.config: while str(num2 + 1) in self.config:
self.config[str(num2)] = self.config[str(num2 + 1)].copy() self.config[str(num2)] = self.config[str(num2 + 1)].copy()
@@ -241,544 +223,23 @@ class Triggers(GajimPlugin):
else: else:
num += 1 num += 1
def _nec_notif(self, obj): def _on_notification(self, obj):
self._nec_all(obj, self.check_rule_apply_notif, self.apply_rule_notif) self._check_all(obj, self._check_rule_apply_notification,
self._apply_rule_notification)
def _nec_decrypted_message_received(self, obj): def _on_message_received(self, obj):
self._nec_all(obj, self.check_rule_apply_decrypted_msg, self._check_all(obj, self._check_rule_apply_msg_received,
self.apply_rule_decrypted_message) self._apply_rule_message_received)
def _nec_gc_message_received(self, obj): def _on_gc_message_received(self, obj):
self._nec_all(obj, self.check_rule_apply_decrypted_msg, self._check_all(obj, self._check_rule_apply_msg_received,
self.apply_rule_decrypted_message) self._apply_rule_message_received)
def _nec_presence_received(self, obj): def _on_presence_received(self, obj):
if obj.old_show < 2 and obj.new_show > 1: if obj.old_show < 2 and obj.new_show > 1:
check_func = self.check_rule_apply_connected check_func = self._check_rule_apply_connected
elif obj.old_show > 1 and obj.new_show < 2: elif obj.old_show > 1 and obj.new_show < 2:
check_func = self.check_rule_apply_disconnected check_func = self._check_rule_apply_disconnected
else: else:
check_func = self.check_rule_apply_status_changed check_func = self._check_rule_apply_status_changed
self._nec_all(obj, check_func, self.apply_rule_presence) self._check_all(obj, check_func, self._apply_rule_presence_received)
class TriggersPluginConfigDialog(GajimPluginConfigDialog):
# {event: widgets_to_disable, }
events_list = {
'message_received': [],
'contact_connected': ['use_systray_cb', 'disable_systray_cb',
'use_roster_cb', 'disable_roster_cb'],
'contact_disconnected': ['use_systray_cb', 'disable_systray_cb',
'use_roster_cb', 'disable_roster_cb'],
'contact_status_change': ['use_systray_cb', 'disable_systray_cb',
'use_roster_cb', 'disable_roster_cb']
#, 'gc_msg_highlight': [], 'gc_msg': []}
}
recipient_types_list = ['contact', 'group', 'groupchat', 'all']
config_options = ['event', 'recipient_type', 'recipients', 'status',
'tab_opened', 'has_focus', 'sound', 'sound_file', 'popup', 'auto_open',
'run_command', 'command', 'systray', 'roster', 'urgency_hint',
'one_shot']
def init(self):
path = self.plugin.local_file_path('config_dialog.ui')
self._ui = get_builder(path, widgets=['plugin_box', 'liststore1', 'liststore2'])
box = self.get_content_area()
box.pack_start(self._ui.plugin_box, True, True, 0)
self._ui.connect_signals(self)
self.connect('hide', self.on_hide)
def on_run(self):
# Fill window
for w in ('conditions_treeview', 'config_box', 'event_combobox',
'recipient_type_combobox', 'recipient_list_entry', 'delete_button',
'online_cb', 'away_cb', 'xa_cb', 'dnd_cb',
'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',
'has_focus_cb', 'not_has_focus_cb', 'sound_entry', 'sound_file_box',
'up_button', 'down_button', 'run_command_cb', 'command_entry',
'one_shot_cb', 'use_urgency_hint_cb', 'disable_urgency_hint_cb'):
self._ui.__dict__[w] = self._ui.get_object(w)
self.config = {}
for n in self.plugin.config:
self.config[int(n)] = self.plugin.config[n]
if not self._ui.conditions_treeview.get_column(0):
# Window never opened
model = Gtk.ListStore(int, str)
model.set_sort_column_id(0, Gtk.SortType.ASCENDING)
self._ui.conditions_treeview.set_model(model)
# '#' Means number
col = Gtk.TreeViewColumn(_('#'))
self._ui.conditions_treeview.append_column(col)
renderer = Gtk.CellRendererText()
col.pack_start(renderer, expand=False)
col.add_attribute(renderer, 'text', 0)
col = Gtk.TreeViewColumn(_('Condition'))
self._ui.conditions_treeview.append_column(col)
renderer = Gtk.CellRendererText()
col.pack_start(renderer, expand=True)
col.add_attribute(renderer, 'text', 1)
else:
model = self._ui.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._ui.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._ui.conditions_treeview.get_selection().unselect_all()
self.active_num = -1
self._ui.config_box.set_sensitive(False)
self._ui.delete_button.set_sensitive(False)
self._ui.down_button.set_sensitive(False)
self._ui.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._ui.event_combobox.set_active(list(self.events_list.keys()).index(
value))
else:
self._ui.event_combobox.set_active(-1)
# recipient_type
value = self.config[self.active_num]['recipient_type']
if value:
self._ui.recipient_type_combobox.set_active(
self.recipient_types_list.index(value))
else:
self._ui.recipient_type_combobox.set_active(-1)
# recipient
value = self.config[self.active_num]['recipients']
if not value:
value = ''
self._ui.recipient_list_entry.set_text(value)
# status
value = self.config[self.active_num]['status']
if value == 'all':
self._ui.all_status_rb.set_active(True)
else:
self._ui.special_status_rb.set_active(True)
values = value.split()
for v in ('online', 'away', 'xa', 'dnd'):
if v in values:
self._ui.__dict__[v + '_cb'].set_active(True)
else:
self._ui.__dict__[v + '_cb'].set_active(False)
self.on_status_radiobutton_toggled(self._ui.all_status_rb)
# tab_opened
value = self.config[self.active_num]['tab_opened']
self._ui.tab_opened_cb.set_active(True)
self._ui.not_tab_opened_cb.set_active(True)
if value == 'no':
self._ui.tab_opened_cb.set_active(False)
elif value == 'yes':
self._ui.not_tab_opened_cb.set_active(False)
# has_focus
if 'has_focus' not in self.config[self.active_num]:
self.config[self.active_num]['has_focus'] = 'both'
value = self.config[self.active_num]['has_focus']
self._ui.has_focus_cb.set_active(True)
self._ui.not_has_focus_cb.set_active(True)
if value == 'no':
self._ui.has_focus_cb.set_active(False)
elif value == 'yes':
self._ui.not_has_focus_cb.set_active(False)
# sound_file
value = self.config[self.active_num]['sound_file']
self._ui.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._ui.__dict__['use_' + option + '_cb'].set_active(True)
else:
self._ui.__dict__['use_' + option + '_cb'].set_active(False)
if value == 'no':
self._ui.__dict__['disable_' + option + '_cb'].set_active(True)
else:
self._ui.__dict__['disable_' + option + '_cb'].set_active(False)
# run_command
value = self.config[self.active_num]['run_command']
self._ui.run_command_cb.set_active(value)
# command
value = self.config[self.active_num]['command']
self._ui.command_entry.set_text(value)
# one shot
if 'one_shot' in self.config[self.active_num]:
value = self.config[self.active_num]['one_shot']
else:
value = False
self._ui.one_shot_cb.set_active(value)
def set_treeview_string(self):
(model, iter_) = self._ui.conditions_treeview.get_selection().get_selected()
if not iter_:
return
ind = self._ui.event_combobox.get_active()
event = ''
if ind > -1:
event = self._ui.event_combobox.get_model()[ind][0]
ind = self._ui.recipient_type_combobox.get_active()
recipient_type = ''
if ind > -1:
recipient_type = self._ui.recipient_type_combobox.get_model()[ind][0]
recipient = ''
if recipient_type != 'everybody':
recipient = self._ui.recipient_list_entry.get_text()
if self._ui.all_status_rb.get_active():
status = ''
else:
status = _('and I am: ')
for st in ('online', 'away', 'xa', 'dnd'):
if self._ui.__dict__[st + '_cb'].get_active():
status += helpers.get_uf_show(st) + ' '
model[iter_][1] = _('When event: %(event)s for category: '
'%(recipient_type)s %(recipient)s %(status)s') % {
'event': event, 'recipient_type': recipient_type,
'recipient': recipient, 'status': 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._ui.up_button.set_sensitive(False)
else:
self._ui.up_button.set_sensitive(True)
_max = self._ui.conditions_treeview.get_model().iter_n_children(None)
if self.active_num == _max - 1:
self._ui.down_button.set_sensitive(False)
else:
self._ui.down_button.set_sensitive(True)
self.initiate_rule_state()
self._ui.config_box.set_sensitive(True)
self._ui.delete_button.set_sensitive(True)
def on_new_button_clicked(self, widget):
model = self._ui.conditions_treeview.get_model()
num = self._ui.conditions_treeview.get_model().iter_n_children(None)
self.config[num] = {'event': 'message_received', 'recipient_type': 'all',
'recipients': '', 'status': 'all', 'tab_opened': 'both',
'has_focus': 'both', 'sound': '', 'sound_file': '', 'popup': '',
'auto_open': '', 'run_command': False, 'command': '', 'systray': '',
'roster': '', 'one_shot': False, 'urgency_hint': False}
iter_ = model.append((num, ''))
path = model.get_path(iter_)
self._ui.conditions_treeview.set_cursor(path)
self.active_num = num
self.set_treeview_string()
self._ui.config_box.set_sensitive(True)
def on_delete_button_clicked(self, widget):
(model, iter_) = self._ui.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._ui.config_box.set_sensitive(False)
self._ui.delete_button.set_sensitive(False)
self._ui.up_button.set_sensitive(False)
self._ui.down_button.set_sensitive(False)
def on_up_button_clicked(self, widget):
(model, iter_) = self._ui.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._ui.conditions_treeview)
def on_down_button_clicked(self, widget):
(model, iter_) = self._ui.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._ui.conditions_treeview)
def on_event_combobox_changed(self, widget):
if self.active_num < 0:
return
active = self._ui.event_combobox.get_active()
if active == -1:
return
else:
event = list(self.events_list.keys())[active]
self.config[self.active_num]['event'] = event
for w in ('use_systray_cb', 'disable_systray_cb', 'use_roster_cb',
'disable_roster_cb'):
self._ui.__dict__[w].set_sensitive(True)
for w in self.events_list[event]:
self._ui.__dict__[w].set_sensitive(False)
self._ui.__dict__[w].set_state(False)
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._ui.recipient_type_combobox.get_active()]
self.config[self.active_num]['recipient_type'] = recipient_type
if recipient_type == 'all':
self._ui.recipient_list_entry.set_sensitive(False)
else:
self._ui.recipient_list_entry.set_sensitive(True)
self.set_treeview_string()
def on_recipient_list_entry_changed(self, widget):
if self.active_num < 0:
return
recipients = widget.get_text()
#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'):
if self._ui.__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._ui.all_status_rb.get_active():
self._ui.status_expander.set_expanded(False)
self.config[self.active_num]['status'] = 'all'
# 'All status' clicked
for st in ('online', 'away', 'xa', 'dnd'):
self._ui.__dict__[st + '_cb'].set_sensitive(False)
else:
self._ui.status_expander.set_expanded(True)
self.set_status_config()
# 'special status' clicked
for st in ('online', 'away', 'xa', 'dnd'):
self._ui.__dict__[st + '_cb'].set_sensitive(True)
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._ui.tab_opened_cb.get_active():
self._ui.has_focus_cb.set_sensitive(True)
self._ui.not_has_focus_cb.set_sensitive(True)
if self._ui.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._ui.has_focus_cb.set_sensitive(False)
self._ui.not_has_focus_cb.set_sensitive(False)
self._ui.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._ui.not_tab_opened_cb.get_active():
if self._ui.tab_opened_cb.get_active():
self.config[self.active_num]['tab_opened'] = 'both'
else:
self.config[self.active_num]['tab_opened'] = 'no'
else:
self._ui.tab_opened_cb.set_active(True)
self.config[self.active_num]['tab_opened'] = 'yes'
# has_focus OR (not xor) not_has_focus must be active
def on_has_focus_cb_toggled(self, widget):
if self.active_num < 0:
return
if self._ui.has_focus_cb.get_active():
if self._ui.not_has_focus_cb.get_active():
self.config[self.active_num]['has_focus'] = 'both'
else:
self.config[self.active_num]['has_focus'] = 'yes'
else:
self._ui.not_has_focus_cb.set_active(True)
self.config[self.active_num]['has_focus'] = 'no'
def on_not_has_focus_cb_toggled(self, widget):
if self.active_num < 0:
return
if self._ui.not_has_focus_cb.get_active():
if self._ui.has_focus_cb.get_active():
self.config[self.active_num]['has_focus'] = 'both'
else:
self.config[self.active_num]['has_focus'] = 'no'
else:
self._ui.has_focus_cb.set_active(True)
self.config[self.active_num]['has_focus'] = '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._ui.disable_sound_cb, 'sound')
if widget.get_active():
self._ui.sound_file_box.set_sensitive(True)
else:
self._ui.sound_file_box.set_sensitive(False)
def on_browse_for_sounds_button_clicked(self, widget, data=None):
self._new_filechooser()
def _new_filechooser(self):
if self.active_num < 0:
return
def on_ok(path_to_snd_file):
self.config[self.active_num]['sound_file'] = path_to_snd_file
self._ui.sound_entry.set_text(path_to_snd_file)
path_to_snd_file = self._ui.sound_entry.get_text()
path_to_snd_file = os.path.join(os.getcwd(), path_to_snd_file)
SoundChooserDialog(on_ok,
path=path_to_snd_file,
transient_for=self)
def on_play_button_clicked(self, widget):
helpers.play_sound_file(self._ui.sound_entry.get_text())
def on_disable_sound_cb_toggled(self, widget):
self.on_disable_it_toggled(widget, self._ui.use_sound_cb, 'sound')
def on_sound_entry_changed(self, widget):
self.config[self.active_num]['sound_file'] = widget.get_text()
def on_use_popup_cb_toggled(self, widget):
self.on_use_it_toggled(widget, self._ui.disable_popup_cb, 'popup')
def on_disable_popup_cb_toggled(self, widget):
self.on_disable_it_toggled(widget, self._ui.use_popup_cb, 'popup')
def on_use_auto_open_cb_toggled(self, widget):
self.on_use_it_toggled(widget, self._ui.disable_auto_open_cb, 'auto_open')
def on_disable_auto_open_cb_toggled(self, widget):
self.on_disable_it_toggled(widget, self._ui.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._ui.command_entry.set_sensitive(True)
else:
self._ui.command_entry.set_sensitive(False)
def on_command_entry_changed(self, widget):
self.config[self.active_num]['command'] = widget.get_text()
def on_use_systray_cb_toggled(self, widget):
self.on_use_it_toggled(widget, self._ui.disable_systray_cb, 'systray')
def on_disable_systray_cb_toggled(self, widget):
self.on_disable_it_toggled(widget, self._ui.use_systray_cb, 'systray')
def on_use_roster_cb_toggled(self, widget):
self.on_use_it_toggled(widget, self._ui.disable_roster_cb, 'roster')
def on_disable_roster_cb_toggled(self, widget):
self.on_disable_it_toggled(widget, self._ui.use_roster_cb, 'roster')
def on_one_shot_cb_toggled(self, widget):
self.config[self.active_num]['one_shot'] = widget.get_active()
self._ui.command_entry.set_sensitive(widget.get_active())
def on_use_urgency_hint_cb_toggled(self, widget):
self.on_use_it_toggled(widget, self._ui.disable_urgency_hint_cb,
'uregency_hint')
def on_disable_urgency_hint_cb_toggled(self, widget):
self.on_disable_it_toggled(widget, self._ui.use_urgency_hint_cb,
'uregency_hint')
def on_hide(self, widget):
# save config
for n in list(self.plugin.config.keys()):
del self.plugin.config[n]
for n in self.config:
self.plugin.config[str(n)] = self.config[n]