Skip to content
Snippets Groups Projects
emoticons_pack.py 14.6 KiB
Newer Older
# -*- coding: utf-8 -*-
##

import gtk
import pango
import gobject
import io
import ConfigParser
import os
import zipfile
import tempfile
from shutil import rmtree
import sys
import imp

from common import gajim
from plugins import GajimPlugin
from plugins.helpers import log_calls
from htmltextview import HtmlTextView
from conversation_textview import ConversationTextview
from dialogs import WarningDialog, HigDialog

(
    C_PIXBUF,
    C_NAME,
    C_DESCRIPTION,
    C_AUTHORS,
    C_CONVERTER,
    C_HOMEPAGE,
    C_UPGRADE) = range(7)


class EmoticonsPackPlugin(GajimPlugin):

    @log_calls('EmoticonsPackPlugin')
    def init(self):
        self.description = _('Install emoticons')
        self.config_dialog = None  # EmoticonsPackPluginConfigDialog(self)
        self.window = None
        self.model = None
        self.connected_ids = {}
        self.tmp_dir = ''

    @log_calls('EmoticonsPackPlugin')
    def activate(self):
        self.pl_menuitem = gajim.interface.roster.xml.get_object(
            'plugins_menuitem')
        self.id_ = self.pl_menuitem.connect_after('activate', self.on_activate)
        if 'plugins' in gajim.interface.instances:
            self.on_activate(None)

    @log_calls('EmoticonsPackPlugin')
    def deactivate(self):
        self.pl_menuitem.disconnect(self.id_)
        if hasattr(self, 'page_num'):
            self.notebook.remove_page(self.notebook.page_num(self.hpaned))
            self.notebook.set_current_page(0)
            for id_, widget in list(self.connected_ids.items()):
                widget.disconnect(id_)
            del self.page_num

    def on_activate(self, widget):
        if 'plugins' not in gajim.interface.instances:
            return
        if hasattr(self, 'page_num'):
            # 'Available' tab exists
            return
        self.installed_plugins_model = gajim.interface.instances[
            'plugins'].installed_plugins_model
        self.notebook = gajim.interface.instances['plugins'].plugins_notebook
        id_ = self.notebook.connect(
            'switch-page', self.on_notebook_switch_page)
        self.connected_ids[id_] = self.notebook
        self.window = gajim.interface.instances['plugins'].window
        id_ = self.window.connect('destroy', self.on_win_destroy)
        self.connected_ids[id_] = self.window
        self.Gtk_BUILDER_FILE_PATH = self.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, ['hpaned2'])
        self.hpaned = self.xml.get_object('hpaned2')
        self.page_num = self.notebook.append_page(self.hpaned, gtk.Label(_(
            'Emoticons')))

        widgets_to_extract = (
            'set_name', 'available_treeview', 'homepage_linkbutton',
            'inslall_upgrade_button', 'authors_label', 'converter_label',)

        for widget_name in widgets_to_extract:
            setattr(self, widget_name, self.xml.get_object(widget_name))

        self.model = gtk.ListStore(
            gtk.gdk.Pixbuf, gobject.TYPE_STRING,
            gobject.TYPE_STRING, gobject.TYPE_STRING,
            gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
        self.available_treeview.set_model(self.model)
        self.available_treeview.set_rules_hint(True)
        self.model.set_sort_column_id(1, gtk.SORT_ASCENDING)

        #self.progressbar.set_property('no-show-all', True)
        renderer = gtk.CellRendererText()
        col = gtk.TreeViewColumn(_('Name'))
        cell = gtk.CellRendererPixbuf()
        col.pack_start(cell, False)
        col.add_attribute(cell, 'pixbuf', C_PIXBUF)
        col.pack_start(renderer, True)
        col.add_attribute(renderer, 'text', C_NAME)
        col.set_property('expand', True)
        col.set_sizing(gtk.TREE_VIEW_COLUMN_GROW_ONLY)
        self.available_treeview.append_column(col)

        renderer = gtk.CellRendererToggle()
        renderer.set_property('activatable', True)
        renderer.connect('toggled', self.available_emoticons_toggled_cb)
        col = gtk.TreeViewColumn(
            _('Install /\nUpgrade'), renderer,  active=C_UPGRADE)
        col.set_property('expand', False)
        col.set_resizable(False)
        self.available_treeview.append_column(col)

        selection = self.available_treeview.get_selection()
        selection.connect(
            'changed', self.available_emoticons_treeview_selection_changed)
        selection.set_mode(gtk.SELECTION_SINGLE)

        self.emoticons_description_textview = ConversationTextview(None)
        sw = self.xml.get_object('scrolledwindow1')
        sw.add(self.emoticons_description_textview.tv)
        self.xml.connect_signals(self)
        self.window.show_all()

    def on_legend_button_clicked(self, widget):
        self.xml.get_object('scrolledwindow1').get_children()[0].destroy()

        treeview_selection = self.available_treeview.get_selection()
        model, iter = treeview_selection.get_selected()
        name = model.get_value(iter, C_NAME)

        label = self.xml.get_object('label2')
        if label.get_text() == 'Legend':
            label.set_text('Description')
            sys.path.append(os.path.join(self.tmp_dir, name))

            import emoticons
            imp.reload(emoticons)

            self.emoticons_description_textview = gtk.TextView()
            sw = self.xml.get_object('scrolledwindow1')
            sw.add(self.emoticons_description_textview)
            sw.show_all()

            buff = self.emoticons_description_textview.get_buffer()
            for icon in emoticons.emoticons:
                icon_file = os.path.join(self.tmp_dir, name, icon)
                with open(icon_file, 'rb') as _file:
                    data = _file.read()
                pbl = gtk.gdk.PixbufLoader()
                pbl.write(data)
                pbl.close()
                if icon.endswith('.gif'):
                    img = gtk.Image()
                    img.set_from_animation(pbl.get_animation())
                    img.show()
                    anchor = buff.create_child_anchor(buff.get_end_iter())
                    self.emoticons_description_textview.add_child_at_anchor(
                        img, anchor)
                else:
                    buff.insert_pixbuf(buff.get_end_iter(), pbl.get_pixbuf())
                text = ' , '.join(emoticons.emoticons[icon])
                buff.insert(buff.get_end_iter(), text + '\n', -1)

            self.emoticons_description_textview.set_property('sensitive', True)
            sys.path.remove(os.path.join(self.tmp_dir, name))

        else:
            self.emoticons_description_textview = ConversationTextview(None)
            sw = self.xml.get_object('scrolledwindow1')
            sw.add(self.emoticons_description_textview.tv)
            sw.show_all()
            label.set_text('Legend')
            desc = _(model.get_value(iter, C_DESCRIPTION))
            if not desc.startswith('<body  '):
                desc = '<body  xmlns=\'http://www.w3.org/1999/xhtml\'>' + \
                    desc + ' </body>'
            desc = desc.replace('preview.image', ('file:' + os.path.join(
                    self.tmp_dir, name, 'preview.png')))
            self.emoticons_description_textview.tv.display_html(
                desc, self.emoticons_description_textview)
            self.emoticons_description_textview.tv.set_property('sensitive', True)

    def dict_to_html(self, dict_):
        desc = ''
        for icon in dict_:
            acr = ' , '.join(dict_[icon])
            desc += ' '+ icon + '  '+ acr + '\n'
        return desc

    def on_inslall_upgrade_clicked(self, widget):
        self.inslall_upgrade_button.set_property('sensitive', False)
        self.errors = ''

        def on_error(func, path, error):
            if func == os.path.islink:
            # if symlink
                os.unlink(path)
                return
            # access is denied or other
            # WarningDialog(_('Can\'t remove dir'), error[1], self.window)
            self.errors += str(error[1])

        name_list = []
        for i in range(len(self.model)):
            if self.model[i][C_UPGRADE]:
                name_list.append(self.model[i][C_NAME])
        for name in name_list:
            # remove dirs
            target_dir = os.path.join(gajim.MY_EMOTS_PATH, name)
            if os.path.isdir(target_dir):
                rmtree(target_dir, False, on_error)

            # unzip new files
            zip_file = os.path.join(self.__path__, 'emoticons_pack.zip')
            with zipfile.ZipFile(zip_file, 'r') as myzip:
                namelist = myzip.namelist()
                for n in namelist:
                    if not n.startswith(name):
                        continue
                    try:
                        icon_file = myzip.extract(n, path=gajim.MY_EMOTS_PATH)
                    except Exception as e:
                        self.errors += str(e)
        # unset all checkbattons
        for i in range(len(self.model)):
            self.model[i][C_UPGRADE] = False

        if self.errors:
            WarningDialog(
                _('Not fully installed'),
                'Access is denied or other', self.window)
        else:
            # show dialog
            dialog = HigDialog(
                None,  gtk.MESSAGE_INFO, gtk.BUTTONS_OK, '',
                _('All selected emoticons installed(upgraded)'))
            dialog.set_modal(False)
            dialog.set_transient_for(self.window)
            dialog.popup()

    def on_win_destroy(self, widget):
        if hasattr(self, 'page_num'):
            del self.page_num

    def available_emoticons_toggled_cb(self, cell, path):
        is_active = self.model[path][C_UPGRADE]
        self.model[path][C_UPGRADE] = not is_active
        dir_list = []
        for i in range(len(self.model)):
            if self.model[i][C_UPGRADE]:
                dir_list.append(self.model[i][C_NAME])
        if not dir_list:
            self.inslall_upgrade_button.set_property('sensitive', False)
        else:
            self.inslall_upgrade_button.set_property('sensitive', True)

    def on_notebook_switch_page(self, widget, page, page_num):
        tab_label_text = self.notebook.get_tab_label_text(self.hpaned)
        if tab_label_text != (_('Emoticons')):
            return

        self.model.clear()
        self.fill_table()
        self.select_root_iter()

    def fill_table(self):
        conf = ConfigParser.ConfigParser()
        # read metadata from contents.ini
        contents_path = os.path.join(self.__path__, 'contents.ini')
        with open(contents_path) as _file:
            conf.readfp(_file)
        for section in conf.sections():
            # get icon
            filename = conf.get(section, 'icon')
            filename = os.path.join(section, filename)
            zip_file = os.path.join(self.__path__, 'emoticons_pack.zip')
            with zipfile.ZipFile(zip_file, 'r') as myzip:
                icon_file = myzip.open(filename, mode='r')
                data = icon_file.read()
            pbl = gtk.gdk.PixbufLoader()
            pbl.set_size(16, 16)
            pbl.write(data)
            pbl.close()
            icon = pbl.get_pixbuf()

            authors = _('Unknown')
            converter = _('Unknown')
            if conf.has_option(section, 'authors'):
                authors = conf.get(section, 'authors')
            if conf.has_option(section, 'converter'):
                authors = conf.get(section, 'converter')

            self.model.append(
                [icon, section,
                    conf.get(section, 'description'),
                    authors, converter,
                    conf.get(section, 'homepage'), False])
            conf.remove_section(section)

    def available_emoticons_treeview_selection_changed(self, treeview_selection):
        model, iter = treeview_selection.get_selected()
        label = self.xml.get_object('label2')
        label.set_text(_('Legend'))
        if iter:
            set_name = model.get_value(iter, C_NAME)
            if os.path.isdir(self.tmp_dir):
                rmtree(self.tmp_dir, True)
            self.tmp_dir = tempfile.mkdtemp()
             # unzip new files
            zip_file = os.path.join(self.__path__, 'emoticons_pack.zip')
            with zipfile.ZipFile(zip_file, 'r') as myzip:
                namelist = myzip.namelist()
                for n in namelist:
                    if not n.startswith(set_name):
                        continue
                    myzip.extract(n, path=self.tmp_dir)

            self.set_name.set_text(set_name)
            self.authors_label.set_text(model.get_value(iter, C_AUTHORS))
            self.converter_label.set_text(model.get_value(iter, C_CONVERTER))
            self.homepage_linkbutton.set_uri(
                model.get_value(iter, C_HOMEPAGE))
            self.homepage_linkbutton.set_label(
                model.get_value(iter, C_HOMEPAGE))
            label = self.homepage_linkbutton.get_children()[0]
            label.set_ellipsize(pango.ELLIPSIZE_END)
            self.homepage_linkbutton.set_property('sensitive', True)

            self.xml.get_object('scrolledwindow1').get_children()[0].destroy()
            self.emoticons_description_textview = ConversationTextview(None)
            sw = self.xml.get_object('scrolledwindow1')
            sw.add(self.emoticons_description_textview.tv)
            sw.show_all()
            desc = _(model.get_value(iter, C_DESCRIPTION))
            if not desc.startswith('<body '):
                desc = '<body  xmlns=\'http://www.w3.org/1999/xhtml\'>' + \
                    desc + ' </body>'
            else:
                desc = desc.replace('preview.image', ('file:' + os.path.join(
                    self.tmp_dir, set_name, 'preview.png')))
            self.emoticons_description_textview.tv.display_html(
                desc, self.emoticons_description_textview)
            self.emoticons_description_textview.tv.set_property('sensitive', True)
        else:
            self.set_name.set_text('')
            self.authors_label.set_text('')
            self.homepage_linkbutton.set_uri('')
            self.homepage_linkbutton.set_label('')
            self.homepage_linkbutton.set_property('sensitive', False)

    def select_root_iter(self):
        if hasattr(self, 'page_num'):
            selection = self.available_treeview.get_selection()
            if selection.count_selected_rows() == 0:
                root_iter = self.model.get_iter_first()
                selection.select_iter(root_iter)
        scr_win = self.xml.get_object('scrolledwindow2')
        vadjustment = scr_win.get_vadjustment()
        if vadjustment:
            vadjustment.set_value(0)
        #GObject.idle_add(self.available_treeview.grab_focus)