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

Source Code for Module dogtail.utils

  1  # -*- coding: utf-8 -*- 
  2  """ 
  3  Various utilities 
  4   
  5  Authors: Ed Rousseau <rousseau@redhat.com>, Zack Cerza <zcerza@redhat.com, David Malcolm <dmalcolm@redhat.com> 
  6  """ 
  7   
  8  __author__ = """Ed Rousseau <rousseau@redhat.com>, 
  9  Zack Cerza <zcerza@redhat.com, 
 10  David Malcolm <dmalcolm@redhat.com> 
 11  """ 
 12   
 13  import os 
 14  import sys 
 15  import subprocess 
 16  import re 
 17  from config import config 
 18  from time import sleep 
 19  from logging import debugLogger as logger 
 20  from logging import TimeStamp 
 21  from errors import DependencyNotFoundError 
 22   
23 -def screenshot(file = 'screenshot.png', timeStamp = True):
24 """ 25 This function wraps the ImageMagick import command to take a screenshot. 26 27 The file argument may be specified as 'foo', 'foo.png', or using any other 28 extension that ImageMagick supports. PNG is the default. 29 30 By default, screenshot filenames are in the format of foo_YYYYMMDD-hhmmss.png . 31 The timeStamp argument may be set to False to name the file foo.png. 32 """ 33 if not isinstance(timeStamp, bool): 34 raise TypeError, "timeStampt must be True or False" 35 # config is supposed to create this for us. If it's not there, bail. 36 assert os.path.isdir(config.scratchDir) 37 38 baseName = ''.join(file.split('.')[0:-1]) 39 fileExt = file.split('.')[-1].lower() 40 if not baseName: 41 baseName = file 42 fileExt = 'png' 43 44 if timeStamp: 45 ts = TimeStamp() 46 newFile = ts.fileStamp(baseName) + '.' + fileExt 47 path = config.scratchDir + newFile 48 else: 49 newFile = baseName + '.' + fileExt 50 path = config.scratchDir + newFile 51 52 import gtk.gdk 53 import gobject 54 rootWindow = gtk.gdk.get_default_root_window() 55 geometry = rootWindow.get_geometry() 56 pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, geometry[2], \ 57 geometry[3]) 58 gtk.gdk.Pixbuf.get_from_drawable(pixbuf, rootWindow, \ 59 rootWindow.get_colormap(), 0, 0, 0, 0, geometry[2], geometry[3]) 60 # gtk.gdk.Pixbuf.save() needs 'jpeg' and not 'jpg' 61 if fileExt == 'jpg': fileExt = 'jpeg' 62 try: pixbuf.save(path, fileExt) 63 except gobject.GError: 64 raise ValueError, "Failed to save screenshot in %s format" % fileExt 65 assert os.path.exists(path) 66 logger.log("Screenshot taken: " + path) 67 return path
68
69 -def run(string, timeout=config.runTimeout, interval=config.runInterval, desktop=None, dumb=False, appName=''):
70 """ 71 Runs an application. [For simple command execution such as 'rm *', use os.popen() or os.system()] 72 If dumb is omitted or is False, polls at interval seconds until the application is finished starting, or until timeout is reached. 73 If dumb is True, returns when timeout is reached. 74 """ 75 if not desktop: from tree import root as desktop 76 args = string.split() 77 name = args[0] 78 os.environ['GTK_MODULES'] = 'gail:atk-bridge' 79 pid = subprocess.Popen(args, env = os.environ).pid 80 81 if not appName: 82 appName=args[0] 83 84 if dumb: 85 # We're starting a non-AT-SPI-aware application. Disable startup detection. 86 doDelay(timeout) 87 else: 88 # Startup detection code 89 # The timing here is not totally precise, but it's good enough for now. 90 time = 0 91 while time < timeout: 92 time = time + interval 93 try: 94 for child in desktop.children[::-1]: 95 if child.name == appName: 96 for grandchild in child.children: 97 if grandchild.roleName == 'frame': 98 from procedural import focus 99 focus.application.node = child 100 doDelay(interval) 101 return pid 102 except AttributeError: pass 103 doDelay(interval) 104 return pid
105
106 -def doDelay(delay=None):
107 """ 108 Utility function to insert a delay (with logging and a configurable 109 default delay) 110 """ 111 if delay is None: 112 delay = config.defaultDelay 113 if config.debugSleep: 114 logger.log("sleeping for %f" % delay) 115 sleep(delay)
116
117 -class Blinker:
118 INTERVAL_MS = 200 119
120 - def __init__(self, x, y, w, h, count = 2):
121 import gobject 122 import gtk.gdk 123 self.count = count 124 self.x = x 125 self.y = y 126 self.w = w 127 self.h = h 128 self.timeout_handler_id = gobject.timeout_add (Blinker.INTERVAL_MS, self.blinkDrawRectangle) 129 gtk.main()
130
131 - def blinkDrawRectangle (self):
132 import gtk.gdk 133 display = gtk.gdk.display_get_default() 134 screen = display.get_default_screen() 135 rootWindow = screen.get_root_window() 136 gc = rootWindow.new_gc() 137 138 gc.set_subwindow (gtk.gdk.INCLUDE_INFERIORS) 139 gc.set_function (gtk.gdk.INVERT) 140 gc.set_line_attributes (3, gtk.gdk.LINE_SOLID, gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER) 141 rootWindow.draw_rectangle (gc, False, self.x, self.y, self.w, self.h); 142 143 self.count-=1 144 145 if self.count <= 0: 146 gtk.main_quit() 147 return False 148 149 return True
150 151 152 a11yGConfKey = '/desktop/gnome/interface/accessibility' 153
154 -def isA11yEnabled():
155 """ 156 Checks if accessibility is enabled via gconf. 157 """ 158 import gconf 159 gconfEnabled = gconf.client_get_default().get_bool(a11yGConfKey) 160 if os.environ.get('GTK_MODULES','').find('gail:atk-bridge') == -1: 161 envEnabled = False 162 else: envEnabled = True 163 return (gconfEnabled or envEnabled)
164
165 -def bailBecauseA11yIsDisabled():
166 if sys.argv[0].endswith("pydoc"): return 167 try: 168 if file("/proc/%s/cmdline" % os.getpid()).read().find('epydoc') != -1: 169 return 170 except: pass 171 logger.log("Dogtail requires that Assistive Technology support be enabled. Aborting...") 172 sys.exit(1)
173
174 -def enableA11y():
175 """ 176 Enables accessibility via gconf. 177 """ 178 import gconf 179 return gconf.client_get_default().set_bool(a11yGConfKey, True)
180
181 -def checkForA11y():
182 """ 183 Checks if accessibility is enabled, and halts execution if it is not. 184 """ 185 if not isA11yEnabled(): bailBecauseA11yIsDisabled()
186
187 -def checkForA11yInteractively():
188 """ 189 Checks if accessibility is enabled, and presents a dialog prompting the 190 user if it should be enabled if it is not already, then halts execution. 191 """ 192 if isA11yEnabled(): return 193 import gtk 194 dialog = gtk.Dialog('Enable Assistive Technology Support?', 195 None, 196 gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, 197 (gtk.STOCK_QUIT, gtk.RESPONSE_CLOSE, 198 "_Enable", gtk.RESPONSE_ACCEPT)) 199 question = """Dogtail requires that Assistive Technology Support be enabled for it to function. Would you like to enable Assistive Technology support now? 200 201 Note that you will have to log out for the change to fully take effect. 202 """.strip() 203 dialog.set_default_response(gtk.RESPONSE_ACCEPT) 204 questionLabel = gtk.Label(question) 205 questionLabel.set_line_wrap(True) 206 dialog.vbox.pack_start(questionLabel) 207 dialog.show_all() 208 result = dialog.run() 209 if result == gtk.RESPONSE_ACCEPT: 210 logger.log("Enabling accessibility...") 211 enableA11y() 212 elif result == gtk.RESPONSE_CLOSE: 213 bailBecauseA11yIsDisabled() 214 dialog.destroy()
215