Skip to content
Snippets Groups Projects
image.py 5.77 KiB
Newer Older
Dicson's avatar
Dicson committed
# -*- coding: utf-8 -*-
##
import gtk
import os
import base64
import urllib2

import chat_control
Dicson's avatar
Dicson committed
from plugins import GajimPlugin
from plugins.helpers import log_calls
from dialogs import ImageChooserDialog, ErrorDialog

Dicson's avatar
Dicson committed
NS_XHTML_IM = 'http://jabber.org/protocol/xhtml-im'             # XEP-0071

Dicson's avatar
Dicson committed

class ImagePlugin(GajimPlugin):
    @log_calls('ImagePlugin')
    def init(self):
        self.config_dialog = None  # ImagePluginConfigDialog(self)
        self.controls = []
        self.gui_extension_points = {
            'chat_control_base': (self.connect_with_chat_control,
                self.disconnect_from_chat_control),
            'chat_control_base_update_toolbar': (self.update_button_state,
                None)}
        self.first_run = True
Dicson's avatar
Dicson committed

    @log_calls('ImagePlugin')
    def connect_with_chat_control(self, control):
        if not isinstance(control, chat_control.ChatControl):
            return
        self.chat_control = control
        base = Base(self, self.chat_control)
        self.controls.append(base)
        if self.first_run:
            # ALT + L
            gtk.binding_entry_add_signal(control.msg_textview,
                gtk.keysyms.l, gtk.gdk.MOD1_MASK, 'mykeypress',
                int, gtk.keysyms.l, gtk.gdk.ModifierType, gtk.gdk.MOD1_MASK)
            self.first_run = False
Dicson's avatar
Dicson committed

    @log_calls('ImagePlugin')
    def disconnect_from_chat_control(self, chat_control):
        for control in self.controls:
            control.disconnect_from_chat_control()
        self.controls = []

    @log_calls('ImagePlugin')
    def update_button_state(self, chat_control):
        for base in self.controls:
            if base.chat_control == chat_control:
                is_support_xhtml = chat_control.contact.supports(NS_XHTML_IM)
                base.button.set_sensitive(is_support_xhtml and not \
                    chat_control.gpg_is_active)
                if not is_support_xhtml:
                    text = _('This contact does not support XHTML_IM')
                else:
                    text = _('Send image')
                base.button.set_tooltip_text(text)


class Base(object):
    def __init__(self, plugin, chat_control):
        self.id_ = chat_control.msg_textview.connect('mykeypress',
            self.on_key_press)
Dicson's avatar
Dicson committed
        self.plugin = plugin
        self.chat_control = chat_control
        actions_hbox = chat_control.xml.get_object('actions_hbox')
        self.button = gtk.Button(label=None, stock=None, use_underline=True)
        self.button.set_property('relief', gtk.RELIEF_NONE)
        self.button.set_property('can-focus', False)
        img = gtk.Image()
Dicson's avatar
Dicson committed
        img.set_from_stock('gtk-orientation-portrait', gtk.ICON_SIZE_MENU)
Dicson's avatar
Dicson committed
        self.button.set_image(img)
        self.button.set_tooltip_text('Send image')
Dicson's avatar
Dicson committed
        send_button = chat_control.xml.get_object('send_button')
        send_button_pos = actions_hbox.child_get_property(send_button,
            'position')
        actions_hbox.add_with_properties(self.button, 'position',
            send_button_pos - 1, 'expand', False)
        id_ = self.button.connect('clicked', self.on_image_button_clicked)
        chat_control.handlers[id_] = self.button
        chat_control.handlers[self.id_] = chat_control.msg_textview
Dicson's avatar
Dicson committed
        self.button.show()

    def on_key_press(self, widget, event_keyval, event_keymod):
        # construct event instance from binding
        event = gtk.gdk.Event(gtk.gdk.KEY_PRESS)  # it's always a key-press here
        event.keyval = event_keyval
        event.state = event_keymod
        event.time = 0  # assign current time

        if event.keyval != gtk.keysyms.l:
            return
        if event.state != gtk.gdk.MOD1_MASK:  # ALT+l
            return
        if not self.chat_control.contact.supports(NS_XHTML_IM):
            from dialogs import WarningDialog
            WarningDialog('Warning', _('This contact does not support XHTML_IM'),
                self.chat_control.parent_win.window)
            return
        self.on_image_button_clicked(widget)

Dicson's avatar
Dicson committed
    def on_image_button_clicked(self, widget):
        def on_ok(widget, path_to_file):
            filesize = os.path.getsize(path_to_file)  # in bytes
            invalid_file = False
            msg = ''
            if os.path.isfile(path_to_file):
                stat = os.stat(path_to_file)
                if stat[6] == 0:
                    invalid_file = True
                    msg = _('File is empty')
            else:
                invalid_file = True
                msg = _('File does not exist')
            if filesize < 60000:
                img = urllib2.quote(base64.standard_b64encode(open(
                    path_to_file, "rb").read()), '')
                if len(img) > 60000:
                    invalid_file = True
                    msg = _('File too big')
            else:
                invalid_file = True
                msg = _('File too big')
            if invalid_file:
                ErrorDialog(_('Could not load image'), msg)
                return

            dlg.destroy()
            msg = 'HTML image'
            extension = os.path.splitext(os.path.split(path_to_file)[1])[1] \
                .lower()[1:]
Evgeniy Popov's avatar
Evgeniy Popov committed
            xhtml = '<body><br/> <img alt="img" src="data:image/%s;base64,%s"/> \
                    </body>' % (extension, img)
Dicson's avatar
Dicson committed
            self.chat_control.send_message(message=msg, xhtml=xhtml)
            self.chat_control.msg_textview.grab_focus()

        dlg = ImageChooserDialog(on_response_ok=on_ok, on_response_cancel=None)

    def disconnect_from_chat_control(self):
        actions_hbox = self.chat_control.xml.get_object('actions_hbox')
        actions_hbox.remove(self.button)
        if self.chat_control.handlers[self.id_].handler_is_connected(self.id_):
            self.chat_control.handlers[self.id_].disconnect(self.id_)
            del self.chat_control.handlers[self.id_]