From 83506314802184f07cc1709fef1d27ad5a7f8e78 Mon Sep 17 00:00:00 2001
From: Denis Fomin <fominde@gmail.com>
Date: Mon, 26 Sep 2011 22:38:52 +0300
Subject: [PATCH] add new url image preview plugin

---
 url_image_preview/__init__.py          |   1 +
 url_image_preview/config_dialog.ui     |  56 +++++++++
 url_image_preview/manifest.ini         |   9 ++
 url_image_preview/url_image_preview.py | 162 +++++++++++++++++++++++++
 4 files changed, 228 insertions(+)
 create mode 100644 url_image_preview/__init__.py
 create mode 100644 url_image_preview/config_dialog.ui
 create mode 100644 url_image_preview/manifest.ini
 create mode 100644 url_image_preview/url_image_preview.py

diff --git a/url_image_preview/__init__.py b/url_image_preview/__init__.py
new file mode 100644
index 00000000..e1e7c710
--- /dev/null
+++ b/url_image_preview/__init__.py
@@ -0,0 +1 @@
+from url_image_preview import UrlImagePreviewPlugin
diff --git a/url_image_preview/config_dialog.ui b/url_image_preview/config_dialog.ui
new file mode 100644
index 00000000..438dd933
--- /dev/null
+++ b/url_image_preview/config_dialog.ui
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy toplevel-contextual -->
+  <object class="GtkWindow" id="window1">
+    <child>
+      <object class="GtkVBox" id="vbox1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkHBox" id="hbox2">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkLabel" id="preview_size_lebel">
+                <property name="width_request">133</property>
+                <property name="visible">True</property>
+                <property name="xalign">0.029999999329447746</property>
+                <property name="label" translatable="yes">Preview size</property>
+                <property name="ellipsize">start</property>
+                <property name="single_line_mode">True</property>
+                <property name="track_visited_links">False</property>
+              </object>
+              <packing>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinButton" id="preview_size">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="has_tooltip">True</property>
+                <property name="tooltip_text" translatable="yes">Preview size(10-512)</property>
+                <property name="invisible_char">&#x25CF;</property>
+                <property name="width_chars">6</property>
+                <property name="snap_to_ticks">True</property>
+                <property name="numeric">True</property>
+                <signal name="value_changed" handler="preview_size_value_changed"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/url_image_preview/manifest.ini b/url_image_preview/manifest.ini
new file mode 100644
index 00000000..772e0166
--- /dev/null
+++ b/url_image_preview/manifest.ini
@@ -0,0 +1,9 @@
+[info]
+name: Url image preview
+short_name: url_image_preview
+version: 0.1
+description: Url image preview in chatbox.
+ Based on patch in ticket #5300:
+ http://trac.gajim.org/attachment/ticket/5300.
+authors = Denis Fomin <fominde@gmail.com>
+homepage = http://trac-plugins.gajim.org/wiki/
diff --git a/url_image_preview/url_image_preview.py b/url_image_preview/url_image_preview.py
new file mode 100644
index 00000000..cf315835
--- /dev/null
+++ b/url_image_preview/url_image_preview.py
@@ -0,0 +1,162 @@
+# -*- coding: utf-8 -*-
+
+import gtk
+import re
+import os
+
+import urllib
+import gobject
+
+from common import gajim
+from plugins import GajimPlugin
+from plugins.helpers import log_calls
+from plugins.gui import GajimPluginConfigDialog
+from conversation_textview import TextViewImage
+
+EXTENSIONS = ('.png','.jpg','.jpeg','.gif','.raw','.svg')
+
+
+class UrlImagePreviewPlugin(GajimPlugin):
+    @log_calls('UrlImagePreviewPlugin')
+    def init(self):
+        self.description = _('Url image preview in chatbox.\n'
+            'Based on patch in ticket #5300:\n'
+            'http://trac.gajim.org/attachment/ticket/5300.')
+        self.config_dialog = UrlImagePreviewPluginConfigDialog(self)
+        self.gui_extension_points = {
+                'chat_control_base': (self.connect_with_chat_control,
+                                       self.disconnect_from_chat_control),
+                'print_special_text': (self.print_special_text,
+                                       self.print_special_text1),}
+        self.config_default_values = {
+                    'PREVIEW_SIZE': (150, 'Preview size(10-512)'),}
+        self.chat_control = None
+        self.controls = []
+
+    @log_calls('UrlImagePreviewPlugin')
+    def connect_with_chat_control(self, chat_control):
+
+        self.chat_control = chat_control
+        control = Base(self, self.chat_control)
+        self.controls.append(control)
+
+    @log_calls('UrlImagePreviewPlugin')
+    def disconnect_from_chat_control(self, chat_control):
+        for control in self.controls:
+            control.disconnect_from_chat_control()
+        self.controls = []
+        self.conn.close()
+
+    def print_special_text(self, tv, special_text, other_tags, graphics=True):
+        for control in self.controls:
+            if control.chat_control.conv_textview != tv:
+                continue
+            control.print_special_text(special_text, other_tags, graphics=True)
+
+    def print_special_text1(self, chat_control, special_text, other_tags=None,
+        graphics=True):
+        for control in self.controls:
+            if control.chat_control == chat_control:
+                control.disconnect_from_chat_control()
+                self.controls.remove(control)
+
+class Base(object):
+    def __init__(self, plugin, chat_control):
+        self.plugin = plugin
+        self.chat_control = chat_control
+        self.textview = self.chat_control.conv_textview
+
+    def print_special_text(self, special_text, other_tags, graphics=True):
+        if not gajim.interface.basic_pattern_re.match(special_text):
+            return
+
+        name, extension = os.path.splitext(special_text)
+        if extension.lower() not in EXTENSIONS:
+            return
+        if not special_text.startswith('http://') and \
+        special_text.startswith('www.'):
+            special_text = 'http://' + special_text
+        if not special_text.startswith('ftp://') and \
+        special_text.startswith('ftp.'):
+            special_text = 'ftp://' + special_text
+
+        # show pics preview
+        buffer_ = self.textview.tv.get_buffer()
+        iter_ = buffer_.get_end_iter()
+        mark = buffer_.create_mark(None, iter_, True)
+        gobject.idle_add(self.insert_pic_preview, mark, special_text, special_text)
+
+    def insert_pic_preview(self, mark, special_text, url):
+        pixbuf = self.get_pixbuf_from_url( url, self.plugin.config[
+            'PREVIEW_SIZE'])
+        if pixbuf:
+            # insert image
+            buffer_ = mark.get_buffer()
+            end_iter = buffer_.get_iter_at_mark(mark)
+            anchor = buffer_.create_child_anchor(end_iter)
+            img = TextViewImage(anchor, special_text)
+            img.set_from_pixbuf(pixbuf)
+            img.show()
+            self.textview.tv.add_child_at_anchor(img, anchor)
+
+
+    def get_pixbuf_from_url(self, url, size):
+        # download image and resize
+        # Returns pixbuf or False if broken image or not connected
+        try:
+            data = urllib.urlopen(url).read()
+            pix = gtk.gdk.PixbufLoader()
+            pix.write(data)
+            pix.close()
+            pixbuf = pix.get_pixbuf()
+            pixbuf, w, h = self.get_pixbuf_of_size(pixbuf, size)
+        except:
+            return False
+        return pixbuf
+
+    def get_pixbuf_of_size(self, pixbuf, size):
+        # Creates a pixbuf that fits in the specified square of sizexsize
+        # while preserving the aspect ratio
+        # Returns tuple: (scaled_pixbuf, actual_width, actual_height)
+        image_width = pixbuf.get_width()
+        image_height = pixbuf.get_height()
+
+        if image_width > image_height:
+            if image_width > size:
+                image_height = int(size / float(image_width) * image_height)
+                image_width = int(size)
+        else:
+            if image_height > size:
+                image_width = int(size / float(image_height) * image_width)
+                image_height = int(size)
+
+        crop_pixbuf = pixbuf.scale_simple(image_width, image_height,
+            gtk.gdk.INTERP_BILINEAR)
+        return (crop_pixbuf, image_width, image_height)
+
+    def disconnect_from_chat_control(self):
+        pass
+
+
+class UrlImagePreviewPluginConfigDialog(GajimPluginConfigDialog):
+    def init(self):
+        self.GTK_BUILDER_FILE_PATH = self.plugin.local_file_path(
+            'config_dialog.ui')
+        self.xml = gtk.Builder()
+        self.xml.set_translation_domain('gajim_plugins')
+        self.xml.add_objects_from_file(self.GTK_BUILDER_FILE_PATH, ['vbox1'])
+        self.preview_size_spinbutton = self.xml.get_object('preview_size')
+        self.preview_size_spinbutton.get_adjustment().set_all(20, 10, 512, 1,
+            10, 0)
+        vbox = self.xml.get_object('vbox1')
+        self.child.pack_start(vbox)
+
+        self.xml.connect_signals(self)
+
+    def on_run(self):
+        self.preview_size_spinbutton.set_value(self.plugin.config[
+            'PREVIEW_SIZE'])
+
+
+    def preview_size_value_changed(self, spinbutton):
+        self.plugin.config['PREVIEW_SIZE'] = spinbutton.get_value()
-- 
GitLab