diff --git a/apps/icons/classes.py b/apps/icons/classes.py
index e3efeb1139..8c88ec732d 100644
--- a/apps/icons/classes.py
+++ b/apps/icons/classes.py
@@ -2,26 +2,60 @@ from __future__ import absolute_import
import os
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+
+import PIL
+
from django.utils.safestring import mark_safe
from django.conf import settings
-from .literals import ERROR, SIZE_SMALL, SIZE_BIG
+from .literals import (ERROR, SIZE_SMALL, SIZE_BIG, ICONSETS_STATIC_DIRECTORY)
class Icon(object):
_registry = {}
+ _cache = {}
def __init__(self, id, icon_set=None):
self.id = id
self.icon_set = icon_set
self.__class__._registry[id] = self
- def get_url(self, size):
+ def get_iconset(self):
from .settings import ICON_SET
- return IconSetBase.get_by_name(self.icon_set or ICON_SET).get_url(self, size)
+ return IconSetBase.get_by_name(self.icon_set or ICON_SET)
+
+ #def get_url(self, size):
+ # #from .settings import ICON_SET
+ # #return IconSetBase.get_by_name(self.icon_set or ICON_SET).get_url_of_icon(self, size)
+ # return self.get_iconset().get_url_of_icon(self, size)
+
+ #def get_as_base64(self, size):
+ # from .settings import ICON_SET
+ # return IconSetBase.get_by_name(self.icon_set or ICON_SET).get_as_base64(self, size)
+
+ #def get_as_filename(self, size):
+ # #from .settings import ICON_SET
+ # #return IconSetBase.get_by_name(self.icon_set or ICON_SET).get_filename_of_icon(self, size)
+ # return self.get_iconset().get_filename_of_icon(self, size)
def display(self, size): # TODO: move to widgets?
- return mark_safe('
' % (settings.STATIC_URL, self.get_url(size)))
+ #return mark_safe('
' % self.get_url(size))
+ #return mark_safe('
' % self.get_as_base64(size))
+ #return mark_safe('
' % self.process(size))
+ #return mark_safe('
' % self.get_iconset().compose(self, size))
+
+ # Cache a composed icon result for a specific size
+ try:
+ result = self.__class__._cache['%d_%s' % (id(self), size)]
+ except KeyError:
+ result = self.get_iconset().compose(self, size)
+ self.__class__._cache['%d_%s' % (id(self), size)] = result
+
+ return mark_safe('
' % result)
def display_small(self):
return self.display(SIZE_SMALL)
@@ -29,12 +63,6 @@ class Icon(object):
def display_big(self):
return self.display(SIZE_BIG)
- #def get_filepath(self):
- # if settings.DEVELOPMENT:
- # return os.path.join(settings.PROJECT_ROOT, 'apps', 'icons', 'static', 'icons', self.get_file_name(SIZE_BIG))
- # else:
- # return os.path.join(settings.STATIC_ROOT, self.get_file_name(SIZE_BIG))
-
class IconSetBase(object):
_registry = {}
@@ -50,9 +78,74 @@ class IconSetBase(object):
def __init__(self):
self.__class__._registry[self.name] = self
- def get_filename(self, icon, size):
- return os.path.join([self.path, size, self.dictionary.get(icon.id, ERROR)])
-
- def get_url(self, icon, size):
- return '%s/%s/%s' % (self.path, size, self.dictionary.get(icon.id, ERROR))
+ #def get_filename_of_icon(self, icon, size):
+ # if settings.DEVELOPMENT:
+ # return os.path.join(settings.PROJECT_ROOT, 'apps', 'icons', 'static', ICONSETS_STATIC_DIRECTORY, self.directory, size, self.dictionary.get(icon.id, ERROR))
+ # else:
+ # return os.path.join(settings.STATIC_ROOT, ICONSETS_STATIC_DIRECTORY, self.directory, size, self.dictionary.get(icon.id, ERROR))
+
+ def get_filename_of_image(self, image_name, size):
+ if settings.DEVELOPMENT:
+ return os.path.join(settings.PROJECT_ROOT, 'apps', 'icons', 'static', ICONSETS_STATIC_DIRECTORY, self.directory, size, image_name)
+ else:
+ return os.path.join(settings.STATIC_ROOT, ICONSETS_STATIC_DIRECTORY, self.directory, size, image_name)
+
+ #def get_url_of_icon(self, icon, size):
+ # return '%s%s/%s/%s/%s' % (settings.STATIC_URL, ICONSETS_STATIC_DIRECTORY, self.directory, size, self.dictionary.get(icon.id, ERROR))
+
+ def get_major_minor(self, icon):
+ return self.dictionary.get(icon.id, ERROR)
+
+ def compose(self, icon, size):
+ try:
+ major, minor = self.get_major_minor(icon)
+ except ValueError:
+ major = self.get_major_minor(icon)
+ minor = None
+
+ major_image = PIL.Image.open(self.get_filename_of_image(major, size))
+ if minor:
+ major_width, major_height = major_image.size
+ minor_image = PIL.Image.open(self.get_filename_of_image(minor, size))
+ minor_image.thumbnail((major_width / 1.6, major_height / 1.6))#, PIL.Image.ANTIALIAS)
+ minor_width, minor_height = minor_image.size
+ major_image.paste(minor_image, (major_width - minor_width, major_height - minor_height), minor_image)
+
+ output = StringIO()
+ major_image.save(output, 'PNG')
+ contents = output.getvalue().encode('base64')
+ output.close()
+ return 'data:image/png;base64,%s' % contents
+
+
+class Verb(object):
+ pass
+
+
+class Load(Verb):
+ def __init__(self, filename):
+ self.filename = filename
+ def execute(self):
+ return PIL.Image.open(self.filename)
+
+
+class Resize(Verb):
+ def __init__(self, image, size, antialias=False):
+ self.image = image
+ self.size = size
+ self.antialias = antialias
+
+ def execute(self):
+ if self.antialias:
+ self.image.thumbnail(self.size, PIL.Image.ANTIALIAS)
+ else:
+ self.image.thumbnail(self.size)
+
+
+class Rotate(Verb):
+ def __init__(self, degrees):
+ self.degrees = degrees
+
+ def execute(self):
+ pass
diff --git a/apps/icons/iconsets/custom.py b/apps/icons/iconsets/custom.py
index e15ef371d4..8a2ad00fcd 100644
--- a/apps/icons/iconsets/custom.py
+++ b/apps/icons/iconsets/custom.py
@@ -8,6 +8,7 @@ class IconSet(IconSetBase):
path = 'custom'
name = 'custom'
label = _(u'Custom')
+ directory='custom'
dictionary = {
FILE_EXTENSION_ERROR: 'file_extension_error.png',
FILE_EXTENSION_UNKNOWN: 'file_extension_unknown.png'
diff --git a/apps/icons/iconsets/fat_cow.py b/apps/icons/iconsets/fat_cow.py
index 9079981a30..d057b317ad 100644
--- a/apps/icons/iconsets/fat_cow.py
+++ b/apps/icons/iconsets/fat_cow.py
@@ -7,20 +7,25 @@ from icons.classes import IconSetBase
class IconSet(IconSetBase):
name='fat_cow'
label=_(u'Fat cow')
- path='fat_cow'
+ directory='fat_cow'
+ available_sizes=['32x32', '16x16']
dictionary={
ADD: 'add.png',
APPLICATION_VIEW_ICONS: 'application_view_icons.png',
ARROW_TURN_RIGHT: 'arrow_turn_right.png',
ARROW_TURN_LEFT: 'arrow_turn_left.png',
ARROW_UP: 'arrow_up.png',
- BIN_CLOSED: 'bin_closed.png',
BIN: 'bin.png',
+ BIN_CLOSED: 'bin_closed.png',
BIN_EMPTY: 'bin_empty.png',
+ BIN_EMPTY_OUT: ['bin_empty.png', 'arrow_turn_right.png'],
+ BIN_MULTIPLE: ['bin_closed.png', 'bin_closed.png'],
+ BIN_RECYCLE: ['bin.png', 'recycle.png'],
BLACKBOARD_SUM: 'blackboard_sum.png',
BOOK: 'book.png',
BOOK_GO: 'book_go.png',
BOOK_OPEN: 'book_open.png',
+ BULLET_GO: 'bullet_go.png',
CAMERA_DELETE: 'camera_delete.png',
CD_BURN: 'cd_burn.png',
COG: 'cog.png',
@@ -59,6 +64,7 @@ class IconSet(IconSetBase):
GROUP_DELETE: 'group_delete.png',
GROUP_KEY: 'group_key.png',
GROUP_LINK: 'group_link.png',
+ GROUP_MEMBERS: ['group.png', 'arrow_refresh.png'],
HOURGLASS: 'hourglass.png',
HOUSE: 'house.png',
INDEX: 'index.png',
@@ -86,8 +92,12 @@ class IconSet(IconSetBase):
MAGNIFIER: 'magnifier.png',
MEDAL_GOLD: 'medal_gold_1.png',
MEDAL_GOLD_ADD: 'medal_gold_add.png',
+ MEDAL_GOLD_EDIT: ['medal_gold_1.png', 'pencil.png'],
MEDAL_GOLD_DELETE: 'medal_gold_delete.png',
- NODE: 'node.png',
+ NODE_TREE: 'node-tree.png',
+ NODE_TREE_ADD: ['node-tree.png', 'add.png'],
+ NODE_TREE_EDIT: ['node-tree.png', 'pencil.png'],
+ NODE_TREE_DELETE: ['node-tree.png', 'delete.png'],
PACKAGE: 'package.png',
PAGE: 'page.png',
PAGE_COPY: 'page_copy.png',
@@ -126,7 +136,7 @@ class IconSet(IconSetBase):
TAB_ADD: 'tab_add.png',
TAB_DELETE: 'tab_delete.png',
TAB_EDIT: 'tab_edit.png',
- TAB_VIEW: 'tab_view.png',
+ TAB_GO: 'tab_go.png',
TABLE: 'table.png',
TABLE_ADD: 'table_add.png',
TABLE_EDIT: 'table_edit.png',
@@ -154,12 +164,17 @@ class IconSet(IconSetBase):
VCARD: 'vcard.png',
VCARD_EDIT: 'vcard_edit.png',
WIZARD: 'wizard.png',
+ WIZARD_ADD: ['wizard.png', 'add.png'],
+ WIZARD_DELETE: ['wizard.png', 'delete.png'],
+ WIZARD_EDIT: ['wizard.png', 'pencil.png'],
+ WIZARD_LIGHTNING: ['wizard.png', 'lightning.png'],
WORLD_GO: 'world_go.png',
WRENCH: 'wrench.png',
XHTML: 'xhtml.png',
XHTML_GO: 'xhtml_go.png',
XHTML_ADD: 'xhtml_add.png',
XHTML_DELETE: 'xhtml_delete.png',
+ XHTML_EDIT: ['xhtml.png', 'pencil.png'],
ZOOM: 'zoom.png',
ZOOM_IN: 'zoom_in.png',
ZOOM_OUT: 'zoom_out.png',
diff --git a/apps/icons/literals.py b/apps/icons/literals.py
index 63a4d6c31e..42718b06c8 100644
--- a/apps/icons/literals.py
+++ b/apps/icons/literals.py
@@ -2,6 +2,7 @@ SIZE_SMALL = '16x16'
SIZE_BIG = '32x32'
DEFAULT_ICON_SET = 'fat_cow'
+ICONSETS_STATIC_DIRECTORY = 'icons'
ADD = 'add'
APPLICATION_VIEW_ICONS = 'application_view_icons'
@@ -11,10 +12,14 @@ ARROW_UP = 'arrow_up'
BIN_CLOSED = 'bin_closed'
BIN = 'bin'
BIN_EMPTY = 'bin_empty'
+BIN_EMPTY_OUT = 'bin_empty_out'
+BIN_MULTIPLE = 'bin_multiple'
+BIN_RECYCLE = 'bin_recyle'
BLACKBOARD_SUM = 'blackboard_sum'
BOOK = 'book'
BOOK_GO = 'book_go'
BOOK_OPEN = 'book_open'
+BULLET_GO = 'bullet_go'
CAMERA_DELETE = 'camera_delete'
CD_BURN = 'cd_burn'
COG = 'cog'
@@ -49,12 +54,13 @@ FOLDER_DELETE = 'folder_delete'
FOLDER_GO = 'folder_go'
FOLDER_PAGE = 'folder_page'
FOLDER_USER = 'folder_user'
-GROUP = 'user'
+GROUP = 'group'
GROUP_ADD = 'group_add'
GROUP_EDIT = 'group_edit'
GROUP_DELETE = 'group_delete'
GROUP_KEY = 'group_key'
GROUP_LINK = 'group_link'
+GROUP_MEMBERS = 'group_members'
HOURGLASS = 'hourglass'
HOUSE = 'house'
INDEX = 'index'
@@ -82,8 +88,12 @@ MAGIC_WAND_2 = 'magic_wand_2'
MAGNIFIER = 'magnifier'
MEDAL_GOLD = 'medal_gold'
MEDAL_GOLD_ADD = 'medal_gold_add'
+MEDAL_GOLD_EDIT = 'medal_gold_edit'
MEDAL_GOLD_DELETE = 'medal_gold_delete'
-NODE = 'node'
+NODE_TREE = 'node_tree'
+NODE_TREE_ADD = 'node_tree_add'
+NODE_TREE_EDIT = 'node_tree_edit'
+NODE_TREE_DELETE = 'node_tree_delete'
PACKAGE = 'package'
PAGE = 'page'
PAGE_COPY = 'page_copy'
@@ -122,7 +132,7 @@ TAB = 'tab'
TAB_ADD = 'tab_add'
TAB_DELETE = 'tab_delete'
TAB_EDIT = 'tab_edit'
-TAB_VIEW = 'tab_view'
+TAB_GO = 'tab_go'
TABLE = 'table'
TABLE_ADD = 'table_add'
TABLE_EDIT = 'table_edit'
@@ -150,12 +160,17 @@ USER_SILHOUETTE = 'user_silhouette'
VCARD = 'vcard'
VCARD_EDIT = 'vcard_edit'
WIZARD = 'wizard'
+WIZARD_ADD = 'wizard_add'
+WIZARD_DELETE = 'wizard_delete'
+WIZARD_EDIT = 'wizard_edit'
+WIZARD_LIGHTNING = 'wizard_lightning'
WORLD_GO = 'world_go'
WRENCH = 'wrench'
XHTML = 'xhtml'
XHTML_GO = 'xhtml_go'
XHTML_ADD = 'xhtml_add'
XHTML_DELETE = 'xhtml_delete'
+XHTML_EDIT = 'xhtml_edit'
ZOOM = 'zoom'
ZOOM_IN = 'zoom_in'
ZOOM_OUT = 'zoom_out'