clickable_nicknames.py 5.59 KB
Newer Older
Dicson's avatar
Dicson committed
1 2
# -*- coding: utf-8 -*-

3 4
from gi.repository import Gtk
from gi.repository import Gdk
Dicson's avatar
Dicson committed
5 6 7

from common import gajim
from plugins import GajimPlugin
8
from plugins.helpers import log_calls
Dicson's avatar
Dicson committed
9 10 11


class ClickableNicknames(GajimPlugin):
12

Dicson's avatar
Dicson committed
13 14
    @log_calls('ClickableNicknamesPlugin')
    def init(self):
Dicson's avatar
Dicson committed
15 16
        self.description = _('Clickable nicknames '
            'in the conversation textview.')
Dicson's avatar
Dicson committed
17
        self.config_dialog = None  # ClickableNicknamesPluginConfigDialog(self)
Dicson's avatar
Dicson committed
18
        self.gui_extension_points = {
Dicson's avatar
Dicson committed
19
                'chat_control_base': (self.connect_with_chat_control,
Dicson's avatar
Dicson committed
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
                                       self.disconnect_from_chat_control)}

        self.is_active = None
        self.gc_controls = {}

        self.tag_names = []
        colors = gajim.config.get('gc_nicknames_colors')
        colors = colors.split(':')
        for i, color in enumerate(colors):
            tagname = 'gc_nickname_color_' + str(i)
            self.tag_names.append(tagname)

    @log_calls('ClickableNicknamesPlugin')
    def activate(self):
        for gc_control in gajim.interface.msg_win_mgr.get_controls('gc'):
            # TODO support minimized groupchat
            if gc_control not in self.gc_controls.keys():
                control = Base(self, gc_control)
                self.gc_controls[gc_control] = control
            else:
                self.gc_controls[gc_control].connect_signals()
        self.is_active = True

    @log_calls('ClickableNicknamesPlugin')
    def deactivate(self):
        for control in self.gc_controls.keys():
            self.gc_controls[control].disconnect_from_chat_control()
        self.gc_controls.clear()
        self.is_active = None

    @log_calls('ClickableNicknamesPlugin')
    def connect_with_chat_control(self, chat_control):
        if chat_control.widget_name != 'groupchat_control':
            return
        if self.is_active:
            control = Base(self, chat_control)
            self.gc_controls[chat_control] = control

    @log_calls('ClickableNicknamesPlugin')
    def disconnect_from_chat_control(self, chat_control):
        pass

Dicson's avatar
Dicson committed
62

Dicson's avatar
Dicson committed
63
class Base(object):
Dicson's avatar
Dicson committed
64

Dicson's avatar
Dicson committed
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
    def __init__(self, plugin, chat_control):
        self.plugin = plugin
        self.chat_control = chat_control
        self.textview = self.chat_control.conv_textview
        self.tags_id = []
        self.change_cursor = False
        self.connect_signals()

    def connect_signals(self):
        # connect signals with textbuffer tags
        self.tag_names = self.plugin.tag_names
        tag_table = self.textview.tv.get_buffer().get_tag_table()
        for name in self.tag_names:
            tag = tag_table.lookup(name)
            if tag:
                id_ = tag.connect('event', self.insert_nick, name)
                self.chat_control.handlers[id_] = tag
                self.tags_id.append((id_, tag))

        self.id_ = self.textview.tv.connect('motion_notify_event',
                self.on_textview_motion_notify_event)
        self.chat_control.handlers[self.id_] = self.textview.tv

    def on_textview_motion_notify_event(self, widget, event):
        # change cursor on the nicks
90 91 92 93
        pointer_x, pointer_y = self.textview.tv.get_window(
            Gtk.TextWindowType.TEXT).get_pointer()[1:3]
        x, y = self.textview.tv.window_to_buffer_coords(Gtk.TextWindowType.TEXT,
            pointer_x, pointer_y)
Dicson's avatar
Dicson committed
94 95 96
        tags = self.textview.tv.get_iter_at_location(x, y).get_tags()
        tag_table = self.textview.tv.get_buffer().get_tag_table()
        if self.change_cursor:
97 98
            self.textview.tv.get_window(Gtk.TextWindowType.TEXT).set_cursor(
                    Gdk.Cursor.new(Gdk.CursorType.XTERM))
Dicson's avatar
Dicson committed
99 100 101
            self.change_cursor = False
        for tag in tags:
            if tag in [x[1] for x in self.tags_id]:
102 103
                self.textview.tv.get_window(Gtk.TextWindowType.TEXT).set_cursor(
                    Gdk.Cursor.new(Gdk.CursorType.HAND2))
Dicson's avatar
Dicson committed
104 105 106 107 108
            self.change_cursor = True
        self.textview.on_textview_motion_notify_event(widget, event)

    def insert_nick(self, texttag, widget, event, iter_, kind):
        # insert nickname to message buffer
109
        if event.type == Gdk.EventType.BUTTON_PRESS and event.button.button == 1:
Dicson's avatar
Dicson committed
110 111 112 113 114 115 116 117 118 119
            # left mouse button clicked
            begin_iter = iter_.copy()
            # we get the begining of the tag
            while not begin_iter.begins_tag(texttag):
                begin_iter.backward_char()
            end_iter = iter_.copy()
            # we get the end of the tag
            while not end_iter.ends_tag(texttag):
                end_iter.forward_char()
            buffer_ = self.textview.tv.get_buffer()
120
            word = buffer_.get_text(begin_iter, end_iter, True)
Dicson's avatar
Dicson committed
121
            nick = word.rstrip().rstrip(gajim.config.get('after_nickname'))
122 123
            if nick.startswith('* '):
                nick = nick.lstrip('* ').split(' ')[0]
Dicson's avatar
Dicson committed
124
            nick = nick.lstrip(gajim.config.get('before_nickname'))
125 126 127 128
            nicks = gajim.contacts.get_nick_list(self.chat_control.account,
                self.chat_control.room_jid)
            if nick not in nicks:
                return
Dicson's avatar
Dicson committed
129 130 131 132 133 134 135 136 137 138 139 140
            nick = nick + gajim.config.get('gc_refer_to_nick_char') + ' '
            message_buffer = self.chat_control.msg_textview.get_buffer()
            message_buffer.insert_at_cursor(nick)
            self.chat_control.msg_textview.grab_focus()

    def disconnect_from_chat_control(self):
        # disconnect signals from textbuffer tags
        for item in self.tags_id:
            if item[1].handler_is_connected(item[0]):
                item[1].disconnect(item[0])
        if self.textview.tv.handler_is_connected(self.id_):
            self.textview.tv.disconnect(self.id_)