PEP8 white space and long line fixes

master
Sascha Silbe 15 years ago
parent ecdaf6b795
commit c9e63eb8ea

@ -74,7 +74,9 @@ from sugar.session import XSMPClient
from sugar import wm
# support deprecated imports
from sugar.activity.widgets import ActivityToolbar, EditToolbar, ActivityToolbox
from sugar.activity.widgets import ActivityToolbar, EditToolbar
from sugar.activity.widgets import ActivityToolbox
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
@ -86,17 +88,20 @@ J_DBUS_SERVICE = 'org.laptop.Journal'
J_DBUS_PATH = '/org/laptop/Journal'
J_DBUS_INTERFACE = 'org.laptop.Journal'
class _ActivitySession(gobject.GObject):
__gsignals__ = {
'quit-requested': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'quit': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
'quit': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
}
def __init__(self):
gobject.GObject.__init__(self)
self._xsmp_client = XSMPClient()
self._xsmp_client.connect('quit-requested', self.__sm_quit_requested_cb)
self._xsmp_client.connect('quit-requested',
self.__sm_quit_requested_cb)
self._xsmp_client.connect('quit', self.__sm_quit_cb)
self._xsmp_client.startup()
@ -133,6 +138,7 @@ class _ActivitySession(gobject.GObject):
def __sm_quit_cb(self, client):
self.emit('quit')
class Activity(Window, gtk.Container):
"""This is the base Activity class that all other Activities derive from.
This is where your activity starts.
@ -160,12 +166,12 @@ class Activity(Window, gtk.Container):
2. Implement read_file() and write_file()
Most activities revolve around creating and storing Journal entries.
For example, Write: You create a document, it is saved to the Journal
and then later you resume working on the document.
For example, Write: You create a document, it is saved to the
Journal and then later you resume working on the document.
read_file() and write_file() will be called by sugar to tell your
Activity that it should load or save the document the user is working
on.
Activity that it should load or save the document the user is
working on.
3. Implement our Activity Toolbars.
The Toolbars are added to your Activity in step 1 (the toolbox), but
@ -177,9 +183,9 @@ class Activity(Window, gtk.Container):
okay, but you should really stop and think about why not!) You do
this with the ActivityToolbox(self) call in step 1.
Usually, you will also need the standard EditToolbar. This is the one
which has the standard copy and paste buttons. You need to derive
your own EditToolbar class from sugar.EditToolbar:
Usually, you will also need the standard EditToolbar. This is the
one which has the standard copy and paste buttons. You need to
derive your own EditToolbar class from sugar.EditToolbar:
class EditToolbar(activity.EditToolbar):
...
@ -200,11 +206,12 @@ class Activity(Window, gtk.Container):
Hint: A good and simple Activity to learn from is the Read activity. To
create your own activity, you may want to copy it and use it as a template.
"""
__gtype_name__ = 'SugarActivity'
__gsignals__ = {
'shared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
}
def __init__(self, handle, create_jobject=True):
@ -368,8 +375,8 @@ class Activity(Window, gtk.Container):
The activity id is sort-of-like the unix process id (PID). However,
unlike PIDs it is only different for each new instance (with
create_jobject = True set) and stays the same everytime a user
resumes an activity. This is also the identity of your Activity to other
XOs for use when sharing.
resumes an activity. This is also the identity of your Activity to
other XOs for use when sharing.
"""
return self._activity_id
@ -378,7 +385,8 @@ class Activity(Window, gtk.Container):
return os.environ['SUGAR_BUNDLE_ID']
def set_canvas(self, canvas):
"""Sets the 'work area' of your activity with the canvas of your choice.
"""Sets the 'work area' of your activity with the canvas of your
choice.
One commonly used canvas is gtk.ScrolledWindow
"""
@ -425,8 +433,8 @@ class Activity(Window, gtk.Container):
~/.sugar/default/MyActivityName/
Activities should ONLY save settings, user preferences and other data
which isn't specific to a journal item here. If (meta-)data is in anyway
specific to a journal entry, it MUST be stored in the DataStore.
which isn't specific to a journal item here. If (meta-)data is in
anyway specific to a journal entry, it MUST be stored in the DataStore.
"""
if os.environ.has_key('SUGAR_ACTIVITY_ROOT') and \
os.environ['SUGAR_ACTIVITY_ROOT']:
@ -446,9 +454,10 @@ class Activity(Window, gtk.Container):
close it.
Although not required, this is also a good time to read all meta-data:
the file itself cannot be changed externally, but the title, description
and other metadata['tags'] may change. So if it is important for you to
notice changes, this is the time to record the originals.
the file itself cannot be changed externally, but the title,
description and other metadata['tags'] may change. So if it is
important for you to notice changes, this is the time to record the
originals.
"""
raise NotImplementedError
@ -461,12 +470,13 @@ class Activity(Window, gtk.Container):
all document data to it.
Additionally, you should also write any metadata needed to resume your
activity. For example, the Read activity saves the current page and zoom
level, so it can display the page.
activity. For example, the Read activity saves the current page and
zoom level, so it can display the page.
Note: Currently, the file_path *WILL* be different from the one you
received in file_read(). Even if you kept the file_path from file_read()
open until now, you must still write the entire file to this file_path.
received in file_read(). Even if you kept the file_path from
file_read() open until now, you must still write the entire file to
this file_path.
"""
raise NotImplementedError
@ -518,6 +528,7 @@ class Activity(Window, gtk.Container):
gtk.gdk.INTERP_BILINEAR)
preview_data = []
def save_func(buf, data):
data.append(buf)
@ -809,8 +820,10 @@ class Activity(Window, gtk.Container):
# DEPRECATED
_shared_activity = property(lambda self: self.shared_activity, None)
_session = None
def _get_session():
global _session
@ -819,14 +832,17 @@ def _get_session():
return _session
def get_bundle_name():
"""Return the bundle name for the current process' bundle"""
return os.environ['SUGAR_BUNDLE_NAME']
def get_bundle_path():
"""Return the bundle path for the current process' bundle"""
return os.environ['SUGAR_BUNDLE_PATH']
def get_activity_root():
"""Returns a path for saving Activity specific preferences, etc."""
if os.environ.has_key('SUGAR_ACTIVITY_ROOT') and \
@ -835,6 +851,7 @@ def get_activity_root():
else:
raise RuntimeError("No SUGAR_ACTIVITY_ROOT set.")
def show_object_in_journal(object_id):
bus = dbus.SessionBus()
obj = bus.get_object(J_DBUS_SERVICE, J_DBUS_PATH)

@ -54,6 +54,8 @@ try:
MAXFD = os.sysconf("SC_OPEN_MAX")
except ValueError:
MAXFD = 256
def _close_fds():
for i in xrange(3, MAXFD):
try:
@ -62,6 +64,7 @@ def _close_fds():
except Exception:
pass
def create_activity_id():
"""Generate a new, unique ID for this activity"""
pservice = presenceservice.get_instance()
@ -84,6 +87,7 @@ def create_activity_id():
return act_id
raise RuntimeError("Cannot generate unique activity id.")
def get_environment(activity):
environ = os.environ.copy()
@ -106,15 +110,17 @@ def get_environment(activity):
os.mkdir(tmp_dir)
environ['SUGAR_BUNDLE_PATH'] = activity.get_path()
environ['SUGAR_BUNDLE_ID'] = activity.get_bundle_id()
environ['SUGAR_BUNDLE_ID'] = activity.get_bundle_id()
environ['SUGAR_ACTIVITY_ROOT'] = activity_root
environ['PATH'] = bin_path + ':' + environ['PATH']
if activity.get_path().startswith(env.get_user_activities_path()):
environ['SUGAR_LOCALEDIR'] = os.path.join(activity.get_path(), 'locale')
environ['SUGAR_LOCALEDIR'] = os.path.join(activity.get_path(),
'locale')
return environ
def get_command(activity, activity_id=None, object_id=None, uri=None):
if not activity_id:
activity_id = create_activity_id()
@ -140,6 +146,7 @@ def get_command(activity, activity_id=None, object_id=None, uri=None):
return command
def open_log_file(activity):
i = 1
while True:
@ -154,10 +161,11 @@ def open_log_file(activity):
i += 1
elif e.errno == ENOSPC:
# not the end of the world; let's try to keep going.
return ('/dev/null', open('/dev/null','w'))
return ('/dev/null', open('/dev/null', 'w'))
else:
raise e
class ActivityCreationHandler(gobject.GObject):
"""Sugar-side activity creation interface
@ -250,7 +258,7 @@ class ActivityCreationHandler(gobject.GObject):
'-u', pwd.getpwuid(os.getuid()).pw_name,
'-i', environ['SUGAR_BUNDLE_ID'],
'-e', environment_dir,
'--'
'--',
] + command
for key, value in environ.items():
@ -310,25 +318,29 @@ class ActivityCreationHandler(gobject.GObject):
logging.error('Datastore find failed %s', err)
self._launch_activity()
def create(bundle, activity_handle=None):
"""Create a new activity from its name."""
if not activity_handle:
activity_handle = ActivityHandle()
return ActivityCreationHandler(bundle, activity_handle)
def create_with_uri(bundle, uri):
"""Create a new activity and pass the uri as handle."""
activity_handle = ActivityHandle(uri=uri)
return ActivityCreationHandler(bundle, activity_handle)
def create_with_object_id(bundle, object_id):
"""Create a new activity and pass the object id as handle."""
activity_handle = ActivityHandle(object_id=object_id)
return ActivityCreationHandler(bundle, activity_handle)
# FIXME we use standalone method here instead of ActivityCreationHandler's
# member to have workaround code, see #1123
def _child_watch_cb(pid, condition, user_data):
# FIXME we use standalone method here instead of ActivityCreationHandler's
# member to have workaround code, see #1123
environment_dir, log_file = user_data
if environment_dir is not None:
subprocess.call(['/bin/rm', '-rf', environment_dir])

@ -19,11 +19,11 @@
STABLE.
"""
class ActivityHandle(object):
"""Data structure storing simple activity metadata"""
def __init__(
self, activity_id=None, object_id=None, uri=None
):
def __init__(self, activity_id=None, object_id=None, uri=None):
"""Initialise the handle from activity_id
activity_id -- unique id for the activity to be
@ -52,7 +52,7 @@ class ActivityHandle(object):
def get_dict(self):
"""Retrieve our settings as a dictionary"""
result = { 'activity_id' : self.activity_id }
result = {'activity_id': self.activity_id}
if self.object_id:
result['object_id'] = self.object_id
if self.uri:
@ -60,11 +60,10 @@ class ActivityHandle(object):
return result
def create_from_dict(handle_dict):
"""Create a handle from a dictionary of parameters"""
result = ActivityHandle(
handle_dict['activity_id'],
result = ActivityHandle(handle_dict['activity_id'],
object_id = handle_dict.get('object_id'),
uri = handle_dict.get('uri'),
)
uri = handle_dict.get('uri'))
return result

@ -24,10 +24,12 @@ import logging
import dbus
import dbus.service
_ACTIVITY_SERVICE_NAME = "org.laptop.Activity"
_ACTIVITY_SERVICE_PATH = "/org/laptop/Activity"
_ACTIVITY_INTERFACE = "org.laptop.Activity"
class ActivityService(dbus.service.Object):
"""Base dbus service object that each Activity uses to export dbus methods.
@ -51,7 +53,7 @@ class ActivityService(dbus.service.Object):
activity_id = activity.get_id()
service_name = _ACTIVITY_SERVICE_NAME + activity_id
object_path = _ACTIVITY_SERVICE_PATH + "/" + activity_id
object_path = _ACTIVITY_SERVICE_PATH + '/' + activity_id
bus = dbus.SessionBus()
bus_name = dbus.service.BusName(service_name, bus=bus)
@ -79,4 +81,3 @@ class ActivityService(dbus.service.Object):
self._activity.get_document_path(async_cb, async_err_cb)
except Exception, e:
async_err_cb(e)

@ -34,9 +34,11 @@ from fnmatch import fnmatch
from sugar import env
from sugar.bundle.activitybundle import ActivityBundle
IGNORE_DIRS = ['dist', '.git']
IGNORE_FILES = ['.gitignore', 'MANIFEST', '*.pyc', '*~', '*.bak', 'pseudo.po']
def list_files(base_dir, ignore_dirs=None, ignore_files=None):
result = []
@ -58,7 +60,9 @@ def list_files(base_dir, ignore_dirs=None, ignore_files=None):
return result
class Config(object):
def __init__(self, source_dir=None, dist_dir = None, dist_name = None):
self.source_dir = source_dir or os.getcwd()
self.dist_dir = dist_dir or os.path.join(self.source_dir, 'dist')
@ -80,7 +84,7 @@ class Config(object):
self.version = bundle.get_activity_version()
self.activity_name = bundle.get_name()
self.bundle_id = bundle.get_bundle_id()
self.bundle_name = reduce(lambda x, y:x+y, self.activity_name.split())
self.bundle_name = reduce(lambda x, y: x+y, self.activity_name.split())
self.bundle_root_dir = self.bundle_name + '.activity'
self.tar_root_dir = '%s-%d' % (self.bundle_name, self.version)
@ -90,7 +94,9 @@ class Config(object):
self.xo_name = '%s-%d.xo' % (self.bundle_name, self.version)
self.tar_name = '%s-%d.tar.bz2' % (self.bundle_name, self.version)
class Builder(object):
def __init__(self, config):
self.config = config
@ -167,7 +173,9 @@ class Builder(object):
for line in manifest:
f.write(line + "\n")
class Packager(object):
def __init__(self, config):
self.config = config
self.package_path = None
@ -175,7 +183,9 @@ class Packager(object):
if not os.path.exists(self.config.dist_dir):
os.mkdir(self.config.dist_dir)
class XOPackager(Packager):
def __init__(self, builder):
Packager.__init__(self, builder.config)
@ -200,7 +210,9 @@ class XOPackager(Packager):
bundle_zip.close()
class SourcePackager(Packager):
def __init__(self, config):
Packager.__init__(self, config)
self.package_path = os.path.join(self.config.dist_dir,
@ -210,7 +222,7 @@ class SourcePackager(Packager):
git_ls = subprocess.Popen(['git', 'ls-files'], stdout=subprocess.PIPE,
cwd=self.config.source_dir)
stdout, _ = git_ls.communicate()
if git_ls.returncode :
if git_ls.returncode:
# Fall back to filtered list
return list_files(self.config.source_dir,
IGNORE_DIRS, IGNORE_FILES)
@ -224,8 +236,9 @@ class SourcePackager(Packager):
os.path.join(self.config.tar_root_dir, f))
tar.close()
class Installer(object):
IGNORES = [ 'po/*', 'MANIFEST', 'AUTHORS' ]
IGNORES = ['po/*', 'MANIFEST', 'AUTHORS']
def __init__(self, builder):
self.config = builder.config
@ -261,6 +274,7 @@ class Installer(object):
shutil.copy(source, dest)
def cmd_dev(config, args):
'''Setup for development'''
@ -280,6 +294,7 @@ def cmd_dev(config, args):
else:
print 'ERROR - A bundle with the same name is already installed.'
def cmd_dist_xo(config, args):
'''Create a xo bundle package'''
@ -290,6 +305,7 @@ def cmd_dist_xo(config, args):
packager = XOPackager(Builder(config))
packager.package()
def cmd_fix_manifest(config, args):
'''Add missing files to the manifest'''
@ -300,6 +316,7 @@ def cmd_fix_manifest(config, args):
builder = Builder(config)
builder.fix_manifest()
def cmd_dist_source(config, args):
'''Create a tar source package'''
@ -310,6 +327,7 @@ def cmd_dist_source(config, args):
packager = SourcePackager(config)
packager.package()
def cmd_install(config, args):
'''Install the activity in the system'''
@ -324,6 +342,7 @@ def cmd_install(config, args):
installer = Installer(Builder(config))
installer.install(suboptions.prefix)
def cmd_genpot(config, args):
'''Generate the gettext pot file'''
@ -354,14 +373,15 @@ def cmd_genpot(config, args):
f.write('msgstr ""\n')
f.close()
args = [ 'xgettext', '--join-existing', '--language=Python',
'--keyword=_', '--add-comments=TRANS:', '--output=%s' % pot_file ]
args = ['xgettext', '--join-existing', '--language=Python',
'--keyword=_', '--add-comments=TRANS:', '--output=%s' % pot_file]
args += python_files
retcode = subprocess.call(args)
if retcode:
print 'ERROR - xgettext failed with return code %i.' % retcode
def cmd_build(config, args):
'''Build generated files'''
@ -372,6 +392,7 @@ def cmd_build(config, args):
builder = Builder(config)
builder.build()
def print_commands():
print 'Available commands:\n'
@ -382,6 +403,7 @@ def print_commands():
print '\n(Type "./setup.py <command> --help" for help about a ' \
'particular command\'s options.'
def start(bundle_name=None):
if bundle_name:
logging.warn("bundle_name deprecated, now comes from activity.info")
@ -397,5 +419,6 @@ def start(bundle_name=None):
except (KeyError, IndexError):
print_commands()
if __name__ == '__main__':
start()

@ -30,17 +30,22 @@ from sugar.activity import activityhandle
from sugar.bundle.activitybundle import ActivityBundle
from sugar import logger
def create_activity_instance(constructor, handle):
activity = constructor(handle)
activity.show()
def get_single_process_name(bundle_id):
return bundle_id
def get_single_process_path(bundle_id):
return '/' + bundle_id.replace('.', '/')
class SingleProcess(dbus.service.Object):
def __init__(self, name_service, constructor):
self.constructor = constructor
@ -54,6 +59,7 @@ class SingleProcess(dbus.service.Object):
handle = activityhandle.create_from_dict(handle_dict)
create_activity_instance(self.constructor, handle)
def main():
parser = OptionParser()
parser.add_option("-b", "--bundle-id", dest="bundle_id",

@ -35,8 +35,10 @@ from sugar.graphics.canvastextview import CanvasTextView
from sugar.bundle.activitybundle import ActivityBundle
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
def _get_icon_name(metadata):
file_name = None
@ -53,16 +55,17 @@ def _get_icon_name(metadata):
return file_name
class NamingToolbar(gtk.Toolbar):
""" Toolbar of the naming alert
"""
__gtype_name__ = 'SugarNamingToolbar'
__gsignals__ = {
'keep-clicked': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([]))
'keep-clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
}
def __init__(self):
gtk.Toolbar.__init__(self)
@ -110,7 +113,9 @@ class NamingToolbar(gtk.Toolbar):
def __keep_button_clicked_cb(self, widget, data=None):
self.emit('keep-clicked')
class FavoriteIcon(CanvasIcon):
def __init__(self, favorite):
CanvasIcon.__init__(self, icon_name='emblem-favorite',
box_width=style.GRID_CELL_SIZE * 3 / 5,
@ -149,7 +154,9 @@ class FavoriteIcon(CanvasIcon):
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg()
class NamingAlert(gtk.Window):
__gtype_name__ = 'SugarNamingAlert'
def __init__(self, activity, bundle_path):
@ -212,11 +219,12 @@ class NamingAlert(gtk.Window):
spacing=style.DEFAULT_SPACING)
body.append(header)
descriptions = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL,
spacing=style.DEFAULT_SPACING * 3,
padding_left=style.GRID_CELL_SIZE,
padding_right=style.GRID_CELL_SIZE,
padding_top=style.DEFAULT_SPACING * 3)
descriptions = hippo.CanvasBox(
orientation=hippo.ORIENTATION_HORIZONTAL,
spacing=style.DEFAULT_SPACING * 3,
padding_left=style.GRID_CELL_SIZE,
padding_right=style.GRID_CELL_SIZE,
padding_top=style.DEFAULT_SPACING * 3)
body.append(descriptions, hippo.PACK_EXPAND)

@ -29,6 +29,7 @@ from sugar.graphics.xocolor import XoColor
from sugar.graphics.icon import Icon
from sugar.bundle.activitybundle import ActivityBundle
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
@ -41,7 +42,9 @@ def _create_activity_icon():
icon = Icon(file=bundle.get_icon(), xo_color=color)
return icon
class ActivityButton(ToolButton):
def __init__(self, activity, **kwargs):
ToolButton.__init__(self, **kwargs)
@ -55,7 +58,9 @@ class ActivityButton(ToolButton):
def __jobject_updated_cb(self, jobject):
self.props.tooltip = jobject['title']
class ActivityToolbarButton(ToolbarButton):
def __init__(self, activity, **kwargs):
toolbar = ActivityToolbar(activity, orientation_left=True)
toolbar.stop.hide()
@ -66,7 +71,9 @@ class ActivityToolbarButton(ToolbarButton):
self.set_icon_widget(icon)
icon.show()
class StopButton(ToolButton):
def __init__(self, activity, **kwargs):
ToolButton.__init__(self, 'activity-stop', **kwargs)
self.props.tooltip = _('Stop')
@ -76,28 +83,38 @@ class StopButton(ToolButton):
def __stop_button_clicked_cb(self, button, activity):
activity.close()
class UndoButton(ToolButton):
def __init__(self, **kwargs):
ToolButton.__init__(self, 'edit-undo', **kwargs)
self.props.tooltip = _('Undo')
self.props.accelerator = '<Ctrl>Q'
class RedoButton(ToolButton):
def __init__(self, **kwargs):
ToolButton.__init__(self, 'edit-redo', **kwargs)
self.props.tooltip = _('Redo')
class CopyButton(ToolButton):
def __init__(self, **kwargs):
ToolButton.__init__(self, 'edit-copy', **kwargs)
self.props.tooltip = _('Copy')
class PasteButton(ToolButton):
def __init__(self, **kwargs):
ToolButton.__init__(self, 'edit-paste', **kwargs)
self.props.tooltip = _('Paste')
class ShareButton(RadioMenuButton):
def __init__(self, activity, **kwargs):
palette = RadioPalette()
@ -137,7 +154,9 @@ class ShareButton(RadioMenuButton):
finally:
self.neighborhood.handler_unblock(self._neighborhood_handle)
class KeepButton(ToolButton):
def __init__(self, activity, **kwargs):
ToolButton.__init__(self, **kwargs)
self.props.tooltip = _('Keep')
@ -154,7 +173,9 @@ class KeepButton(ToolButton):
def __keep_button_clicked_cb(self, button, activity):
activity.copy()
class TitleEntry(gtk.ToolItem):
def __init__(self, activity, **kwargs):
gtk.ToolItem.__init__(self)
self.set_expand(False)
@ -195,6 +216,7 @@ class TitleEntry(gtk.ToolItem):
self._update_title_sid = None
return False
class ActivityToolbar(gtk.Toolbar):
"""The Activity toolbar with the Journal entry title, sharing,
Keep and Stop buttons
@ -202,6 +224,7 @@ class ActivityToolbar(gtk.Toolbar):
All activities should have this toolbar. It is easiest to add it to your
Activity by using the ActivityToolbox.
"""
def __init__(self, activity, orientation_left=False):
gtk.Toolbar.__init__(self)
@ -232,6 +255,7 @@ class ActivityToolbar(gtk.Toolbar):
self.insert(self.stop, -1)
self.stop.show()
class EditToolbar(gtk.Toolbar):
"""Provides the standard edit toolbar for Activities.
@ -265,6 +289,7 @@ class EditToolbar(gtk.Toolbar):
# And make it visible:
self._edit_toolbar.show()
"""
def __init__(self):
gtk.Toolbar.__init__(self)
@ -289,6 +314,7 @@ class EditToolbar(gtk.Toolbar):
self.insert(self.paste, -1)
self.paste.show()
class ActivityToolbox(Toolbox):
"""Creates the Toolbox for the Activity
@ -307,6 +333,7 @@ class ActivityToolbox(Toolbox):
# And make it visible:
toolbox.show()
"""
def __init__(self, activity):
Toolbox.__init__(self)

@ -31,6 +31,7 @@ from sugar import util
from sugar.bundle.bundle import Bundle, \
MalformedBundleException, NotInstalledException
class ActivityBundle(Bundle):
"""A Sugar activity bundle
@ -89,8 +90,8 @@ class ActivityBundle(Bundle):
return ret
def _read_manifest(self):
"""return a list with the lines in MANIFEST, with invalid lines replaced
by empty lines.
"""return a list with the lines in MANIFEST, with invalid lines
replaced by empty lines.
Since absolute order carries information on file history, it should
be preserved. For instance, when renaming a file, you should leave
@ -170,7 +171,7 @@ class ActivityBundle(Bundle):
if cp.has_option(section, 'mime_types'):
mime_list = cp.get(section, 'mime_types').strip(';')
self._mime_types = [ mime.strip() for mime in mime_list.split(';') ]
self._mime_types = [mime.strip() for mime in mime_list.split(';')]
if cp.has_option(section, 'show_launcher'):
if cp.get(section, 'show_launcher') == 'no':
@ -251,10 +252,10 @@ class ActivityBundle(Bundle):
"""Get the activity bundle id"""
return self._bundle_id
# FIXME: this should return the icon data, not a filename, so that
# we don't need to create a temp file in the zip case
def get_icon(self):
"""Get the activity icon name"""
# FIXME: this should return the icon data, not a filename, so that
# we don't need to create a temp file in the zip case
icon_path = os.path.join('activity', self._icon + '.svg')
if self._zip_file is None:
return os.path.join(self._path, icon_path)
@ -301,7 +302,7 @@ class ActivityBundle(Bundle):
# List installed files
manifestfiles = self.get_files(self._raw_manifest())
paths = []
paths = []
for root, dirs_, files in os.walk(install_path):
rel_path = root[len(install_path) + 1:]
for f in files:
@ -320,7 +321,7 @@ class ActivityBundle(Bundle):
# Is anything in MANIFEST left over after accounting for all files?
if manifestfiles:
err = ("Bundle %s: files in MANIFEST not included: %s"%
(self._name,str(manifestfiles)))
(self._name, str(manifestfiles)))
if strict_manifest:
raise MalformedBundleException(err)
else:
@ -351,7 +352,7 @@ class ActivityBundle(Bundle):
mime_types = self.get_mime_types()
if mime_types is not None:
installed_icons_dir = os.path.join(xdg_data_home,
'icons/sugar/scalable/mimetypes')
'icons/sugar/scalable/mimetypes')
if not os.path.isdir(installed_icons_dir):
os.makedirs(installed_icons_dir)
@ -390,7 +391,7 @@ class ActivityBundle(Bundle):
mime_types = self.get_mime_types()
if mime_types is not None:
installed_icons_dir = os.path.join(xdg_data_home,
'icons/sugar/scalable/mimetypes')
'icons/sugar/scalable/mimetypes')
if os.path.isdir(installed_icons_dir):
for f in os.listdir(installed_icons_dir):
path = os.path.join(installed_icons_dir, f)

@ -26,24 +26,31 @@ import shutil
import StringIO
import zipfile
class AlreadyInstalledException(Exception):
pass
class NotInstalledException(Exception):
pass
class InvalidPathException(Exception):
pass
class ZipExtractException(Exception):
pass
class RegistrationException(Exception):
pass
class MalformedBundleException(Exception):
pass
class Bundle(object):
"""A Sugar activity, content module, etc.
@ -71,7 +78,7 @@ class Bundle(object):
# manifest = self._get_file(self._infodir + '/contents')
# if manifest is None:
# raise MalformedBundleException('No manifest file')
#
# signature = self._get_file(self._infodir + '/contents.sig')
# if signature is None:
# raise MalformedBundleException('No signature file')
@ -112,7 +119,7 @@ class Bundle(object):
if self._zip_file is None:
path = os.path.join(self._path, filename)
try:
f = open(path,"rb")
f = open(path, "rb")
except IOError:
return None
else:

@ -29,6 +29,7 @@ from sugar import env
from sugar.bundle.bundle import Bundle, NotInstalledException, \
MalformedBundleException
class ContentBundle(Bundle):
"""A Sugar content bundle
@ -78,8 +79,8 @@ class ContentBundle(Bundle):
try:
if int(version) != 1:
raise MalformedBundleException(
'Content bundle %s has unknown host_version number %s' %
(self._path, version))
'Content bundle %s has unknown host_version '
'number %s' % (self._path, version))
except ValueError:
raise MalformedBundleException(
'Content bundle %s has invalid host_version number %s' %
@ -209,17 +210,17 @@ class ContentBundle(Bundle):
def get_start_uri(self):
return "file://" + urllib.pathname2url(self.get_start_path())
# TODO treat ContentBundle in special way
# needs rethinking while fixing ContentBundle support
def get_bundle_id(self):
# TODO treat ContentBundle in special way
# needs rethinking while fixing ContentBundle support
if self._bundle_class is not None:
return self._bundle_class
else:
return self._global_name
# TODO treat ContentBundle in special way
# needs rethinking while fixing ContentBundle support
def get_activity_version(self):
# TODO treat ContentBundle in special way
# needs rethinking while fixing ContentBundle support
return self._library_version
def is_installed(self):

@ -29,10 +29,10 @@ import gobject
from sugar.datastore import dbus_helpers
from sugar import mime
class DSMetadata(gobject.GObject):
__gsignals__ = {
'updated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([]))
'updated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
}
def __init__(self, props=None):
@ -80,7 +80,9 @@ class DSMetadata(gobject.GObject):
else:
return default
class DSObject(object):
def __init__(self, object_id, metadata=None, file_path=None):
self.object_id = object_id
self._metadata = metadata
@ -129,13 +131,14 @@ class DSObject(object):
def __del__(self):
if not self._destroyed:
logging.warning('DSObject was deleted without cleaning up first. ' \
logging.warning('DSObject was deleted without cleaning up first. '
'Call DSObject.destroy() before disposing it.')
self.destroy()
def copy(self):
return DSObject(None, self._metadata.copy(), self._file_path)
def get(object_id):
logging.debug('datastore.get')
metadata = dbus_helpers.get_properties(object_id)
@ -144,12 +147,14 @@ def get(object_id):
# TODO: register the object for updates
return ds_object
def create():
metadata = DSMetadata()
metadata['mtime'] = datetime.now().isoformat()
metadata['timestamp'] = int(time.time())
return DSObject(object_id=None, metadata=metadata, file_path=None)
def write(ds_object, update_mtime=True, transfer_ownership=False,
reply_handler=None, error_handler=None, timeout=-1):
logging.debug('datastore.write')
@ -185,10 +190,12 @@ def write(ds_object, update_mtime=True, transfer_ownership=False,
# TODO: register the object for updates
logging.debug('Written object %s to the datastore.', ds_object.object_id)
def delete(object_id):
logging.debug('datastore.delete')
dbus_helpers.delete(object_id)
def find(query, sorting=None, limit=None, offset=None, properties=None,
reply_handler=None, error_handler=None):
@ -217,6 +224,7 @@ def find(query, sorting=None, limit=None, offset=None, properties=None,
return objects, total_count
def copy(jobject, mount_point):
new_jobject = jobject.copy()
@ -238,17 +246,22 @@ def copy(jobject, mount_point):
write(new_jobject)
def mount(uri, options, timeout=-1):
return dbus_helpers.mount(uri, options, timeout=timeout)
def unmount(mount_point_id):
dbus_helpers.unmount(mount_point_id)
def mounts():
return dbus_helpers.mounts()
def complete_indexing():
return dbus_helpers.complete_indexing()
def get_unique_values(key):
return dbus_helpers.get_unique_values(key)

@ -31,6 +31,7 @@ DS_DBUS_PATH = "/org/laptop/sugar/DataStore"
_data_store = None
def _get_data_store():
global _data_store
@ -41,12 +42,14 @@ def _get_data_store():
DS_DBUS_INTERFACE)
return _data_store
def create(properties, filename, transfer_ownership=False):
object_id = _get_data_store().create(dbus.Dictionary(properties), filename,
transfer_ownership)
logging.debug('dbus_helpers.create: ' + object_id)
return object_id
def update(uid, properties, filename, transfer_ownership=False,
reply_handler=None, error_handler=None, timeout=-1):
debug_props = properties.copy()
@ -64,19 +67,23 @@ def update(uid, properties, filename, transfer_ownership=False,
_get_data_store().update(uid, dbus.Dictionary(properties),
filename, transfer_ownership)
def delete(uid):
logging.debug('dbus_helpers.delete: %r', uid)
_get_data_store().delete(uid)
def get_properties(uid):
logging.debug('dbus_helpers.get_properties: %s', uid)
return _get_data_store().get_properties(uid, byte_arrays=True)
def get_filename(uid):
filename = _get_data_store().get_filename(uid)
logging.debug('dbus_helpers.get_filename: %s, %s', uid, filename)
return filename
def find(query, properties, reply_handler, error_handler):
logging.debug('dbus_helpers.find: %r %r', query, properties)
if reply_handler and error_handler:
@ -86,19 +93,23 @@ def find(query, properties, reply_handler, error_handler):
else:
return _get_data_store().find(query, properties, byte_arrays=True)
def mount(uri, options, timeout=-1):
return _get_data_store().mount(uri, options, timeout=timeout)
def unmount(mount_point_id):
_get_data_store().unmount(mount_point_id)
def mounts():
return _get_data_store().mounts()
def get_unique_values(key):
return _get_data_store().get_uniquevaluesfor(
key, dbus.Dictionary({}, signature='ss'))
def complete_indexing():
return _get_data_store().complete_indexing()

@ -22,12 +22,14 @@ STABLE.
import os
def is_emulator():
if os.environ.has_key('SUGAR_EMULATOR'):
if os.environ['SUGAR_EMULATOR'] == 'yes':
return True
return False
def get_profile_path(path=None):
if os.environ.has_key('SUGAR_PROFILE'):
profile_id = os.environ['SUGAR_PROFILE']
@ -46,6 +48,7 @@ def get_profile_path(path=None):
else:
return base
def get_logs_path(path=None):
base = os.environ.get('SUGAR_LOGS_DIR', get_profile_path('logs'))
if path != None:
@ -53,8 +56,10 @@ def get_logs_path(path=None):
else:
return base
def get_user_activities_path():
return os.path.expanduser('~/Activities')
def get_user_library_path():
return os.path.expanduser('~/Library')

@ -54,8 +54,10 @@ import math
from sugar.graphics import style
from sugar.graphics.icon import Icon
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
class Alert(gtk.EventBox):
"""
UI interface for Alerts
@ -78,18 +80,14 @@ class Alert(gtk.EventBox):
__gtype_name__ = 'SugarAlert'
__gsignals__ = {
'response': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([object]))
}
'response': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object])),
}
__gproperties__ = {
'title' : (str, None, None, None,
gobject.PARAM_READWRITE),
'msg' : (str, None, None, None,
gobject.PARAM_READWRITE),
'icon' : (object, None, None,
gobject.PARAM_WRITABLE)
}
'title': (str, None, None, None, gobject.PARAM_READWRITE),
'msg': (str, None, None, None, gobject.PARAM_READWRITE),
'icon': (object, None, None, gobject.PARAM_WRITABLE),
}
def __init__(self, **kwargs):

@ -24,12 +24,13 @@ import time
import gobject
EASE_OUT_EXPO = 0
EASE_IN_EXPO = 1
EASE_IN_EXPO = 1
class Animator(gobject.GObject):
__gsignals__ = {
'completed': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
'completed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
}
def __init__(self, duration, fps=20, easing=EASE_OUT_EXPO):
@ -111,7 +112,9 @@ class Animator(gobject.GObject):
else:
return True
class Animation(object):
def __init__(self, start, end):
self.start = start
self.end = end

@ -20,7 +20,9 @@ import hippo
from sugar.graphics import style
class CanvasTextView(hippo.CanvasWidget):
def __init__(self, text, **kwargs):
hippo.CanvasWidget.__init__(self, **kwargs)
self.text_view_widget = gtk.TextView()

@ -26,12 +26,15 @@ from sugar.graphics import style
from sugar.graphics.icon import Icon
from sugar.graphics.palette import Palette, ToolInvoker, WidgetInvoker
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
def get_svg_color_string(color):
return '#%.2X%.2X%.2X' % (color.red / 257, color.green / 257,
color.blue / 257)
class _ColorButton(gtk.Button):
"""This is a ColorButton for Sugar. It is similar to the gtk.ColorButton,
but does not have any alpha support.
@ -42,8 +45,8 @@ class _ColorButton(gtk.Button):
"""
__gtype_name__ = 'SugarColorButton'
__gsignals__ = { 'color-set' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
tuple())}
__gsignals__ = {'color-set': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
tuple())}
def __init__(self, **kwargs):
self._title = _('Choose a color')
@ -78,7 +81,7 @@ class _ColorButton(gtk.Button):
if self._has_palette and self._has_invoker:
self._invoker = WidgetInvoker(self)
# FIXME: This is a hack.
self._invoker.has_rectangle_gap = lambda : False
self._invoker.has_rectangle_gap = lambda: False
self._invoker.palette = self._palette
def create_palette(self):
@ -86,7 +89,8 @@ class _ColorButton(gtk.Button):
self._palette = _ColorPalette(color=self._color,
primary_text=self._title)
self._palette.connect('color-set', self.__palette_color_set_cb)
self._palette.connect('notify::color', self.__palette_color_changed)
self._palette.connect('notify::color', self.
__palette_color_changed)
return self._palette
@ -192,8 +196,8 @@ class _ColorButton(gtk.Button):
getter=_get_accept_drag,
setter=_set_accept_drag)
# Drag and Drop
def __drag_begin_cb(self, widget, context):
# Drag and Drop
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8,
style.SMALL_ICON_SIZE,
style.SMALL_ICON_SIZE)
@ -235,10 +239,11 @@ class _ColorPalette(Palette):
_BLUE = 2
__gtype_name__ = 'SugarColorPalette'
# The color-set signal is emitted when the user is finished selecting
# a color.
__gsignals__ = { 'color-set' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
tuple())}
__gsignals__ = {'color-set': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
tuple())}
def __init__(self, **kwargs):
self._color = gtk.gdk.Color(0, 0, 0)
@ -300,8 +305,6 @@ class _ColorPalette(Palette):
return scale
def _build_swatches(self):
for child in self._swatch_tray.get_children():
child.destroy()
@ -384,7 +387,6 @@ class _ColorPalette(Palette):
color = gobject.property(type=object, getter=get_color, setter=set_color)
def _add_accelerator(tool_button):
if not tool_button.props.accelerator or not tool_button.get_toplevel() or \
not tool_button.child:
@ -403,20 +405,24 @@ def _add_accelerator(tool_button):
tool_button.child.add_accelerator('clicked', accel_group, keyval, mask,
gtk.ACCEL_LOCKED | gtk.ACCEL_VISIBLE)
def _hierarchy_changed_cb(tool_button, previous_toplevel):
_add_accelerator(tool_button)
def setup_accelerator(tool_button):
_add_accelerator(tool_button)
tool_button.connect('hierarchy-changed', _hierarchy_changed_cb)
# This not ideal. It would be better to subclass gtk.ToolButton, however
# the python bindings do not seem to be powerfull enough for that.
# (As we need to change a variable in the class structure.)
class ColorToolButton(gtk.ToolItem):
# This not ideal. It would be better to subclass gtk.ToolButton, however
# the python bindings do not seem to be powerfull enough for that.
# (As we need to change a variable in the class structure.)
__gtype_name__ = 'SugarColorToolButton'
__gsignals__ = { 'color-set' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
tuple())}
__gsignals__ = {'color-set': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
tuple())}
def __init__(self, icon_name='color-preview', **kwargs):
self._accelerator = None
@ -528,4 +534,3 @@ class ColorToolButton(gtk.ToolItem):
def __color_set_cb(self, widget):
self.emit('color-set')

@ -22,7 +22,9 @@ STABLE.
import gobject
import gtk
class ComboBox(gtk.ComboBox):
__gtype_name__ = 'SugarComboBox'
def __init__(self):

@ -22,7 +22,9 @@ STABLE.
import gtk
import hippo
class CanvasEntry(hippo.CanvasEntry):
def set_background(self, color_spec):
"""
Parameters

@ -33,9 +33,12 @@ import cairo
from sugar.graphics.xocolor import XoColor
from sugar.util import LRU
_BADGE_SIZE = 0.45
class _SVGLoader(object):
def __init__(self):
self._cache = LRU(50)
@ -61,20 +64,26 @@ class _SVGLoader(object):
import rsvg # XXX this is very slow! why?
return rsvg.Handle(data=icon)
class _IconInfo(object):
def __init__(self):
self.file_name = None
self.attach_x = 0
self.attach_y = 0
class _BadgeInfo(object):
def __init__(self):
self.attach_x = 0
self.attach_y = 0
self.size = 0
self.icon_padding = 0
class _IconBuffer(object):
_surface_cache = LRU(50)
_loader = _SVGLoader()
@ -219,7 +228,7 @@ class _IconBuffer(object):
self.stroke_color = None
self.fill_color = None
def _get_insensitive_pixbuf (self, pixbuf, widget):
def _get_insensitive_pixbuf(self, pixbuf, widget):
if not (widget and widget.style):
return pixbuf
@ -309,7 +318,9 @@ class _IconBuffer(object):
xo_color = property(_get_xo_color, _set_xo_color)
class Icon(gtk.Image):
__gtype_name__ = 'SugarIcon'
def __init__(self, **kwargs):
@ -510,7 +521,9 @@ class Icon(gtk.Image):
badge_name = gobject.property(
type=str, getter=get_badge_name, setter=set_badge_name)
class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'CanvasIcon'
def __init__(self, **kwargs):
@ -932,11 +945,13 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
palette = property(get_palette, set_palette)
class CellRendererIcon(gtk.GenericCellRenderer):
__gtype_name__ = 'SugarCellRendererIcon'
__gsignals__ = {
'clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [object])
'clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [object]),
}
def __init__(self, tree_view):
@ -1073,8 +1088,8 @@ class CellRendererIcon(gtk.GenericCellRenderer):
return False
def on_render(self, window, widget, background_area, cell_area, expose_area,
flags):
def on_render(self, window, widget, background_area, cell_area,
expose_area, flags):
has_prelit_colors = None not in [self._prelit_fill_color,
self._prelit_stroke_color]
if flags & gtk.CELL_RENDERER_PRELIT and has_prelit_colors and \
@ -1100,6 +1115,7 @@ class CellRendererIcon(gtk.GenericCellRenderer):
cr.rectangle(expose_area)
cr.paint()
def get_icon_state(base_name, perc, step=5):
strength = round(perc / step) * step
icon_theme = gtk.icon_theme_get_default()
@ -1111,6 +1127,7 @@ def get_icon_state(base_name, perc, step=5):
strength = strength + step
def get_icon_file_name(icon_name):
icon_theme = gtk.icon_theme_get_default()
info = icon_theme.lookup_icon(icon_name, gtk.ICON_SIZE_LARGE_TOOLBAR, 0)
@ -1119,4 +1136,3 @@ def get_icon_file_name(icon_name):
filename = info.get_filename()
del info
return filename

@ -25,6 +25,7 @@ from sugar.graphics.icon import _SVGLoader
ICON_ENTRY_PRIMARY = _sugarext.ICON_ENTRY_PRIMARY
ICON_ENTRY_SECONDARY = _sugarext.ICON_ENTRY_SECONDARY
class IconEntry(_sugarext.IconEntry):
def __init__(self):
@ -103,4 +104,3 @@ class IconEntry(_sugarext.IconEntry):
self.hide_clear_button()
else:
self.show_clear_button()

@ -27,7 +27,9 @@ import gtk
from sugar.graphics.icon import Icon
class MenuItem(gtk.ImageMenuItem):
def __init__(self, text_label=None, icon_name=None, text_maxlen=60,
xo_color=None, file_name=None):
gobject.GObject.__init__(self)
@ -91,4 +93,3 @@ class MenuItem(gtk.ImageMenuItem):
accelerator = gobject.property(type=str, setter=set_accelerator,
getter=get_accelerator)

@ -27,13 +27,14 @@ STABLE.
import gtk
import gobject
class Notebook(gtk.Notebook):
__gtype_name__ = 'SugarNotebook'
__gproperties__ = {
'can-close-tabs': (bool, None, None, False,
gobject.PARAM_READWRITE |
gobject.PARAM_CONSTRUCT_ONLY)
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY),
}
def __init__(self, **kwargs):

@ -27,11 +27,14 @@ import dbus
from sugar.datastore import datastore
J_DBUS_SERVICE = 'org.laptop.Journal'
J_DBUS_INTERFACE = 'org.laptop.Journal'
J_DBUS_PATH = '/org/laptop/Journal'
class ObjectChooser(object):
def __init__(self, title=None, parent=None, flags=None, buttons=None,
what_filter=None):
# For backwards compatibility:
@ -127,4 +130,3 @@ class ObjectChooser(object):
# Journal service disappeared from the bus
self._response_code = gtk.RESPONSE_CANCEL
self._cleanup()

@ -39,16 +39,18 @@ from sugar import _sugarext
from sugar.graphics.palettewindow import MouseSpeedDetector, Invoker, \
WidgetInvoker, CanvasInvoker, ToolInvoker, CellRendererInvoker
class Palette(PaletteWindow):
PRIMARY = 0
SECONDARY = 1
__gtype_name__ = 'SugarPalette'
# DEPRECATED: label is passed with the primary-text property, accel_path
# is set via the invoker property, and menu_after_content is not used
def __init__(self, label=None, accel_path=None, menu_after_content=False,
text_maxlen=60, **kwargs):
# DEPRECATED: label is passed with the primary-text property,
# accel_path is set via the invoker property, and menu_after_content
# is not used
self._primary_text = None
self._secondary_text = None
@ -238,10 +240,9 @@ class Palette(PaletteWindow):
def get_secondary_text(self):
return self._secondary_text
secondary_text = gobject.property(type=str, getter=get_secondary_text,
setter=set_secondary_text)
secondary_text = gobject.property(type=str,
getter=get_secondary_text,
setter=set_secondary_text)
def _show_icon(self):
self._label_alignment.set_padding(0, 0, 0, style.DEFAULT_SPACING)
self._icon_box.show()
@ -362,7 +363,9 @@ class Palette(PaletteWindow):
self._palette_state = state
class PaletteActionBar(gtk.HButtonBox):
def add_action(self, label, icon_name=None):
button = gtk.Button(label)
@ -374,11 +377,13 @@ class PaletteActionBar(gtk.HButtonBox):
self.pack_start(button)
button.show()
class _Menu(_sugarext.Menu):
__gtype_name__ = 'SugarPaletteMenu'
__gsignals__ = {
'item-inserted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
'item-inserted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
}
def __init__(self, palette):
@ -410,7 +415,9 @@ class _Menu(_sugarext.Menu):
def do_deactivate(self):
self._palette.hide()
class _SecondaryAnimation(animator.Animation):
def __init__(self, palette):
animator.Animation.__init__(self, 0.0, 1.0)
self._palette = palette
@ -418,4 +425,3 @@ class _SecondaryAnimation(animator.Animation):
def next_frame(self, current):
if current == 1.0:
self._palette.set_palette_state(Palette.SECONDARY)

@ -21,8 +21,10 @@ STABLE.
import gobject
_groups = {}
def get_group(group_id):
if _groups.has_key(group_id):
group = _groups[group_id]
@ -32,13 +34,14 @@ def get_group(group_id):
return group
class Group(gobject.GObject):
__gsignals__ = {
'popup' : (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
'popdown' : (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([]))
'popup': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'popdown': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
}
def __init__(self):
gobject.GObject.__init__(self)
self._up = False

@ -31,8 +31,9 @@ from sugar.graphics import palettegroup
from sugar.graphics import animator
from sugar.graphics import style
# Helper function to find the gap position and size of widget a
def _calculate_gap(a, b):
"""Helper function to find the gap position and size of widget a"""
# Test for each side if the palette and invoker are
# adjacent to each other.
gap = True
@ -63,6 +64,7 @@ def _calculate_gap(a, b):
else:
return False
class MouseSpeedDetector(gobject.GObject):
__gsignals__ = {
@ -125,17 +127,15 @@ class MouseSpeedDetector(gobject.GObject):
return True
class PaletteWindow(gtk.Window):
__gtype_name__ = 'SugarPaletteWindow'
__gsignals__ = {
'popup' : (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
'popdown' : (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
'activate' : (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([]))
'popup': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'popdown': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'activate': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
}
def __init__(self, **kwargs):
@ -401,7 +401,9 @@ class PaletteWindow(gtk.Window):
palette_state = property(get_palette_state)
class _PopupAnimation(animator.Animation):
def __init__(self, palette):
animator.Animation.__init__(self, 0.0, 1.0)
self._palette = palette
@ -410,7 +412,9 @@ class _PopupAnimation(animator.Animation):
if current == 1.0:
self._palette.show()
class _PopdownAnimation(animator.Animation):
def __init__(self, palette):
animator.Animation.__init__(self, 0.0, 1.0)
self._palette = palette
@ -419,27 +423,25 @@ class _PopdownAnimation(animator.Animation):
if current == 1.0:
self._palette.hide()
class Invoker(gobject.GObject):
__gtype_name__ = 'SugarPaletteInvoker'
__gsignals__ = {
'mouse-enter': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'mouse-leave': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'right-click': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'focus-out': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
'focus-out': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
}
ANCHORED = 0
AT_CURSOR = 1
BOTTOM = [(0.0, 0.0, 0.0, 1.0),
(-1.0, 0.0, 1.0, 1.0)]
RIGHT = [(0.0, 0.0, 1.0, 0.0),
(0.0, -1.0, 1.0, 1.0)]
TOP = [(0.0, -1.0, 0.0, 0.0),
(-1.0, -1.0, 1.0, 0.0)]
LEFT = [(-1.0, 0.0, 0.0, 0.0),
(-1.0, -1.0, 0.0, 1.0)]
BOTTOM = [(0.0, 0.0, 0.0, 1.0), (-1.0, 0.0, 1.0, 1.0)]
RIGHT = [(0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 1.0, 1.0)]
TOP = [(0.0, -1.0, 0.0, 0.0), (-1.0, -1.0, 1.0, 0.0)]
LEFT = [(-1.0, 0.0, 0.0, 0.0), (-1.0, -1.0, 0.0, 1.0)]
def __init__(self):
gobject.GObject.__init__(self)
@ -531,8 +533,9 @@ class Invoker(gobject.GObject):
alignment = self.get_alignment(palette_dim)
rect = self._get_position_for_alignment(alignment, palette_dim)
# In case our efforts to find an optimum place inside the screen failed,
# just make sure the palette fits inside the screen if at all possible.
# In case our efforts to find an optimum place inside the screen
# failed, just make sure the palette fits inside the screen if at all
# possible.
rect.x = max(0, rect.x)
rect.y = max(0, rect.y)
@ -642,7 +645,9 @@ class Invoker(gobject.GObject):
palette = gobject.property(
type=object, setter=set_palette, getter=get_palette)
class WidgetInvoker(Invoker):
def __init__(self, parent=None, widget=None):
Invoker.__init__(self)
@ -663,11 +668,11 @@ class WidgetInvoker(Invoker):
self.notify('widget')
self._enter_hid = self._widget.connect('enter-notify-event',
self.__enter_notify_event_cb)
self.__enter_notify_event_cb)
self._leave_hid = self._widget.connect('leave-notify-event',
self.__leave_notify_event_cb)
self.__leave_notify_event_cb)
self._release_hid = self._widget.connect('button-release-event',
self.__button_release_event_cb)
self.__button_release_event_cb)
self.attach(parent)
@ -750,7 +755,9 @@ class WidgetInvoker(Invoker):
return self._widget
widget = gobject.property(type=object, getter=_get_widget, setter=None)
class CanvasInvoker(Invoker):
def __init__(self, parent=None):
Invoker.__init__(self)
@ -806,7 +813,9 @@ class CanvasInvoker(Invoker):
def get_toplevel(self):
return hippo.get_canvas_for_item(self._item).get_toplevel()
class ToolInvoker(WidgetInvoker):
def __init__(self, parent=None):
WidgetInvoker.__init__(self)
@ -826,7 +835,9 @@ class ToolInvoker(WidgetInvoker):
else:
return self.LEFT + self.RIGHT
class CellRendererInvoker(Invoker):
def __init__(self):
Invoker.__init__(self)
@ -910,14 +921,16 @@ class CellRendererInvoker(Invoker):
self.notify_mouse_leave()
def __button_release_event_cb(self, widget, event):
if event.button == 1 and self._point_in_cell_renderer(event.x, event.y):
if event.button == 1 and self._point_in_cell_renderer(event.x,
event.y):
tree_view = self._tree_view
path, column_, x_, y_ = tree_view.get_path_at_pos(int(event.x),
int(event.y))
self._cell_renderer.emit('clicked', path)
# So the treeview receives it and knows a drag isn't going on
return False
if event.button == 3 and self._point_in_cell_renderer(event.x, event.y):
if event.button == 3 and self._point_in_cell_renderer(event.x,
event.y):
self.notify_right_click()
return True
else:
@ -951,4 +964,3 @@ class CellRendererInvoker(Invoker):
def get_default_position(self):
return self.AT_CURSOR

@ -21,7 +21,10 @@ STABLE.
import gtk
class Panel(gtk.VBox):
__gtype_name__ = 'SugarPanel'
def __init__(self):
gtk.VBox.__init__(self)

@ -20,7 +20,9 @@ import gtk
from sugar.graphics.toolbutton import ToolButton
from sugar.graphics.palette import Palette
class RadioMenuButton(ToolButton):
def __init__(self, **kwargs):
ToolButton.__init__(self, **kwargs)
self.selected_button = None
@ -44,7 +46,9 @@ class RadioMenuButton(ToolButton):
else:
self.palette.popup(immediate=True, state=Palette.SECONDARY)
class RadioToolsButton(RadioMenuButton):
def __init__(self, **kwargs):
RadioMenuButton.__init__(self, **kwargs)
@ -53,7 +57,9 @@ class RadioToolsButton(RadioMenuButton):
return
self.selected_button.emit('clicked')
class RadioPalette(Palette):
def __init__(self, **kwargs):
Palette.__init__(self, **kwargs)

@ -27,11 +27,13 @@ from sugar.graphics.icon import Icon
from sugar.graphics.palette import Palette, ToolInvoker
from sugar.graphics import toolbutton
class RadioToolButton(gtk.RadioToolButton):
"""
An implementation of a "push" button.
"""
__gtype_name__ = 'SugarRadioToolButton'
def __init__(self, **kwargs):
@ -76,7 +78,8 @@ class RadioToolButton(gtk.RadioToolButton):
def get_tooltip(self):
return self._tooltip
tooltip = gobject.property(type=str, setter=set_tooltip, getter=get_tooltip)
tooltip = gobject.property(type=str, setter=set_tooltip,
getter=get_tooltip)
def set_accelerator(self, accelerator):
"""
@ -177,4 +180,3 @@ class RadioToolButton(gtk.RadioToolButton):
allocation.width, allocation.height)
gtk.RadioToolButton.do_expose_event(self, event)

@ -25,6 +25,7 @@ import hippo
from sugar.graphics import style
class CanvasRoundBox(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'SugarRoundBox'

@ -28,9 +28,11 @@ import logging
import gtk
import pango
FOCUS_LINE_WIDTH = 2
_TAB_CURVATURE = 1
def _compute_zoom_factor():
if os.environ.has_key('SUGAR_SCALING'):
try:
@ -41,7 +43,9 @@ def _compute_zoom_factor():
return 1.0
class Font(object):
def __init__(self, desc):
self._desc = desc
@ -51,7 +55,9 @@ class Font(object):
def get_pango_desc(self):
return pango.FontDescription(self._desc)
class Color(object):
def __init__(self, color, alpha=1.0):
self._r, self._g, self._b = self._html_to_rgb(color)
self._a = alpha
@ -91,9 +97,11 @@ class Color(object):
else:
return self.get_html()
def zoom(units):
return int(ZOOM_FACTOR * units)
ZOOM_FACTOR = _compute_zoom_factor()
DEFAULT_SPACING = zoom(15)

@ -25,7 +25,9 @@ import gtk
from sugar.graphics.icon import Icon
from sugar.graphics.palette import Palette, ToolInvoker
class ToggleToolButton(gtk.ToggleToolButton):
__gtype_name__ = "SugarToggleToolButton"
def __init__(self, named_icon=None):

@ -24,7 +24,9 @@ from sugar.graphics.palette import PaletteWindow, ToolInvoker
from sugar.graphics.toolbutton import ToolButton
from sugar.graphics import palettegroup
class ToolbarButton(ToolButton):
def __init__(self, page=None, **kwargs):
ToolButton.__init__(self, **kwargs)
@ -132,7 +134,9 @@ class ToolbarButton(ToolButton):
gtk.ToolButton.do_expose_event(self, event)
_paint_arrow(self, event, gtk.ARROW_UP)
class ToolbarBox(gtk.VBox):
def __init__(self, padding=style.TOOLBOX_HORIZONTAL_PADDING):
gtk.VBox.__init__(self)
self.expanded_button = None
@ -177,7 +181,9 @@ class ToolbarBox(gtk.VBox):
self.toolbar.parent.parent.modify_bg(state, color)
self.toolbar.modify_bg(state, color)
class _ToolbarPalette(PaletteWindow):
def __init__(self, **kwargs):
PaletteWindow.__init__(self, **kwargs)
self.toolbar_box = None
@ -232,7 +238,9 @@ class _ToolbarPalette(PaletteWindow):
if self._focus == 0:
self.popdown(immediate=True)
class _Box(gtk.EventBox):
def __init__(self):
gtk.EventBox.__init__(self)
self.connect('expose-event', self.do_expose_event)
@ -251,6 +259,7 @@ class _Box(gtk.EventBox):
alloc.width - style.FOCUS_LINE_WIDTH * 2,
style.FOCUS_LINE_WIDTH)
def _setup_page(page_widget, color, hpad):
vpad = style.FOCUS_LINE_WIDTH
page_widget.child.set_padding(vpad, vpad, hpad, hpad)
@ -264,6 +273,7 @@ def _setup_page(page_widget, color, hpad):
page_widget.modify_bg(gtk.STATE_NORMAL, color)
page_widget.modify_bg(gtk.STATE_PRELIGHT, color)
def _embody_page(box_class, widget):
widget.show()
alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0)
@ -275,6 +285,7 @@ def _embody_page(box_class, widget):
box.show()
return box
def _paint_arrow(widget, event, arrow_type):
alloc = widget.allocation
x = alloc.x + alloc.width / 2 - style.TOOLBAR_ARROW_SIZE / 2

@ -25,13 +25,14 @@ import hippo
from sugar.graphics import style
class Toolbox(gtk.VBox):
__gtype_name__ = 'SugarToolbox'
__gsignals__ = {
'current-toolbar-changed': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([int]))
gobject.TYPE_NONE, ([int])),
}
def __init__(self):
@ -98,4 +99,3 @@ class Toolbox(gtk.VBox):
return self._notebook.get_current_page()
current_toolbar = property(get_current_toolbar, set_current_toolbar)

@ -28,6 +28,7 @@ import gobject
from sugar.graphics.icon import Icon
from sugar.graphics.palette import Palette, ToolInvoker
def _add_accelerator(tool_button):
if not tool_button.props.accelerator or not tool_button.get_toplevel() or \
not tool_button.child:
@ -46,14 +47,18 @@ def _add_accelerator(tool_button):
tool_button.child.add_accelerator('clicked', accel_group, keyval, mask,
gtk.ACCEL_LOCKED | gtk.ACCEL_VISIBLE)
def _hierarchy_changed_cb(tool_button, previous_toplevel):
_add_accelerator(tool_button)
def setup_accelerator(tool_button):
_add_accelerator(tool_button)
tool_button.connect('hierarchy-changed', _hierarchy_changed_cb)
class ToolButton(gtk.ToolButton):
__gtype_name__ = "SugarToolButton"
def __init__(self, icon_name=None, **kwargs):
@ -97,7 +102,8 @@ class ToolButton(gtk.ToolButton):
def get_tooltip(self):
return self._tooltip
tooltip = gobject.property(type=str, setter=set_tooltip, getter=get_tooltip)
tooltip = gobject.property(type=str, setter=set_tooltip,
getter=get_tooltip)
def set_accelerator(self, accelerator):
self._accelerator = accelerator

@ -25,10 +25,11 @@ import gobject
from sugar.graphics.combobox import ComboBox
from sugar.graphics import style
class ToolComboBox(gtk.ToolItem):
__gproperties__ = {
'label-text' : (str, None, None, None,
gobject.PARAM_WRITABLE),
'label-text': (str, None, None, None, gobject.PARAM_WRITABLE),
}
def __init__(self, combo=None, **kwargs):

@ -27,17 +27,17 @@ from sugar.graphics.palette import ToolInvoker
from sugar.graphics.toolbutton import ToolButton
from sugar.graphics.icon import Icon
_PREVIOUS_PAGE = 0
_NEXT_PAGE = 1
class _TrayViewport(gtk.Viewport):
__gproperties__ = {
'scrollable' : (bool, None, None, False,
gobject.PARAM_READABLE),
'can-scroll-prev' : (bool, None, None, False,
gobject.PARAM_READABLE),
'can-scroll-next' : (bool, None, None, False,
gobject.PARAM_READABLE),
'scrollable': (bool, None, None, False, gobject.PARAM_READABLE),
'can-scroll-prev': (bool, None, None, False, gobject.PARAM_READABLE),
'can-scroll-next': (bool, None, None, False, gobject.PARAM_READABLE),
}
def __init__(self, orientation):
@ -161,6 +161,7 @@ class _TrayViewport(gtk.Viewport):
class _TrayScrollButton(ToolButton):
def __init__(self, icon_name, scroll_direction):
ToolButton.__init__(self)
self._viewport = None
@ -194,7 +195,6 @@ class _TrayScrollButton(ToolButton):
self._viewport_can_scroll_dir_changed_cb)
self.set_sensitive(self._viewport.props.can_scroll_next)
def _viewport_scrollable_changed_cb(self, viewport, pspec):
self.props.visible = self._viewport.props.scrollable
@ -211,19 +211,21 @@ class _TrayScrollButton(ToolButton):
viewport = property(fset=set_viewport)
ALIGN_TO_START = 0
ALIGN_TO_END = 1
class HTray(gtk.HBox):
__gtype_name__ = 'SugarHTray'
__gproperties__ = {
'align' : (int, None, None, 0, 1, ALIGN_TO_START,
gobject.PARAM_READWRITE |
gobject.PARAM_CONSTRUCT_ONLY),
'drag-active' : (bool, None, None, False,
gobject.PARAM_READWRITE)
'align': (int, None, None, 0, 1, ALIGN_TO_START,
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY),
'drag-active': (bool, None, None, False, gobject.PARAM_READWRITE),
}
def __init__(self, **kwargs):
self._drag_active = False
self.align = ALIGN_TO_START
@ -299,15 +301,15 @@ class HTray(gtk.HBox):
def scroll_to_item(self, item):
self._viewport.scroll_to_item(item)
class VTray(gtk.VBox):
__gtype_name__ = 'SugarVTray'
__gproperties__ = {
'align' : (int, None, None, 0, 1, ALIGN_TO_START,
gobject.PARAM_READWRITE |
gobject.PARAM_CONSTRUCT_ONLY),
'drag-active' : (bool, None, None, False,
gobject.PARAM_READWRITE)
'align': (int, None, None, 0, 1, ALIGN_TO_START,
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY),
'drag-active': (bool, None, None, False, gobject.PARAM_READWRITE),
}
def __init__(self, **kwargs):
@ -385,11 +387,15 @@ class VTray(gtk.VBox):
def scroll_to_item(self, item):
self._viewport.scroll_to_item(item)
class TrayButton(ToolButton):
def __init__(self, **kwargs):
ToolButton.__init__(self, **kwargs)
class _IconWidget(gtk.EventBox):
__gtype_name__ = "SugarTrayIconWidget"
def __init__(self, icon_name=None, xo_color=None):
@ -413,7 +419,9 @@ class _IconWidget(gtk.EventBox):
def get_icon(self):
return self._icon
class TrayIcon(gtk.ToolItem):
__gtype_name__ = "SugarTrayIcon"
def __init__(self, icon_name=None, xo_color=None):
@ -458,4 +466,3 @@ class TrayIcon(gtk.ToolItem):
def get_icon(self):
return self._icon_widget.get_icon()
icon = property(get_icon, None)

@ -26,8 +26,10 @@ import warnings
from sugar.graphics.icon import Icon
_UNFULLSCREEN_BUTTON_VISIBILITY_TIMEOUT = 2
class UnfullscreenButton(gtk.Window):
def __init__(self):
@ -77,7 +79,9 @@ class UnfullscreenButton(gtk.Window):
def _screen_size_changed_cb(self, screen):
self._reposition()
class Window(gtk.Window):
def __init__(self, **args):
self._enable_fullscreen_mode = True
@ -263,8 +267,7 @@ class Window(gtk.Window):
return self._enable_fullscreen_mode
enable_fullscreen_mode = gobject.property(type=object,
setter=set_enable_fullscreen_mode,
getter=get_enable_fullscreen_mode)
setter=set_enable_fullscreen_mode, getter=get_enable_fullscreen_mode)
# DEPRECATED

@ -204,6 +204,7 @@ colors = [
['#BCCDFF', '#AC32FF'], \
]
def _parse_string(color_string):
if color_string == 'white':
return ['#ffffff', '#414141']
@ -216,10 +217,13 @@ def _parse_string(color_string):
else:
return None
def is_valid(color_string):
return (_parse_string(color_string) != None)
class XoColor:
def __init__(self, color_string=None):
if color_string == None or not is_valid(color_string):
n = int(random.random() * (len(colors) - 1))
@ -242,6 +246,7 @@ class XoColor:
def to_string(self):
return '%s,%s' % (self.stroke, self.fill)
if __name__ == "__main__":
import sys
import re

@ -29,14 +29,18 @@ import gobject
import SimpleHTTPServer
import SocketServer
__authinfos = {}
def _add_authinfo(authinfo):
__authinfos[threading.currentThread()] = authinfo
def get_authinfo():
return __authinfos.get(threading.currentThread())
def _del_authinfo():
del __authinfos[threading.currentThread()]
@ -172,16 +176,17 @@ class ChunkedGlibHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
self.end_headers()
return f
class GlibURLDownloader(gobject.GObject):
"""Grabs a URL in chunks, returning to the mainloop after each chunk"""
__gsignals__ = {
'finished': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
'error': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
'error': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'progress': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT]))
([gobject.TYPE_PYOBJECT])),
}
CHUNK_SIZE = 4096

@ -26,8 +26,10 @@ import dbus
import gobject
import telepathy
_logger = logging.getLogger('sugar.presence.activity')
class Activity(gobject.GObject):
"""UI interface for an Activity in the presence service
@ -43,23 +45,23 @@ class Activity(gobject.GObject):
"""
__gsignals__ = {
'buddy-joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'buddy-left': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'new-channel': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
([gobject.TYPE_PYOBJECT])),
'buddy-left': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'new-channel': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
}
__gproperties__ = {
'id' : (str, None, None, None, gobject.PARAM_READABLE),
'name' : (str, None, None, None, gobject.PARAM_READWRITE),
'tags' : (str, None, None, None, gobject.PARAM_READWRITE),
'color' : (str, None, None, None, gobject.PARAM_READWRITE),
'type' : (str, None, None, None, gobject.PARAM_READABLE),
'private' : (bool, None, None, True, gobject.PARAM_READWRITE),
'joined' : (bool, None, None, False, gobject.PARAM_READABLE),
'id': (str, None, None, None, gobject.PARAM_READABLE),
'name': (str, None, None, None, gobject.PARAM_READWRITE),
'tags': (str, None, None, None, gobject.PARAM_READWRITE),
'color': (str, None, None, None, gobject.PARAM_READWRITE),
'type': (str, None, None, None, gobject.PARAM_READABLE),
'private': (bool, None, None, True, gobject.PARAM_READWRITE),
'joined': (bool, None, None, False, gobject.PARAM_READABLE),
}
_PRESENCE_SERVICE = "org.laptop.Sugar.Presence"
@ -175,10 +177,10 @@ class Activity(gobject.GObject):
elif pspec.name == "private":
return self._private
# FIXME: need an asynchronous API to set these properties, particularly
# 'private'
def do_set_property(self, pspec, val):
"""Set a particular property in our property dictionary"""
# FIXME: need an asynchronous API to set these properties,
# particularly 'private'
if pspec.name == "name":
self._activity.SetProperties({'name': val})
self._name = val

@ -24,6 +24,7 @@ import gobject
import gtk
import dbus
class Buddy(gobject.GObject):
"""UI interface for a Buddy in the presence service
@ -40,26 +41,26 @@ class Buddy(gobject.GObject):
'icon': (XXX pixel data for an icon?)
See __gproperties__
"""
__gsignals__ = {
'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([])),
'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'joined-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
([gobject.TYPE_PYOBJECT])),
'left-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
([gobject.TYPE_PYOBJECT])),
'property-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
([gobject.TYPE_PYOBJECT])),
}
__gproperties__ = {
'key' : (str, None, None, None, gobject.PARAM_READABLE),
'icon' : (str, None, None, None, gobject.PARAM_READABLE),
'nick' : (str, None, None, None, gobject.PARAM_READABLE),
'color' : (str, None, None, None, gobject.PARAM_READABLE),
'current-activity' : (object, None, None, gobject.PARAM_READABLE),
'owner' : (bool, None, None, False, gobject.PARAM_READABLE),
'ip4-address' : (str, None, None, None, gobject.PARAM_READABLE),
'tags' : (str, None, None, None, gobject.PARAM_READABLE),
'key': (str, None, None, None, gobject.PARAM_READABLE),
'icon': (str, None, None, None, gobject.PARAM_READABLE),
'nick': (str, None, None, None, gobject.PARAM_READABLE),
'color': (str, None, None, None, gobject.PARAM_READABLE),
'current-activity': (object, None, None, gobject.PARAM_READABLE),
'owner': (bool, None, None, False, gobject.PARAM_READABLE),
'ip4-address': (str, None, None, None, gobject.PARAM_READABLE),
'tags': (str, None, None, None, gobject.PARAM_READABLE),
}
_PRESENCE_SERVICE = "org.laptop.Sugar.Presence"

@ -63,13 +63,12 @@ class PresenceService(gobject.GObject):
([gobject.TYPE_PYOBJECT])),
'activity-shared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
gobject.TYPE_PYOBJECT]))
gobject.TYPE_PYOBJECT])),
}
_PS_BUDDY_OP = DBUS_PATH + "/Buddies/"
_PS_ACTIVITY_OP = DBUS_PATH + "/Activities/"
def __init__(self, allow_offline_iface=True):
"""Initialise the service and attempt to connect to events
"""
@ -98,6 +97,7 @@ class PresenceService(gobject.GObject):
self._get_ps()
_ps_ = None
def _get_ps(self):
"""Retrieve dbus interface to PresenceService
@ -123,17 +123,16 @@ class PresenceService(gobject.GObject):
self._bus.get_object(DBUS_SERVICE,
DBUS_PATH,
follow_name_owner_changes=True),
DBUS_INTERFACE
)
DBUS_INTERFACE)
except dbus.exceptions.DBusException, err:
_logger.error(
"""Failure retrieving %r interface from
the D-BUS service %r %r: %s""",
DBUS_INTERFACE, DBUS_SERVICE, DBUS_PATH, err
)
DBUS_INTERFACE, DBUS_SERVICE, DBUS_PATH, err)
if self._allow_offline_iface:
return _OfflineInterface()
raise RuntimeError("Failed to connect to the presence service.")
raise RuntimeError('Failed to connect to the presence '
'service.')
else:
self._ps_ = ps
ps.connect_to_signal('BuddyAppeared',
@ -150,11 +149,9 @@ class PresenceService(gobject.GObject):
self._private_invitation_cb)
return self._ps_
_ps = property(
_get_ps, None, None,
_ps = property(_get_ps, None, None,
"""DBUS interface to the PresenceService
(services/presence/presenceservice)"""
)
(services/presence/presenceservice)""")
def _new_object(self, object_path):
"""Turn new object path into (cached) Buddy/Activity instance
@ -207,7 +204,8 @@ class PresenceService(gobject.GObject):
return False
def _buddy_appeared_cb(self, op):
"""Callback for dbus event (forwards to method to emit GObject event)"""
"""Callback for dbus event (forwards to method to emit GObject
event)"""
gobject.idle_add(self._emit_buddy_appeared_signal, op)
def _emit_buddy_disappeared_signal(self, object_path):
@ -218,9 +216,9 @@ class PresenceService(gobject.GObject):
obj = self._objcache[object_path]
self.emit('buddy-disappeared', obj)
# We cannot maintain the object in the cache because that would keep
# a lot of objects from being collected. That includes UI objects
# due to signals using strong references.
# We cannot maintain the object in the cache because that would
# keep a lot of objects from being collected. That includes UI
# objects due to signals using strong references.
# If we want to cache some despite the memory usage increase,
# we could use a LRU cache limited to some value.
del self._objcache[object_path]
@ -229,7 +227,8 @@ class PresenceService(gobject.GObject):
return False
def _buddy_disappeared_cb(self, object_path):
"""Callback for dbus event (forwards to method to emit GObject event)"""
"""Callback for dbus event (forwards to method to emit GObject
event)"""
gobject.idle_add(self._emit_buddy_disappeared_signal, object_path)
def _emit_activity_invitation_signal(self, activity_path, buddy_path,
@ -240,7 +239,8 @@ class PresenceService(gobject.GObject):
return False
def _activity_invitation_cb(self, activity_path, buddy_path, message):
"""Callback for dbus event (forwards to method to emit GObject event)"""
"""Callback for dbus event (forwards to method to emit GObject
event)"""
gobject.idle_add(self._emit_activity_invitation_signal, activity_path,
buddy_path, message)
@ -252,7 +252,8 @@ class PresenceService(gobject.GObject):
return False
def _private_invitation_cb(self, bus_name, connection, channel, chan_type):
"""Callback for dbus event (forwards to method to emit GObject event)"""
"""Callback for dbus event (forwards to method to emit GObject
event)"""
gobject.idle_add(self._emit_private_invitation_signal, bus_name,
connection, channel, chan_type)
@ -262,7 +263,8 @@ class PresenceService(gobject.GObject):
return False
def _activity_appeared_cb(self, object_path):
"""Callback for dbus event (forwards to method to emit GObject event)"""
"""Callback for dbus event (forwards to method to emit GObject
event)"""
gobject.idle_add(self._emit_activity_appeared_signal, object_path)
def _emit_activity_disappeared_signal(self, object_path):
@ -271,7 +273,8 @@ class PresenceService(gobject.GObject):
return False
def _activity_disappeared_cb(self, object_path):
"""Callback for dbus event (forwards to method to emit GObject event)"""
"""Callback for dbus event (forwards to method to emit GObject
event)"""
gobject.idle_add(self._emit_activity_disappeared_signal, object_path)
def get(self, object_path):
@ -288,11 +291,9 @@ class PresenceService(gobject.GObject):
"""
try:
resp = self._ps.GetActivities()
except dbus.exceptions.DBusException, err:
_logger.warn(
"""Unable to retrieve activity list from presence service: %s"""
% err
)
except dbus.exceptions.DBusException:
_logger.exception('Unable to retrieve activity list from '
'presence service')
return []
else:
acts = []
@ -311,10 +312,8 @@ class PresenceService(gobject.GObject):
if error_handler:
error_handler(e)
else:
_logger.warn(
"""Unable to retrieve activity-list from presence service: %s"""
% e
)
_logger.warn('Unable to retrieve activity-list from presence '
'service: %s', e)
def get_activities_async(self, reply_handler=None, error_handler=None):
"""Retrieve set of all activities from service asyncronously
@ -331,7 +330,6 @@ class PresenceService(gobject.GObject):
error_handler=lambda e: \
self._get_activities_error_cb(error_handler, e))
def get_activity(self, activity_id, warn_if_none=True):
"""Retrieve single Activity object for the given unique id
@ -357,11 +355,9 @@ class PresenceService(gobject.GObject):
"""
try:
resp = self._ps.GetBuddies()
except dbus.exceptions.DBusException, err:
_logger.warn(
"""Unable to retrieve buddy-list from presence service: %s"""
% err
)
except dbus.exceptions.DBusException:
_logger.exception('Unable to retrieve buddy-list from presence '
'service')
return []
else:
buddies = []
@ -380,10 +376,8 @@ class PresenceService(gobject.GObject):
if error_handler:
error_handler(e)
else:
_logger.warn(
"""Unable to retrieve buddy-list from presence service: %s"""
% e
)
_logger.warn('Unable to retrieve buddy-list from presence '
'service: %s', e)
def get_buddies_async(self, reply_handler=None, error_handler=None):
"""Retrieve set of all buddies from service asyncronously
@ -411,12 +405,9 @@ class PresenceService(gobject.GObject):
"""
try:
buddy_op = self._ps.GetBuddyByPublicKey(dbus.ByteArray(key))
except dbus.exceptions.DBusException, err:
_logger.warn(
"""Unable to retrieve buddy handle
for %r from presence service: %s"""
% key, err
)
except dbus.exceptions.DBusException:
_logger.exception('Unable to retrieve buddy handle for %r from '
'presence service', key)
return None
return self._new_object(buddy_op)
@ -450,12 +441,9 @@ class PresenceService(gobject.GObject):
"""Retrieves the laptop "owner" Buddy object."""
try:
owner_op = self._ps.GetOwner()
except dbus.exceptions.DBusException, err:
_logger.warn(
"""Unable to retrieve local user/owner
from presence service: %s"""
% err
)
except dbus.exceptions.DBusException:
_logger.exception('Unable to retrieve local user/owner from '
'presence service')
raise RuntimeError("Could not get owner object.")
return self._new_object(owner_op)
@ -526,7 +514,8 @@ class PresenceService(gobject.GObject):
return bus_name, object_path
class _OfflineInterface( object ):
class _OfflineInterface(object):
"""Offline-presence-service interface
Used to mimic the behaviour of a real PresenceService sufficiently
@ -535,33 +524,33 @@ class _OfflineInterface( object ):
XXX we could likely return a "MockOwner" object reasonably
easily, but would it be worth it?
"""
def raiseException( self, *args, **named ):
def raiseException(self, *args, **named):
"""Raise dbus.exceptions.DBusException"""
raise dbus.exceptions.DBusException(
"""PresenceService Interface not available"""
)
raise dbus.exceptions.DBusException('PresenceService Interface not '
'available')
GetActivities = raiseException
GetActivityById = raiseException
GetBuddies = raiseException
GetBuddyByPublicKey = raiseException
GetOwner = raiseException
GetPreferredConnection = raiseException
def ShareActivity(
self, actid, atype, name, properties,
reply_handler, error_handler,
):
def ShareActivity(self, actid, atype, name, properties, reply_handler,
error_handler):
"""Pretend to share and fail..."""
exc = IOError(
"""Unable to share activity as PresenceService
is not currenly available"""
)
return error_handler( exc )
exc = IOError('Unable to share activity as PresenceService is not '
'currently available')
return error_handler(exc)
class _MockPresenceService(gobject.GObject):
"""Test fixture allowing testing of items that use PresenceService
See PresenceService for usage and purpose
"""
__gsignals__ = {
'buddy-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
@ -575,7 +564,7 @@ class _MockPresenceService(gobject.GObject):
'activity-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'activity-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT]))
([gobject.TYPE_PYOBJECT])),
}
def __init__(self):
@ -599,11 +588,13 @@ class _MockPresenceService(gobject.GObject):
def share_activity(self, activity, properties=None):
return None
_ps = None
def get_instance(allow_offline_iface=False):
"""Retrieve this process' view of the PresenceService"""
global _ps
if not _ps:
_ps = PresenceService(allow_offline_iface)
return _ps

@ -20,7 +20,7 @@
STABLE.
"""
__all__ = ('TubeConnection',)
__all__ = ('TubeConnection', )
__docformat__ = 'reStructuredText'
@ -34,10 +34,10 @@ logger = logging.getLogger('telepathy.tubeconn')
class TubeConnection(Connection):
# pylint: disable-msg=W0212
# Confused by __new__
def __new__(cls, conn, tubes_iface, tube_id, address=None,
group_iface=None, mainloop=None):
# pylint: disable-msg=W0212
# Confused by __new__
if address is None:
address = tubes_iface.GetDBusTubeAddress(tube_id)
self = super(TubeConnection, cls).__new__(cls, address,
@ -58,9 +58,9 @@ class TubeConnection(Connection):
return self
# pylint: disable-msg=W0201
# Confused by __new__
def _on_get_self_handle_reply(self, handle):
# pylint: disable-msg=W0201
# Confused by __new__
self.self_handle = handle
match = self._tubes_iface.connect_to_signal('DBusNamesChanged',
self._on_dbus_names_changed)

@ -29,8 +29,10 @@ from sugar import env
from sugar import util
from sugar.graphics.xocolor import XoColor
_profile = None
class Profile(object):
"""Local user's current options/profile information
@ -46,6 +48,7 @@ class Profile(object):
pubkey -- public ssh key
privkey_hash -- SHA has of the child's public key
"""
def __init__(self, path):
self._pubkey = None
self._privkey_hash = None
@ -194,6 +197,7 @@ class Profile(object):
fd.write(text)
fd.close()
def get_profile():
global _profile
@ -203,14 +207,17 @@ def get_profile():
return _profile
def get_nick_name():
client = gconf.client_get_default()
return client.get_string("/desktop/sugar/user/nick")
def get_color():
client = gconf.client_get_default()
color = client.get_string("/desktop/sugar/user/color")
return XoColor(color)
def get_pubkey():
return get_profile().pubkey

@ -23,11 +23,15 @@ import os
from sugar import _sugarext
class XSMPClient(_sugarext.SMClientXSMP):
def __init__(self):
_sugarext.SMClientXSMP.__init__(self)
class SessionManager(object):
def __init__(self):
address = _sugarext.xsmp_init()
os.environ['SESSION_MANAGER'] = address

@ -31,8 +31,10 @@ import logging
import atexit
import traceback
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
def printable_hash(in_hash):
"""Convert binary hash data into printable characters."""
printable = ""
@ -40,12 +42,14 @@ def printable_hash(in_hash):
printable = printable + binascii.b2a_hex(char)
return printable
def sha_data(data):
"""sha1 hash some bytes."""
sha_hash = hashlib.sha1()
sha_hash.update(data)
return sha_hash.digest()
def unique_id(data = ''):
"""Generate a likely-unique ID for whatever purpose
@ -66,6 +70,7 @@ def unique_id(data = ''):
ACTIVITY_ID_LEN = 40
def is_hex(s):
try:
int(s, 16)
@ -74,6 +79,7 @@ def is_hex(s):
return True
def validate_activity_id(actid):
"""Validate an activity ID."""
if not isinstance(actid, (str, unicode)):
@ -84,6 +90,7 @@ def validate_activity_id(actid):
return False
return True
def set_proc_title(title):
"""Sets the process title so ps and top show more
descriptive names. This does not modify argv[0]
@ -106,13 +113,17 @@ def set_proc_title(title):
except Exception:
return False
class Node(object):
__slots__ = ['prev', 'next', 'me']
def __init__(self, prev, me):
self.prev = prev
self.me = me
self.next = None
class LRU:
"""
Implementation of a length-limited O(1) LRU queue.
@ -120,20 +131,24 @@ class LRU:
http://pype.sourceforge.net
Copyright 2003 Josiah Carlson.
"""
# pylint: disable-msg=W0102,W0612
def __init__(self, count, pairs=[]):
# pylint: disable-msg=W0102,W0612
self.count = max(count, 1)
self.d = {}
self.first = None
self.last = None
for key, value in pairs:
self[key] = value
def __contains__(self, obj):
return obj in self.d
def __getitem__(self, obj):
a = self.d[obj].me
self[a[0]] = a[1]
return a[1]
def __setitem__(self, obj, val):
if obj in self.d:
del self[obj]
@ -155,6 +170,7 @@ class LRU:
a.next = None
del self.d[a.me[0]]
del a
def __delitem__(self, obj):
nobj = self.d[obj]
if nobj.prev:
@ -166,31 +182,37 @@ class LRU:
else:
self.last = nobj.prev
del self.d[obj]
def __iter__(self):
cur = self.first
while cur != None:
cur2 = cur.next
yield cur.me[1]
cur = cur2
def iteritems(self):
cur = self.first
while cur != None:
cur2 = cur.next
yield cur.me
cur = cur2
def iterkeys(self):
return iter(self.d)
def itervalues(self):
for i, j in self.iteritems():
yield j
def keys(self):
return self.d.keys()
units = [['%d year', '%d years', 356 * 24 * 60 * 60],
['%d month', '%d months', 30 * 24 * 60 * 60],
['%d week', '%d weeks', 7 * 24 * 60 * 60],
['%d day', '%d days', 24 * 60 * 60],
['%d hour', '%d hours', 60 * 60],
units = [['%d year', '%d years', 356 * 24 * 60 * 60],
['%d month', '%d months', 30 * 24 * 60 * 60],
['%d week', '%d weeks', 7 * 24 * 60 * 60],
['%d day', '%d days', 24 * 60 * 60],
['%d hour', '%d hours', 60 * 60],
['%d minute', '%d minutes', 60]]
AND = _(' and ')
@ -210,24 +232,28 @@ ELAPSED = _('%s ago')
# strings need to be used, then we need to call ngettext() in a fake way so
# xgettext will pick them up as plurals.
def ngettext(singular, plural, n):
pass
# TRANS: Relative dates (eg. 1 month and 5 days).
ngettext('%d year', '%d years', 1)
ngettext('%d month', '%d months', 1)
ngettext('%d week', '%d weeks', 1)
ngettext('%d day', '%d days', 1)
ngettext('%d hour', '%d hours', 1)
ngettext('%d year', '%d years', 1)
ngettext('%d month', '%d months', 1)
ngettext('%d week', '%d weeks', 1)
ngettext('%d day', '%d days', 1)
ngettext('%d hour', '%d hours', 1)
ngettext('%d minute', '%d minutes', 1)
del ngettext
# End of plurals hack
# gettext perfs hack (#7959)
_i18n_timestamps_cache = LRU(60)
def timestamp_to_elapsed_string(timestamp, max_levels=2):
levels = 0
time_period = ''
@ -265,9 +291,12 @@ def timestamp_to_elapsed_string(timestamp, max_levels=2):
return ELAPSED % time_period
_tracked_paths = {}
class TempFilePath(str):
def __new__(cls, path=None):
if path is None:
fd, path = tempfile.mkstemp()
@ -293,6 +322,7 @@ class TempFilePath(str):
else:
_tracked_paths[self] -= 1
def _cleanup_temp_files():
logging.debug('_cleanup_temp_files')
for path in _tracked_paths.keys():

@ -21,6 +21,7 @@ UNSTABLE. Used only internally by Activity and jarabe.
import gtk
def get_activity_id(wnck_window):
window = gtk.gdk.window_foreign_new(wnck_window.get_xid())
prop_info = window.property_get('_SUGAR_ACTIVITY_ID', 'STRING')
@ -29,6 +30,7 @@ def get_activity_id(wnck_window):
else:
return prop_info[2]
def get_bundle_id(wnck_window):
window = gtk.gdk.window_foreign_new(wnck_window.get_xid())
prop_info = window.property_get('_SUGAR_BUNDLE_ID', 'STRING')
@ -37,10 +39,12 @@ def get_bundle_id(wnck_window):
else:
return prop_info[2]
def set_activity_id(window, activity_id):
window.property_change('_SUGAR_ACTIVITY_ID', 'STRING', 8,
gtk.gdk.PROP_MODE_REPLACE, activity_id)
def set_bundle_id(window, bundle_id):
window.property_change('_SUGAR_BUNDLE_ID', 'STRING', 8,
gtk.gdk.PROP_MODE_REPLACE, bundle_id)

Loading…
Cancel
Save