diff --git a/emoticons_pack/__init__.py b/emoticons_pack/__init__.py
new file mode 100644
index 0000000..496821a
--- /dev/null
+++ b/emoticons_pack/__init__.py
@@ -0,0 +1 @@
+from .emoticons_pack import EmoticonsPackPlugin
diff --git a/emoticons_pack/config_dialog.ui b/emoticons_pack/config_dialog.ui
new file mode 100644
index 0000000..691da97
--- /dev/null
+++ b/emoticons_pack/config_dialog.ui
@@ -0,0 +1,405 @@
+
+
+
+
+
+
diff --git a/emoticons_pack/contents.ini b/emoticons_pack/contents.ini
new file mode 100644
index 0000000..7524e51
--- /dev/null
+++ b/emoticons_pack/contents.ini
@@ -0,0 +1,89 @@
+[MacThemes2]
+icon: Smile.png
+description:
+ Mac Themes 2 Smilies
+
+
+authors: David Lanham
+homepage: https://trac.gajim.org/wiki/MacThemes2
+
+[Citters Emoticons from Psi]
+icon: smile.png
+description:
+ Citters Emoticons from Psi
+
+
+converter: churchyard (JID: churchyard@njs.netlab.cz)
+homepage: https://trac.gajim.org/wiki/cittersemoticons
+
+[Google Talk Emoticons]
+icon: equal_smile.gif
+description:
+ Google Talk Emoticons
+
+
+converter: Chris Cook
+homepage: https://trac.gajim.org/wiki/gtalkemoticons
+
+[ICQ6 Emoticons]
+icon: Smiley1.gif
+description:
+ ICQ6 Emoticons
+
+
+homepage: https://trac.gajim.org/wiki/ICQ6-emotions
+
+[Kolobok Animated Emoticons]
+icon: ab.gif
+description:
+ Kolobok Animated Emoticons
+
+
+homepage: https://trac.gajim.org/wiki/kolobok-animated-emoticons
+
+[Pidgin Emoticons]
+icon: smile.png
+description:
+ Pidgin Emoticons
+
+
+homepage: https://trac.gajim.org/wiki/PidginEmoticons
+
+[Psynova qip's theme]
+icon: ab.gif
+authors: zOrg
+description:
+ Psynova qip's theme
+
+
+homepage: https://trac.gajim.org/wiki/psynovaemoticons
+
+[Yahoo Emoticons]
+icon: equal_smile.gif
+description:
+ Yahoo Emoticons
+
+
+homepage: https://trac.gajim.org/wiki/YahooEmoticons
+
+[Nekomoticons]
+icon: s01.jpg
+authors: somik (http://somik.deviantart.com/)
+converter: Dotterian (http://dotterian.ru/)
+description:
+ Nekomoticons
+
+
+homepage: https://trac.gajim.org/wiki/Nekomoticons
+
+[Trollicons]
+icon: Happy-EverythingWentBetterThanExpected.png
+authors: Sagar Pandya
+ Chris Li
+ Jonathan E. Chen
+converter: Matthieu L.
+description:
+ Trollicons (Rage Icons for Gajim)
+
+
+homepage: https://github.com/sagargp/trollicons/blob/master/readme.md#downloads
diff --git a/emoticons_pack/emoticons_pack.png b/emoticons_pack/emoticons_pack.png
new file mode 100644
index 0000000..7aec288
Binary files /dev/null and b/emoticons_pack/emoticons_pack.png differ
diff --git a/emoticons_pack/emoticons_pack.py b/emoticons_pack/emoticons_pack.py
new file mode 100644
index 0000000..a099d48
--- /dev/null
+++ b/emoticons_pack/emoticons_pack.py
@@ -0,0 +1,361 @@
+# -*- coding: utf-8 -*-
+##
+
+from gi.repository import Gtk
+from gi.repository import GdkPixbuf
+from gi.repository import Pango
+from gi.repository 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(
+ GdkPixbuf.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.SortType.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.TreeViewColumnSizing.GROW_ONLY)
+ self.available_treeview.append_column(col)
+
+ renderer = Gtk.CellRendererToggle()
+ renderer.set_property('activatable', True)
+ renderer.connect('toggled', self.available_plugins_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_plugins_treeview_selection_changed)
+ selection.set_mode(Gtk.SelectionMode.SINGLE)
+
+ self.plugin_description_textview = ConversationTextview(None)
+ sw = self.xml.get_object('scrolledwindow1')
+ sw.add(self.plugin_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.plugin_description_textview = Gtk.TextView()
+ sw = self.xml.get_object('scrolledwindow1')
+ sw.add(self.plugin_description_textview)
+ sw.show_all()
+
+ buff = self.plugin_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 = GdkPixbuf.PixbufLoader()
+ pbl.write(data)
+ pbl.close()
+ 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.plugin_description_textview.set_property('sensitive', True)
+ sys.path.remove(os.path.join(self.tmp_dir, name))
+
+ else:
+ self.plugin_description_textview = ConversationTextview(None)
+ sw = self.xml.get_object('scrolledwindow1')
+ sw.add(self.plugin_description_textview.tv)
+ sw.show_all()
+ label.set_text('Legend')
+ desc = _(model.get_value(iter, C_DESCRIPTION))
+ if not desc.startswith('' + \
+ desc + ' '
+ desc = desc.replace('preview.image', ('file:' + os.path.join(
+ self.tmp_dir, name, 'preview.png')))
+ self.plugin_description_textview.tv.display_html(
+ desc, self.plugin_description_textview)
+ self.plugin_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.MessageType.INFO, Gtk.ButtonsType.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_plugins_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.read_file(_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 = GdkPixbuf.PixbufLoader()
+ pbl.set_size(16, 16)
+ pbl.write(data)
+ pbl.close()
+ icon = pbl.get_pixbuf()
+
+ self.model.append(
+ [icon, section,
+ conf.get(section, 'description'),
+ conf.get(section, 'authors', fallback=_('Unknown')),
+ conf.get(section, 'converter', fallback=_('Unknown')),
+ conf.get(section, 'homepage'), False])
+ conf.remove_section(section)
+
+ def available_plugins_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.EllipsizeMode.END)
+ self.homepage_linkbutton.set_property('sensitive', True)
+
+ self.xml.get_object('scrolledwindow1').get_children()[0].destroy()
+ self.plugin_description_textview = ConversationTextview(None)
+ sw = self.xml.get_object('scrolledwindow1')
+ sw.add(self.plugin_description_textview.tv)
+ sw.show_all()
+ desc = _(model.get_value(iter, C_DESCRIPTION))
+ if not desc.startswith('' + \
+ desc + ' '
+ else:
+ desc = desc.replace('preview.image', ('file:' + os.path.join(
+ self.tmp_dir, set_name, 'preview.png')))
+ self.plugin_description_textview.tv.display_html(
+ desc, self.plugin_description_textview)
+ self.plugin_description_textview.tv.set_property('sensitive', True)
+ else:
+ self._clear_available_plugin_info()
+
+ def _clear_available_plugin_info(self):
+ 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)
+
+ desc_textbuffer = self.plugin_description_textview.tv.get_buffer()
+ desc_textbuffer.set_text('')
+ self.plugin_description_textview.tv.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')
+ scr_win.get_vadjustment().set_value(0)
+ #GObject.idle_add(self.available_treeview.grab_focus)
diff --git a/emoticons_pack/emoticons_pack.zip b/emoticons_pack/emoticons_pack.zip
new file mode 100644
index 0000000..a5fb1e8
Binary files /dev/null and b/emoticons_pack/emoticons_pack.zip differ
diff --git a/emoticons_pack/manifest.ini b/emoticons_pack/manifest.ini
new file mode 100644
index 0000000..f74e636
--- /dev/null
+++ b/emoticons_pack/manifest.ini
@@ -0,0 +1,8 @@
+[info]
+name: Emoticons pack
+short_name: emoticons_pack
+version: 0.0.0
+description: Install emoticons
+authors: Denis Fomin
+homepage: http://trac-plugins.gajim.org/wiki/PluginInstallerPlugin
+min_gajim_version: 0.15.10