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.utils (c) Whise (Helder Fraga) 2008 <helder.fraga@hotmail.com> 
  9  #  Originaly by RYX (Rico Pfaus) 2007 <ryx@ryxperience.com> 
 10  # 
 11  # TODO: move more functions here when possible 
 12  # 
 13   
 14  import screenlets 
 15  import gtk 
 16  import dbus 
 17  import os 
 18  import sys 
 19  import stat 
 20  import gettext 
 21  import re 
 22  import urllib 
 23  gettext.textdomain('screenlets') 
 24  gettext.bindtextdomain('screenlets', screenlets.INSTALL_PREFIX +  '/share/locale') 
 25  import gobject 
 26  from distutils.version import LooseVersion 
 27  from subprocess import * 
 28  from HTMLParser import HTMLParser 
 29  from BeautifulSoup import BeautifulStoneSoup 
 30  try: 
 31          import gnomevfs 
 32  except: 
 33          pass 
34 -def _(s):
35 return gettext.gettext(s)
36 37 # ------------------------------------------------------------------------------ 38 # FUNCTIONS 39 # ------------------------------------------------------------------------------ 40 41
42 -class MLStripper(HTMLParser):
43 - def __init__(self):
44 self.reset() 45 self.fed = []
46 - def handle_data(self, d):
47 self.fed.append(d)
48 - def get_data(self):
49 return ''.join(self.fed)
50
51 -def html_to_pango (html):
52 """Simple html to pango stripper.""" 53 s = MLStripper() 54 s.feed(html) 55 no_html = s.get_data() 56 decoded = BeautifulStoneSoup(no_html, convertEntities=BeautifulStoneSoup.HTML_ENTITIES) 57 result = decoded.encode("UTF-8") 58 return result.strip(" \n") 59 60
61 -def get_autostart_dir():
62 """Returns the system autostart directory""" 63 desktop_environment = 'gnome' 64 65 if os.environ.get('KDE_FULL_SESSION') == 'true': 66 desktop_environment = 'kde' 67 elif os.environ.get('GNOME_DESKTOP_SESSION_ID'): 68 desktop_environment = 'gnome' 69 else: 70 try: 71 import commands 72 info = commands.getoutput('xprop -root _DT_SAVE_MODE') 73 if ' = "xfce4"' in info: 74 desktop_environment = 'xfce' 75 except (OSError, RuntimeError): 76 pass 77 78 79 80 if desktop_environment == 'kde': 81 return os.environ['HOME'] + '/.kde/Autostart/' 82 elif desktop_environment == 'gnome': 83 return os.environ['HOME'] + '/.config/autostart/' 84 elif desktop_environment == 'xfce': 85 return os.environ['HOME'] + '/.config/autostart/'
86 87 if os.geteuid()==0: 88 # we run as root, install system-wide 89 USER = 0 90 DIR_USER = screenlets.INSTALL_PREFIX + '/share/screenlets' 91 DIR_AUTOSTART = '/etc/xdg/autostart' # TODO: use pyxdg here 92 else: 93 # we run as normal user, install into $HOME 94 USER = 1 95 DIR_USER = os.environ['HOME'] + '/.screenlets' 96 DIR_AUTOSTART = get_autostart_dir() 97 98 99
100 -def is_manager_running_me():
101 """checks if the one starting the screenlet is the screenlets manager""" 102 if str(sys.argv[0]).find('screenlets-manager') != -1: 103 return True 104 else: 105 return False
106
107 -def containsAll(str, set):
108 """Check whether 'str' contains ALL of the chars in 'set'""" 109 for c in set: 110 if c not in str: return 0; 111 return 1;
112 -def containsAny(str, set):
113 """Check whether 'str' contains ANY of the chars in 'set'""" 114 return 1 in [c in str for c in set]
115
116 -def create_autostarter (name):
117 """Create a .desktop-file for the screenlet with the given name in 118 $HOME/.config/autostart.""" 119 if not os.path.isdir(DIR_AUTOSTART): 120 # create autostart directory, if not existent 121 if screenlets.show_question(None, 122 _("There is no existing autostart directory for your user account yet. Do you want me to automatically create it for you?"), 123 _('Error')): 124 print "Auto-create autostart dir ..." 125 os.system('mkdir %s' % DIR_AUTOSTART) 126 if not os.path.isdir(DIR_AUTOSTART): 127 screenlets.show_error(None, _("Automatic creation failed. Please manually create the directory:\n%s") % DIR_AUTOSTART, _('Error')) 128 return False 129 else: 130 screenlets.show_message(None, _("Please manually create the directory:\n%s") % DIR_AUTOSTART) 131 return False 132 if name.endswith('Screenlet'): 133 name = name[:-9] 134 starter = '%s%sScreenlet.desktop' % (DIR_AUTOSTART, name) 135 136 for f in os.listdir(DIR_AUTOSTART): 137 a = f.find(name + 'Screenlet') 138 if a != -1: 139 print str(f) + ' duplicate entry' 140 os.system('rm %s%s' % (chr(34)+DIR_AUTOSTART,f+chr(34))) 141 print 'Removed duplicate entry' 142 if not os.path.isfile(starter) and not os.path.exists(os.environ['HOME'] + '/.config/autostart/CalendarScreenlet'): 143 path = find_first_screenlet_path(name) 144 if path: 145 print "Create autostarter for: %s/%sScreenlet.py" % (path, name) 146 code = ['[Desktop Entry]'] 147 code.append('Name=%sScreenlet' % name) 148 code.append('Encoding=UTF-8') 149 code.append('Version=1.0') 150 code.append('Type=Application') 151 code.append('Exec= python -u %s/%sScreenlet.py' % (path, name)) 152 code.append('X-GNOME-Autostart-enabled=true') 153 #print code 154 f = open(starter, 'w') 155 if f: 156 for l in code: 157 f.write(l + '\n') 158 f.close() 159 return True 160 print 'Failed to create autostarter for %s.' % name 161 return False 162 else: 163 print "Starter already exists." 164 return True
165
166 -def delete_autostarter ( name):
167 """Delete the autostart for the given screenlet.""" 168 if name.endswith('Screenlet'): 169 name = name[:-9] 170 print 'Delete autostarter for %s.' % name 171 os.system('rm %s%sScreenlet.desktop' % (DIR_AUTOSTART, name)) 172 for f in os.listdir(DIR_AUTOSTART): 173 a = f.find(name + 'Screenlet') 174 if a != -1: 175 print str(f) + ' duplicate entry' 176 os.system('rm %s%s' % (chr(34)+DIR_AUTOSTART,f+chr(34))) 177 print 'Removed duplicate entry'
178
179 -def get_screenlet_linux_name_by_class_path(path):
180 """Returns screenlet name on form 'foobar-screenlet' by main screenlet class file path.""" 181 return path.lower().replace(".py", "").split("/")[path.count("/")].replace("screenlet", "-screenlet")
182
183 -def get_screenlet_linux_name_by_class_name(name):
184 """Returns screenlet name on form 'foobar-screenlet' by screenlet class name.""" 185 return name.lower().replace("screenlet", "-screenlet")
186
187 -def get_screenlet_linux_name_by_short_class_name(name):
188 """Returns screenlet name on form 'foobar-screenlet' by shortened screenlet class name.""" 189 return name.lower() + "-screenlet"
190
191 -def is_screenlets_ppa_enabled():
192 """Detect if Screenlets default PPA is enabled on system.""" 193 import commands 194 result = commands.getstatusoutput("ls /etc/apt/sources.list.d/screenlets*ppa*.list | xargs grep '^deb.*'")[0] 195 return result == 0
196
197 -def get_translator(path):
198 """Returns translator by screenlet class path from __file__.""" 199 mo_domain = get_screenlet_linux_name_by_class_path(path) 200 201 t = gettext.translation(mo_domain, screenlets.INSTALL_PREFIX + '/share/locale', fallback = True) 202 203 if not isinstance(t, gettext.GNUTranslations): 204 cut_path_here = path.rfind('/') 205 if cut_path_here > 0: 206 screenlet_dir = path[0:cut_path_here] 207 else: 208 screenlet_dir = os.getcwd() 209 mo_dir = screenlet_dir + "/mo" 210 t = gettext.translation(mo_domain, mo_dir, fallback = True) 211 return t.lgettext
212
213 -def _contains_path (string):
214 """Internal function: Returns true if the given string contains one of the 215 Screenlets paths.""" 216 # use saved paths for performance reasons 217 for path in screenlets.SCREENLETS_PATH: 218 if string.find(path) > -1: 219 return True 220 return False
221
222 -def create_user_dir ():
223 """Create the userdir for the screenlets.""" 224 if not os.path.isdir(os.environ['HOME'] + '/.screenlets'): 225 try: 226 os.mkdir(os.environ['HOME'] + '/.screenlets') 227 except: 228 print 'coulnt create user dir'
229 230
231 -def find_first_screenlet_path (screenlet_name):
232 """Scan the Screenlets paths for the occurence of screenlet "name" with the 233 highest version and return the full path to it. This function is used to get 234 the theme/data directories for a Screenlet and run the Screenlet.""" 235 available_versions_paths = [] 236 # use saved paths for performance reasons 237 for dir in screenlets.SCREENLETS_PATH: 238 try: 239 for name in os.listdir(dir): 240 name_py = name + 'Screenlet.py' 241 path = dir + '/' + name 242 if not stat.S_ISDIR(os.stat(path).st_mode): 243 continue 244 # if path exists 245 if os.access(path + '/' + name_py, os.F_OK): 246 if name == screenlet_name: 247 available_versions_paths.append(path) 248 else: 249 #print "utils.find_first_screenlet_path: "+\ 250 # "LISTED PATH NOT EXISTS: " + path 251 pass 252 except OSError: # Raised by os.listdir: the directory doesn't exist 253 pass 254 if len(available_versions_paths) == 1: 255 return available_versions_paths[0] 256 elif len(available_versions_paths) > 1: 257 path_and_version = [] 258 for version_path in available_versions_paths: 259 path_and_version.append({'version': get_screenlet_metadata_by_path(version_path)['version'], 'path': version_path}) 260 261 sorted_versions = sorted(path_and_version, key=lambda x: LooseVersion(x["version"]), reverse=True) 262 return sorted_versions[0]['path'] 263 264 # nothing found 265 return None
266
267 -def get_screenlet_icon (screenlet_name,width,height):
268 img = gtk.gdk.pixbuf_new_from_file_at_size(\ 269 screenlets.INSTALL_PREFIX + '/share/screenlets-manager/noimage.svg',width,height) 270 # use saved paths for performance reasons 271 for path in screenlets.SCREENLETS_PATH: 272 for ext in ['svg', 'png']: 273 img_path = "%s/%s/icon.%s" % (path, screenlet_name, ext) 274 if os.path.isfile(img_path): 275 try: 276 img = gtk.gdk.pixbuf_new_from_file_at_size(img_path,width,height) 277 except Exception, ex: 278 pass 279 return img
280
281 -def getBetween(data, first, last):
282 x = len(first) 283 begin = data.find(first) +x 284 end = data.find(last, begin) 285 return data[begin:end]
286
287 -def get_screenlet_metadata_by_path (path):
288 """Returns a dict with name, info, author and version of the given 289 screenlet. Use with care because it may import the screenlet 290 module and shouldn't be used too often due to performance issues.""" 291 292 chunks = path.split('/') 293 classname = chunks[len(chunks)-1] + 'Screenlet' 294 295 try: 296 slfile = open(path + '/'+ classname + '.py','r') 297 sldata = slfile.read() 298 slfile.close() 299 name = getBetween(sldata,'__name__','\n') 300 name1 = getBetween(name ,"'","'") 301 if name1.find(' = ') != -1: name1 = getBetween(name ,chr(34),chr(34)) 302 info = getBetween(sldata,'__desc__','\n') 303 info1 = getBetween(info ,"'","'") 304 if info1.find(' = ') != -1: info1 = getBetween(info ,chr(34),chr(34)) 305 if info1.find('_doc_') != -1: 306 info1 = getBetween(sldata ,'class ' + classname,'__name__') 307 info1 = getBetween(info1 ,chr(34) +chr(34)+chr(34),chr(34)+chr(34)+chr(34)) 308 author = getBetween(sldata,'__author__','\n') 309 author1 = getBetween(author ,"'","'") 310 if author1.find(' = ') != -1: author1 = getBetween(author ,chr(34),chr(34)) 311 version = getBetween(sldata,'__version__','\n') 312 version1 = getBetween(version ,"'","'") 313 if version1.find(' = ') != -1: version1 = getBetween(version ,chr(34),chr(34)) 314 requires1=[] 315 if sldata.find('__requires__') > 0: 316 requires = getBetween(sldata,'__requires__',']') 317 if len(requires) > 0: 318 cleaned = requires.split('[')[1].replace("'", "").replace('"', '').replace('\n', '').replace('\t', '') 319 requires1 = "".join(cleaned.split()).split(",") 320 321 return {'name' : name1, 322 'info' : gettext.dgettext(get_screenlet_linux_name_by_class_name(name1), info1), 323 'author' : author1, 324 'version' : version1, 325 'requires' : requires1 326 } 327 except: 328 try: 329 # add path to PYTHONPATH 330 if sys.path.count(path) == 0: 331 sys.path.insert(0, path) 332 slmod = __import__(classname) 333 cls = getattr(slmod, classname) 334 sys.path.remove(path) 335 return {'name' : cls.__name__, 336 'info' : gettext.dgettext(get_screenlet_linux_name_by_class_name(cls.__name__), cls.__desc__), 337 'author' : cls.__author__, 338 'version' : cls.__version__, 339 'requires' : cls.__requires__ 340 } 341 except Exception, ex: 342 print "Unable to load '%s' from %s: %s " % (screenlet_name, path, ex) 343 return None
344
345 -def get_screenlet_metadata (screenlet_name):
346 """Returns a dict with name, info, author and version of the given 347 screenlet. Use with care because it always imports the screenlet 348 module and shouldn't be used too often due to performance issues.""" 349 # find path to file 350 path = find_first_screenlet_path(screenlet_name) 351 352 return get_screenlet_metadata_by_path(path)
353
354 -def refresh_available_screenlet_paths ():
355 """Checks the system Screenlets directory for screenlet packs 356 and updates screenlets.SCREENLETS_PATH. Doesn't remove outdated paths 357 (this doesn't hurt anyone).""" 358 paths = screenlets.SCREENLETS_PATH 359 for name in os.listdir(screenlets.DIR_USER_ROOT): 360 path = screenlets.DIR_USER_ROOT + '/' + name 361 # check if entry is a dir 362 if name.startswith(screenlets.SCREENLETS_PACK_PREFIX): 363 if path not in paths: 364 if stat.S_ISDIR(os.stat(path).st_mode): 365 paths.append(path)
366
367 -def list_available_screenlets ():
368 """Scan the Screenlets paths for all existing screenlets and return their 369 names (without trailing "Screenlet") as a list of strings.""" 370 sls = [] 371 # first refresh 372 refresh_available_screenlet_paths() 373 # use saved paths for performance reasons 374 for dir in screenlets.SCREENLETS_PATH: 375 try: 376 for name in os.listdir(dir): 377 path = dir + '/' + name 378 # check if entry is a dir 379 if not stat.S_ISDIR(os.stat(path).st_mode): 380 continue 381 # if path exists, add it to list 382 if os.access(path + '/' + name + 'Screenlet.py', os.F_OK): 383 if not sls.count(name): 384 sls.append(name) 385 else: 386 pass 387 except OSError: # Raised by os.listdir: the directory doesn't exist 388 pass 389 sls.sort() 390 return sls
391 392 import session
393 -def list_running_screenlets ():
394 """Returns a list with names of running screenlets or None if no 395 Screenlet is currently running. Function returns False if an error 396 happened!""" 397 running = [] 398 tempfile = screenlets.TMP_DIR + '/' + screenlets.TMP_FILE 399 if not os.path.isfile(tempfile): 400 return None 401 f = open(tempfile, 'r') 402 if f: 403 running = f.readlines() 404 f.close() 405 for i in xrange(len(running)): 406 running[i] = running[i][:-1] # strip trailing EOL 407 408 p = os.popen("ps aux | awk '/Screenlet.py/{ print $11, $12, $13, $14, $15, $16 }'") 409 lst = [] 410 regex = re.compile('/([A-Za-z0-9]+)Screenlet.py ') 411 for line in p.readlines(): 412 if not line.endswith('awk /Screenlet.py/{\n') and line != 'sh -c\n' \ 413 and _contains_path(line): 414 slname = regex.findall(line) 415 if slname and type(slname) == list and len(slname) > 0: 416 lst.append(slname[0]+'Screenlet') 417 p.close() 418 for a in lst: 419 if a not in running: 420 running.append(a) 421 return running
422 423 424
425 -def list_running_screenlets2 ():
426 """Returns a list with names of running screenlets. The list can be empty if 427 no Screenlet is currently running.""" 428 p = os.popen("ps aux | awk '/Screenlet.py/{ print $11, $12, $13, $14, $15, $16 }'") 429 lst = [] 430 regex = re.compile('/([A-Za-z0-9]+)Screenlet.py ') 431 for line in p.readlines(): 432 if not line.endswith('awk /Screenlet.py/{\n') and line != 'sh -c\n' \ 433 and _contains_path(line): 434 slname = regex.findall(line) 435 if slname and type(slname) == list and len(slname) > 0: 436 lst.append(slname[0]+'Screenlet') 437 p.close() 438 return lst
439 440 441 442
443 -def get_screenlet_process (name):
444 """Returns the PID of the given screenlet (if running) or None.""" 445 p = os.popen("ps aux | awk '/[" + name[0] + "]" + name[1:] + \ 446 "Screenlet.py/{ print $2, $11, $12, $13, $14, $15, $16 }'") 447 line = p.readlines() 448 p.close() 449 #print line 450 if len(line) and _contains_path(line[0]): 451 return int(line[0].split(' ')[0]) 452 return None
453
454 -def get_user_dir(key, default):
455 """http://www.freedesktop.org/wiki/Software/xdg-user-dirs""" 456 457 user_dirs_dirs = os.path.expanduser("~/.config/user-dirs.dirs") 458 if os.path.exists(user_dirs_dirs): 459 f = open(user_dirs_dirs, "r") 460 for line in f.readlines(): 461 if line.startswith(key): 462 return os.path.expandvars(line[len(key)+2:-2]) 463 return default
464
465 -def get_daemon_iface ():
466 """Check if the daemon is already running and return its interface.""" 467 bus = dbus.SessionBus() 468 if bus: 469 try: 470 proxy_obj = bus.get_object(screenlets.DAEMON_BUS, screenlets.DAEMON_PATH) 471 if proxy_obj: 472 return dbus.Interface(proxy_obj, screenlets.DAEMON_IFACE) 473 474 except Exception, ex: 475 print "Error in ScreenletsManager.connect_daemon: %s" % ex 476 return None
477
478 -def get_desktop_dir():
479 """Returns desktop dir""" 480 desktop_dir = get_user_dir("XDG_DESKTOP_DIR", os.path.expanduser("~/Desktop")) 481 desktop_dir = urllib.unquote(desktop_dir) 482 return desktop_dir
483
484 -def get_filename_on_drop(sel_data):
485 """Returns filenames of window droped files""" 486 filename = '' 487 filenames = [] 488 # get text-elements in selection data 489 try: 490 txt = unicode.encode(sel_data.get_text(), 'utf-8') 491 except: 492 txt = sel_data.get_text() 493 txta = urllib.unquote(txt) 494 txta = str(txta).split('\n') 495 496 for txt in txta: 497 if txt and txt != '': 498 # if it is a filename, use it 499 if txt.startswith('file://'): 500 filename = txt[7:] 501 else: 502 print 'Invalid string: %s.' % txt 503 else: 504 # else get uri-part of selection 505 uris = sel_data.get_uris() 506 if uris and len(uris)>0: 507 #print "URIS: "+str(uris ) 508 filename = uris[0][7:] 509 if filename != '': 510 filenames.append(chr(34) +filename + chr(34)) 511 512 return filenames
513
514 -def LoadPlaces():
515 """Returns mount points in media""" 516 mountlist = os.popen('mount -l').read() 517 prog = re.compile("^/dev/.*?\son\s/media/(.*?) .*?(\[(.*?)\])?$", re.MULTILINE) 518 return prog.findall(mountlist)
519
520 -def LoadBookmarks():
521 """Returns gtk bookmarks """ 522 _bookmarks_path = os.path.expanduser("~/.gtk-bookmarks") 523 _places = [] 524 try: 525 for line in file(_bookmarks_path): 526 line = line.strip() 527 528 if " " in line: 529 uri, name = line.split(" ", 1) 530 531 else: 532 uri = line 533 534 path = urllib.splittype(uri)[1] 535 name = urllib.unquote(os.path.split(path)[1]) 536 537 try: 538 if os.path.exists(uri): 539 continue 540 # Protect against a broken bookmarks file 541 except TypeError: 542 continue 543 544 _places.append((uri, name)) 545 return _places 546 except IOError, err: 547 print "Error loading GTK bookmarks:", err
548
549 -def quit_screenlet_by_name ( name):
550 """Quit all instances of the given screenlet type.""" 551 # get service for instance and call quit method 552 service = screenlets.services.get_service_by_name(name) 553 if service: 554 service.quit()
555
556 -def quit_all_screenlets():
557 558 a = list_running_screenlets() 559 if a != None: 560 for s in a: 561 if s.endswith('Screenlet'): 562 s = s[:-9] 563 try: 564 quit_screenlet_by_name(s) 565 except: 566 pass
567
568 -def restart_all_screenlets():
569 quit_all_screenlets() 570 for s in os.listdir(DIR_AUTOSTART): 571 if s.lower().endswith('screenlet.desktop'): 572 #s = s[:-17] 573 os.system('sh '+ DIR_AUTOSTART + s + ' &')
574
575 -def readMountFile( filename):
576 """Reads fstab file""" 577 fstab = [] 578 f = open(filename, 'r') 579 for line in f: 580 if (not line.isspace() and not line.startswith('#') and not line.lower().startswith('none')) : 581 fstabline = line.split() 582 if fstabline[1] != 'none' and fstabline[1] != '/proc': fstab.append(fstabline[1]) 583 584 fstab.sort() 585 return fstab
586
587 -def read_file( filename):
588 """Reads a file""" 589 f = open(filename, 'r') 590 t = f.read() 591 f.close() 592 return t
593 594
595 -def strip_html(string):
596 """Strips HTML tags of a string""" 597 return re.sub(r"<.*?>|</.*?>","",string)
598 599 600
601 -def lookup_daemon_autostart ():
602 """Adds Screenlets-daemon to autostart if not already""" 603 if not os.path.isdir(DIR_AUTOSTART): 604 # create autostart directory, if not existent 605 if screenlets.show_question(None, _("There is no existing autostart directory for your user account yet. Do you want me to automatically create it for you?"), _('Error')): 606 print "Auto-create autostart dir ..." 607 os.system('mkdir %s' % DIR_AUTOSTART) 608 if not os.path.isdir(DIR_AUTOSTART): 609 screenlets.show_error(None, _("Automatic creation failed. Please manually create the directory:\n%s") % DIR_AUTOSTART, _('Error')) 610 return False 611 else: 612 screenlets.show_message(None, _("Please manually create the directory:\n%s") % DIR_AUTOSTART) 613 return False 614 starter = '%sScreenlets Daemon.desktop' % (DIR_AUTOSTART) 615 616 if not os.path.isfile(starter) and os.path.isfile('%sscreenlets-daemon.desktop' % (DIR_AUTOSTART)) == False: 617 print "Create autostarter for: Screenlets Daemon" 618 code = ['[Desktop Entry]'] 619 code.append('Encoding=UTF-8') 620 code.append('Version=1.0') 621 code.append('Name=Screenlets Daemon') 622 code.append('Type=Application') 623 code.append('Exec=%s/share/screenlets-manager/screenlets-daemon.py' % (screenlets.INSTALL_PREFIX)) 624 code.append('X-GNOME-Autostart-enabled=true') 625 f = open(starter, 'w') 626 if f: 627 for l in code: 628 f.write(l + '\n') 629 f.close() 630 return True 631 print 'Failed to create autostarter for %s.' % name 632 return False 633 else: 634 print "Starter already exists." 635 return True
636
637 -def launch_screenlet(screenlet):
638 """Launches a screenlet""" 639 name = str(screenlet) 640 if not screenlets.launch_screenlet(name): 641 screenlets.show_error(None, _('Failed to add %sScreenlet.') % name)
642 643 644
645 -def xdg_open(name):
646 """Opens anything""" 647 os.system('xdg-open ' + name + ' &')
648 649 # ------------------------------------------------------------------------------ 650 # CLASSES 651 # ------------------------------------------------------------------------------ 652
653 -class ScreenletInfo(object):
654 """A container with info about a screenlet.""" 655
656 - def __init__ (self, name, lname, info, author, version, icon):
657 self.name = name 658 self.lname = lname 659 self.info = info.replace("\n", '').replace('\t', ' ') 660 self.author = author 661 self.version = version 662 self.icon = icon 663 self.active = False 664 self.system = not os.path.isfile('%s/%s/%sScreenlet.py' % (DIR_USER, name, name)) 665 self.autostart = os.path.isfile(DIR_AUTOSTART + '/' + name + 'Screenlet.desktop')
666 667 668
669 -class FileMonitor(gobject.GObject):
670 ''' 671 A simple wrapper around Gnome VFS file monitors. Emits created, deleted, 672 and changed events. Incoming events are queued, with the latest event 673 cancelling prior undelivered events. 674 ''' 675 676 677 __gsignals__ = { 678 "event" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, 679 (gobject.TYPE_STRING, gobject.TYPE_INT)), 680 "created" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), 681 "deleted" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), 682 "changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)) 683 } 684
685 - def __init__(self, path):
686 gobject.GObject.__init__(self) 687 688 if os.path.isabs(path): 689 self.path = "file://" + path 690 else: 691 self.path = path 692 try: 693 self.type = gnomevfs.get_file_info(path).type 694 except gnomevfs.Error: 695 self.type = gnomevfs.MONITOR_FILE 696 697 self.monitor = None 698 self.pending_timeouts = {}
699
700 - def open(self):
701 if not self.monitor: 702 if self.type == gnomevfs.FILE_TYPE_DIRECTORY: 703 monitor_type = gnomevfs.MONITOR_DIRECTORY 704 else: 705 monitor_type = gnomevfs.MONITOR_FILE 706 self.monitor = gnomevfs.monitor_add(self.path, monitor_type, self._queue_event)
707
708 - def _clear_timeout(self, info_uri):
709 try: 710 gobject.source_remove(self.pending_timeouts[info_uri]) 711 del self.pending_timeouts[info_uri] 712 except KeyError: 713 pass
714
715 - def _queue_event(self, monitor_uri, info_uri, event):
716 self._clear_timeout(info_uri) 717 self.pending_timeouts[info_uri] = \ 718 gobject.timeout_add(250, self._timeout_cb, monitor_uri, info_uri, event)
719
720 - def queue_changed(self, info_uri):
721 self._queue_event(self.path, info_uri, gnomevfs.MONITOR_EVENT_CHANGED)
722
723 - def close(self):
724 gnomevfs.monitor_cancel(self.monitor) 725 self.monitor = None
726
727 - def _timeout_cb(self, monitor_uri, info_uri, event):
728 if event in (gnomevfs.MONITOR_EVENT_METADATA_CHANGED, 729 gnomevfs.MONITOR_EVENT_CHANGED): 730 self.emit("changed", info_uri) 731 elif event == gnomevfs.MONITOR_EVENT_CREATED: 732 self.emit("created", info_uri) 733 elif event == gnomevfs.MONITOR_EVENT_DELETED: 734 self.emit("deleted", info_uri) 735 self.emit("event", info_uri, event) 736 737 self._clear_timeout(info_uri) 738 return False
739 740
741 -class IniReader(object):
742 """A simple config/ini-reader class. This is only used for reading the 743 theme.conf files yet, thus it only uses string-values. 744 TODO: add writing-functions and let backend use this, too""" 745
746 - def __init__ (self):
747 self.options = [] 748 self.sections = {}
749
750 - def list_options (self, section=''):
751 """Return all options (alternatively only from the given section).""" 752 if section != '': 753 return self.sections[section] 754 else: 755 return self.options
756
757 - def get_option (self, name, section=''):
758 """Get a variable from the config (optional: only get vars from the 759 specified section).""" 760 if section != '': 761 l = self.sections[section] 762 else: 763 l = self.options 764 for o in l: 765 if o[0] == name: 766 return o[1] 767 return None
768
769 - def has_section (self, name):
770 """Returns true if the given section exists.""" 771 return self.sections.has_key(name)
772
773 - def load (self, filename):
774 """Load a config/ini-file and save vars in internal list.""" 775 f=None 776 try: 777 f = open (filename, "r") 778 except: 779 print "File %s not found" % str(filename) 780 if f: 781 section_name = '' 782 for line in f.readlines(): 783 # strip whitespace/tabs on the left 784 line = line.lstrip().lstrip('\t') 785 #print line 786 # ignore comment, EOL and too short lines 787 if len(line) < 4 or line[0] in ("#", "\n", ";"): 788 pass 789 else: 790 # split var/value and trim 791 tmp = line.split('=', 1) 792 # no '=' found? check for section name 793 if len(tmp) < 2 and len(line) > 5 and line[0] == '[': 794 section_name = line[:-1][1:-1] 795 self.sections[section_name] = [] 796 #print "Section found: %s" % section_name 797 else: 798 # two entries? split var/value 799 var = tmp[0].rstrip().rstrip('\t') 800 val = tmp[1][:-1].lstrip() # remove EOL 801 #print "VAR: %s=%s" % (var, val) 802 # and add them to lists 803 if var != '' and val != '': 804 o = [var, val] 805 self.options.append(o) 806 if section_name != '': 807 try: 808 self.sections[section_name].append(o) 809 except: 810 print "Section %s not found!" % section_name 811 f.close() 812 return True 813 else: 814 return False
815 816 817
818 -class Notifier(object):
819 """A simple and conveniet wrapper for the notification-service. Allows 820 screenlets to easily pop up notes with their own icon (if any).""" 821
822 - def __init__ (self, screenlet=None):
823 self.bus = dbus.SessionBus() 824 self.notifications = dbus.Interface(\ 825 self.bus.get_object('org.freedesktop.Notifications', 826 '/org/freedesktop/Notifications'), 'org.freedesktop.Notifications') 827 self.screenlet = screenlet
828
829 - def notify (self, message, title='', icon='', timeout=-1, screenlet=None):
830 """Send a notification to org.freedesktop.Notifications. The message 831 should contain the text you want to display, title may define a title 832 (summary) for the message, icon can be the full path to an icon, 833 timeout can be set to the desired displaying time in milliseconds.""" 834 if self.bus and self.notifications: 835 if not screenlet: 836 screenlet = self.screenlet 837 if screenlet: 838 p = find_first_screenlet_path(screenlet.__class__.__name__[:-9]) 839 if p: 840 icon = p + '/icon.svg' 841 title = screenlet.__name__ 842 self.notifications.Notify('Screenlets', 0, icon, title, message, 843 [], {}, timeout) 844 return True 845 else: 846 print "Notify: No DBus running or notifications-daemon unavailable." 847 return False
848 849 850 if __name__ == '__main__': 851 852 # get info about screenlet 853 print get_screenlet_metadata('Clock') 854 855 # find first path 856 print "Find first occurence of a Screenlet:" 857 print find_first_screenlet_path('Clock') 858 print find_first_screenlet_path('Orloj') 859 print find_first_screenlet_path('Weather') 860 print find_first_screenlet_path('Foo') 861 862 # list available 863 print "\nList all installed Screenlets:" 864 avail = list_available_screenlets() 865 avail.sort() 866 print avail 867 868 # IniReader 869 print "\nTest INI-reader:" 870 ini = IniReader() 871 if not ini.load('/usr/share/screenlets/CPUMeter/themes/default/theme.conf'): 872 print "Error while loading ini-file" 873 else: 874 # check for section 875 if ini.has_section('Theme'): 876 # get option-values from within a section 877 print ini.get_option('name', section='Theme') 878 print ini.get_option('info', section='Theme') 879 # check for existence of a section 880 if ini.has_section('Options'): 881 for o in ini.list_options(section='Options'): 882 print o[0] 883 884 # notify 885 print "\nNotify-test:" 886 n = Notifier() 887 n.notify('Hi there! This is sent through screenlets.utils.Notifier.notify', 888 title='Test') 889 n.notify('A second note ..', title='Another note', timeout=2000) 890 n.notify('A second note ..', title='Another note', icon='/usr/share/screenlets/Notes/icon.svg') 891 892 # some tests of the list/find screenlets functions 893 print "\nRunning screenlets: " 894 print list_running_screenlets2() 895 print "\n" 896 print get_screenlet_process('Clock') 897 print get_screenlet_process('Ruler') 898 print get_screenlet_process('Webtest') 899