Ticket #803: viewsourceopenwith

File viewsourceopenwith, 7.4 KB (added by homunq, 12 years ago)

this is a diff against Tomeu's checkin

Line 
1diff --git a/src/jarabe/journal/misc.py b/src/jarabe/journal/misc.py
2index b29b744..aa689a0 100644
3--- a/src/jarabe/journal/misc.py
4+++ b/src/jarabe/journal/misc.py
5@@ -132,16 +132,17 @@ def _get_activities_for_mime(mime_type):
6 
7 def get_activities(metadata):
8     activities = []
9+    registry = bundleregistry.get_registry()
10 
11     bundle_id = metadata.get('activity', '')
12     if bundle_id:
13-        activity_info = bundleregistry.get_registry().get_bundle(bundle_id)
14+        activity_info = registry.get_bundle(bundle_id)
15         if activity_info:
16             activities.append(activity_info)
17 
18     mime_type = metadata.get('mime_type', '')
19     if mime_type:
20-        activities_info = _get_activities_for_mime(mime_type)
21+        activities_info = registry.get_activities_for_lineage(mime_type)
22         for activity_info in activities_info:
23             if activity_info not in activities:
24                 activities.append(activity_info)
25diff --git a/src/jarabe/model/bundleregistry.py b/src/jarabe/model/bundleregistry.py
26index 42d39b0..e687b75 100644
27--- a/src/jarabe/model/bundleregistry.py
28+++ b/src/jarabe/model/bundleregistry.py
29@@ -29,6 +29,7 @@ from sugar.bundle.contentbundle import ContentBundle
30 from sugar.bundle.bundle import MalformedBundleException, \
31     AlreadyInstalledException, RegistrationException
32 from sugar import env
33+from sugar import mime
34 
35 from jarabe import config
36 
37@@ -241,6 +242,13 @@ class BundleRegistry(gobject.GObject):
38         else:
39             return None
40 
41+    def get_activities_for_lineage(self, mime_type):
42+        result = self.get_activities_for_type(mime_type)
43+        if not result:
44+            for parent_mime in mime.get_mime_parents(mime_type):
45+                result.extend(self.get_activities_for_type(parent_mime))
46+        return result
47+
48     def _find_bundle(self, bundle_id, version):
49         for bundle in self._bundles:
50             if bundle.get_bundle_id() == bundle_id and \
51diff --git a/src/jarabe/view/viewsource.py b/src/jarabe/view/viewsource.py
52index 870b176..9f71987 100644
53--- a/src/jarabe/view/viewsource.py
54+++ b/src/jarabe/view/viewsource.py
55@@ -33,15 +33,71 @@ from sugar.graphics.xocolor import XoColor
56 from sugar.graphics.menuitem import MenuItem
57 from sugar.graphics.toolbutton import ToolButton
58 from sugar.graphics.radiotoolbutton import RadioToolButton
59-from sugar.bundle.activitybundle import ActivityBundle
60+from sugar.graphics.menuitem import MenuItem
61+from sugar.activity.bundlebuilder import XOPackager, Config, Builder
62+from sugar import mime
63+from sugar import profile
64+from sugar.activity import activityfactory
65+from sugar.activity.activity import SCOPE_PRIVATE
66 from sugar.datastore import datastore
67 from sugar import mime
68+from sugar.bundle.activitybundle import ActivityBundle
69+from jarabe.model import bundleregistry
70+from tempfile import gettempdir
71 
72 _SOURCE_FONT = pango.FontDescription('Monospace %d' % style.FONT_SIZE)
73 
74 _logger = logging.getLogger('ViewSource')
75 map_activity_to_window = {}
76 
77+ACTIVITY_MIME = "application/vnd.olpc-sugar"
78+
79+def _bundle_activity(path):
80+    builder = XOPackager(Builder(Config(path, gettempdir(), None)))
81+    builder.package()
82+   
83+    jobject = datastore.create()
84+
85+    metadata = {
86+        'title': _('%s Bundle') % builder.config.activity_name,
87+        'title_set_by_user': '1',
88+        'suggested_filename': '%s-%d.xo' % (builder.config.bundle_name,
89+                                            builder.config.version),
90+        'icon-color': profile.get_color().to_string(),
91+        'mime_type': 'application/vnd.olpc-sugar',
92+        'activity' : builder.config.bundle_id,
93+        'share-scope' : SCOPE_PRIVATE,
94+        'preview' : '',
95+        'source' : path,
96+        }
97+    for k, v in metadata.items():
98+        jobject.metadata[k] = v # dict.update method is missing =(
99+    jobject.file_path = builder.package_path
100+    datastore.write(jobject)
101+    #jobject.destroy()
102+    os.remove(builder.package_path)
103+    return jobject.object_id
104+   
105+class DocumentData(dict):
106+    """'version' should always be a key.
107+   
108+    if version is 1, other keys should be
109+        ('mime_type', 'title', 'path', 'human_readable')"""
110+    def __init__(self, *args, **kwargs):
111+        super(DocumentData, self).__init__(*args,**kwargs)
112+       
113+        required_keys = ('mime_type', 'title', 'path', 'human_readable')
114+       
115+        if self["version"] == 1:
116+            if [1 for key in required_keys
117+                    if (key not in self.keys())]:
118+                logging.error("Activity returned misversioned data on "
119+                              "current document")
120+        else:
121+            for key in required_keys:
122+                self[key] = None
123+            _logger.debug('Current document data in unknown version')
124+
125 def setup_view_source(activity):
126     service = activity.get_service()
127     if service is not None:
128@@ -280,6 +336,10 @@ class Toolbar(gtk.Toolbar):
129             self._add_separator()
130 
131         if bundle_path is not None and os.path.exists(bundle_path):
132+            self._add_source(DocumentData(version=1, mime_type=ACTIVITY_MIME,
133+                                            title=title, path=bundle_path,
134+                                            human_readable=True),
135+                             'printer') #TODO: get a better icon
136             activity_button = RadioToolButton()
137             icon = Icon(file=file_name,
138                         icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR,
139@@ -311,6 +371,53 @@ class Toolbar(gtk.Toolbar):
140         self.insert(stop, -1)
141         stop.show()
142 
143+    def _add_source(self, data, icon):
144+       
145+        button = RadioToolButton(named_icon=icon)
146+        group = getattr(self, 'group', None)
147+        if group:
148+            button.props.group = group
149+        else:
150+            self.group = button
151+           
152+        if data["human_readable"]:
153+            button.connect('toggled', self.__button_toggled_cb, data["path"])
154+       
155+        button.props.tooltip = data["title"]
156+        self.insert(button, -1)
157+        button.show()
158+       
159+        if data["mime_type"]:
160+            registry = bundleregistry.get_registry()
161+            activities = registry.get_activities_for_lineage(data["mime_type"])
162+            if activities:
163+                palette = button.get_palette()
164+               
165+                menuitem = gtk.SeparatorMenuItem()
166+                palette.menu.append(menuitem)
167+                menuitem.show()
168+               
169+                for activity in activities:
170+                    menuitem = MenuItem(activity.get_name(),
171+                                        activity.get_icon())
172+                    menuitem.connect('activate', self._launch_with,
173+                                     (activity,data["path"],data["mime_type"]))
174+                    palette.menu.append(menuitem)
175+                    menuitem.show()
176+
177+    def _launch_with(self, menuitem, options):
178+        activity, path, mime_type = options
179+        if mime_type == ACTIVITY_MIME:
180+            object_id = _bundle_activity(path)
181+        else:
182+            object_id = self.activity_service.bundleSource(path, mime_type)
183+       
184+        if object_id:
185+            activityfactory.create_with_object_id(activity, object_id)
186+        else:
187+            logging.error("Failed to rebundle activity for editing source."
188+                          "Mime type:" + mime_type)
189+       
190     def _add_separator(self, expand=False):
191         separator = gtk.SeparatorToolItem()
192         separator.props.draw = False