Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu@tomeuvizoso.net>2007-12-03 11:42:21 (GMT)
committer Tomeu Vizoso <tomeu@tomeuvizoso.net>2007-12-03 11:42:21 (GMT)
commit5e942edddcc2596192aace300811406dd18d9a81 (patch)
treeb563638bd26a828f8ecbae8f4823cb7acb9d71d7 /lib
parent8b5cf46945584272fcce48981b9632539eb43c7e (diff)
#5106: Implement an object chooser callable through dbus.
Diffstat (limited to 'lib')
-rw-r--r--lib/sugar/graphics/objectchooser.py259
1 files changed, 86 insertions, 173 deletions
diff --git a/lib/sugar/graphics/objectchooser.py b/lib/sugar/graphics/objectchooser.py
index 9458bad..59f1a8a 100644
--- a/lib/sugar/graphics/objectchooser.py
+++ b/lib/sugar/graphics/objectchooser.py
@@ -17,190 +17,103 @@
import logging
import time
-from gettext import gettext as _
+import gobject
import gtk
-import hippo
+import dbus
-from sugar.bundle.activitybundle import ActivityBundle
-from sugar.graphics import style
-from sugar.graphics.icon import CanvasIcon
-from sugar.graphics.xocolor import XoColor
-from sugar.graphics.roundbox import CanvasRoundBox
from sugar.datastore import datastore
-from sugar import activity
-from sugar import mime
-# 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.
+J_DBUS_SERVICE = 'org.laptop.Journal'
+J_DBUS_INTERFACE = 'org.laptop.Journal'
+J_DBUS_PATH = '/org/laptop/Journal'
-class ObjectChooser(gtk.Dialog):
- def __init__(self, title=None, parent=None, flags=0):
- gtk.Dialog.__init__(self, title, parent, flags, (gtk.STOCK_CANCEL,
- gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
-
- self._jobjects = None
- self._query = {}
- self._selected_entry = False
-
- self._box = hippo.CanvasBox()
- self._box.props.background_color = style.COLOR_PANEL_GREY.get_int()
- self._box.props.spacing = style.DEFAULT_SPACING
- self._box.props.padding = style.DEFAULT_SPACING
-
- canvas = hippo.Canvas()
- canvas.set_root(self._box)
-
- scrolled_window = gtk.ScrolledWindow()
- scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+class ObjectChooser(object):
+ def __init__(self, title=None, parent=None, flags=None, buttons=None):
+ # For backwards compatibility:
+ # - We ignore title, flags and buttons.
+ # - 'parent' can be a xid or a gtk.gdk.Window
- scrolled_window.add_with_viewport(canvas)
- canvas.show()
+ if title is not None or flags is not None or buttons is not None:
+ logging.warning('Invocation of ObjectChooser() has deprecated '
+ 'parameters.')
- self.vbox.add(scrolled_window)
- scrolled_window.show()
-
- scrolled_window.props.shadow_type = gtk.SHADOW_NONE
- scrolled_window.get_child().props.shadow_type = gtk.SHADOW_NONE
-
- self.refresh()
+ if parent is None:
+ parent_xid = 0
+ elif hasattr(parent, 'window') and hasattr(parent.window, 'xid'):
+ parent_xid = parent.window.xid
+ else:
+ parent_xid = parent
+
+ self._parent_xid = parent_xid
+ self._main_loop = None
+ self._object_id = None
+ self._bus = None
+ self._chooser_id = None
+ self._response_code = gtk.RESPONSE_NONE
- height = self.get_screen().get_height() * 3 / 4
- width = self.get_screen().get_width() * 3 / 4
- self.set_default_size(width, height)
-
- def update_with_query(self, query):
- self._query = query
- self.refresh()
-
- def refresh(self):
- logging.debug('ListView.refresh: %r' % self._query)
- self._jobjects, total_count = datastore.find(self._query, sorting=['-mtime'])
- self._update()
-
- def _update(self):
- self._box.remove_all()
- for jobject in self._jobjects:
- entry_view = CollapsedEntry(jobject)
- entry_view.connect('button-release-event',
- self._entry_view_button_release_event_cb)
- self._box.append(entry_view)
-
- def _entry_view_button_release_event_cb(self, entry_view, event):
- if self._selected_entry:
- self._selected_entry.set_selected(False)
- entry_view.set_selected(True)
- self._selected_entry = entry_view
+ def run(self):
+ self._object_id = None
+
+ self._main_loop = gobject.MainLoop()
+
+ self._bus = dbus.SessionBus(mainloop=self._main_loop)
+ self._bus.add_signal_receiver(
+ self.__name_owner_changed_cb,
+ signal_name="NameOwnerChanged",
+ dbus_interface="org.freedesktop.DBus",
+ arg0=J_DBUS_SERVICE)
+
+ obj = self._bus.get_object(J_DBUS_SERVICE, J_DBUS_PATH)
+ journal = dbus.Interface(obj, J_DBUS_INTERFACE)
+ journal.connect_to_signal('ObjectChooserResponse',
+ self.__chooser_response_cb)
+ journal.connect_to_signal('ObjectChooserCancelled',
+ self.__chooser_cancelled_cb)
+ self._chooser_id = journal.ChooseObject(self._parent_xid)
+
+ gtk.gdk.threads_leave()
+ try:
+ self._main_loop.run()
+ finally:
+ gtk.gdk.threads_enter()
+ self._main_loop = None
+
+ return self._response_code
def get_selected_object(self):
- if self._selected_entry:
- return self._selected_entry.jobject
- else:
+ if self._object_id is None:
return None
-
-class CollapsedEntry(CanvasRoundBox):
- _DATE_COL_WIDTH = style.zoom(100)
- _BUDDIES_COL_WIDTH = style.zoom(50)
-
- def __init__(self, jobject):
- CanvasRoundBox.__init__(self)
- self.props.box_height = style.zoom(75)
- self.props.spacing = style.DEFAULT_SPACING
- self.props.border_color = style.COLOR_BLACK.get_int()
- self.props.background_color = style.COLOR_PANEL_GREY.get_int()
-
- self.jobject = jobject
- self._icon_name = None
-
- date = hippo.CanvasText(text=self._format_date(),
- xalign=hippo.ALIGNMENT_START,
- font_desc=style.FONT_NORMAL.get_pango_desc(),
- box_width=self._DATE_COL_WIDTH)
- self.append(date)
-
- icon = CanvasIcon(icon_name=self._get_icon_name(),
- box_width=style.zoom(75))
-
- if self.jobject.metadata.has_key('icon-color'):
- icon.props.xo_color = XoColor(self.jobject.metadata['icon-color'])
-
- self.append(icon)
-
- title = hippo.CanvasText(text=self._format_title(),
- xalign=hippo.ALIGNMENT_START,
- font_desc=style.FONT_BOLD.get_pango_desc(),
- size_mode=hippo.CANVAS_SIZE_WRAP_WORD)
- self.append(title)
-
- def _get_icon_name(self):
- if self._icon_name:
- return self._icon_name
-
- if self.jobject.is_activity_bundle():
- bundle = ActivityBundle(self.jobject.file_path)
- self._icon_name = bundle.get_icon()
-
- if self.jobject.metadata['activity']:
- service_name = self.jobject.metadata['activity']
- activity_info = activity.get_registry().get_activity(service_name)
- if activity_info:
- self._icon_name = activity_info.icon
-
- mime_type = self.jobject.metadata['mime_type']
- if not self._icon_name and mime_type:
- self._icon_name = mime.get_mime_icon(mime_type)
- if not self._icon_name:
- self._icon_name = 'image-missing'
-
- return self._icon_name
-
- def _format_date(self):
- """ Convert from a string in iso format to a more human-like format. """
- return _get_elapsed_string(self.jobject.metadata['mtime'])
-
- def _format_title(self):
- return '"%s"' % self.jobject.metadata['title']
-
- def set_selected(self, selected):
- if selected:
- self.props.border_color = style.COLOR_WHITE.get_int()
- self.props.background_color = style.COLOR_WHITE.get_int()
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
+ return datastore.get(self._object_id)
+
+ def destroy(self):
+ self._cleanup()
+
+ def _cleanup(self):
+ if self._main_loop is not None:
+ self._main_loop.quit()
+ self._main_loop = None
+ self._bus = None
+
+ def __chooser_response_cb(self, chooser_id, object_id):
+ if chooser_id != self._chooser_id:
+ return
+ logging.debug('ObjectChooser.__chooser_response_cb: %r' % object_id)
+ self._response_code = gtk.RESPONSE_ACCEPT
+ self._object_id = object_id
+ self._cleanup()
+
+ def __chooser_cancelled_cb(self, chooser_id):
+ if chooser_id != self._chooser_id:
+ return
+ logging.debug('ObjectChooser.__chooser_cancelled_cb: %r' % chooser_id)
+ self._response_code = gtk.RESPONSE_CANCEL
+ self._cleanup()
+
+ def __name_owner_changed_cb(self, name, old, new):
+ logging.debug('ObjectChooser.__name_owner_changed_cb')
+ # Journal service disappeared from the bus
+ self._response_code = gtk.RESPONSE_CANCEL
+ self._cleanup()