Esempio n. 1
0
    def __init__(self, color, bg_color, lang_rtl):
        self._lang_rtl = lang_rtl
        gtk.TextView.__init__(self)
        self.set_editable(False)
        self.set_cursor_visible(False)
        self.set_wrap_mode(gtk.WRAP_WORD_CHAR)
        self.get_buffer().set_text("", 0)
        self.iter_text = self.get_buffer().get_iter_at_offset(0)
        self.fg_tag = self.get_buffer().create_tag("foreground_color",
            foreground=color.get_html())
        self._subscript_tag = self.get_buffer().create_tag('subscript',
                    rise=-7 * pango.SCALE) # in pixels
        self._empty = True
        self.palette = None
        self._mouse_detector = MouseSpeedDetector(self, 200, 5)
        self._mouse_detector.connect('motion-slow', self.__mouse_slow_cb)
        self.modify_base(gtk.STATE_NORMAL, bg_color.get_gdk_color())

        self.add_events(gtk.gdk.POINTER_MOTION_MASK | \
                        gtk.gdk.BUTTON_PRESS_MASK | \
                        gtk.gdk.BUTTON_RELEASE_MASK | \
                        gtk.gdk.LEAVE_NOTIFY_MASK)

        self.connect('event-after', self.__event_after_cb)
        self.connect('button-press-event', self.__button_press_cb)
        self.motion_notify_id = self.connect('motion-notify-event', \
                self.__motion_notify_cb)
        self.connect('visibility-notify-event', self.__visibility_notify_cb)
        self.connect('leave-notify-event', self.__leave_notify_event_cb)
Esempio n. 2
0
    def __init__(self, color, bg_color, lang_rtl):
        self._lang_rtl = lang_rtl
        gtk.TextView.__init__(self)
        self.set_editable(False)
        self.set_cursor_visible(False)
        self.set_wrap_mode(gtk.WRAP_WORD_CHAR)
        self.get_buffer().set_text("", 0)
        self.iter_text = self.get_buffer().get_iter_at_offset(0)
        self.fg_tag = self.get_buffer().create_tag("foreground_color",
            foreground=color.get_html())
        self._subscript_tag = self.get_buffer().create_tag('subscript',
                    rise=-7 * pango.SCALE) # in pixels
        self._empty = True
        self.palette = None
        self._mouse_detector = MouseSpeedDetector(self, 200, 5)
        self._mouse_detector.connect('motion-slow', self.__mouse_slow_cb)
        self.modify_base(gtk.STATE_NORMAL, bg_color.get_gdk_color())

        self.add_events(gtk.gdk.POINTER_MOTION_MASK | \
                        gtk.gdk.BUTTON_PRESS_MASK | \
                        gtk.gdk.BUTTON_RELEASE_MASK | \
                        gtk.gdk.LEAVE_NOTIFY_MASK)

        self.connect('event-after', self.__event_after_cb)
        self.connect('button-press-event', self.__button_press_cb)
        self.motion_notify_id = self.connect('motion-notify-event', \
                self.__motion_notify_cb)
        self.connect('visibility-notify-event', self.__visibility_notify_cb)
        self.connect('leave-notify-event', self.__leave_notify_event_cb)
Esempio n. 3
0
class TextBox(gtk.TextView):

    hand_cursor = gtk.gdk.Cursor(gtk.gdk.HAND2)

    def __init__(self, color, bg_color, lang_rtl):
        self._lang_rtl = lang_rtl
        gtk.TextView.__init__(self)
        self.set_editable(False)
        self.set_cursor_visible(False)
        self.set_wrap_mode(gtk.WRAP_WORD_CHAR)
        self.get_buffer().set_text("", 0)
        self.iter_text = self.get_buffer().get_iter_at_offset(0)
        self.fg_tag = self.get_buffer().create_tag("foreground_color",
            foreground=color.get_html())
        self._subscript_tag = self.get_buffer().create_tag('subscript',
                    rise=-7 * pango.SCALE) # in pixels
        self._empty = True
        self.palette = None
        self._mouse_detector = MouseSpeedDetector(self, 200, 5)
        self._mouse_detector.connect('motion-slow', self.__mouse_slow_cb)
        self.modify_base(gtk.STATE_NORMAL, bg_color.get_gdk_color())

        self.add_events(gtk.gdk.POINTER_MOTION_MASK | \
                        gtk.gdk.BUTTON_PRESS_MASK | \
                        gtk.gdk.BUTTON_RELEASE_MASK | \
                        gtk.gdk.LEAVE_NOTIFY_MASK)

        self.connect('event-after', self.__event_after_cb)
        self.connect('button-press-event', self.__button_press_cb)
        self.motion_notify_id = self.connect('motion-notify-event', \
                self.__motion_notify_cb)
        self.connect('visibility-notify-event', self.__visibility_notify_cb)
        self.connect('leave-notify-event', self.__leave_notify_event_cb)

    def __leave_notify_event_cb(self, widget, event):
        self._mouse_detector.stop()

    def __button_press_cb(self, widget, event):
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
            # To disable the standard textview popup
            return True

    # Links can be activated by clicking.
    def __event_after_cb(self, widget, event):
        if event.type != gtk.gdk.BUTTON_RELEASE:
            return False

        x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET,
            int(event.x), int(event.y))
        iter_tags = self.get_iter_at_location(x, y)

        for tag in iter_tags.get_tags():
            url = tag.get_data('url')
            if url is not None:
                if event.button == 3:
                    palette = tag.get_data('palette')
                    xw, yw = self.get_toplevel().get_pointer()
                    palette.move(int(xw), int(yw))
                    palette.popup()
                else:
                    self._show_via_journal(url)
                break

        return False

    def _show_via_journal(self, url):
        """Ask the journal to display a URL"""
        logging.debug('Create journal entry for URL: %s', url)
        jobject = datastore.create()
        metadata = {
            'title': "%s: %s" % (_('URL from Chat'), url),
            'title_set_by_user': '******',
            'icon-color': profile.get_color().to_string(),
            'mime_type': 'text/uri-list',
            }
        for k, v in metadata.items():
            jobject.metadata[k] = v
        file_path = join(get_activity_root(), 'instance', '%i_' % time.time())
        open(file_path, 'w').write(url + '\r\n')
        os.chmod(file_path, 0755)
        jobject.set_file_path(file_path)
        datastore.write(jobject)
        show_object_in_journal(jobject.object_id)
        jobject.destroy()
        os.unlink(file_path)

    def check_url_hovering(self, x, y):
        # Looks at all tags covering the position (x, y) in the text view,
        # and if one of them is a link return True

        hovering = False
        # When check on_slow_mouse event, the position can be out
        # of the widget and return negative values.
        if x < 0 or y < 0:
            return hovering

        self.palette = None
        iter_tags = self.get_iter_at_location(x, y)

        tags = iter_tags.get_tags()
        for tag in tags:
            url = tag.get_data('url')
            self.palette = tag.get_data('palette')
            if url is not None:
                hovering = True
                break
        return hovering

    def set_cursor_if_appropriate(self, x, y):
        # Looks at all tags covering the position (x, y) in the text view,
        # and if one of them is a link, change the cursor to the "hands" cursor

        hovering_over_link = self.check_url_hovering(x, y)
        win = self.get_window(gtk.TEXT_WINDOW_TEXT)
        if hovering_over_link:
            win.set_cursor(self.hand_cursor)
            self._mouse_detector.start()
        else:
            win.set_cursor(None)
            self._mouse_detector.stop()

    def __mouse_slow_cb(self, widget):
        x, y = self.get_pointer()
        hovering_over_link = self.check_url_hovering(x, y)
        if hovering_over_link:
            if self.palette is not None:
                xw, yw = self.get_toplevel().get_pointer()
                self.palette.move(xw, yw)
                self.palette.popup()
                self._mouse_detector.stop()
        else:
            if self.palette is not None:
                self.palette.popdown()

    # Update the cursor image if the pointer moved.
    def __motion_notify_cb(self, widget, event):
        x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET,
            int(event.x), int(event.y))
        self.set_cursor_if_appropriate(x, y)
        self.window.get_pointer()
        return False

    def __visibility_notify_cb(self, widget, event):
        # Also update the cursor image if the window becomes visible
        # (e.g. when a window covering it got iconified).

        wx, wy, __ = self.window.get_pointer()
        bx, by = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, wx, wy)
        self.set_cursor_if_appropriate(bx, by)
        return False

    def __palette_mouse_enter_cb(self, widget, event):
        self.handler_block(self.motion_notify_id)

    def __palette_mouse_leave_cb(self, widget, event):
        self.handler_unblock(self.motion_notify_id)

    def add_text(self, text):
        buf = self.get_buffer()

        if not self._empty:
            buf.insert(self.iter_text, '\n')

        words = text.split()
        for word in words:
            if _URL_REGEXP.search(word) is not None:
                tag = buf.create_tag(None,
                    foreground="blue", underline=pango.UNDERLINE_SINGLE)
                tag.set_data("url", word)
                palette = _URLMenu(word)
                palette.connect('enter-notify-event',
                        self.__palette_mouse_enter_cb)
                palette.connect('leave-notify-event',
                        self.__palette_mouse_leave_cb)
                tag.set_data('palette', palette)
                buf.insert_with_tags(self.iter_text, word, tag,
                        self.fg_tag)
            else:
                for i in smilies.parse(word):
                    if isinstance(i, gtk.gdk.Pixbuf):
                        start = self.iter_text.get_offset()
                        buf.insert_pixbuf(self.iter_text, i)
                        buf.apply_tag(self._subscript_tag,
                                buf.get_iter_at_offset(start), self.iter_text)
                    else:
                        buf.insert_with_tags(self.iter_text, i, self.fg_tag)
            buf.insert_with_tags(self.iter_text, ' ',
                    self.fg_tag)

        self._empty = False
Esempio n. 4
0
class TextBox(gtk.TextView):

    hand_cursor = gtk.gdk.Cursor(gtk.gdk.HAND2)

    def __init__(self, color, bg_color, lang_rtl):
        self._lang_rtl = lang_rtl
        gtk.TextView.__init__(self)
        self.set_editable(False)
        self.set_cursor_visible(False)
        self.set_wrap_mode(gtk.WRAP_WORD_CHAR)
        self.get_buffer().set_text("", 0)
        self.iter_text = self.get_buffer().get_iter_at_offset(0)
        self.fg_tag = self.get_buffer().create_tag("foreground_color",
            foreground=color.get_html())
        self._subscript_tag = self.get_buffer().create_tag('subscript',
                    rise=-7 * pango.SCALE) # in pixels
        self._empty = True
        self.palette = None
        self._mouse_detector = MouseSpeedDetector(self, 200, 5)
        self._mouse_detector.connect('motion-slow', self.__mouse_slow_cb)
        self.modify_base(gtk.STATE_NORMAL, bg_color.get_gdk_color())

        self.add_events(gtk.gdk.POINTER_MOTION_MASK | \
                        gtk.gdk.BUTTON_PRESS_MASK | \
                        gtk.gdk.BUTTON_RELEASE_MASK | \
                        gtk.gdk.LEAVE_NOTIFY_MASK)

        self.connect('event-after', self.__event_after_cb)
        self.connect('button-press-event', self.__button_press_cb)
        self.motion_notify_id = self.connect('motion-notify-event', \
                self.__motion_notify_cb)
        self.connect('visibility-notify-event', self.__visibility_notify_cb)
        self.connect('leave-notify-event', self.__leave_notify_event_cb)

    def __leave_notify_event_cb(self, widget, event):
        self._mouse_detector.stop()

    def __button_press_cb(self, widget, event):
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
            # To disable the standard textview popup
            return True

    # Links can be activated by clicking.
    def __event_after_cb(self, widget, event):
        if event.type != gtk.gdk.BUTTON_RELEASE:
            return False

        x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET,
            int(event.x), int(event.y))
        iter_tags = self.get_iter_at_location(x, y)

        for tag in iter_tags.get_tags():
            url = tag.get_data('url')
            if url is not None:
                if event.button == 3:
                    palette = tag.get_data('palette')
                    xw, yw = self.get_toplevel().get_pointer()
                    palette.move(int(xw), int(yw))
                    palette.popup()
                else:
                    self._show_via_journal(url)
                break

        return False

    def _show_via_journal(self, url):
        """Ask the journal to display a URL"""
        logging.debug('Create journal entry for URL: %s', url)
        jobject = datastore.create()
        metadata = {
            'title': "%s: %s" % (_('URL from Chat'), url),
            'title_set_by_user': '******',
            'icon-color': profile.get_color().to_string(),
            'mime_type': 'text/uri-list',
            }
        for k, v in metadata.items():
            jobject.metadata[k] = v
        file_path = join(get_activity_root(), 'instance', '%i_' % time.time())
        open(file_path, 'w').write(url + '\r\n')
        os.chmod(file_path, 0755)
        jobject.set_file_path(file_path)
        datastore.write(jobject)
        show_object_in_journal(jobject.object_id)
        jobject.destroy()
        os.unlink(file_path)

    def check_url_hovering(self, x, y):
        # Looks at all tags covering the position (x, y) in the text view,
        # and if one of them is a link return True

        hovering = False
        # When check on_slow_mouse event, the position can be out
        # of the widget and return negative values.
        if x < 0 or y < 0:
            return hovering

        self.palette = None
        iter_tags = self.get_iter_at_location(x, y)

        tags = iter_tags.get_tags()
        for tag in tags:
            url = tag.get_data('url')
            self.palette = tag.get_data('palette')
            if url is not None:
                hovering = True
                break
        return hovering

    def set_cursor_if_appropriate(self, x, y):
        # Looks at all tags covering the position (x, y) in the text view,
        # and if one of them is a link, change the cursor to the "hands" cursor

        hovering_over_link = self.check_url_hovering(x, y)
        win = self.get_window(gtk.TEXT_WINDOW_TEXT)
        if hovering_over_link:
            win.set_cursor(self.hand_cursor)
            self._mouse_detector.start()
        else:
            win.set_cursor(None)
            self._mouse_detector.stop()

    def __mouse_slow_cb(self, widget):
        x, y = self.get_pointer()
        hovering_over_link = self.check_url_hovering(x, y)
        if hovering_over_link:
            if self.palette is not None:
                xw, yw = self.get_toplevel().get_pointer()
                self.palette.move(xw, yw)
                self.palette.popup()
                self._mouse_detector.stop()
        else:
            if self.palette is not None:
                self.palette.popdown()

    # Update the cursor image if the pointer moved.
    def __motion_notify_cb(self, widget, event):
        x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET,
            int(event.x), int(event.y))
        self.set_cursor_if_appropriate(x, y)
        self.window.get_pointer()
        return False

    def __visibility_notify_cb(self, widget, event):
        # Also update the cursor image if the window becomes visible
        # (e.g. when a window covering it got iconified).

        wx, wy, __ = self.window.get_pointer()
        bx, by = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, wx, wy)
        self.set_cursor_if_appropriate(bx, by)
        return False

    def __palette_mouse_enter_cb(self, widget, event):
        self.handler_block(self.motion_notify_id)

    def __palette_mouse_leave_cb(self, widget, event):
        self.handler_unblock(self.motion_notify_id)

    def add_text(self, text):
        buf = self.get_buffer()

        if not self._empty:
            buf.insert(self.iter_text, '\n')

        words = text.split()
        for word in words:
            if _URL_REGEXP.match(word) is not None:
                tag = buf.create_tag(None,
                    foreground="blue", underline=pango.UNDERLINE_SINGLE)
                tag.set_data("url", word)
                palette = _URLMenu(word)
                palette.connect('enter-notify-event',
                        self.__palette_mouse_enter_cb)
                palette.connect('leave-notify-event',
                        self.__palette_mouse_leave_cb)
                tag.set_data('palette', palette)
                buf.insert_with_tags(self.iter_text, word, tag,
                        self.fg_tag)
            else:
                for i in smilies.parse(word):
                    if isinstance(i, gtk.gdk.Pixbuf):
                        start = self.iter_text.get_offset()
                        buf.insert_pixbuf(self.iter_text, i)
                        buf.apply_tag(self._subscript_tag,
                                buf.get_iter_at_offset(start), self.iter_text)
                    else:
                        buf.insert_with_tags(self.iter_text, i, self.fg_tag)
            buf.insert_with_tags(self.iter_text, ' ',
                    self.fg_tag)

        self._empty = False