diff options
author | Aleksey Lim <alsroot@member.fsf.org> | 2009-05-26 11:16:01 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@member.fsf.org> | 2009-05-26 11:16:01 (GMT) |
commit | 2302c3d2cf1688a5d8b44c4f927f96a0e4d58c04 (patch) | |
tree | 4b3bc949141a172415ffc8d2e767dc0a0667abca /port | |
parent | 584443c3db446e59d70778e37a2602fd58cb6c60 (diff) |
Update sugar-port
Diffstat (limited to 'port')
-rw-r--r-- | port/AUTHORS | 1 | ||||
-rw-r--r-- | port/NEWS | 8 | ||||
-rw-r--r-- | port/README | 5 | ||||
-rw-r--r-- | port/TODO | 0 | ||||
-rw-r--r-- | port/activity.py | 34 | ||||
-rw-r--r-- | port/chooser.py | 4 | ||||
-rw-r--r-- | port/epydoc | 21 | ||||
-rw-r--r-- | port/images/tempo1.svg | 8 | ||||
-rw-r--r-- | port/images/tempo2.svg | 9 | ||||
-rw-r--r-- | port/images/tempo3.svg | 8 | ||||
-rw-r--r-- | port/images/tempo4.svg | 9 | ||||
-rw-r--r-- | port/images/tempo5.svg | 9 | ||||
-rw-r--r-- | port/images/tempo6.svg | 11 | ||||
-rw-r--r-- | port/images/tempo7.svg | 9 | ||||
-rw-r--r-- | port/images/tempo8.svg | 10 | ||||
-rw-r--r-- | port/pixbuf.py | 179 | ||||
l--------- | port/port | 1 | ||||
-rw-r--r-- | port/tarball.py | 15 | ||||
-rw-r--r-- | port/temposlider.py | 142 |
19 files changed, 358 insertions, 125 deletions
diff --git a/port/AUTHORS b/port/AUTHORS deleted file mode 100644 index 47ead6c..0000000 --- a/port/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -Aleksey Lim <alsroot@member.fsf.org> diff --git a/port/NEWS b/port/NEWS deleted file mode 100644 index 0dcfeb5..0000000 --- a/port/NEWS +++ /dev/null @@ -1,8 +0,0 @@ -1 - -* Add tarball.py -* Add json import wrapper -* Add object chooser -* Add activity classes -* Add pixbuf methods -* Add TempoSlider and ScrolledBox widgets diff --git a/port/README b/port/README index bd0dade..256200d 100644 --- a/port/README +++ b/port/README @@ -7,6 +7,11 @@ Cornerstone purposes for this project: * Total backwards compatibility for sugar-port API * Run on all sugar platforms beginning from 0.82 +In most cases sugar-port could be embedded to activity's directory tree. +There is no need to include the whole sugar-port project only top level +files/directories you are using directly - sugar-port's top level entities +don't import each other. + Get it ------ diff --git a/port/TODO b/port/TODO deleted file mode 100644 index e69de29..0000000 --- a/port/TODO +++ /dev/null diff --git a/port/activity.py b/port/activity.py index dfe6a4a..e3b6fdd 100644 --- a/port/activity.py +++ b/port/activity.py @@ -17,6 +17,7 @@ import gtk import logging import telepathy +import gobject import sugar.activity.activity as toolkit from sugar.presence.sugartubeconn import SugarTubeConnection @@ -27,6 +28,18 @@ _NEW_INSTANCE = 1 _PRE_INSTANCE = 2 _POST_INSTANCE = 3 +class CursorFactory: + __shared_state = {"cursors": {}} + + def __init__(self): + self.__dict__ = self.__shared_state + + def get_cursor(self, cur_type): + if not self.cursors.has_key(cur_type): + cur = gtk.gdk.Cursor(cur_type) + self.cursors[cur_type] = cur + return self.cursors[cur_type] + class Activity(toolkit.Activity): """Basic activity class""" @@ -57,6 +70,10 @@ class Activity(toolkit.Activity): """ raise NotImplementedError + def on_save_instance(self, cb, *args): + """ Register callback which will be invoked before save_instance """ + self.__on_save_instance.append((cb, args)) + def share_instance(self, connection, is_initiator): """ Activity was shared/joined. @@ -98,6 +115,17 @@ class Activity(toolkit.Activity): alert.show_all() self.add_alert(alert) + def get_cursor(self): + return self._cursor + + def set_cursor(self, cursor): + if not isinstance(cursor, gtk.gdk.Cursor): + cursor = CursorFactory().get_cursor(cursor) + + if self._cursor != cursor: + self._cursor = cursor + self.window.set_cursor(self._cursor) + def __init__(self, canvas, handle): """ Initialise the Activity. @@ -120,6 +148,10 @@ class Activity(toolkit.Activity): self.__resume_filename = None self.__postponed_share = [] + self.__on_save_instance = [] + + self._cursor = None + self.set_cursor(gtk.gdk.LEFT_PTR) # XXX do it after(possible) read_file() invoking # have to rely on calling read_file() from map_cb in sugar-toolkit @@ -153,6 +185,8 @@ class Activity(toolkit.Activity): def write_file(self, filepath): """Subclass should not override this method""" + for cb, args in self.__on_save_instance: + cb(*args) self.save_instance(filepath) def __map_canvasactivity_cb(self, widget): diff --git a/port/chooser.py b/port/chooser.py index b7046be..e2df259 100644 --- a/port/chooser.py +++ b/port/chooser.py @@ -34,9 +34,9 @@ def pick(cb=None, default=None, parent=None, what=None): * cb(jobject), if object was choosen and cb is not None * jobject, if object was choosen and cb is None - * None, otherwise + * default, otherwise - NOTE: what make sense only for sugar >= 0.84 + NOTE: 'what' makes sense only for sugar >= 0.84 """ what = what and {'what_filter': what} or {} chooser = ObjectChooser(parent=parent, **what) diff --git a/port/epydoc b/port/epydoc deleted file mode 100644 index 3e4852c..0000000 --- a/port/epydoc +++ /dev/null @@ -1,21 +0,0 @@ -[epydoc] - -modules: *.py -output: html -target: html/ -verbosity: 0 -debug: 0 - -# Generation options -docformat: epytext -parse: yes -introspect: no -inheritance: listed -private: no -imports: no -sourcecode: yes - -# Output options -name: sugar-port -url: http://wiki.sugarlabs.org/go/Development_Team/sugar-port -frames: yes diff --git a/port/images/tempo1.svg b/port/images/tempo1.svg deleted file mode 100644 index bb9aeec..0000000 --- a/port/images/tempo1.svg +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
-<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M23.5,6.5c3,3,7,7,9,11c-7,5-4,6-3,26c-1,1-8,1-9,0c0,0,2,1,2-1
- c0-3-2-7-2-11c0-2,1-4,1-6c0-3-2-1-2-3c0-3,3-8,3-11c0-2-1-1-2-2v-3H23.5z"/>
-</svg>
diff --git a/port/images/tempo2.svg b/port/images/tempo2.svg deleted file mode 100644 index 4a98310..0000000 --- a/port/images/tempo2.svg +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
-<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M27.5,44.5v-3C28.5,42.5,28.5,43.5,27.5,44.5z M26.5,10.5
- c2,2,2,6,2,8c0,4-3,11-3,13s4,7,7,10c-2,2-4,3-5,5h-6c1-1,2-3,2-5c0-3-2-9-3-14c0,0,0-1-1,0v-6c0-3,3-8,3-11c0-1-2-2-2-6h3
- C23.5,5.5,26.5,9.5,26.5,10.5z"/>
-</svg>
diff --git a/port/images/tempo3.svg b/port/images/tempo3.svg deleted file mode 100644 index bd893bd..0000000 --- a/port/images/tempo3.svg +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
-<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M30.5,17.5c0,3-2,2-2,4c0,3,4,14,7,21c-1,0-3,1-5,1c1-1,2,0,2-3
- c0-2-4-7-6-10c-3,3-5,8-7,13c-1,0-3-1-4-1c3-3,7-14,7-18s-1-3-4-4c3-2,4-8,4-14h3C23.5,9.5,30.5,14.5,30.5,17.5z"/>
-</svg>
diff --git a/port/images/tempo4.svg b/port/images/tempo4.svg deleted file mode 100644 index 6fa5afa..0000000 --- a/port/images/tempo4.svg +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
-<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M34.5,22.5c-1-1-2-4-5-6c-1,2,0,3,0,6c0,2-3,4-3,7c0,2,4,2,4,4
- c0,3-1,4-2,5c0-1,0-3-1-4c-1,3-2,7-3,10c-4-3,0-6,0-9s-3-11-4-17l-4,4c1-5,8.25-11.12,7.25-16.12c0.68,0.68,3.029,0,2.87,2.12
- C26.5,10.25,33.62,17.75,34.5,22.5z"/>
-</svg>
diff --git a/port/images/tempo5.svg b/port/images/tempo5.svg deleted file mode 100644 index 9500e7e..0000000 --- a/port/images/tempo5.svg +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
-<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M24.5,13.5c2,1,5,3,5,6c0,2-2,3-2,5c0,9,11,4,11,13c-1,0-3-2-4-3
- c-3-1-9,1-10-3c-2,3-5,7-7,11c-3,0-3-1-4-1c0-2,3-3,4-6s4-8,4-10c0-3-1-3-2-5c-1,0-2,1-3,2c0-1,2-3,2-4c1-2,3-5,2-8c0,0,1-1,4-2
- C25.5,9.5,25.5,11.5,24.5,13.5z"/>
-</svg>
diff --git a/port/images/tempo6.svg b/port/images/tempo6.svg deleted file mode 100644 index 9844fd6..0000000 --- a/port/images/tempo6.svg +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
-<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M22.5,10.5c3,2,7,5,7,7c0,3-4,8-4,10c0,3,1,3,1,5h5l2-2l2,2v4
- c-1,0-3-2-5-2c-3,0-5,1-8,1c-1,3-2,7-2,10h-5c1-1,3-3,3-4c1-5,1-11,1-18l-1-1c-1,1-1.75,2.88-2.75,2.88c0,0-0.25-0.63-0.25-1.63
- c4-4,2-8.25,2-13.25c0-1,0.25-2.5,0.38-5.38L22.5,5.5C23.12,6.5,22.5,8.5,22.5,10.5z"/>
-<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#333333" stroke="#333333" stroke-linecap="round" stroke-linejoin="round" points="
- 25,20 25.25,16.75 26.5,17.88 "/>
-</svg>
diff --git a/port/images/tempo7.svg b/port/images/tempo7.svg deleted file mode 100644 index 54bed80..0000000 --- a/port/images/tempo7.svg +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
-<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M20.5,7.5c1,1,1,3,1,4c10,4,8,6,8,14c0,2,6,9,10,13c-1,2-2,4-4,5
- c1.62-8.88-8.75-13.88-12-15c-1,1-1,0-1,2c0,3,2,5,3,7c-1,1-3,2-6,2c0-1,2-1,2-4c0-2-4-4-4-6c0-3,3-4,5-6c-3-8-8-2-11-6h6
- c0-1,1,0,1-3c0-2-1-1-2-2l1-5H20.5z"/>
-</svg>
diff --git a/port/images/tempo8.svg b/port/images/tempo8.svg deleted file mode 100644 index 2c0154f..0000000 --- a/port/images/tempo8.svg +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
-<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M20.5,12.5c0.67,0.4,0.4,1.9,1.75,2.25s1.05-0.38,1.5-0.37
- c4.971,0,10.95-0.88,11.75,7.12c-1-2-3-4-5-5l-4,1c1,2,4,4,5,7c1,1,1,4,1,6c3,3,8-1,11,6c-2.88-0.82-4.25-2.62-12.75-2.75
- c-1.561-0.02-2.34-1.561-3.75-1.87c-3.42-0.76-4.67-0.38-5.5-0.38c-3,0-8,7-11,7c-2,0-3-1-3-2c4,2,8-4,9-7c2-1,5-1,8-3c-2-4-6-5-8-3
- l-6-6l2-2c1,1,1,2,1,4c1,0,4.12,0.38,6.12-0.62L16.5,17.5v-5H20.5z"/>
-</svg>
diff --git a/port/pixbuf.py b/port/pixbuf.py index 4390fef..ba6d0f5 100644 --- a/port/pixbuf.py +++ b/port/pixbuf.py @@ -14,10 +14,16 @@ """gtk.gdk.Pixbuf extensions""" +import re import os import cStringIO -import tempfile import gtk +import rsvg +import cairo +import logging + +from sugar.graphics.xocolor import XoColor +from sugar.util import LRU def to_file(pixbuf): """Convert pixbuf object to file object""" @@ -38,13 +44,170 @@ def to_str(pixbuf): def from_str(str): """Convert string to pixbuf object""" - file_d, path = tempfile.mkstemp() + loader = gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') + loader.write(str) + loader.close() + + return loader.get_pixbuf() + +def from_svg_at_size(filename=None, width=None, height=None, handle=None, + keep_ratio=True): + """Scale and load SVG into pixbuf""" + + if not handle: + handle = rsvg.Handle(filename) + + dimensions = handle.get_dimension_data() + icon_width = dimensions[0] + icon_height = dimensions[1] + + if icon_width != width or icon_height != height: + ratio_width = float(width) / icon_width + ratio_height = float(height) / icon_height + + if keep_ratio: + ratio = min(ratio_width, ratio_height) + if ratio_width != ratio: + ratio_width = ratio + width = int(icon_width * ratio) + elif ratio_height != ratio: + ratio_height = ratio + height = int(icon_height * ratio) + else: + ratio_width = 1 + ratio_height = 1 + + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + context = cairo.Context(surface) + context.scale(ratio_width, ratio_height) + handle.render_cairo(context) + + loader = gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') + surface.write_to_png(loader) + loader.close() + + return loader.get_pixbuf() + +def sugar_icon(file_name=None, icon_name=None, + width=None, height=None, + color=None, + insensitive_widget=None): + """Load sugar icon into pixbuf + + NOTE: Function can load all image formats but makes sense only for SVG + (due to color argument, see load_svg()) + + NOTE: Function caches results + + Arguments: + file_name path to filename with image + (mutually exclusive for icon_name) + icon_name name of icon + (mutually exclusive for icon_name) + width width of final image + height height of final image + color defines stroke and fill colors for final SVG image + in string notion, could be: + * tuple of (stroke_color, fill_color) + * XoColor + * scalar value for stroke and fill colors + insensitive_widget render icon in insensitive mode + """ + def load_svg(): + entities = {} + if fill_color: + entities['fill_color'] = fill_color + if stroke_color: + entities['stroke_color'] = stroke_color + + f = open(icon_filename, 'r') + icon = f.read() + f.close() + + for entity, value in entities.items(): + xml = '<!ENTITY %s "%s">' % (entity, value) + icon = re.sub('<!ENTITY %s .*>' % entity, xml, icon) + + return rsvg.Handle(data=icon) + + def get_insensitive_pixbuf(): + if not (insensitive_widget and insensitive_widget.style): + return pixbuf + + icon_source = gtk.IconSource() + # Special size meaning "don't touch" + icon_source.set_size(-1) + icon_source.set_pixbuf(pixbuf) + icon_source.set_state(gtk.STATE_INSENSITIVE) + icon_source.set_direction_wildcarded(False) + icon_source.set_size_wildcarded(False) + + # Please note that the pixbuf returned by this function is leaked + # with current stable versions of pygtk. The relevant bug is + # http://bugzilla.gnome.org/show_bug.cgi?id=502871 + # -- 2007-12-14 Benjamin Berg + pixbuf = insensitive_widget.style.render_icon(icon_source, + insensitive_widget.get_direction(), gtk.STATE_INSENSITIVE, -1, + insensitive_widget, "sugar-icon") + + return pixbuf + + def get_cache_key(): + return (icon_filename, fill_color, stroke_color, width, height, + insensitive_widget is None) + + if isinstance(color, XoColor): + stroke_color = color.get_stroke_color() + fill_color = color.get_fill_color() + elif isinstance(color, tuple): + stroke_color = color[0] + fill_color = color[1] + else: + stroke_color = color + fill_color = color + + if file_name: + icon_filename = file_name + elif icon_name: + theme = gtk.icon_theme_get_default() + info = theme.lookup_icon(icon_name, width or 50, 0) + if info: + icon_filename = info.get_filename() + del info + else: + logging.warning('No icon with the name %s ' + 'was found in the theme.' % icon_name) + else: + return None + + cache_key = get_cache_key() + if cache_key in _sugar_icon_cache: + return _sugar_icon_cache[cache_key] + + logging.debug('sugar_icon: file_name=%s icon_name=%s width=%s height=%s ' \ + 'color=%s' % (file_name, icon_name, width, height, color)) + + is_svg = icon_filename.endswith('.svg') + + if is_svg: + handle = load_svg() + if width and height: + pixbuf = from_svg_at_size(handle=handle, width=width, height=height, + keep_ratio=True) + else: + pixbuf = handle.get_pixbuf() + else: + if width and height: + pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(icon_filename, + width, height) + else: + pixbuf = gtk.gdk.pixbuf_new_from_file(icon_filename) + + if insensitive_widget: + pixbuf = get_insensitive_pixbuf() - file_o = os.fdopen(file_d, 'w') - file_o.write(str) - file_o.close() + _sugar_icon_cache[cache_key] = pixbuf - out = gtk.gdk.pixbuf_new_from_file(path) - os.unlink(path) + return pixbuf - return out +_sugar_icon_cache = LRU(50) diff --git a/port/port b/port/port deleted file mode 120000 index 945c9b4..0000000 --- a/port/port +++ /dev/null @@ -1 +0,0 @@ -.
\ No newline at end of file diff --git a/port/tarball.py b/port/tarball.py index d07a3e1..9e842b9 100644 --- a/port/tarball.py +++ b/port/tarball.py @@ -23,8 +23,6 @@ import zipfile import tempfile import shutil -import port.pixbuf as pixbuf - class TarballError(Exception): """Base Tarball exception.""" pass @@ -124,7 +122,10 @@ class Tarball: def read_pixbuf(self, arcname): """Returns pixbuf object of given file from tarball.""" - return pixbuf.from_str(self.read(arcname)) + loader = gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') + loader.write(self.read(arcname)) + loader.close() + return loader.get_pixbuf() def write(self, arcname, data, mode=0644): """ @@ -147,8 +148,12 @@ class Tarball: self.__tar.addfile(info, cStringIO.StringIO(data)) def __write_pixbuf(self, info, data): - buffer = pixbuf.to_file(data) - buffer.seek(0, os.SEEK_END) + def push(pixbuf, buffer): + buffer.write(pixbuf) + + buffer = cStringIO.StringIO() + data.save_to_callback(push, 'png', user_data=buffer) + info.size = buffer.tell() buffer.seek(0) self.__tar.addfile(info, buffer) diff --git a/port/temposlider.py b/port/temposlider.py index 9d14be8..6950453 100644 --- a/port/temposlider.py +++ b/port/temposlider.py @@ -12,8 +12,9 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import os import gtk +import rsvg +import cairo from sugar.graphics import style @@ -26,7 +27,7 @@ class TempoSlider(gtk.HBox): self._image.show() # used to store tempo updates while the slider is active - self._delayed = 0 + self._delayed = 0 self._active = False self.adjustment = gtk.Adjustment(min_value, min_value, max_value, @@ -68,10 +69,10 @@ class TempoSlider(gtk.HBox): self.adjustment.upper, 0, 7) if not self._pixbuf[img]: - self._pixbuf[img] = gtk.gdk.pixbuf_new_from_file_at_size( - os.path.join(os.path.dirname(__file__), 'images', - 'tempo' + str(img+1) + '.svg'), - style.STANDARD_ICON_SIZE, style.STANDARD_ICON_SIZE) + svg = rsvg.Handle(data=IMAGE[img]) + self._pixbuf[img] = _from_svg_at_size(handle=svg, + width=style.STANDARD_ICON_SIZE, + height=style.STANDARD_ICON_SIZE) self._image.set_from_pixbuf(self._pixbuf[img]) @@ -83,3 +84,132 @@ class TempoSlider(gtk.HBox): if self._delayed != 0: self.set_value(self._delayed, True) self._delayed = 0 + +def _from_svg_at_size(filename=None, width=None, height=None, handle=None, + keep_ratio=True): + """ import from pixbuf.py """ + + if not handle: + handle = rsvg.Handle(filename) + + dimensions = handle.get_dimension_data() + icon_width = dimensions[0] + icon_height = dimensions[1] + + if icon_width != width or icon_height != height: + ratio_width = float(width) / icon_width + ratio_height = float(height) / icon_height + + if keep_ratio: + ratio = min(ratio_width, ratio_height) + if ratio_width != ratio: + ratio_width = ratio + width = int(icon_width * ratio) + elif ratio_height != ratio: + ratio_height = ratio + height = int(icon_height * ratio) + else: + ratio_width = 1 + ratio_height = 1 + + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + context = cairo.Context(surface) + context.scale(ratio_width, ratio_height) + handle.render_cairo(context) + + loader = gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') + surface.write_to_png(loader) + loader.close() + + return loader.get_pixbuf() + +IMAGE = [None] * 8 + +IMAGE[0] = """<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve"> +<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M23.5,6.5c3,3,7,7,9,11c-7,5-4,6-3,26c-1,1-8,1-9,0c0,0,2,1,2-1 + c0-3-2-7-2-11c0-2,1-4,1-6c0-3-2-1-2-3c0-3,3-8,3-11c0-2-1-1-2-2v-3H23.5z"/> +</svg> +""" + +IMAGE[1] = """<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve"> +<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M27.5,44.5v-3C28.5,42.5,28.5,43.5,27.5,44.5z M26.5,10.5 + c2,2,2,6,2,8c0,4-3,11-3,13s4,7,7,10c-2,2-4,3-5,5h-6c1-1,2-3,2-5c0-3-2-9-3-14c0,0,0-1-1,0v-6c0-3,3-8,3-11c0-1-2-2-2-6h3 + C23.5,5.5,26.5,9.5,26.5,10.5z"/> +</svg> +""" + +IMAGE[2] = """<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve"> +<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M30.5,17.5c0,3-2,2-2,4c0,3,4,14,7,21c-1,0-3,1-5,1c1-1,2,0,2-3 + c0-2-4-7-6-10c-3,3-5,8-7,13c-1,0-3-1-4-1c3-3,7-14,7-18s-1-3-4-4c3-2,4-8,4-14h3C23.5,9.5,30.5,14.5,30.5,17.5z"/> +</svg> +""" + +IMAGE[3] = """<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve"> +<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M34.5,22.5c-1-1-2-4-5-6c-1,2,0,3,0,6c0,2-3,4-3,7c0,2,4,2,4,4 + c0,3-1,4-2,5c0-1,0-3-1-4c-1,3-2,7-3,10c-4-3,0-6,0-9s-3-11-4-17l-4,4c1-5,8.25-11.12,7.25-16.12c0.68,0.68,3.029,0,2.87,2.12 + C26.5,10.25,33.62,17.75,34.5,22.5z"/> +</svg> +""" + +IMAGE[4] = """<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve"> +<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M24.5,13.5c2,1,5,3,5,6c0,2-2,3-2,5c0,9,11,4,11,13c-1,0-3-2-4-3 + c-3-1-9,1-10-3c-2,3-5,7-7,11c-3,0-3-1-4-1c0-2,3-3,4-6s4-8,4-10c0-3-1-3-2-5c-1,0-2,1-3,2c0-1,2-3,2-4c1-2,3-5,2-8c0,0,1-1,4-2 + C25.5,9.5,25.5,11.5,24.5,13.5z"/> +</svg> +""" + +IMAGE[5] = """<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve"> +<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M22.5,10.5c3,2,7,5,7,7c0,3-4,8-4,10c0,3,1,3,1,5h5l2-2l2,2v4 + c-1,0-3-2-5-2c-3,0-5,1-8,1c-1,3-2,7-2,10h-5c1-1,3-3,3-4c1-5,1-11,1-18l-1-1c-1,1-1.75,2.88-2.75,2.88c0,0-0.25-0.63-0.25-1.63 + c4-4,2-8.25,2-13.25c0-1,0.25-2.5,0.38-5.38L22.5,5.5C23.12,6.5,22.5,8.5,22.5,10.5z"/> +<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#333333" stroke="#333333" stroke-linecap="round" stroke-linejoin="round" points=" + 25,20 25.25,16.75 26.5,17.88 "/> +</svg> +""" + +IMAGE[6] = """<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve"> +<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M20.5,7.5c1,1,1,3,1,4c10,4,8,6,8,14c0,2,6,9,10,13c-1,2-2,4-4,5 + c1.62-8.88-8.75-13.88-12-15c-1,1-1,0-1,2c0,3,2,5,3,7c-1,1-3,2-6,2c0-1,2-1,2-4c0-2-4-4-4-6c0-3,3-4,5-6c-3-8-8-2-11-6h6 + c0-1,1,0,1-3c0-2-1-1-2-2l1-5H20.5z"/> +</svg> +""" + +IMAGE[7] = """<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve"> +<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M20.5,12.5c0.67,0.4,0.4,1.9,1.75,2.25s1.05-0.38,1.5-0.37 + c4.971,0,10.95-0.88,11.75,7.12c-1-2-3-4-5-5l-4,1c1,2,4,4,5,7c1,1,1,4,1,6c3,3,8-1,11,6c-2.88-0.82-4.25-2.62-12.75-2.75 + c-1.561-0.02-2.34-1.561-3.75-1.87c-3.42-0.76-4.67-0.38-5.5-0.38c-3,0-8,7-11,7c-2,0-3-1-3-2c4,2,8-4,9-7c2-1,5-1,8-3c-2-4-6-5-8-3 + l-6-6l2-2c1,1,1,2,1,4c1,0,4.12,0.38,6.12-0.62L16.5,17.5v-5H20.5z"/> +</svg> +""" |