diff options
author | Walter Bender <walter@sugarlabs.org> | 2013-07-19 16:55:19 (GMT) |
---|---|---|
committer | Walter Bender <walter@sugarlabs.org> | 2013-07-19 16:55:19 (GMT) |
commit | 84db297f0ef771c69c67fb94c975ef052441725f (patch) | |
tree | 201b88decc6cee5c6337241611cf8a502b15612c |
new project
-rw-r--r-- | activity.py | 179 | ||||
-rw-r--r-- | activity/activity.info | 8 | ||||
-rw-r--r-- | activity/activity.svg | 86 | ||||
-rw-r--r-- | icons/image-save.svg | 88 |
4 files changed, 361 insertions, 0 deletions
diff --git a/activity.py b/activity.py new file mode 100644 index 0000000..8c2c224 --- /dev/null +++ b/activity.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2011-2013 Walter Bender + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# You should have received a copy of the GNU General Public License +# along with this library; if not, write to the Free Software +# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA + +import os +import glob + +from sugar3.activity import activity +from sugar3.graphics.toolbarbox import ToolbarBox +from sugar3.activity.widgets import StopButton +from sugar3.graphics.toolbutton import ToolButton +from sugar3.activity.widgets import _create_activity_icon as ActivityIcon +from sugar3.graphics.alert import NotifyAlert +from sugar3.graphics import style +from sugar3.datastore import datastore +from sugar3 import profile + +from gi.repository import Gtk +from gi.repository import Gdk +from gi.repository import GdkPixbuf +from gi.repository import GObject + +from gettext import gettext as _ + +MIME_TYPES = {'svg': 'image/svg+xml', 'png': 'image/png', 'gif': 'image/gif', + 'jpg': 'image/jpg'} + + +class ClipArtActivity(activity.Activity): + + def __init__(self, handle): + activity.Activity.__init__(self, handle, False) + + self._selected_image = None + self.max_participants = 1 + + self.toolbar_box = ToolbarBox() + self.toolbar = self.toolbar_box.toolbar + + activity_button = ToolButton() + icon = ActivityIcon(None) + activity_button.set_icon_widget(icon) + activity_button.set_tooltip(self.get_title()) + stop_button = StopButton(self) + + separator = Gtk.SeparatorToolItem() + separator.props.draw = False + separator.set_expand(True) + + self.save_button = ToolButton('image-save') + self.save_button.set_tooltip(_('Save to Journal')) + self.save_button.connect('clicked', self._save_to_journal) + self.save_button.set_sensitive(False) + + self.toolbar.insert(activity_button, 0) + self.toolbar.insert(Gtk.SeparatorToolItem(), -1) + self.toolbar.insert(self.save_button, -1) + + self.toolbar.insert(separator, -1) + self.toolbar.insert(stop_button, -1) + + artwork_paths = self._scan() + + scrolled_window = Gtk.ScrolledWindow() + scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN) + scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, + Gtk.PolicyType.AUTOMATIC) + self.set_canvas(scrolled_window) + scrolled_window.show() + + store = Gtk.ListStore(GdkPixbuf.Pixbuf, str) + + icon_view = Gtk.IconView.new_with_model(store) + icon_view.set_selection_mode(Gtk.SelectionMode.SINGLE) + icon_view.connect('selection-changed', self._clipart_selected, + store) + icon_view.set_pixbuf_column(0) + icon_view.grab_focus() + scrolled_window.add(icon_view) + icon_view.show() + + self.set_toolbar_box(self.toolbar_box) + self.set_canvas(self.canvas) + self.show_all() + + self._notify() + GObject.idle_add(fill_clipart_list, store, artwork_paths) + + def _save_to_journal(self, widget): + if self._selected_image is None: + return + + basename = os.path.basename(self._selected_image) + dsobject = datastore.create() + dsobject.metadata['title'] = basename[:-4] + dsobject.metadata['icon-color'] = profile.get_color().to_string() + dsobject.metadata['mime_type'] = MIME_TYPES[basename.split('.')[-1]] + dsobject.set_file_path(self._selected_image) + datastore.write(dsobject) + dsobject.destroy() + + self.save_button.set_sensitive(False) + + def _get_selected_path(self, widget, store): + try: + iter_ = store.get_iter(widget.get_selected_items()[0]) + image_path = store.get(iter_, 1)[0] + + return image_path, iter_ + except: + return None + + def _clipart_selected(self, widget, store): + selected = self._get_selected_path(widget, store) + + if selected is None: + self._selected_image = None + self.save_button.set_sensitive(False) + return + + image_path, _iter = selected + iter_ = store.get_iter(widget.get_selected_items()[0]) + image_path = store.get(iter_, 1)[0] + + self._selected_image = image_path + self.save_button.set_sensitive(True) + + def _scan(self): + # We need a list of all the .png, .jpg, .gif, and .svg files + # in ~/Activities. We don't need to search Documents since + # that is already available through the Journal. + root_path = os.path.join(os.path.expanduser('~'), 'Activities') + artwork_paths = [] + for suffix in ['.png', '.jpg', '.gif', '.svg']: + # Look in ~/Activities/* and ~/Activities/*/* + file_list = glob.glob(os.path.join(root_path, '*', '*' + suffix)) + for f in file_list: + artwork_paths.append(f) + file_list = glob.glob(os.path.join(root_path, '*', '*', + '*' + suffix)) + for f in file_list: + artwork_paths.append(f) + return artwork_paths + + def _notify(self): + alert = NotifyAlert() + alert.props.title = _('Scanning for clipart') + msg = _('Please wait.') + alert.props.msg = msg + + def remove_alert(alert, response_id): + self.remove_alert(alert) + + alert.connect('response', remove_alert) + self.add_alert(alert) + + +def fill_clipart_list(store, artwork_paths): + ''' + Append images from the artwork_paths to the store. + ''' + for filepath in artwork_paths: + pixbuf = None + try: + pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( + filepath, style.XLARGE_ICON_SIZE, + style.XLARGE_ICON_SIZE) + except: + pass + else: + store.append([pixbuf, filepath]) diff --git a/activity/activity.info b/activity/activity.info new file mode 100644 index 0000000..6a1ce09 --- /dev/null +++ b/activity/activity.info @@ -0,0 +1,8 @@ +[Activity] +name = ClipArt +bundle_id = org.sugarlabs.ClipArt +icon = activity +exec = sugar-activity activity.ClipArtActivity +show_launcher = yes +activity_version = 1 +summary = displays available clipart that can be saved to the Sugar Journal diff --git a/activity/activity.svg b/activity/activity.svg new file mode 100644 index 0000000..e6a4c60 --- /dev/null +++ b/activity/activity.svg @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ + <!ENTITY fill_color "#FFFFFF"> + <!ENTITY stroke_color "#010101"> +]> +<svg + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg3059" + style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round"> +<g + transform="matrix(0.55205508,0,0,0.55205508,77.118464,18.235971)" + id="g4382"><g + transform="translate(-80.093659,12.220029)" + id="g4308" + style="fill:none;stroke:&stroke_color;;stroke-opacity:1"> + <g + id="g4310" + style="fill:none;stroke:&stroke_color;;stroke-opacity:1"> + <path + d="m 6.736,49.002 h 24.52 c 2.225,0 3.439,-1.447 3.439,-3.441 v -27.28 c 0,-1.73 -1.732,-3.441 -3.439,-3.441 h -4.389" + id="path4312" + style="fill:none;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g><g + transform="translate(-80.093659,12.220029)" + id="g4314" + style="fill:none;stroke:&stroke_color;;stroke-opacity:1"> + <g + id="g4316" + style="fill:none;stroke:&stroke_color;;stroke-opacity:1"> + <path + d="m 26.867,38.592 c 0,1.836 -1.345,3.201 -3.441,4.047 L 6.736,49.002 V 14.84 l 16.69,-8.599 c 2.228,-0.394 3.441,0.84 3.441,2.834 v 29.517 z" + id="path4318" + style="fill:none;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g><path + d="m -70.669659,54.827029 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543" + id="path4320" + style="fill:none;stroke:&stroke_color;;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,44.226029 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543" + id="path4322" + style="fill:none;stroke:&stroke_color;;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,33.898029 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544" + id="path4324" + style="fill:none;stroke:&stroke_color;;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><line + style="fill:none;stroke:&stroke_color;;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + x1="-66.884659" + x2="-66.884659" + y1="58.753029" + y2="23.725029" + id="line4326" /></g><g + transform="matrix(1.1623273,0,0,1.1623273,-14.422024,-12.63995)" + id="g3882" + style="fill:none;stroke:&stroke_color;;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"><g + id="g3884" + style="fill:none;stroke:&stroke_color;;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><polygon + points="43.041,21.577 35.281,13.812 15.204,13.812 15.204,35.189 43.041,35.189 " + id="polygon3886" + style="fill:none;stroke:&stroke_color;;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><polyline + id="polyline3888" + points="35.281,13.812 35.281,21.577 43.041,21.577 " + style="fill:none;stroke:&stroke_color;;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g><path + d="m 19.426691,12.275117 c -4.727185,0 -8.666312,4.714399 -8.666312,4.714399 0,0 3.939127,4.737646 8.666312,4.735322 4.729509,-0.0046 8.668637,-4.739971 8.668637,-4.739971 0,0 -3.939128,-4.713237 -8.668637,-4.70975 z m 0,8.039818 c -1.830666,0 -3.314958,-1.484292 -3.314958,-3.31612 0,-1.827179 1.484292,-3.314958 3.314958,-3.314958 1.828341,0 3.312632,1.487779 3.312632,3.314958 0,1.831828 -1.484291,3.31612 -3.312632,3.31612 z" + id="path3890" + style="fill:&stroke_color;;fill-opacity:1;stroke:none;display:inline" /><circle + cx="29.207001" + cy="25.863001" + r="1.294" + transform="matrix(1.1623273,0,0,1.1623273,-14.520241,-13.061294)" + id="circle3892" + style="fill:&fill_color;;fill-opacity:1;stroke:&stroke_color;;stroke-opacity:1;display:inline" /><g + transform="matrix(1,0,0,-1,-24.850339,47.707501)" + id="g4770"><g + transform="translate(34.0803,-1006.42)" + id="g4772"><polyline + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" + style="fill:none;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + points="51.562,15.306 41.17,16.188 42.053,5.794" + id="polyline4774" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776" + style="fill:none;stroke:&stroke_color;;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></svg> diff --git a/icons/image-save.svg b/icons/image-save.svg new file mode 100644 index 0000000..26523e6 --- /dev/null +++ b/icons/image-save.svg @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"> +<g + transform="matrix(0.55205508,0,0,0.55205508,77.118464,18.235971)" + id="g4382"><g + transform="translate(-80.093659,12.220029)" + id="g4308" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <g + id="g4310" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <path + d="m 6.736,49.002 h 24.52 c 2.225,0 3.439,-1.447 3.439,-3.441 v -27.28 c 0,-1.73 -1.732,-3.441 -3.439,-3.441 h -4.389" + id="path4312" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g><g + transform="translate(-80.093659,12.220029)" + id="g4314" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <g + id="g4316" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <path + d="m 26.867,38.592 c 0,1.836 -1.345,3.201 -3.441,4.047 L 6.736,49.002 V 14.84 l 16.69,-8.599 c 2.228,-0.394 3.441,0.84 3.441,2.834 v 29.517 z" + id="path4318" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g><path + d="m -70.669659,54.827029 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543" + id="path4320" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,44.226029 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543" + id="path4322" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,33.898029 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544" + id="path4324" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><line + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + x1="-66.884659" + x2="-66.884659" + y1="58.753029" + y2="23.725029" + id="line4326" /></g><g + transform="matrix(1.1623273,0,0,1.1623273,-14.422024,-12.63995)" + id="g3882" + style="fill:none;stroke:#ffffff;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"><g + id="g3884" + style="fill:none;stroke:#ffffff;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><polygon + points="43.041,21.577 35.281,13.812 15.204,13.812 15.204,35.189 43.041,35.189 " + id="polygon3886" + style="fill:none;stroke:#ffffff;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><polyline + id="polyline3888" + points="35.281,13.812 35.281,21.577 43.041,21.577 " + style="fill:none;stroke:#ffffff;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g><path + d="m 19.426691,12.275117 c -4.727185,0 -8.666312,4.714399 -8.666312,4.714399 0,0 3.939127,4.737646 8.666312,4.735322 4.729509,-0.0046 8.668637,-4.739971 8.668637,-4.739971 0,0 -3.939128,-4.713237 -8.668637,-4.70975 z m 0,8.039818 c -1.830666,0 -3.314958,-1.484292 -3.314958,-3.31612 0,-1.827179 1.484292,-3.314958 3.314958,-3.314958 1.828341,0 3.312632,1.487779 3.312632,3.314958 0,1.831828 -1.484291,3.31612 -3.312632,3.31612 z" + id="path3890" + style="fill:#ffffff;fill-opacity:1;stroke:none;display:inline" /><circle + cx="29.207001" + cy="25.863001" + r="1.294" + transform="matrix(1.1623273,0,0,1.1623273,-14.520241,-13.061294)" + id="circle3892" + style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;display:inline" /><g + transform="matrix(1,0,0,-1,-24.850339,47.707501)" + id="g4770"><g + transform="translate(34.0803,-1006.42)" + id="g4772"><polyline + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + points="51.562,15.306 41.17,16.188 42.053,5.794" + id="polyline4774" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></svg> |