From 070d467e1370edf464b9f3651e0bb78f30be2b32 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Mon, 3 Sep 2007 18:41:35 +0200 Subject: [PATCH 1/5] Add testcase for exercising the icon cache. --- tests/graphics/iconcache.py | 72 +++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 tests/graphics/iconcache.py diff --git a/tests/graphics/iconcache.py b/tests/graphics/iconcache.py new file mode 100644 index 00000000..703ec130 --- /dev/null +++ b/tests/graphics/iconcache.py @@ -0,0 +1,72 @@ +# Copyright (C) 2007, Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +""" +Test the sugar.graphics.icon.* cache. +""" + +import gtk + +from sugar.graphics.icon import Icon +from sugar.graphics.xocolor import XoColor +from sugar import logger + +logger.start('iconcache') + +import common + +test = common.Test() + +data = [ + ['battery-000', '#FF8F00,#FF2B34'], + ['battery-010', '#D1A3FF,#00A0FF'], + ['battery-020', '#FF8F00,#FF2B34'], + ['battery-030', '#00A0FF,#D1A3FF'], + ['battery-040', '#AC32FF,#FF2B34'], + ['battery-050', '#D1A3FF,#00A0FF'], + ['battery-060', '#AC32FF,#FF2B34'], + ['battery-070', '#00A0FF,#D1A3FF'], + ['battery-080', '#FF8F00,#FF2B34'], + ['battery-090', '#D1A3FF,#00A0FF'], + ['battery-100', '#AC32FF,#FF2B34']] + +def _button_activated_cb(button): + import random + + global data + random.shuffle(data) + + for i in range(0, len(test.get_children()) - 1): + test.get_children()[i].props.icon_name = data[i][0] + test.get_children()[i].props.xo_color = XoColor(data[i][1]) + +for d in data: + icon = Icon(icon_name=d[0], + icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR, + xo_color=XoColor(d[1])) + test.pack_start(icon) + icon.show() + +button = gtk.Button("mec mac") +test.pack_start(button) +button.connect('activate', _button_activated_cb) +button.show() + +test.show() + +if __name__ == "__main__": + common.main(test) From 0b3f68774954eedefe2b87847f512f1512eb6899 Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Mon, 3 Sep 2007 21:05:45 +0200 Subject: [PATCH 2/5] Fix distcheck --- po/POTFILES.in | 4 +++- shell/view/frame/frame.py | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index 336c8886..bbea3f02 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,7 +1,6 @@ shell/intro/intro.py shell/view/BuddyMenu.py shell/view/clipboardmenu.py -shell/view/frame/zoombox.py services/shell/objecttypeservice.py shell/hardware/keydialog.py shell/view/home/activitiesdonut.py @@ -11,3 +10,6 @@ shell/view/home/HomeBox.py shell/view/home/MeshBox.py shell/view/devices/battery.py sugar/activity/activity.py +shell/view/devices/network/wireless.py +shell/view/frame/activitybutton.py +shell/view/frame/zoomtoolbar.py diff --git a/shell/view/frame/frame.py b/shell/view/frame/frame.py index 2784835f..3ca1b920 100644 --- a/shell/view/frame/frame.py +++ b/shell/view/frame/frame.py @@ -28,7 +28,6 @@ from sugar.clipboard import clipboardservice from view.frame.eventarea import EventArea from view.frame.ActivitiesBox import ActivitiesBox from view.frame.zoomtoolbar import ZoomToolbar -from view.frame.overlaybox import OverlayBox from view.frame.friendstray import FriendsTray from view.frame.framewindow import FrameWindow from view.frame.clipboardpanelwindow import ClipboardPanelWindow From 382910b0bac9216df4e3ffc79dce1e450fb88afd Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Mon, 3 Sep 2007 21:08:40 +0200 Subject: [PATCH 3/5] Snapshot 0b3f687749. --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 561f5b09..21cd9e7c 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +Snapshot 0b3f687749 + * #3088: Fix style of zoom buttons palettes. (marco) * Refactor activity share/join in Activity.__init__() to be clearer and cover all cases (dcbw) From 07107fb81baf6e2b96181b294c4c375367d102f9 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Mon, 3 Sep 2007 21:26:30 +0200 Subject: [PATCH 4/5] #2896: Remove sugar.date module. --- NEWS | 2 ++ sugar/Makefile.am | 1 - sugar/date.py | 57 --------------------------------- sugar/graphics/objectchooser.py | 43 +++++++++++++++++++++++-- tests/lib/runall.py | 2 -- tests/lib/test_date.py | 30 ----------------- 6 files changed, 43 insertions(+), 92 deletions(-) delete mode 100644 sugar/date.py delete mode 100644 tests/lib/test_date.py diff --git a/NEWS b/NEWS index 21cd9e7c..34f5a30d 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +* #2896: Remove sugar.date module. (tomeu) + Snapshot 0b3f687749 * #3088: Fix style of zoom buttons palettes. (marco) diff --git a/sugar/Makefile.am b/sugar/Makefile.am index dffca334..4b94ff14 100644 --- a/sugar/Makefile.am +++ b/sugar/Makefile.am @@ -3,7 +3,6 @@ SUBDIRS = activity clipboard graphics objects presence datastore sugardir = $(pythondir)/sugar sugar_PYTHON = \ __init__.py \ - date.py \ env.py \ logger.py \ ltihooks.py \ diff --git a/sugar/date.py b/sugar/date.py deleted file mode 100644 index 3f4dcc2e..00000000 --- a/sugar/date.py +++ /dev/null @@ -1,57 +0,0 @@ -"""Simple date-representation model""" - -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import datetime - -class Date(object): - """Date-object storing a simple time.time() float - - Useful to display dates in the UI in an - abbreviated and easy to read format. - """ - def __init__(self, timestamp): - """Initialise via a timestamp (floating point value)""" - self._today = datetime.date.today() - self._timestamp = timestamp - - def __str__(self): - """Produce a formatted date representation - - Eventually this should produce a localised version - of the date. At the moment it always produces English - dates in long form with Today and Yesterday - special-cased and dates from this year not presenting - the year in the date. - """ - date = datetime.date.fromtimestamp(self._timestamp) - - # FIXME localization - if date == self._today: - result = 'Today' - elif date == self._today - datetime.timedelta(1): - result = 'Yesterday' - elif date.year == self._today.year: - result = date.strftime('%B %d') - else: - result = date.strftime('%B %d, %Y') - - time = datetime.datetime.fromtimestamp(self._timestamp) - result = result + ', ' + time.strftime('%I:%M %p') - - return result diff --git a/sugar/graphics/objectchooser.py b/sugar/graphics/objectchooser.py index 4128cf31..1c0dd3ae 100644 --- a/sugar/graphics/objectchooser.py +++ b/sugar/graphics/objectchooser.py @@ -17,6 +17,7 @@ import logging import time +from gettext import gettext as _ import gtk import hippo @@ -31,6 +32,9 @@ from sugar.datastore import datastore from sugar import activity from sugar.objects import objecttype +# TODO: Activities should request the Journal to open objectchooser dialogs. In +# that way, we'll be able to reuse most of this code inside the Journal. + class ObjectChooser(gtk.Dialog): def __init__(self, title=None, parent=None, flags=0): gtk.Dialog.__init__(self, title, parent, flags, (gtk.STOCK_CANCEL, @@ -156,8 +160,7 @@ class CollapsedEntry(CanvasRoundBox): def _format_date(self): """ Convert from a string in iso format to a more human-like format. """ - ti = time.strptime(self.jobject.metadata['mtime'], "%Y-%m-%dT%H:%M:%S") - return str(Date(time.mktime(ti))) + return _get_elapsed_string(self.jobject.metadata['mtime']) def _format_title(self): return '"%s"' % self.jobject.metadata['title'] @@ -169,3 +172,39 @@ class CollapsedEntry(CanvasRoundBox): else: self.props.border_color = style.COLOR_BLACK.get_int() self.props.background_color = style.COLOR_PANEL_GREY.get_int() + +def _get_elapsed_string(date_string, max_levels=2): + ti = time.strptime(date_string, "%Y-%m-%dT%H:%M:%S") + + 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], + [_('%d second'), _('%d seconds'), 1]] + levels = 0 + result = '' + elapsed_seconds = int(time.time() - time.mktime(ti)) + for name_singular, name_plural, factor in units: + elapsed_units = elapsed_seconds / factor + if elapsed_units > 0: + + if levels > 0: + if max_levels - levels == 1: + result += _(' and ') + else: + result += _(', ') + + if elapsed_units == 1: + result += name_singular % elapsed_units + else: + result += name_plural % elapsed_units + elapsed_seconds -= elapsed_units * factor + levels += 1 + + if levels == max_levels: + break + + return result + diff --git a/tests/lib/runall.py b/tests/lib/runall.py index 6ee9442f..ae1bb3ae 100644 --- a/tests/lib/runall.py +++ b/tests/lib/runall.py @@ -17,14 +17,12 @@ import unittest -import test_date import test_mime runner = unittest.TextTestRunner() loader = unittest.TestLoader() suite = unittest.TestSuite() -suite.addTest(loader.loadTestsFromModule(test_date)) suite.addTest(loader.loadTestsFromModule(test_mime)) runner.run(suite) diff --git a/tests/lib/test_date.py b/tests/lib/test_date.py deleted file mode 100644 index c6da871e..00000000 --- a/tests/lib/test_date.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import datetime -import unittest - -from sugar.date import Date - -class TestDate(unittest.TestCase): - def test_today(self): - date = Date(datetime.date(2000, 1, 1)) - date._today = datetime.date(2000, 1, 1) - self.assertEqual(str(date), 'Today') - -if __name__ == "__main__": - unittest.main() From 3617dd163525a9be18ed91c1b968b460aded7063 Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Mon, 3 Sep 2007 23:08:49 +0200 Subject: [PATCH 5/5] Cleanup Bundle to not require SUGAR_PREFIX to be set. Also start using properties rather than set/getters. --- NEWS | 2 ++ services/shell/bundleregistry.py | 2 +- sugar/activity/activityfactoryservice.py | 2 +- sugar/activity/bundle.py | 27 +++++++++++++----------- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index 21cd9e7c..1da917ce 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +* #3025: Make bundlebuilder work even if SUGAR_PREFIX is not set. (marco) + Snapshot 0b3f687749 * #3088: Fix style of zoom buttons palettes. (marco) diff --git a/services/shell/bundleregistry.py b/services/shell/bundleregistry.py index 19d00328..fbcef878 100644 --- a/services/shell/bundleregistry.py +++ b/services/shell/bundleregistry.py @@ -56,7 +56,7 @@ class _ServiceManager(object): def add(self, bundle): util.write_service(bundle.get_service_name(), - bundle.get_exec(), self._path) + bundle.get_command(), self._path) class BundleRegistry(gobject.GObject): """Service that tracks the available activity bundles""" diff --git a/sugar/activity/activityfactoryservice.py b/sugar/activity/activityfactoryservice.py index 63265a13..682abaa0 100644 --- a/sugar/activity/activityfactoryservice.py +++ b/sugar/activity/activityfactoryservice.py @@ -163,4 +163,4 @@ def run(bundle_path): _sugarext.set_application_name(bundle.get_name()) factory = ActivityFactoryService(bundle.get_service_name(), - bundle.get_class()) + bundle.activity_class) diff --git a/sugar/activity/bundle.py b/sugar/activity/bundle.py index 8bf33866..cccff5ae 100644 --- a/sugar/activity/bundle.py +++ b/sugar/activity/bundle.py @@ -59,6 +59,9 @@ class Bundle: self._init_with_path(path) def _init_with_path(self, path): + self.activity_class = None + self.bundle_exec = None + self._name = None self._icon = None self._service_name = None @@ -116,18 +119,10 @@ class Bundle: logging.error('%s must specify a name' % self._path) if cp.has_option(section, 'class'): - self._class = cp.get(section, 'class') - self._exec = '%s --bundle-path="%s"' % ( - env.get_bin_path(_PYTHON_FACTORY), self._path) + self.activity_class = cp.get(section, 'class') elif cp.has_option(section, 'exec'): - self._class = None - cmdline = cp.get(section, 'exec') - cmdline = os.path.join(self._path, cmdline) - cmdline = cmdline.replace('$SUGAR_BUNDLE_PATH', self._path) - cmdline = os.path.expandvars(cmdline) - self._exec = cmdline + self.bundle_exec = cp.get(section, 'exec') else: - self._exec = None self._valid = False logging.error('%s must specify exec or class' % self._path) @@ -232,9 +227,17 @@ class Bundle: """Get the activity version""" return self._activity_version - def get_exec(self): + def get_command(self): """Get the command to execute to launch the activity factory""" - return self._exec + if self.bundle_exec: + command = os.path.join(self._path, self.bundle_exec) + command = command.replace('$SUGAR_BUNDLE_PATH', self._path) + command = os.path.expandvars(command) + else: + command = '%s --bundle-path="%s"' % ( + env.get_bin_path(_PYTHON_FACTORY), self._path) + + return command def get_class(self): """Get the main Activity class"""