~ubuntu-branches/debian/sid/sugar-toolkit-gtk3/sid

« back to all changes in this revision

Viewing changes to src/sugar3/graphics/objectchooser.py

  • Committer: Package Import Robot
  • Author(s): Jonas Smedegaard
  • Date: 2015-04-17 10:34:39 UTC
  • mfrom: (4.1.4 experimental)
  • Revision ID: package-import@ubuntu.com-20150417103439-xsqh30o8p0v6bflp
Tags: 0.104.1-5
* Move packaging to Debian Sugar Team.
* Update package relations:
  + Fix depend on python-gi-cairo.
    Thanks to Martin Abente and James Cameron.
* Fix typo in libsugarext-dev short description.
  Closes: bug#747026. Thanks to Anders Jonsson.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
"""
21
21
 
22
22
import logging
 
23
import StringIO
 
24
import cairo
23
25
 
24
26
from gi.repository import GObject
25
27
from gi.repository import Gtk
27
29
import dbus
28
30
 
29
31
from sugar3.datastore import datastore
 
32
from sugar3.activity.activity import PREVIEW_SIZE
30
33
 
31
34
 
32
35
J_DBUS_SERVICE = 'org.laptop.Journal'
33
36
J_DBUS_INTERFACE = 'org.laptop.Journal'
34
37
J_DBUS_PATH = '/org/laptop/Journal'
35
38
 
 
39
FILTER_TYPE_MIME_BY_ACTIVITY = 'mime_by_activity'
 
40
FILTER_TYPE_GENERIC_MIME = 'generic_mime'
 
41
FILTER_TYPE_ACTIVITY = 'activity'
 
42
 
 
43
 
 
44
def get_preview_pixbuf(preview_data, width=-1, height=-1):
 
45
    """Retrive a pixbuf with the content of the preview field
 
46
 
 
47
    Keyword arguments:
 
48
    metadata -- the metadata dictionary.
 
49
                Can't be None, use metadata.get('preview', '')
 
50
    width -- the pixbuf width, if is not set, the default width will be used
 
51
    height -- the pixbuf width, if is not set, the default height will be used
 
52
 
 
53
    Return: a Pixbuf or None if couldn't create it
 
54
 
 
55
    """
 
56
    if width == -1:
 
57
        width = PREVIEW_SIZE[0]
 
58
 
 
59
    if height == -1:
 
60
        height = PREVIEW_SIZE[1]
 
61
 
 
62
    pixbuf = None
 
63
 
 
64
    if len(preview_data) > 4:
 
65
        if preview_data[1:4] != 'PNG':
 
66
            # TODO: We are close to be able to drop this.
 
67
            import base64
 
68
            preview_data = base64.b64decode(preview_data)
 
69
 
 
70
        png_file = StringIO.StringIO(preview_data)
 
71
        try:
 
72
            # Load image and scale to dimensions
 
73
            surface = cairo.ImageSurface.create_from_png(png_file)
 
74
            png_width = surface.get_width()
 
75
            png_height = surface.get_height()
 
76
 
 
77
            preview_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
 
78
                                                 width, height)
 
79
            cr = cairo.Context(preview_surface)
 
80
 
 
81
            scale_w = width * 1.0 / png_width
 
82
            scale_h = height * 1.0 / png_height
 
83
            scale = min(scale_w, scale_h)
 
84
 
 
85
            cr.scale(scale, scale)
 
86
 
 
87
            cr.set_source_rgba(1, 1, 1, 0)
 
88
            cr.set_operator(cairo.OPERATOR_SOURCE)
 
89
            cr.paint()
 
90
            cr.set_source_surface(surface)
 
91
            cr.paint()
 
92
 
 
93
            pixbuf = Gdk.pixbuf_get_from_surface(preview_surface, 0, 0,
 
94
                                                 width, height)
 
95
        except Exception:
 
96
            logging.exception('Error while loading the preview')
 
97
 
 
98
    return pixbuf
 
99
 
36
100
 
37
101
class ObjectChooser(object):
38
102
 
39
 
    def __init__(self, parent=None, what_filter=None):
 
103
    def __init__(self, parent=None, what_filter=None, filter_type=None,
 
104
                 show_preview=False):
 
105
        """Initialise the ObjectChoser
 
106
 
 
107
        parent -- the widget calling ObjectChooser
 
108
 
 
109
        what_filter -- string
 
110
 
 
111
            string should be an activity bundle_id or a generic mime
 
112
            type as defined in mime.py used to determine which objects
 
113
            will be presented in the object chooser
 
114
 
 
115
        filter_type -- string
 
116
 
 
117
            string should be one of [None, FILTER_TYPE_GENERIC_MIME,
 
118
            FILTER_TYPE_ACTIVITY, FILTER_TYPE_MIME_BY_ACTIVITY]
 
119
 
 
120
            If filter_type is None, the default behavior of the
 
121
            what_filter is applied (for backward compatibility),
 
122
            this option is DEPRECATED.
 
123
 
 
124
            If filter_type is FILTER_TYPE_GENERIC_MIME, the
 
125
            what_filter should be a generic mime type defined in
 
126
            mime.py; the object chooser will filter based in the
 
127
            'mime_type' metadata field.
 
128
 
 
129
            If filter_type is FILTER_TYPE_ACTIVITY, the what_filter
 
130
            should by an activity bundle_id; the object chooser
 
131
            will filter based in the 'activity' metadata field.
 
132
 
 
133
            If filter_type is FILTER_TYPE_MIME_BY_ACTIVITY, the
 
134
            what_filter should be an activity bundle_id; the object
 
135
            chooser will filter based on the 'mime_type' metadata
 
136
            field and the mime types defined by the activity in the
 
137
            activity.info file.
 
138
 
 
139
        show_preview -- boolean
 
140
 
 
141
            if True will show the preview image asociated with
 
142
            the object in the Journal. This option is only available
 
143
            if filter_type is selected.
 
144
        """
 
145
 
40
146
        if parent is None:
41
147
            parent_xid = 0
42
148
        elif hasattr(parent, 'get_window') and hasattr(parent.get_window(),
46
152
            parent_xid = parent
47
153
 
48
154
        self._parent_xid = parent_xid
 
155
        self._show_preview = show_preview
49
156
        self._main_loop = None
50
157
        self._object_id = None
51
158
        self._bus = None
52
159
        self._chooser_id = None
53
160
        self._response_code = Gtk.ResponseType.NONE
54
161
        self._what_filter = what_filter
 
162
        if filter_type is not None:
 
163
            # verify is one of the availables types
 
164
            # add here more types if needed
 
165
            if filter_type not in [FILTER_TYPE_MIME_BY_ACTIVITY,
 
166
                                   FILTER_TYPE_GENERIC_MIME,
 
167
                                   FILTER_TYPE_ACTIVITY]:
 
168
                raise Exception('filter_type not implemented')
 
169
 
 
170
        self._filter_type = filter_type
55
171
 
56
172
    def run(self):
57
173
        self._object_id = None
60
176
 
61
177
        self._bus = dbus.SessionBus(mainloop=self._main_loop)
62
178
        self._bus.add_signal_receiver(
63
 
                self.__name_owner_changed_cb,
64
 
                signal_name='NameOwnerChanged',
65
 
                dbus_interface='org.freedesktop.DBus',
66
 
                arg0=J_DBUS_SERVICE)
 
179
            self.__name_owner_changed_cb,
 
180
            signal_name='NameOwnerChanged',
 
181
            dbus_interface='org.freedesktop.DBus',
 
182
            arg0=J_DBUS_SERVICE)
67
183
 
68
184
        obj = self._bus.get_object(J_DBUS_SERVICE, J_DBUS_PATH)
69
185
        journal = dbus.Interface(obj, J_DBUS_INTERFACE)
77
193
        else:
78
194
            what_filter = self._what_filter
79
195
 
80
 
        self._chooser_id = journal.ChooseObject(self._parent_xid, what_filter)
 
196
        if self._filter_type is None:
 
197
            self._chooser_id = journal.ChooseObject(
 
198
                self._parent_xid, what_filter)
 
199
        else:
 
200
            self._chooser_id = journal.ChooseObjectWithFilter(
 
201
                self._parent_xid, what_filter, self._filter_type,
 
202
                self._show_preview)
81
203
 
82
204
        Gdk.threads_leave()
83
205
        try:
106
228
    def __chooser_response_cb(self, chooser_id, object_id):
107
229
        if chooser_id != self._chooser_id:
108
230
            return
109
 
        logging.debug('ObjectChooser.__chooser_response_cb: %r', object_id)
 
231
        logging.debug('ObjectChooser.__chooser_response_cb: %r' % object_id)
110
232
        self._response_code = Gtk.ResponseType.ACCEPT
111
233
        self._object_id = object_id
112
234
        self._cleanup()
114
236
    def __chooser_cancelled_cb(self, chooser_id):
115
237
        if chooser_id != self._chooser_id:
116
238
            return
117
 
        logging.debug('ObjectChooser.__chooser_cancelled_cb: %r', chooser_id)
 
239
        logging.debug('ObjectChooser.__chooser_cancelled_cb: %r' % chooser_id)
118
240
        self._response_code = Gtk.ResponseType.CANCEL
119
241
        self._cleanup()
120
242