1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 import os
36 import glob
37 import random
38 from xdg import BaseDirectory
39
40 import backend
41 import services
42 import utils
43
44 import dbus
45
46 import gettext
47
48 gettext.textdomain('screenlets')
49 gettext.bindtextdomain('screenlets', '/usr/share/locale')
50
52 return gettext.gettext(s)
53
54
55
56 TMP_DIR = '/tmp/screenlets'
57 TMP_FILE = 'screenlets.' + os.environ['USER'] + '.running'
58
59
61 """The ScreenletSession manages instances of a Screenlet and handles
62 saving/restoring options. Each Screenlet contains a reference to its
63 session. Multiple instances of the same Screenlet share the same
64 session-object."""
65
66
67 - def __init__ (self, screenlet_classobj, backend_type='caching', name='default'):
68 object.__init__(self)
69
70 if not screenlet_classobj.__name__.endswith('Screenlet'):
71
72 raise Exception(_("""ScreenletSession.__init__ has to be called with a
73 valid Screenlet-classobject as first argument!"""))
74
75 self.name = name
76 self.screenlet = screenlet_classobj
77 self.instances = []
78 self.tempfile = TMP_DIR + '/' + TMP_FILE
79
80 self.__parse_commandline()
81
82 p = screenlet_classobj.__name__[:-9] + '/' + self.name + '/'
83 self.path = BaseDirectory.load_first_config('Screenlets/' + p)
84 if self.path == None:
85 self.path = BaseDirectory.save_config_path('Screenlets/' + p)
86 if self.path:
87 if backend_type == 'caching':
88 self.backend = backend.CachingBackend(path=self.path)
89 elif backend_type == 'gconf':
90 self.backend = backend.GconfBackend()
91 else:
92
93 self.backend = backend.ScreenletsBackend()
94 print _("Unable to init backend - settings will not be saved!")
95
96
97 self.connect_daemon()
98
100 """Connect to org.screenlets.ScreenletsDaemon."""
101 self.daemon_iface = None
102 bus = dbus.SessionBus()
103 if bus:
104 try:
105 bus_name = 'org.screenlets.ScreenletsDaemon'
106 path = '/org/screenlets/ScreenletsDaemon'
107 iface = 'org.screenlets.ScreenletsDaemon'
108 proxy_obj = bus.get_object(bus_name, path)
109 if proxy_obj:
110 self.daemon_iface = dbus.Interface(proxy_obj, iface)
111 except Exception, ex:
112 print _("Error in screenlets.session.connect_daemon: %s") % ex
113
115 """Create a new instance with ID 'id' and add it to this session. The
116 function returns either the new Screenlet-instance or None."""
117 print _("Creating new instance: ")
118
119 if id==None or id=='' or self.get_instance_by_id(id) != None:
120 print _("ID is unset or already in use - creating new one!")
121 id = self.__get_next_id()
122 dirlst = glob.glob(self.path + '*')
123 tdlen = len(self.path)
124 for filename in dirlst:
125 filename = filename[tdlen:]
126 print _('File: %s') % filename
127 if filename.endswith(id + '.ini'):
128
129 sl = self.create_instance(id=filename[:-4], enable_saving=False)
130 if sl:
131
132 print _("Set options in %s") % sl.__name__
133
134 self.__restore_options_from_backend(sl, self.path+filename)
135 sl.enable_saving(True)
136
137 sl.finish_loading()
138 return sl
139 sl = self.screenlet(id=id, session=self, **keyword_args)
140 if sl:
141 self.instances.append(sl)
142
143 sl.x = sl.x
144 return sl
145 return None
146
148 """Delete the given instance with ID 'id' and remove its session file.
149 When the last instance within the session is removed, the session dir
150 is completely removed."""
151 sl = self.get_instance_by_id(id)
152 if sl:
153
154 self.instances.remove(sl)
155
156 try:
157 self.backend.delete_instance(id)
158 except Exception:
159 print _("Failed to remove INI-file for instance (not critical).")
160
161 if len(self.instances) == 0:
162
163 print _("Removing last instance from session")
164
165 print _("TODO: remove self.path: %s") % self.path
166 try:
167 os.rmdir(self.path)
168 except:
169 print _("Failed to remove session dir '%s' - not empty?") % self.name
170
171
172 sl.quit_on_close = True
173 else:
174 print _("Removing instance from session but staying alive")
175 sl.quit_on_close = False
176
177 sl.close()
178 del sl
179 return True
180 return False
181
183 """Return the instance with the given id from within this session."""
184 for inst in self.instances:
185 if inst.id == id:
186 return inst
187 return None
188
190 """quit the given instance with ID 'id'"""
191
192 sl = self.get_instance_by_id(id)
193 if sl:
194 print self.instances
195
196
197
198 if len(self.instances) == 1:
199 sl.quit_on_close = True
200 else:
201 print _("Removing instance from session but staying alive")
202 sl.quit_on_close = False
203 self.backend.flush()
204 sl.close()
205 self.instances.remove(sl)
206 print sl
207
208 return True
209 return False
210
211
213 """Start a new session (or restore an existing session) for the
214 current Screenlet-class. Creates a new instance when none is found.
215 Returns True if everything worked well, else False."""
216
217
218
219 sln = self.screenlet.__name__[:-9]
220 running = utils.list_running_screenlets()
221 if running and running.count(self.screenlet.__name__) > 0:
222
223 print _("Found a running session of %s, adding new instance by service.") % sln
224 srvc = services.get_service_by_name(sln)
225 if srvc:
226 print _("Adding new instance through: %s") % str(srvc)
227 srvc.add('')
228 return False
229
230 self.__register_screenlet()
231
232 print _("Loading instances in: %s") % self.path
233 if self.__load_instances():
234
235 print _("Restored instances from session '%s' ...") % self.name
236
237
238 self.__run_session(self.instances[0])
239 else:
240
241 print _('No instance(s) found in session-path, creating new one.')
242 sl = self.screenlet(session=self, id=self.__get_next_id())
243 if sl:
244
245 self.instances.append(sl)
246
247
248 self.backend.save_option(sl.id, 'x', sl.x)
249
250 sl.finish_loading()
251
252
253 self.__run_session(sl)
254 else:
255 print _('Failed creating instance of: %s') % self.classobj.__name__
256
257 self.__unregister_screenlet()
258 return False
259
260 return True
261
263 """Create new entry for this session in the global TMP_FILE."""
264
265 if not os.path.isfile(self.tempfile) and not self.__create_tempfile():
266 print _('Error: Unable to create temp entry - screenlets-manager will not work properly.')
267 return False
268
269 f = open(self.tempfile, 'a')
270 if f:
271
272 running = utils.list_running_screenlets()
273 if running.count(self.screenlet.__name__) == 0:
274 print _("Creating new entry for %s in %s") % (self.screenlet.__name__, self.tempfile)
275 f.write(self.screenlet.__name__ + '\n')
276 f.close()
277
278
279 if self.daemon_iface:
280 self.daemon_iface.register_screenlet(self.screenlet.__name__)
281
283 """Create the global temporary file for saving screenlets. The file is
284 used for indicating which screnlets are currently running."""
285
286 if not os.path.isdir(TMP_DIR):
287 print _("No global tempfile found, creating new one.")
288 os.mkdir(TMP_DIR)
289 if not os.path.isdir(TMP_DIR):
290 print _('Error: Unable to create temp directory %s - screenlets-manager will not work properly.') % TMP_DIR
291 return False
292 else:
293
294 f = open(self.tempfile, 'w')
295 f.close()
296 return True
297
299 """Delete this session's entry from the gloabl tempfile (and delete the
300 entire file if no more running screenlets are set."""
301 if not name:
302 name = self.screenlet.__name__
303
304
305 if self.daemon_iface:
306 try:
307 self.daemon_iface.unregister_screenlet(name)
308 except Exception, ex:
309 print _("Failed to unregister from daemon: %s") % ex
310
311
312 running = utils.list_running_screenlets()
313 if running and len(running) > 0:
314 print _("Removing entry for %s from global tempfile %s") % (name, self.tempfile)
315 try:
316 running.remove(name)
317 except:
318
319 print _("Entry not found. Will (obviously) not be removed.")
320 return True
321
322 if running and len(running) > 0:
323
324 f = open(self.tempfile, 'w')
325 if f:
326 for r in running:
327 f.write(r + '\n')
328 f.close()
329 return True
330 else:
331 print _("Error global tempfile not found. Some error before?")
332 return False
333 else:
334 print _('No more screenlets running.')
335 self.__delete_tempfile(name)
336 else:
337 print _('No screenlets running?')
338 return False
339
341 """Delete the tempfile for this session."""
342 if self.tempfile and os.path.isfile(self.tempfile):
343 print _("Deleting global tempfile %s") % self.tempfile
344 try:
345 os.remove(self.tempfile)
346 return True
347 except:
348 print _("Error: Failed to delete global tempfile")
349 return False
350
352 """Get the next ID for an instance of the assigned Screenlet."""
353 num = 1
354 sln = self.screenlet.__name__[:-9]
355 id = sln + str(num)
356 while self.get_instance_by_id(id) != None:
357 id = sln + str(num)
358 num += 1
359 return id
360
362 """Check for existing instances in the current session, create them
363 and store them into self.instances if any are found. Returns True if
364 at least one instance was found, else False."""
365 dirlst = glob.glob(self.path + '*')
366 tdlen = len(self.path)
367 for filename in dirlst:
368 filename = filename[tdlen:]
369 print _('File: %s') % filename
370 if filename.endswith('.ini'):
371
372 sl = self.create_instance(id=filename[:-4], enable_saving=False)
373 if sl:
374
375 print _("Set options in %s") % sl.__name__
376
377 self.__restore_options_from_backend(sl, self.path+filename)
378 sl.enable_saving(True)
379
380 sl.finish_loading()
381 else:
382 print _("Failed to create instance of '%s'!") % filename[:-4]
383
384 if len(self.instances) > 0:
385 return True
386 return False
387
388
408
410 """Run the session by calling the main handler of the given Screenlet-
411 instance. Handles sigkill (?) and keyboard interrupts."""
412
413 import signal
414 def on_kill():
415 print _("Screenlet has been killed. TODO: make this an event")
416 signal.signal(signal.SIGTERM, on_kill)
417
418 tempfile = self.screenlet.__name__
419
420 try:
421
422 main_instance.main()
423 except KeyboardInterrupt:
424
425 self.backend.flush()
426 print _("Screenlet '%s' has been interrupted by keyboard. TODO: make this an event") % self.screenlet.__name__
427 except Exception, ex:
428 print _("Exception in ScreenletSession: ") + ex
429
430 self.__unregister_screenlet(name=tempfile)
431
433 """Check commandline args for "--session" argument and set session
434 name if found. Runs only once during __init__.
435 TODO: handle more arguments and maybe allow setting options by
436 commandline"""
437 import sys
438 for arg in sys.argv[1:]:
439
440 if arg.startswith('--session=') and len(arg)>10:
441 self.name = arg[10:]
442
443
444
446 """A very simple utility-function to easily create/start a new session."""
447 if threading:
448 import gtk
449 gtk.gdk.threads_init()
450 session = ScreenletSession(classobj, backend_type=backend)
451 session.start()
452