1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
import json
from pathlib import Path
from functools import partial
from gi.repository import Gtk
from gajim.common import configpaths
from gajim.plugins import GajimPlugin
from gajim.plugins.plugins_i18n import _
from quick_replies.quick_replies import DEFAULT_DATA
from quick_replies.gtk.config import ConfigDialog
class QuickRepliesPlugin(GajimPlugin):
def init(self):
self.description = _('Adds a menu with customizable quick replies')
self.config_dialog = partial(ConfigDialog, self)
self.gui_extension_points = {
'chat_control_base': (self._connect_chat_control,
self._disconnect_chat_control),
}
self._buttons = {}
self.quick_replies = self._load_quick_replies()
def _connect_chat_control(self, chat_control):
button = QuickRepliesButton(chat_control, self.quick_replies)
self._buttons[chat_control.control_id] = button
actions_hbox = chat_control.xml.get_object('hbox')
actions_hbox.pack_start(button, False, False, 0)
actions_hbox.reorder_child(
button, len(actions_hbox.get_children()) - 2)
button.show()
def _disconnect_chat_control(self, chat_control):
button = self._buttons.get(chat_control.control_id)
if button is not None:
button.destroy()
self._buttons.pop(chat_control.control_id, None)
@staticmethod
def _load_quick_replies():
try:
data_path = Path(configpaths.get('PLUGINS_DATA'))
except KeyError:
# PLUGINS_DATA was added in 1.0.99.1
return DEFAULT_DATA
path = data_path / 'quick_replies' / 'quick_replies'
if not path.exists():
return DEFAULT_DATA
with path.open('r') as file:
quick_replies = json.load(file)
return quick_replies
@staticmethod
def _save_quick_replies(quick_replies):
try:
data_path = Path(configpaths.get('PLUGINS_DATA'))
except KeyError:
# PLUGINS_DATA was added in 1.0.99.1
return
path = data_path / 'quick_replies'
if not path.exists():
path.mkdir(parents=True)
filepath = path / 'quick_replies'
with filepath.open('w') as file:
json.dump(quick_replies, file)
def set_quick_replies(self, quick_replies):
self.quick_replies = quick_replies
self._save_quick_replies(quick_replies)
self._update_buttons()
def _update_buttons(self):
for button in self._buttons.values():
button.update_menu(self.quick_replies)
class QuickRepliesButton(Gtk.MenuButton):
def __init__(self, chat_control, replies):
Gtk.MenuButton.__init__(self)
self.get_style_context().add_class('chatcontrol-actionbar-button')
self.set_property('relief', Gtk.ReliefStyle.NONE)
self.set_can_focus(False)
plugin_path = Path(__file__).parent
img_path = plugin_path.resolve() / 'quick_replies.png'
img = Gtk.Image.new_from_file(str(img_path))
self.set_image(img)
self.set_tooltip_text(_('Quick Replies'))
self._chat_control = chat_control
self.update_menu(replies)
def update_menu(self, replies):
self._menu = Gtk.Menu()
for reply in replies:
item = Gtk.MenuItem.new_with_label(label=reply)
item.connect('activate', self._on_insert, reply)
self._menu.append(item)
self._menu.show_all()
self.set_popup(self._menu)
def _on_insert(self, _widget, text):
message_buffer = self._chat_control.msg_textview.get_buffer()
self._chat_control.msg_textview.remove_placeholder()
message_buffer.insert_at_cursor(text.rstrip() + ' ')
self._chat_control.msg_textview.grab_focus()
|