Package screenlets :: Module utils
[hide private]
[frames] | no frames]

Source Code for Module screenlets.utils

  1  # This application is released under the GNU General Public License  
  2  # v3 (or, at your option, any later version). You can find the full  
  3  # text of the license under http://www.gnu.org/licenses/gpl.txt.  
  4  # By using, editing and/or distributing this software you agree to  
  5  # the terms and conditions of this license.  
  6  # Thank you for using free software! 
  7   
  8  #  screenlets.session (c) RYX (Rico Pfaus) 2007 <ryx@ryxperience.com> 
  9  # 
 10  # INFO: 
 11  # The screenlets.utils module contains functions that are somehow needed 
 12  # by the Screenlet-class or parts of the framework, but don't necessarily 
 13  # have to be part of the Screenlet-class itself. 
 14  # 
 15  # TODO: move more functions here when possible 
 16  # 
 17   
 18  import screenlets 
 19  import dbus 
 20  import os 
 21  import sys 
 22  import stat 
 23  import gettext 
 24  import re 
 25  import urllib 
 26  gettext.textdomain('screenlets') 
 27  gettext.bindtextdomain('screenlets', '/usr/share/locale') 
 28  import gobject 
 29  try: 
 30          import gnomevfs 
 31  except: 
 32          pass 
33 -def _(s):
34 return gettext.gettext(s)
35 36 37 # ------------------------------------------------------------------------------ 38 # FUNCTIONS 39 # ------------------------------------------------------------------------------ 40 41
42 -def is_manager_running_me():
43 """checks if the one starting the screenlet is the screenlets manager""" 44 if str(sys.argv[0]).find('screenlets-manager') != -1: 45 return True 46 else: 47 return False
48
49 -def create_user_dir ():
50 """Create the userdir for the screenlets.""" 51 if not os.path.isdir(os.environ['HOME'] + '/.screenlets'): 52 try: 53 os.mkdir(os.environ['HOME'] + '/.screenlets') 54 except: 55 print 'coulnt create user dir'
56
57 -def find_first_screenlet_path (screenlet_name):
58 """Scan the SCREENLETS_PATH for the first occurence of screenlet "name" and 59 return the full path to it. This function is used to get the theme/data 60 directories for a Screenlet.""" 61 for dir in screenlets.SCREENLETS_PATH: 62 try: 63 for name in os.listdir(dir): 64 name_py = name + 'Screenlet.py' 65 path = dir + '/' + name 66 if not stat.S_ISDIR(os.stat(path).st_mode): 67 continue 68 # if path exists 69 if os.access(path + '/' + name_py, os.F_OK): 70 if name == screenlet_name: 71 return path 72 else: 73 #print "utils.find_first_screenlet_path: "+\ 74 # "LISTED PATH NOT EXISTS: " + path 75 pass 76 except OSError: # Raised by os.listdir: the directory doesn't exist 77 pass 78 # nothing found 79 return None
80
81 -def get_screenlet_metadata (screenlet_name):
82 """Returns a dict with name, info, author and version of the given 83 screenlet. Use with care because it always imports the screenlet 84 module and shouldn't be used too often due to performance issues.""" 85 # find path to file 86 path = find_first_screenlet_path(screenlet_name) 87 classname = screenlet_name + 'Screenlet' 88 # add path to PYTHONPATH 89 if sys.path.count(path) == 0: 90 sys.path.insert(0, path) 91 try: 92 slmod = __import__(classname) 93 cls = getattr(slmod, classname) 94 sys.path.remove(path) 95 return {'name' : cls.__name__, 96 'info' : cls.__desc__, 97 'author' : cls.__author__, 98 'version' : cls.__version__ 99 } 100 except Exception, ex: 101 print _("Unable to load '%s' from %s: %s ") % (screenlet_name, path, ex) 102 return None
103
104 -def list_available_screenlets ():
105 """Scan the SCREENLETS_PATHs for all existing screenlets and return their 106 names (without trailing "Screenlet") as a list of strings.""" 107 sls = [] 108 for dir in screenlets.SCREENLETS_PATH: 109 try: 110 for name in os.listdir(dir): 111 path = dir + '/' + name 112 # check if entry is a dir 113 if not stat.S_ISDIR(os.stat(path).st_mode): 114 continue 115 # if path exists, add it to list 116 if os.access(path + '/' + name + 'Screenlet.py', os.F_OK): 117 if not sls.count(name): 118 sls.append(name) 119 else: 120 print _("LISTED PATH NOT EXISTS: ") + path 121 except OSError: # Raised by os.listdir: the directory doesn't exist 122 pass 123 return sls
124 125 import session
126 -def list_running_screenlets ():
127 """Returns a list with names of running screenlets or None if no 128 Screenlet is currently running. Function returns False if an error 129 happened!""" 130 tempfile = session.TMP_DIR + '/' + session.TMP_FILE 131 if not os.path.isfile(tempfile): 132 return None 133 f = open(tempfile, 'r') 134 if f: 135 running = f.readlines() 136 f.close() 137 for i in xrange(len(running)): 138 running[i] = running[i][:-1] # strip trailing EOL 139 return running 140 return False
141
142 -def _contains_path (string):
143 """Internal function: Returns true if the given string contains one of the 144 SCREENLETS_PATH entries.""" 145 for p in screenlets.SCREENLETS_PATH: 146 if string.find(p) > -1: 147 return True 148 return False
149
150 -def list_running_screenlets2 ():
151 """Returns a list with names of running screenlets. The list can be empty if 152 no Screenlet is currently running.""" 153 p = os.popen("ps aux | awk '/Screenlet.py/{ print $11, $12, $13, $14, $15, $16 }'") 154 lst = [] 155 regex = re.compile('/([A-Za-z0-9]+)Screenlet.py ') 156 for line in p.readlines(): 157 if not line.endswith('awk /Screenlet.py/{\n') and line != 'sh -c\n' \ 158 and _contains_path(line): 159 slname = regex.findall(line) 160 if slname and type(slname) == list and len(slname) > 0: 161 lst.append(slname[0]) 162 p.close() 163 return lst
164 165
166 -def get_GMail_Num(login, password):
167 """This output the number of messages of gmail box""" 168 169 f = os.popen("wget --no-check-certificate -qO - https://" + login + ":" + password + "@mail.google.com/mail/feed/atom") 170 a = f.read() 171 f.close() 172 match = re.search("<fullcount>([0-9]+)</fullcount>", a) 173 if match == None: 174 return None 175 else: 176 return match.group(1)
177 178 179
180 -def get_Mail_Num(server, login, passwd):
181 """This output the number of messages of mail box""" 182 try: 183 import poplib 184 except ImportError, err: 185 print " !!!Please install python poplib :", err 186 return None 187 m = poplib.POP3(server) 188 m.user(login) 189 m.pass_(passwd) 190 out = m.stat() 191 m.quit() 192 num = out[0] 193 return num
194
195 -def get_evolution_contacts():
196 """Returns a list of evolution contacts""" 197 contacts = [] 198 199 try: 200 import evolution 201 except ImportError, err: 202 print " !!!Please install python evolution bindings Unable to import evolution bindings:", err 203 return None 204 205 try: 206 if evolution: 207 for book_id in evolution.ebook.list_addressbooks(): 208 book = evolution.ebook.open_addressbook(book_id[1]) 209 if book: 210 for contact in book.get_all_contacts(): 211 212 contacts.append(contact) 213 except: 214 if evolution: 215 for book_id in evolution.list_addressbooks(): 216 book = evolution.open_addressbook(book_id[1]) 217 if book: 218 for contact in book.get_all_contacts(): 219 220 contacts.append(contact) 221 222 return contacts
223
224 -def get_screenlet_process (name):
225 """Returns the PID of the given screenlet (if running) or None.""" 226 p = os.popen("ps aux | awk '/[" + name[0] + "]" + name[1:] + \ 227 "Screenlet.py/{ print $2, $11, $12, $13, $14, $15, $16 }'") 228 line = p.readlines() 229 p.close() 230 #print line 231 if len(line) and _contains_path(line[0]): 232 return int(line[0].split(' ')[0]) 233 return None
234
235 -def get_user_dir(key, default):
236 """http://www.freedesktop.org/wiki/Software/xdg-user-dirs""" 237 238 user_dirs_dirs = os.path.expanduser("~/.config/user-dirs.dirs") 239 if os.path.exists(user_dirs_dirs): 240 f = open(user_dirs_dirs, "r") 241 for line in f.readlines(): 242 if line.startswith(key): 243 return os.path.expandvars(line[len(key)+2:-2]) 244 return default
245
246 -def get_desktop_dir():
247 """Returns desktop dir""" 248 desktop_dir = get_user_dir("XDG_DESKTOP_DIR", os.path.expanduser("~/Desktop")) 249 desktop_dir = urllib.unquote(desktop_dir) 250 return desktop_dir
251
252 -def get_filename_on_drop(sel_data):
253 filename = '' 254 filenames = [] 255 # get text-elements in selection data 256 try: 257 txt = unicode.encode(sel_data.get_text(), 'utf-8') 258 except: 259 txt = sel_data.get_text() 260 txta = urllib.unquote(txt) 261 txta = str(txta).split('\n') 262 263 for txt in txta: 264 if txt and txt != '': 265 # if it is a filename, use it 266 if txt.startswith('file://'): 267 filename = txt[7:] 268 else: 269 print 'Invalid string: %s.' % txt 270 else: 271 # else get uri-part of selection 272 uris = sel_data.get_uris() 273 if uris and len(uris)>0: 274 #print "URIS: "+str(uris ) 275 filename = uris[0][7:] 276 if filename != '': 277 filenames.append(chr(34) +filename + chr(34)) 278 279 return filenames
280
281 -def LoadPlaces():
282 """Returns mount points in media""" 283 mountlist = os.popen('mount -l').read() 284 prog = re.compile("^/dev/.*?\son\s/media/(.*?) .*?(\[(.*?)\])?$", re.MULTILINE) 285 return prog.findall(mountlist)
286
287 -def LoadBookmarks():
288 """Returns gtk bookmarks """ 289 _bookmarks_path = os.path.expanduser("~/.gtk-bookmarks") 290 _places = [] 291 try: 292 for line in file(_bookmarks_path): 293 line = line.strip() 294 295 if " " in line: 296 uri, name = line.split(" ", 1) 297 298 else: 299 uri = line 300 301 path = urllib.splittype(uri)[1] 302 name = urllib.unquote(os.path.split(path)[1]) 303 304 try: 305 if os.path.exists(uri): 306 continue 307 # Protect against a broken bookmarks file 308 except TypeError: 309 continue 310 311 _places.append((uri, name)) 312 return _places 313 except IOError, err: 314 print "Error loading GTK bookmarks:", err
315
316 -def readMountFile( filename):
317 fstab = [] 318 f = open(filename, 'r') 319 for line in f: 320 if (not line.isspace() and not line.startswith('#') and not line.lower().startswith('none')) : 321 fstabline = line.split() 322 if fstabline[1] != 'none' and fstabline[1] != '/proc': fstab.append(fstabline[1]) 323 324 fstab.sort() 325 return fstab
326
327 -def read_file( filename):
328 329 f = open(filename, 'r') 330 t = f.read() 331 f.close() 332 return t
333 334
335 -def strip_html(string):
336 return re.sub(r"<.*?>|</.*?>","",string)
337 338 # ------------------------------------------------------------------------------ 339 # CLASSES 340 # ------------------------------------------------------------------------------ 341
342 -class FileMonitor(gobject.GObject):
343 ''' 344 A simple wrapper around Gnome VFS file monitors. Emits created, deleted, 345 and changed events. Incoming events are queued, with the latest event 346 cancelling prior undelivered events. 347 ''' 348 349 350 __gsignals__ = { 351 "event" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, 352 (gobject.TYPE_STRING, gobject.TYPE_INT)), 353 "created" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), 354 "deleted" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), 355 "changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)) 356 } 357
358 - def __init__(self, path):
359 gobject.GObject.__init__(self) 360 361 if os.path.isabs(path): 362 self.path = "file://" + path 363 else: 364 self.path = path 365 try: 366 self.type = gnomevfs.get_file_info(path).type 367 except gnomevfs.Error: 368 self.type = gnomevfs.MONITOR_FILE 369 370 self.monitor = None 371 self.pending_timeouts = {}
372
373 - def open(self):
374 if not self.monitor: 375 if self.type == gnomevfs.FILE_TYPE_DIRECTORY: 376 monitor_type = gnomevfs.MONITOR_DIRECTORY 377 else: 378 monitor_type = gnomevfs.MONITOR_FILE 379 self.monitor = gnomevfs.monitor_add(self.path, monitor_type, self._queue_event)
380
381 - def _clear_timeout(self, info_uri):
382 try: 383 gobject.source_remove(self.pending_timeouts[info_uri]) 384 del self.pending_timeouts[info_uri] 385 except KeyError: 386 pass
387
388 - def _queue_event(self, monitor_uri, info_uri, event):
389 self._clear_timeout(info_uri) 390 self.pending_timeouts[info_uri] = \ 391 gobject.timeout_add(250, self._timeout_cb, monitor_uri, info_uri, event)
392
393 - def queue_changed(self, info_uri):
394 self._queue_event(self.path, info_uri, gnomevfs.MONITOR_EVENT_CHANGED)
395
396 - def close(self):
397 gnomevfs.monitor_cancel(self.monitor) 398 self.monitor = None
399
400 - def _timeout_cb(self, monitor_uri, info_uri, event):
401 if event in (gnomevfs.MONITOR_EVENT_METADATA_CHANGED, 402 gnomevfs.MONITOR_EVENT_CHANGED): 403 self.emit("changed", info_uri) 404 elif event == gnomevfs.MONITOR_EVENT_CREATED: 405 self.emit("created", info_uri) 406 elif event == gnomevfs.MONITOR_EVENT_DELETED: 407 self.emit("deleted", info_uri) 408 self.emit("event", info_uri, event) 409 410 self._clear_timeout(info_uri) 411 return False
412 413
414 -class IniReader:
415 """A simple config/ini-reader class. This is only used for reading the 416 theme.conf files yet, thus it only uses string-values. 417 TODO: add writing-functions and let backend use this, too""" 418
419 - def __init__ (self):
420 self.options = [] 421 self.sections = {}
422
423 - def list_options (self, section=''):
424 """Return all options (alternatively only from the given section).""" 425 if section != '': 426 return self.sections[section] 427 else: 428 return self.options
429
430 - def get_option (self, name, section=''):
431 """Get a variable from the config (optional: only get vars from the 432 specified section).""" 433 if section != '': 434 l = self.sections[section] 435 else: 436 l = self.options 437 for o in l: 438 if o[0] == name: 439 return o[1] 440 return None
441
442 - def has_section (self, name):
443 """Returns true if the given section exists.""" 444 return self.sections.has_key(name)
445
446 - def load (self, filename):
447 """Load a config/ini-file and save vars in internal list.""" 448 f=None 449 try: 450 f = open (filename, "r") 451 except: 452 print _("File %s not found") % str(filename) 453 if f: 454 section_name = '' 455 for line in f.readlines(): 456 # strip whitespace/tabs on the left 457 line = line.lstrip().lstrip('\t') 458 #print line 459 # ignore comment, EOL and too short lines 460 if len(line) < 4 or line[0] in ("#", "\n", ";"): 461 pass 462 else: 463 # split var/value and trim 464 tmp = line.split('=', 1) 465 # no '=' found? check for section name 466 if len(tmp) < 2 and len(line) > 5 and line[0] == '[': 467 section_name = line[:-1][1:-1] 468 self.sections[section_name] = [] 469 #print "Section found: %s" % section_name 470 else: 471 # two entries? split var/value 472 var = tmp[0].rstrip().rstrip('\t') 473 val = tmp[1][:-1].lstrip() # remove EOL 474 #print "VAR: %s=%s" % (var, val) 475 # and add them to lists 476 if var != '' and val != '': 477 o = [var, val] 478 self.options.append(o) 479 if section_name != '': 480 try: 481 self.sections[section_name].append(o) 482 except: 483 print _("Section %s not found!") % section_name 484 f.close() 485 return True 486 else: 487 return False
488
489 -class Notifier:
490 """A simple and conveniet wrapper for the notification-service. Allows 491 screenlets to easily pop up notes with their own icon (if any).""" 492
493 - def __init__ (self, screenlet=None):
494 self.bus = dbus.SessionBus() 495 self.notifications = dbus.Interface(\ 496 self.bus.get_object('org.freedesktop.Notifications', 497 '/org/freedesktop/Notifications'), 'org.freedesktop.Notifications') 498 self.screenlet = screenlet
499
500 - def notify (self, message, title='', icon='', timeout=-1, screenlet=None):
501 """Send a notification to org.freedesktop.Notifications. The message 502 should contain the text you want to display, title may define a title 503 (summary) for the message, icon can be the full path to an icon, 504 timeout can be set to the desired displaying time in milliseconds.""" 505 if self.bus and self.notifications: 506 if not screenlet: 507 screenlet = self.screenlet 508 if screenlet: 509 p = find_first_screenlet_path(screenlet.__class__.__name__[:-9]) 510 if p: 511 icon = p + '/icon.svg' 512 title = screenlet.__name__ 513 self.notifications.Notify('Screenlets', 0, icon, title, message, 514 [], {}, timeout) 515 return True 516 else: 517 print _("Notify: No DBus running or notifications-daemon unavailable.") 518 return False
519 520 521 if __name__ == '__main__': 522 523 # get info about screenlet 524 print get_screenlet_metadata('Clock') 525 526 # find first path 527 print "Find first occurence of a Screenlet:" 528 print find_first_screenlet_path('Clock') 529 print find_first_screenlet_path('Orloj') 530 print find_first_screenlet_path('Weather') 531 print find_first_screenlet_path('Foo') 532 533 # list available 534 print "\nList all installed Screenlets:" 535 avail = list_available_screenlets() 536 avail.sort() 537 print avail 538 539 # IniReader 540 print "\nTest INI-reader:" 541 ini = IniReader() 542 if not ini.load('/usr/share/screenlets/CPUMeter/themes/default/theme.conf'): 543 print "Error while loading ini-file" 544 else: 545 # check for section 546 if ini.has_section('Theme'): 547 # get option-values from within a section 548 print ini.get_option('name', section='Theme') 549 print ini.get_option('info', section='Theme') 550 # check for existence of a section 551 if ini.has_section('Options'): 552 for o in ini.list_options(section='Options'): 553 print o[0] 554 555 # notify 556 print "\nNotify-test:" 557 n = Notifier() 558 n.notify('Hi there! This is sent through screenlets.utils.Notifier.notify', 559 title='Test') 560 n.notify('A second note ..', title='Another note', timeout=2000) 561 n.notify('A second note ..', title='Another note', icon='/usr/share/screenlets/Notes/icon.svg') 562 563 # some tests of the list/find screenlets functions 564 print "\nRunning screenlets: " 565 print list_running_screenlets2() 566 print "\n" 567 print get_screenlet_process('Clock') 568 print get_screenlet_process('Ruler') 569 print get_screenlet_process('Webtest') 570