diff --git a/src/chat_control.py b/src/chat_control.py index 8f069b3e0..2fe95cf79 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -664,11 +664,11 @@ class ChatControl(ChatControlBase): """ Just moved the mouse so show the cursor """ - cursor = Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR) + cursor = gtkgui_helpers.get_cursor('LEFT_PTR') self.parent_win.window.get_window().set_cursor(cursor) def on_location_eventbox_enter_notify_event(self, widget, event): - cursor = Gdk.Cursor.new(Gdk.CursorType.HAND2) + cursor = gtkgui_helpers.get_cursor('HAND2') self.parent_win.window.get_window().set_cursor(cursor) def _on_window_motion_notify(self, widget, event): diff --git a/src/conversation_textview.py b/src/conversation_textview.py index 753d3c2d1..0429743c0 100644 --- a/src/conversation_textview.py +++ b/src/conversation_textview.py @@ -193,9 +193,10 @@ class ConversationTextview(GObject.GObject): # no need to inherit TextView, use it as atrribute is safer self.tv = HtmlTextView() + # we have to override HtmlTextView Event handlers + # because we dont inherit self.tv.hyperlink_handler = self.hyperlink_handler - - self.tv.set_has_tooltip(True) + self.tv.connect_tooltip(self.query_tooltip) # set properties self.tv.set_border_width(1) @@ -219,23 +220,16 @@ class ConversationTextview(GObject.GObject): self.auto_scrolling = False # connect signals - id_ = self.tv.connect('motion_notify_event', - self.on_textview_motion_notify_event) - self.handlers[id_] = self.tv id_ = self.tv.connect('populate_popup', self.on_textview_populate_popup) self.handlers[id_] = self.tv id_ = self.tv.connect('button_press_event', self.on_textview_button_press_event) self.handlers[id_] = self.tv - id_ = self.tv.connect('draw', self.on_textview_draw) self.handlers[id_] = self.tv - id_ = self.tv.connect('query-tooltip', self.query_tooltip) - self.handlers[id_] = self.tv - self.account = account - self.change_cursor = False + self.cursor_changed = False self.last_time_printout = 0 style = self.tv.get_style_context() @@ -331,12 +325,11 @@ class ConversationTextview(GObject.GObject): # holds a mark at the end of --- line self.focus_out_end_mark = None - self.xep0184_warning_tooltip = tooltips.BaseTooltip() - self.smooth_id = None self.just_cleared = False def query_tooltip(self, widget, x_pos, y_pos, keyboard_mode, tooltip): + window = widget.get_window(Gtk.TextWindowType.TEXT) x_pos, y_pos = self.tv.window_to_buffer_coords( Gtk.TextWindowType.TEXT, x_pos, y_pos) if Gtk.MINOR_VERSION > 18: @@ -351,13 +344,37 @@ class ConversationTextview(GObject.GObject): 'been said since the\nlast time you paid attention to this ' 'group chat')) return True - + if tag_name == 'xep0184-warning': + tooltip.set_text(_( + 'This icon indicates that this message has not ' + 'yet\nbeen received by the remote ' + "end. If this icon stays\nfor a long time, it's likely the " + 'message got lost.')) + window.set_cursor(gtkgui_helpers.get_cursor('LEFT_PTR')) + self.cursor_changed = True + return True + if getattr(tag, 'is_anchor', False): + text = getattr(tag, 'title', False) + if text: + if len(text) > 50: + text = text[:47] + '…' + tooltip.set_text(text) + window.set_cursor(gtkgui_helpers.get_cursor('HAND2')) + self.cursor_changed = True + return True + if tag_name in ('url', 'mail', 'xmpp', 'sth_at_sth'): + window.set_cursor(gtkgui_helpers.get_cursor('HAND2')) + self.cursor_changed = True + return False try: text = self.corrected_text_list[tag_name] tooltip.set_markup(text) return True except KeyError: pass + if self.cursor_changed: + window.set_cursor(gtkgui_helpers.get_cursor('XTERM')) + self.cursor_changed = False return False def del_handlers(self): @@ -634,31 +651,6 @@ class ConversationTextview(GObject.GObject): # appeared) GLib.idle_add(self.scroll_to_end) - def show_xep0184_warning_tooltip(self): - self.xep0184_warning_tooltip.timeout = 0 - w = self.tv.get_window(Gtk.TextWindowType.TEXT) - device = w.get_display().get_device_manager().get_client_pointer() - pointer = w.get_device_position(device) - x = pointer[1] - y = pointer[2] - iter_ = self.tv.get_iter_at_location(x, y) - if isinstance(iter_, tuple): - iter_ = iter_[1] - tags = iter_.get_tags() - tag_table = self.tv.get_buffer().get_tag_table() - xep0184_warning = False - for tag in tags: - if tag == tag_table.lookup('xep0184-warning'): - xep0184_warning = True - break - if xep0184_warning and not self.xep0184_warning_tooltip.win: - # check if the current pointer is still over the line - position = w.get_origin()[1:] - self.xep0184_warning_tooltip.show_tooltip(_('This icon indicates ' - 'that this message has not yet\nbeen received by the remote ' - "end. If this icon stays\nfor a long time, it's likely the " - 'message got lost.'), 8, position[1] + y) - def on_textview_draw(self, widget, ctx): return #TODO @@ -687,45 +679,6 @@ class ConversationTextview(GObject.GObject): return True return False - def on_textview_motion_notify_event(self, widget, event): - """ - Change the cursor to a hand when we are over a mail or an url - """ - w = self.tv.get_window(Gtk.TextWindowType.TEXT) - device = w.get_display().get_device_manager().get_client_pointer() - pointer = w.get_device_position(device) - x, y = self.tv.window_to_buffer_coords(Gtk.TextWindowType.TEXT, - pointer[1], pointer[2]) - iter_ = self.tv.get_iter_at_location(x, y) - if isinstance(iter_, tuple): - iter_ = iter_[1] - tags = iter_.get_tags() - if self.change_cursor: - w.set_cursor(Gdk.Cursor.new(Gdk.CursorType.XTERM)) - self.change_cursor = False - tag_table = self.tv.get_buffer().get_tag_table() - xep0184_warning = False - - for tag in tags: - if tag in (tag_table.lookup('url'), tag_table.lookup('mail'), \ - tag_table.lookup('xmpp'), tag_table.lookup('sth_at_sth')): - w.set_cursor(Gdk.Cursor.new(Gdk.CursorType.HAND2)) - self.change_cursor = True - elif tag == tag_table.lookup('xep0184-warning'): - xep0184_warning = True - - if self.xep0184_warning_tooltip.timeout != 0 or \ - self.xep0184_warning_tooltip.shown: - # Check if we should hide the XEP-184 warning tooltip - if not xep0184_warning: - self.xep0184_warning_tooltip.hide_tooltip() - - if xep0184_warning and not self.xep0184_warning_tooltip.win: - self.xep0184_warning_tooltip.timeout = GLib.timeout_add(500, - self.show_xep0184_warning_tooltip) - w.set_cursor(Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR)) - self.change_cursor = True - def clear(self, tv = None): """ Clear text in the textview diff --git a/src/dialogs.py b/src/dialogs.py index 6de9ce78b..d31fcffc5 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -5723,5 +5723,5 @@ class BigAvatarWindow(Gtk.Window): """ Just moved the mouse so show the cursor """ - cursor = Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR) + cursor = gtkgui_helpers.get_cursor('LEFT_PTR') self.get_window().set_cursor(cursor) diff --git a/src/gtkgui_helpers.py b/src/gtkgui_helpers.py index ef84ae04b..1c313761a 100644 --- a/src/gtkgui_helpers.py +++ b/src/gtkgui_helpers.py @@ -494,6 +494,11 @@ def get_invisible_cursor(): cursor_pixbuf, 0, 0) return cursor +def get_cursor(attr): + display = Gdk.Display.get_default() + cursor = getattr(Gdk.CursorType, attr) + return Gdk.Cursor.new_for_display(display, cursor) + def get_current_desktop(window): """ Return the current virtual desktop for given window diff --git a/src/htmltextview.py b/src/htmltextview.py index 4fe90c6a6..1a8d9509e 100644 --- a/src/htmltextview.py +++ b/src/htmltextview.py @@ -52,6 +52,7 @@ if __name__ == '__main__': import common.configpaths common.configpaths.gajimpaths.init(None) from common import gajim +import gtkgui_helpers from gtkgui_helpers import get_icon_pixmap from common import helpers from common.exceptions import GajimGeneralException @@ -841,21 +842,20 @@ class HtmlTextView(Gtk.TextView): self.set_wrap_mode(Gtk.WrapMode.CHAR) self.set_editable(False) self._changed_cursor = False - self.connect('destroy', self.__destroy_event) - self.connect('motion-notify-event', self.__motion_notify_event) - self.connect('leave-notify-event', self.__leave_event) - self.connect('enter-notify-event', self.__motion_notify_event) + self.set_has_tooltip(True) self.connect('realize', self.on_html_text_view_realized) self.connect('unrealize', self.on_html_text_view_unrealized) self.connect('copy-clipboard', self.on_html_text_view_copy_clipboard) self.id_ = self.connect('button-release-event', self.on_left_mouse_button_release) self.get_buffer().eol_tag = self.get_buffer().create_tag('eol') - self.tooltip = tooltips.BaseTooltip() self.config = gajim.config self.interface = gajim.interface # end big hack + def connect_tooltip(self, func=None): + self.connect('query-tooltip', func or self.__query_tooltip) + def create_tags(self): buffer_ = self.get_buffer() @@ -880,65 +880,27 @@ class HtmlTextView(Gtk.TextView): self.tagSthAtSth.set_property('underline', Pango.Underline.SINGLE) self.tagSthAtSth.connect('event', self.hyperlink_handler, 'sth_at_sth') - def __destroy_event(self, widget): - if self.tooltip.timeout != 0 or self.tooltip.shown: - self.tooltip.hide_tooltip() - - def __leave_event(self, widget, event): + def __query_tooltip(self, widget, x_pos, y_pos, keyboard_mode, tooltip): + window = widget.get_window(Gtk.TextWindowType.TEXT) + x_pos, y_pos = self.window_to_buffer_coords( + Gtk.TextWindowType.TEXT, x_pos, y_pos) + if Gtk.MINOR_VERSION > 18: + iter_ = self.get_iter_at_position(x_pos, y_pos)[1] + else: + iter_ = self.get_iter_at_position(x_pos, y_pos)[0] + for tag in iter_.get_tags(): + if getattr(tag, 'is_anchor', False): + text = getattr(tag, 'title', False) + if text: + if len(text) > 50: + text = text[:47] + '…' + tooltip.set_text(text) + if not self._changed_cursor: + window.set_cursor(gtkgui_helpers.get_cursor('HAND2')) + self._changed_cursor = True + return True if self._changed_cursor: - window = widget.get_window(Gtk.TextWindowType.TEXT) - window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.XTERM)) - self._changed_cursor = False - - def show_tooltip(self, tag): - self.tooltip.timeout = 0 - if not self.tooltip.win: - # check if the current pointer is still over the line - w = self.get_window(Gtk.TextWindowType.TEXT) - device = w.get_display().get_device_manager().get_client_pointer() - pointer = w.get_device_position(device) - x = pointer[1] - y = pointer[2] - iter_ = self.get_iter_at_location(x, y) - if isinstance(iter_, tuple): - iter_ = iter_[1] - tags = iter_.get_tags() - is_over_anchor = False - for tag_ in tags: - if getattr(tag_, 'is_anchor', False): - is_over_anchor = True - break - if not is_over_anchor: - return - text = getattr(tag, 'title', False) - if text: - if len(text) > 50: - text = text[:47] + '…' - position = w.get_origin()[1:] - self.tooltip.show_tooltip(text, 8, position[1] + y) - - def __motion_notify_event(self, widget, event): - w = widget.get_window(Gtk.TextWindowType.TEXT) - device = w.get_display().get_device_manager().get_client_pointer() - pointer = w.get_device_position(device) - x = pointer[1] - y = pointer[2] - iter_ = widget.get_iter_at_location(x, y) - if isinstance(iter_, tuple): - iter_ = iter_[1] - tags = iter_.get_tags() - anchor_tags = [tag for tag in tags if getattr(tag, 'is_anchor', False)] - if self.tooltip.timeout != 0 or self.tooltip.shown: - # Check if we should hide the line tooltip - if not anchor_tags: - self.tooltip.hide_tooltip() - if not self._changed_cursor and anchor_tags: - w.set_cursor(Gdk.Cursor.new(Gdk.CursorType.HAND2)) - self._changed_cursor = True - self.tooltip.timeout = GLib.timeout_add(500, self.show_tooltip, - anchor_tags[0]) - elif self._changed_cursor and not anchor_tags: - w.set_cursor(Gdk.Cursor.new(Gdk.CursorType.XTERM)) + window.set_cursor(gtkgui_helpers.get_cursor('XTERM')) self._changed_cursor = False return False @@ -1157,13 +1119,13 @@ if __name__ == '__main__': y = pointer[2] tags = htmlview.tv.get_iter_at_location(x, y).get_tags() if change_cursor: - w.set_cursor(Gdk.Cursor.new(Gdk.CursorType.XTERM)) + w.set_cursor(gtkgui_helpers.get_cursor('XTERM')) change_cursor = None tag_table = htmlview.tv.get_buffer().get_tag_table() for tag in tags: try: if tag.is_anchor: - w.set_cursor(Gdk.Cursor.new(Gdk.CursorType.HAND2)) + w.set_cursor(gtkgui_helpers.get_cursor('HAND2')) change_cursor = tag elif tag == tag_table.lookup('focus-out-line'): over_line = True @@ -1178,7 +1140,7 @@ if __name__ == '__main__': # line_tooltip.timeout = GLib.timeout_add(500, # show_line_tooltip) # htmlview.tv.get_window(Gtk.TextWindowType.TEXT).set_cursor( - # Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR)) + # gtkgui_helpers.get_cursor('LEFT_PTR')) # change_cursor = tag htmlview.tv.connect('motion_notify_event', on_textview_motion_notify_event) diff --git a/src/plugins/gui.py b/src/plugins/gui.py index 33352b5ff..4837d9e50 100644 --- a/src/plugins/gui.py +++ b/src/plugins/gui.py @@ -70,6 +70,7 @@ class PluginsWindow(object): setattr(self, widget_name, self.xml.get_object(widget_name)) self.plugin_description_textview = HtmlTextView() + self.plugin_description_textview.connect_tooltip() self.plugin_description_textview.set_wrap_mode(Gtk.WrapMode.WORD) sw = self.xml.get_object('scrolledwindow2') sw.add(self.plugin_description_textview)