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

Source Code for Module screenlets.utils

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