update 7-zip to 4.64
[sugaredwine.git] / bin / sugar-run-from-journal
blobe278e165b4bce4ac89a8419ac27f33d31a0bb744
1 #!/usr/bin/env python
2 # Copyright (C) 2007, One Laptop Per Child
3 # Copyright (C) 2008, Vincent Povirk for CodeWeavers
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2 of the License, or (at your option) any later version.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the
17 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 # Boston, MA 02111-1307, USA.
20 # This sucks. To get the object chooser to work outside the main activity
21 # process, I had to cpoy the class from the sugar library and remove parts of
22 # it, apparently because I'm not getting some glib magic right.
24 # Hopefully the API won't change drastically.
26 import os
27 import traceback
29 import dbus
30 import dbus.mainloop.glib
32 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
34 import gobject
36 J_DBUS_SERVICE = 'org.laptop.Journal'
37 J_DBUS_INTERFACE = 'org.laptop.Journal'
38 J_DBUS_PATH = '/org/laptop/Journal'
40 RESPONSE_NONE = -1
41 RESPONSE_CANCEL = -6
42 RESPONSE_ACCEPT = -3
44 class ObjectChooser(object):
45 def __init__(self, parent=None):
46 if parent is None:
47 parent_xid = 0
48 elif hasattr(parent, 'window') and hasattr(parent.window, 'xid'):
49 parent_xid = parent.window.xid
50 else:
51 parent_xid = parent
53 self._parent_xid = parent_xid
54 self._object_id = None
55 self._bus = None
56 self._chooser_id = None
57 self._response_code = RESPONSE_NONE
59 def run(self):
60 self._object_id = None
62 self._main_loop = gobject.MainLoop()
64 self._bus = dbus.SessionBus()
65 self._bus.add_signal_receiver(
66 self.__name_owner_changed_cb,
67 signal_name="NameOwnerChanged",
68 dbus_interface="org.freedesktop.DBus",
69 arg0=J_DBUS_SERVICE)
71 obj = self._bus.get_object(J_DBUS_SERVICE, J_DBUS_PATH)
72 journal = dbus.Interface(obj, J_DBUS_INTERFACE)
73 journal.connect_to_signal('ObjectChooserResponse',
74 self.__chooser_response_cb)
75 journal.connect_to_signal('ObjectChooserCancelled',
76 self.__chooser_cancelled_cb)
77 self._chooser_id = journal.ChooseObject(self._parent_xid)
79 self._main_loop.run()
81 self._main_loop = None
83 return self._response_code
85 def get_selected_object(self):
86 if self._object_id is None:
87 return None
88 else:
89 from sugar.datastore import datastore
90 return datastore.get(self._object_id)
92 def destroy(self):
93 self._cleanup()
95 def _cleanup(self):
96 if self._main_loop is not None:
97 self._main_loop.quit()
98 self._main_loop = None
99 self._bus = None
101 def __chooser_response_cb(self, chooser_id, object_id):
102 if chooser_id != self._chooser_id:
103 return
104 print('ObjectChooser.__chooser_response_cb: %r' % object_id)
105 self._response_code = RESPONSE_ACCEPT
106 self._object_id = object_id
107 self._cleanup()
109 def __chooser_cancelled_cb(self, chooser_id):
110 if chooser_id != self._chooser_id:
111 return
112 print('ObjectChooser.__chooser_cancelled_cb: %r' % chooser_id)
113 self._response_code = RESPONSE_CANCEL
114 self._cleanup()
116 def __name_owner_changed_cb(self, name, old, new):
117 print('ObjectChooser.__name_owner_changed_cb')
118 # Journal service disappeared from the bus
119 self._response_code = RESPONSE_CANCEL
120 self._cleanup()
122 def start_wine(*args):
123 gobject.spawn_async(
124 ['wine', 'explorer', '/desktop=%s' % os.environ['WINE_DESKTOP_NAME']] + [str(x) for x in args],
125 flags=gobject.SPAWN_SEARCH_PATH)
127 def start_object(dsobject):
128 import shutil
129 import sys
130 from sugar.activity import activity
131 sys.path.insert(0, activity.get_bundle_path())
132 import filenames
133 file_path = dsobject.get_file_path()
134 fd, filename = filenames.create_dsobject_file(dsobject.metadata)
135 os.chmod(filename, int('0770', 8))
136 shutil.copyfile(file_path, filename)
137 os.close(fd)
138 # FIXME: delete the file when this activity instance exits?
139 start_wine('start', '/unix', filename)
142 def start_chooser_object(chooser):
143 try:
144 response = chooser.run()
145 if int(response) == RESPONSE_ACCEPT:
146 dsobject = chooser.get_selected_object()
147 try:
148 start_object(dsobject)
149 finally:
150 dsobject.destroy()
151 finally:
152 chooser.destroy()
154 def on_chooser_realize(widget):
155 # If ObjectChooser is a subclass of gtk.Dialog (old sugar-toolkit), we can't
156 # use an XID for the transient parent. Instead, we set it through gdk when
157 # the window is realized.
158 try:
159 import gtk
160 widget.window.set_transient_for(gtk.gdk.window_foreign_new(int(os.environ['SUGARED_WINE_TOPLEVEL'])))
161 except:
162 traceback.print_exc()
164 try:
165 chooser = ObjectChooser(parent=int(os.environ['SUGARED_WINE_TOPLEVEL']))
166 start_chooser_object(chooser)
167 except:
168 traceback.print_exc()
169 import sugar.graphics.objectchooser
170 chooser = sugar.graphics.objectchooser.ObjectChooser()
171 try:
172 chooser.connect('realize', on_chooser_realize)
173 except:
174 traceback.print_exc()
175 start_chooser_object(chooser)