Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/tutorius
diff options
context:
space:
mode:
Diffstat (limited to 'tutorius')
-rw-r--r--tutorius/addon.py13
-rw-r--r--tutorius/properties.py23
-rw-r--r--tutorius/propwidgets.py110
3 files changed, 142 insertions, 4 deletions
diff --git a/tutorius/addon.py b/tutorius/addon.py
index ca729ae..1fd5143 100644
--- a/tutorius/addon.py
+++ b/tutorius/addon.py
@@ -78,9 +78,16 @@ def create(name, *args, **kwargs):
comp_metadata = _cache[name]
try:
return comp_metadata['class'](*args, **kwargs)
- except:
- logging.debug("Could not instantiate %s with parameters %s, %s"%(comp_metadata['name'],str(args), str(kwargs)))
- return None
+ except Exception, e:
+ LOGGER.error("Could not instantiate %s with parameters %s, %s"%\
+ (comp_metadata['name'],str(args), str(kwargs)))
+
+ # fetch frame information to complement exception with traceback
+ type, value, tb = sys.exc_info()
+ formatted_tb = traceback.format_tb(tb)
+ LOGGER.error('Error loadin tutorius add-on named [%s]:\n%s\n%s' % \
+ (name, '\n'.join(formatted_tb), str(e)))
+ return None
except KeyError:
logging.debug("Addon not found for class '%s'", name)
return None
diff --git a/tutorius/properties.py b/tutorius/properties.py
index b363a2a..1905117 100644
--- a/tutorius/properties.py
+++ b/tutorius/properties.py
@@ -37,7 +37,8 @@ from .propwidgets import PropWidget, \
IntPropWidget, \
FloatPropWidget, \
IntArrayPropWidget, \
- ResourcePropWidget
+ ResourcePropWidget, \
+ ScreenClipPropWidget
import logging
LOGGER = logging.getLogger("properties")
@@ -390,6 +391,26 @@ class TResourceProperty(TutoriusProperty):
self.default = self.validate("")
+class TScreenClipProperty(TResourceProperty):
+ """
+ Represents an image resource from a screen capture
+
+ When the system encounters a resource, it knows that it refers to a file in
+ the resource folder and that it should translate this resource name to an
+ absolute file name before it is executed.
+ """
+
+ widget_class = ScreenClipPropWidget
+
+ def __init__(self, *args, **kwargs):
+ """
+ Creates a new resource pointing to an existing resource.
+
+ @param resource_name The file name of the resource (should be only the
+ file name itself, no directory information)
+ """
+ super(TScreenClipProperty, self).__init__(*args, **kwargs)
+
class TEnumProperty(TutoriusProperty):
"""
Represents a value in a given enumeration. This means that the value will
diff --git a/tutorius/propwidgets.py b/tutorius/propwidgets.py
index 3debf98..0e6c200 100644
--- a/tutorius/propwidgets.py
+++ b/tutorius/propwidgets.py
@@ -24,6 +24,8 @@ from jarabe.journal.objectchooser import ObjectChooser
from sugar.datastore.datastore import DSObject
from sugar import mime
import uuid
+import tempfile
+import os
import logging
LOGGER = logging.getLogger("sugar.tutorius.propwidgets")
@@ -570,3 +572,111 @@ class ResourcePropWidget(PropWidget):
"""
raise RuntimeError('Cannot select a default resource')
+class ScreenClipPropWidget(PropWidget):
+ """Allows adding and changing tutorial resources."""
+ def _on_drag_end(self, widget, event, pixbuf):
+ from . import creator
+ widget.destroy()
+
+ end_x, end_y = event.get_coords()
+ width = abs(end_x - self.start_x)
+ height = abs(end_y - self.start_y)
+ x_off = min(self.start_x, end_x)
+ y_off = min(self.start_y, end_y)
+
+ cropped = pixbuf.subpixbuf(x_off, y_off, width, height)
+
+ tmp_name = tempfile.mktemp(suffix='.png')
+ try:
+ cropped.save(tmp_name, 'png')
+ creator_obj = creator.default_creator()
+ resource_id = creator_obj.set_resource(self.obj_prop, tmp_name)
+ self.obj_prop = resource_id
+ finally:
+ os.unlink(tmp_name)
+
+ self.notify()
+
+ def _on_drag_start(self, widget, event, pixbuf):
+ widget.connect('button-release-event', self._on_drag_end, pixbuf)
+ widget.connect('motion-notify-event', self._on_drag_move, pixbuf)
+ self.start_x, self.start_y = event.get_coords()
+
+ def _on_drag_move(self, widget, event, pixbuf):
+ if gtk.gdk.events_pending():
+ return
+
+ end_x, end_y = event.get_coords()
+ width = abs(end_x - self.start_x)
+ height = abs(end_y - self.start_y)
+ x_off = min(self.start_x, end_x)
+ y_off = min(self.start_y, end_y)
+
+ ctx = widget.window.cairo_create()
+ ctx.set_source_pixbuf(pixbuf, 0, 0)
+ ctx.paint()
+
+ ctx.set_source_rgb(0, 0, 0)
+ ctx.rectangle(x_off, y_off, width, height)
+ ctx.stroke()
+
+ def _get_capture(self, widget):
+ """
+ Select a resource and add it through the creator.
+ This is expected to run in the same process, alongside the creator.
+ """
+ # take screen capture
+ root = gtk.gdk.get_default_root_window()
+ width, height = root.get_size()
+ pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8,
+ width, height)
+ pixbuf.get_from_drawable(src=root,
+ cmap=gtk.gdk.colormap_get_system(),
+ src_x=0, src_y=0,
+ dest_x=0, dest_y=0,
+ width=width, height=height)
+
+ win = gtk.Window()
+ image = gtk.Image()
+ image.set_from_pixbuf(pixbuf)
+ win.add(image)
+ win.show_all()
+ win.set_app_paintable(True)
+ win.fullscreen()
+ win.present()
+ win.add_events(gtk.gdk.BUTTON_PRESS_MASK | \
+ gtk.gdk.BUTTON_RELEASE_MASK | \
+ gtk.gdk.POINTER_MOTION_MASK)
+ win.connect('button-press-event', self._on_drag_start, pixbuf)
+
+ def create_widget(self, init_value=None):
+ """
+ Create the Edit Widget for a property
+ @param init_value initial value
+ @return gtk.Widget
+ """
+ propwdg = gtk.Button("Clip Screen")
+ propwdg.connect_after("clicked", self._get_capture)
+ return propwdg
+
+ def refresh_widget(self):
+ """
+ Force the widget to update it's value in case the property has changed
+ """
+ # Nothing to refresh
+ pass
+
+ @classmethod
+ def run_dialog(cls, parent, obj_prop, propname):
+ """
+ Class Method.
+ Prompts the user for changing an object's property
+ @param parent widget
+ @param obj_prop TPropContainer to edit
+ @param propname name of property to edit
+ """
+ # TODO We're assuming all reasource creation is done from the creator
+ # and not from the probe since there is a requirement to know the guid
+ # to add resources. But for this resource type, this could technically
+ # be done in the probe.
+ raise RuntimeError('Cannot select a default resource')