[sugar] Read activity modifications

Don Hopkins dhopkins
Thu May 10 02:07:20 EDT 2007


I've been working on making the Read activity usable in book mode, and 
adding other improvements.
I'm updating it to work against the latest build, and I'll put up a tar 
file soon.
Here's a summary of my changes and ideas for further improvements.

    -Don

Loading icons for gtk buttons from SVG files.
  Wrote a LoadIcon(fileName) function that loads an svg file and returns 
a GTK pixbuf.
    TODO: support different file formats (XPM, PNG, PDF, etc).
    TODO: support scaling of the image to a particular size.
    TODO: caching images according to file name and size.
  Made a gtk.IconFactory for the activity.
    Loop over all SVG files in the icons subdirectory of the bundle path.
      Loaded all SVG files into icon pixbufs, wrapped them in IconSets, 
and added them to the icon manager.
      TODO: make a smart IconFactory that supports lazy loading of icons.
  Icons are named the same as the file name with the extension stripped 
off.
  Icons should have a prefix like "read-" to distinguish them from other 
icons (like the "stock-" icons).
  GTK widgets can be configured to use named icons by setting their 
stock-id property.

Implement a new set of toolbars and buttons using custom "Action" 
classes and UIManager.
  Defined SugarAction, SugarToggleAction, SugarRadioAction subclasses of 
stock GTK Action classes, mixing in SugarActionMixin.
  Defined SugarToolButton, SugarToggleToolButton, SugarRadioToolButton 
subclasses of GTK ToolButton classes, mixing in SugarWidgetMixin.
  Defined SugarActionMixin and SugarWidgetMixin classes for shared 
Sugar-specific behavior and state.
    Added support for "allowed" property, like "sensitive" (enabled), 
but it will let you set the focus to the control and see a tooltip 
telling the reason it's not allowed.
    Added support for "reason" property, a translated text string that 
explains the reason an action is not allowed to the user.
    TODO: Implement visual indication of "allow" state.
    TODO: Make actions show tooltip with disallow reason if user tries 
to invoke un-allowed control, but not invoke callback.
  Rewrote gtk.ActionGroup methods add_actions, add_toggle_actions, 
add_radio_actions in Python instead of C (from pygtk).
    Instead of making them differently named class-specific methods of 
gtk.ActionGroup, I re-factored them into generic "add_actions" methods 
on the corresponding classes.
    So instead of calling action_group.add_toggle_actions(entries), you 
call SugarToggleAction.add_actions(action_group, entries), or whatever 
class you want to add.
    This makes it much easier to extend the system with your own sets of 
Actions and Widgets, by subclassing SugarAction, and mixin 
SugarWidgetMixin into the widget.
      TODO: Implement search string entry field, page number entry 
field, page count label, as application specific Action/Widget sets.
    The gtk.ActionGroup add_*_actions api took a list of entries, where 
each entry was a tuple with positional arguments filled with "None" 
placeholders.
    That was brittle and hard to use, and impossible to extend by adding 
new parameters.
    Instead, the new interface takes a list of entries, where each entry 
is a dictionary instead of a tuple, so it's possible to pass additional 
arguments and omit unused keys.
    The dictionary entry based API is more open-ended and flexible, so 
we can seamlessly add additional parameters in the future without 
breaking the API.
    Defined optional "action_class" parameter to each entry that 
specifies the class to make, which defaults to "self", the class you're 
calling the add_action class method on.
      So subclasses of Action will automatically get instances of their 
class when you call add_action on their class.
      TODO: Factor out any class-specific behavior from add_actions into 
class method hooks, so Action subclasses can define their own hooks 
instead of redefining their own entire add_action methods.
    Defined optional *args and **kwargs parameters to add_actions, as 
well as to each entry, which are merged and passed to the callback.
    You can specify additional parameters to each set of actions you 
create at once, and to each individual action, which makes it possible 
to define more general purpose actions that you can customize with 
parameters and additional callbacks, instead of defining a new special 
purpose Action class for each control.

Made a UIManager to create the toolbars from an XML user interface 
description.
  TODO: Implement an open-ended extensible Pythonic SugarUIManager.
  TODO: Allow the applilcation to register new action classes 
corresponding to XML elements in the user interface descriptions.
  TODO: Extend the SugarUIManager to support other kinds of interfaces 
beyond toolbars and menus: gamepad navigation, pie menus, etc.

Implement enabling and disabling actions and toolbar buttons.
  Actions automatically take care of enabling and disabling all of their 
corresponding toolbar buttons and menu items (proxies).
  Implemented a higher level _set_action_sensitive(self, action_name, 
sensitive, reason=None) interface for setting the sensitivity and reason 
an action is insensitive, which lets you pass a translated string that 
describes why an action is disabled, that helps the user figure out what 
to do about it.
  Wrote code to call _set_action_sensitive at the appropriate time to 
enable and disable evince controls (back page, next page, first page, 
last page, zoom in, zoom out).
  TODO: Use "allowed" instead of "sensitive" to disable controls, so the 
user can navigate to them and see tooltips about why they're disabled.

Defined SugarActions for most of the interesting evince functions, 
SugarToggleActions for boolean properties, SugarRadioAction for 
enumerated properties.
Defined toolbars with buttons and separators to control evince.
Made icons for all of the buttons (first cut placeholder programmer art 
for now: round buttons with tiny text labels).

Defined a _bundle_path instance variable in XbookActivity that tells 
where the root of the Read activity bundle is.
Added a _startup_file_name instance variable to XbookActivity, 
initialized to "userguide.pdf" that's read from the documents 
sub-directory of the bundle_path.
  This is currently to help me test the Read activity, because the "open 
file" button is no longer supported.
  But the default startup document could be used to throw up a useful 
introduction with links to libraries and documentation. (Once links in 
PDF documents work properly).

Wrote a "MANIFEST" file that lists all the files to be installed into 
the activity directory.
  If you don't have a "MANIFEST" file, the activity builder looks at the 
subversion source code control system to figure out which files to 
bundle, which doesn't work during development before the files have been 
added to source code control.

    -Don




More information about the Sugar-devel mailing list