PEP8 white space and long line fixes
This commit is contained in:
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…
Reference in New Issue
Block a user