| Package lib ::
        Module scripting |  | 
   1   
   2   
   3   
   4   
   5   
   6   
   7   
   8   
   9   
  10   
  11   
  12   
  13   
  14   
  15   
  16   
  17   
  18  import subprocess, threading, time, re 
  19  import common 
  20   
  21   
  22   
  23   
  24   
  26      """ 
  27      Provides access to the keyboard for event generation. 
  28      """ 
  29       
  31          self.mediator = mediator 
   32           
  34          """ 
  35          Send a sequence of keys via keyboard events 
  36           
  37          Usage: C{keyboard.send_keys(keyString)} 
  38           
  39          @param keyString: string of keys (including special keys) to send 
  40          """ 
  41          self.mediator.interface.begin_send() 
  42          self.mediator.send_string(keyString.decode("utf-8")) 
  43          self.mediator.interface.finish_send() 
   44           
  46          """ 
  47          Send a keyboard event 
  48           
  49          Usage: C{keyboard.send_key(key, repeat=1)} 
  50           
  51          @param key: they key to be sent (e.g. "s" or "<enter>") 
  52          @param repeat: number of times to repeat the key event 
  53          """         
  54          for x in xrange(repeat): 
  55              self.mediator.send_key(key.decode("utf-8")) 
  56          self.mediator.flush() 
   57           
  59          """ 
  60          Send a key down event 
  61           
  62          Usage: C{keyboard.press_key(key)} 
  63           
  64          The key will be treated as down until a matching release_key() is sent. 
  65          @param key: they key to be pressed (e.g. "s" or "<enter>") 
  66          """ 
  67          self.mediator.press_key(key.decode("utf-8")) 
   68           
  70          """ 
  71          Send a key up event 
  72           
  73          Usage: C{keyboard.release_key(key)} 
  74           
  75          If the specified key was not made down using press_key(), the event will be  
  76          ignored. 
  77          @param key: they key to be released (e.g. "s" or "<enter>") 
  78          """ 
  79          self.mediator.release_key(key.decode("utf-8"))         
   80   
  82          """ 
  83          Fake a keypress 
  84   
  85          Usage: C{keyboard.fake_keypress(key, repeat=1)} 
  86   
  87          Uses XTest to 'fake' a keypress. This is useful to send keypresses to some 
  88          applications which won't respond to keyboard.send_key() 
  89   
  90          @param key: they key to be sent (e.g. "s" or "<enter>") 
  91          @param repeat: number of times to repeat the key event 
  92          """ 
  93          for x in xrange(repeat): 
  94              self.mediator.fake_keypress(key.decode("utf-8")) 
   95               
  97          """ 
  98          Wait for a keypress or key combination 
  99           
 100          Usage: C{keyboard.wait_for_keypress(self, key, modifiers=[], timeOut=10.0)} 
 101           
 102          Note: this function cannot be used to wait for modifier keys on their own 
 103   
 104          @param key: they key to wait for 
 105          @param modifiers: list of modifiers that should be pressed with the key 
 106          @param timeOut: maximum time, in seconds, to wait for the keypress to occur 
 107          """ 
 108          w = iomediator.Waiter(key, modifiers, None, timeOut) 
 109          w.wait() 
   110           
 111   
 113      """ 
 114      Provides access to send mouse clicks 
 115      """ 
 117          self.mediator = mediator     
  118       
 120          """ 
 121          Send a mouse click relative to the active window 
 122           
 123          Usage: C{mouse.click_relative(x, y, button)} 
 124           
 125          @param x: x-coordinate in pixels, relative to upper left corner of window 
 126          @param y: y-coordinate in pixels, relative to upper left corner of window 
 127          @param button: mouse button to simulate (left=1, middle=2, right=3) 
 128          """ 
 129          self.mediator.send_mouse_click(x, y, button, True) 
  130           
 132          """ 
 133          Send a mouse click relative to the current mouse position 
 134           
 135          Usage: C{mouse.click_relative_self(x, y, button)} 
 136           
 137          @param x: x-offset in pixels, relative to current mouse position 
 138          @param y: y-offset in pixels, relative to current mouse position 
 139          @param button: mouse button to simulate (left=1, middle=2, right=3) 
 140          """ 
 141          self.mediator.send_mouse_click_relative(x, y, button) 
  142           
 144          """ 
 145          Send a mouse click relative to the screen (absolute) 
 146           
 147          Usage: C{mouse.click_absolute(x, y, button)} 
 148           
 149          @param x: x-coordinate in pixels, relative to upper left corner of window 
 150          @param y: y-coordinate in pixels, relative to upper left corner of window 
 151          @param button: mouse button to simulate (left=1, middle=2, right=3) 
 152          """ 
 153          self.mediator.send_mouse_click(x, y, button, False) 
  154           
 156          """ 
 157          Wait for a mouse click 
 158           
 159          Usage: C{mouse.wait_for_click(self, button, timeOut=10.0)} 
 160   
 161          @param button: they mouse button click to wait for as a button number, 1-9 
 162          @param timeOut: maximum time, in seconds, to wait for the keypress to occur 
 163          """ 
 164          button = int(button) 
 165          w = iomediator.Waiter(None, None, button, timeOut) 
 166          w.wait() 
   167               
 168               
 170      """ 
 171      Allows persistent storage of values between invocations of the script. 
 172      """ 
 173       
 175          """ 
 176          Store a value 
 177           
 178          Usage: C{store.set_value(key, value)} 
 179          """ 
 180          self[key] = value 
  181           
 183          """ 
 184          Get a value 
 185           
 186          Usage: C{store.get_value(key)} 
 187          """ 
 188          return self[key]         
  189           
 191          """ 
 192          Remove a value 
 193           
 194          Usage: C{store.remove_value(key)} 
 195          """ 
 196          del self[key] 
  197           
 199          """ 
 200          Store a global value 
 201           
 202          Usage: C{store.set_global_value(key, value)} 
 203           
 204          The value stored with this method will be available to all scripts. 
 205          """ 
 206          Store.GLOBALS[key] = value 
  207           
 209          """ 
 210          Get a global value 
 211           
 212          Usage: C{store.get_global_value(key)} 
 213          """ 
 214          return self.GLOBALS[key]         
  215           
 217          """ 
 218          Remove a global value 
 219           
 220          Usage: C{store.remove_global_value(key)} 
 221          """ 
 222          del self.GLOBALS[key] 
   223           
 224           
 226      """ 
 227      Provides a simple interface for the display of some basic dialogs to collect information from the user. 
 228       
 229      This version uses KDialog to integrate well with KDE. To pass additional arguments to KDialog that are  
 230      not specifically handled, use keyword arguments. For example, to pass the --geometry argument to KDialog 
 231      to specify the desired size of the dialog, pass C{geometry="700x400"} as one of the parameters. All 
 232      keyword arguments must be given as strings. 
 233   
 234      A note on exit codes: an exit code of 0 indicates that the user clicked OK. 
 235      """ 
 236       
 238          for k, v in kwargs.iteritems(): 
 239              args.append("--" + k) 
 240              args.append(v) 
 241   
 242          p = subprocess.Popen(["kdialog", "--title", title] + args, stdout=subprocess.PIPE) 
 243          retCode = p.wait() 
 244          output = p.stdout.read()[:-1]  
 245           
 246          return (retCode, output) 
  247   
 248 -    def info_dialog(self, title="Information", message="", **kwargs): 
  249          """ 
 250          Show an information dialog 
 251   
 252          Usage: C{dialog.info_dialog(title="Information", message="", **kwargs)} 
 253   
 254          @param title: window title for the dialog 
 255          @param message: message displayed in the dialog 
 256          @return: a tuple containing the exit code and user input 
 257          @rtype: C{tuple(int, str)} 
 258          """ 
 259          return self._run_kdialog(title, ["--msgbox", message], kwargs) 
  260           
 274           
 275 -    def password_dialog(self, title="Enter password", message="Enter password", **kwargs): 
  276          """ 
 277          Show a password input dialog 
 278           
 279          Usage: C{dialog.password_dialog(title="Enter password", message="Enter password", **kwargs)} 
 280           
 281          @param title: window title for the dialog 
 282          @param message: message displayed above the password input box 
 283          @return: a tuple containing the exit code and user input 
 284          @rtype: C{tuple(int, str)} 
 285          """ 
 286          return self._run_kdialog(title, ["--password", message], kwargs)         
  287           
 289          """ 
 290          Show a combobox menu 
 291           
 292          Usage: C{dialog.combo_menu(options, title="Choose an option", message="Choose an option", **kwargs)} 
 293           
 294          @param options: list of options (strings) for the dialog 
 295          @param title: window title for the dialog 
 296          @param message: message displayed above the combobox 
 297          @return: a tuple containing the exit code and user choice 
 298          @rtype: C{tuple(int, str)} 
 299          """ 
 300          return self._run_kdialog(title, ["--combobox", message] + options, kwargs) 
  301           
 303          """ 
 304          Show a single-selection list menu 
 305           
 306          Usage: C{dialog.list_menu(options, title="Choose a value", message="Choose a value", default=None, **kwargs)} 
 307           
 308          @param options: list of options (strings) for the dialog 
 309          @param title: window title for the dialog 
 310          @param message: message displayed above the list 
 311          @param default: default value to be selected 
 312          @return: a tuple containing the exit code and user choice 
 313          @rtype: C{tuple(int, str)} 
 314          """ 
 315           
 316          choices = [] 
 317          optionNum = 0 
 318          for option in options: 
 319              choices.append(str(optionNum)) 
 320              choices.append(option) 
 321              if option == default: 
 322                  choices.append("on") 
 323              else: 
 324                  choices.append("off") 
 325              optionNum += 1 
 326               
 327          retCode, result = self._run_kdialog(title, ["--radiolist", message] + choices, kwargs) 
 328          choice = options[int(result)] 
 329           
 330          return retCode, choice         
  331           
 333          """ 
 334          Show a multiple-selection list menu 
 335           
 336          Usage: C{dialog.list_menu_multi(options, title="Choose one or more values", message="Choose one or more values", defaults=[], **kwargs)} 
 337           
 338          @param options: list of options (strings) for the dialog 
 339          @param title: window title for the dialog 
 340          @param message: message displayed above the list 
 341          @param defaults: list of default values to be selected 
 342          @return: a tuple containing the exit code and user choice 
 343          @rtype: C{tuple(int, str)} 
 344          """ 
 345           
 346          choices = [] 
 347          optionNum = 0 
 348          for option in options: 
 349              choices.append(str(optionNum)) 
 350              choices.append(option) 
 351              if option in defaults: 
 352                  choices.append("on") 
 353              else: 
 354                  choices.append("off") 
 355              optionNum += 1 
 356               
 357          retCode, output = self._run_kdialog(title, ["--separate-output", "--checklist", message] + choices, kwargs) 
 358          results = output.split() 
 359       
 360          choices = [] 
 361          for index in results: 
 362              choices.append(options[int(index)]) 
 363           
 364          return retCode, choices 
  365           
 366 -    def open_file(self, title="Open File", initialDir="~", fileTypes="*|All Files", rememberAs=None, **kwargs): 
  367          """ 
 368          Show an Open File dialog 
 369           
 370          Usage: C{dialog.open_file(title="Open File", initialDir="~", fileTypes="*|All Files", rememberAs=None, **kwargs)} 
 371           
 372          @param title: window title for the dialog 
 373          @param initialDir: starting directory for the file dialog 
 374          @param fileTypes: file type filter expression 
 375          @param rememberAs: gives an ID to this file dialog, allowing it to open at the last used path next time 
 376          @return: a tuple containing the exit code and file path 
 377          @rtype: C{tuple(int, str)} 
 378          """ 
 379          if rememberAs is not None: 
 380              return self._run_kdialog(title, ["--getopenfilename", initialDir, fileTypes, ":" + rememberAs], kwargs) 
 381          else: 
 382              return self._run_kdialog(title, ["--getopenfilename", initialDir, fileTypes], kwargs) 
  383           
 384 -    def save_file(self, title="Save As", initialDir="~", fileTypes="*|All Files", rememberAs=None, **kwargs): 
  385          """ 
 386          Show a Save As dialog 
 387           
 388          Usage: C{dialog.save_file(title="Save As", initialDir="~", fileTypes="*|All Files", rememberAs=None, **kwargs)} 
 389           
 390          @param title: window title for the dialog 
 391          @param initialDir: starting directory for the file dialog 
 392          @param fileTypes: file type filter expression 
 393          @param rememberAs: gives an ID to this file dialog, allowing it to open at the last used path next time 
 394          @return: a tuple containing the exit code and file path 
 395          @rtype: C{tuple(int, str)} 
 396          """ 
 397          if rememberAs is not None: 
 398              return self._run_kdialog(title, ["--getsavefilename", initialDir, fileTypes, ":" + rememberAs], kwargs) 
 399          else: 
 400              return self._run_kdialog(title, ["--getsavefilename", initialDir, fileTypes], kwargs) 
  401   
 402 -    def choose_directory(self, title="Select Directory", initialDir="~", rememberAs=None, **kwargs): 
  403          """ 
 404          Show a Directory Chooser dialog 
 405           
 406          Usage: C{dialog.choose_directory(title="Select Directory", initialDir="~", rememberAs=None, **kwargs)} 
 407           
 408          @param title: window title for the dialog 
 409          @param initialDir: starting directory for the directory chooser dialog 
 410          @param rememberAs: gives an ID to this file dialog, allowing it to open at the last used path next time 
 411          @return: a tuple containing the exit code and chosen path 
 412          @rtype: C{tuple(int, str)} 
 413          """ 
 414          if rememberAs is not None: 
 415              return self._run_kdialog(title, ["--getexistingdirectory", initialDir, ":" + rememberAs], kwargs) 
 416          else: 
 417              return self._run_kdialog(title, ["--getexistingdirectory", initialDir], kwargs) 
  418           
 420          """ 
 421          Show a Colour Chooser dialog 
 422           
 423          Usage: C{dialog.choose_colour(title="Select Colour")} 
 424           
 425          @param title: window title for the dialog 
 426          @return: a tuple containing the exit code and colour 
 427          @rtype: C{tuple(int, str)} 
 428          """ 
 429          return self._run_kdialog(title, ["--getcolor"], kwargs) 
  430   
 431 -    def calendar(self, title="Choose a date", format="%Y-%m-%d", date="today", **kwargs): 
  432          """ 
 433          Show a calendar dialog 
 434   
 435          Usage: C{dialog.calendar_dialog(title="Choose a date", format="%Y-%m-%d", date="YYYY-MM-DD", **kwargs)} 
 436   
 437          Note: the format and date parameters are not currently used 
 438   
 439          @param title: window title for the dialog 
 440          @param format: format of date to be returned 
 441          @param date: initial date as YYYY-MM-DD, otherwise today 
 442          @return: a tuple containing the exit code and date 
 443          @rtype: C{tuple(int, str)} 
 444          """ 
 445          return self._run_kdialog(title, ["--calendar"], kwargs) 
   446           
 447           
 449      """ 
 450      Simplified access to some system commands. 
 451      """     
 452       
 454          """ 
 455          Execute a shell command 
 456           
 457          Usage: C{system.exec_command(command, getOutput=True)} 
 458   
 459          Set getOutput to False if the command does not exit and return immediately. Otherwise 
 460          AutoKey will not respond to any hotkeys/abbreviations etc until the process started 
 461          by the command exits. 
 462           
 463          @param command: command to be executed (including any arguments) - e.g. "ls -l" 
 464          @param getOutput: whether to capture the (stdout) output of the command 
 465          @raise subprocess.CalledProcessError: if the command returns a non-zero exit code 
 466          """ 
 467          if getOutput: 
 468              p = subprocess.Popen(command, shell=True, bufsize=-1, stdout=subprocess.PIPE) 
 469              retCode = p.wait() 
 470              output = p.stdout.read()[:-1] 
 471              if retCode != 0: 
 472                  raise subprocess.CalledProcessError(retCode, output) 
 473              else: 
 474                  return output 
 475          else: 
 476              subprocess.Popen(command, shell=True, bufsize=-1) 
  477       
 479          """ 
 480          Create a file with contents 
 481           
 482          Usage: C{system.create_file(fileName, contents="")} 
 483           
 484          @param fileName: full path to the file to be created 
 485          @param contents: contents to insert into the file 
 486          """ 
 487          f = open(fileName, "w") 
 488          f.write(contents) 
 489          f.close() 
   490           
 491           
 493      """ 
 494      Provides a simple interface for the display of some basic dialogs to collect information from the user. 
 495       
 496      This version uses Zenity to integrate well with GNOME. To pass additional arguments to Zenity that are  
 497      not specifically handled, use keyword arguments. For example, to pass the --timeout argument to Zenity 
 498      pass C{timeout="15"} as one of the parameters. All keyword arguments must be given as strings. 
 499   
 500      A note on exit codes: an exit code of 0 indicates that the user clicked OK. 
 501      """ 
 502       
 504          for k, v in kwargs.iteritems(): 
 505              args.append("--" + k) 
 506              args.append(v) 
 507   
 508          p = subprocess.Popen(["zenity", "--title", title] + args, stdout=subprocess.PIPE) 
 509          retCode = p.wait() 
 510          output = p.stdout.read()[:-1]  
 511           
 512          return (retCode, output) 
  513       
 514 -    def info_dialog(self, title="Information", message="", **kwargs): 
  515          """ 
 516          Show an information dialog 
 517           
 518          Usage: C{dialog.info_dialog(title="Information", message="", **kwargs)} 
 519           
 520          @param title: window title for the dialog 
 521          @param message: message displayed in the dialog 
 522          @return: a tuple containing the exit code and user input 
 523          @rtype: C{tuple(int, str)} 
 524          """ 
 525          return self._run_zenity(title, ["--info", "--text", message], kwargs) 
  526           
 540           
 541 -    def password_dialog(self, title="Enter password", message="Enter password", **kwargs): 
  542          """ 
 543          Show a password input dialog 
 544           
 545          Usage: C{dialog.password_dialog(title="Enter password", message="Enter password")} 
 546           
 547          @param title: window title for the dialog 
 548          @param message: message displayed above the password input box 
 549          @return: a tuple containing the exit code and user input 
 550          @rtype: C{tuple(int, str)} 
 551          """ 
 552          return self._run_zenity(title, ["--entry", "--text", message, "--hide-text"], kwargs) 
 553           
 554       
 555          """ 
 556          Show a combobox menu - not supported by zenity 
 557           
 558          Usage: C{dialog.combo_menu(options, title="Choose an option", message="Choose an option")} 
 559           
 560          @param options: list of options (strings) for the dialog 
 561          @param title: window title for the dialog 
 562          @param message: message displayed above the combobox       
 563          """ 
  564           
 565           
 567          """ 
 568          Show a single-selection list menu 
 569           
 570          Usage: C{dialog.list_menu(options, title="Choose a value", message="Choose a value", default=None, **kwargs)} 
 571           
 572          @param options: list of options (strings) for the dialog 
 573          @param title: window title for the dialog 
 574          @param message: message displayed above the list 
 575          @param default: default value to be selected 
 576          @return: a tuple containing the exit code and user choice 
 577          @rtype: C{tuple(int, str)} 
 578          """ 
 579           
 580          choices = [] 
 581           
 582          for option in options: 
 583              if option == default: 
 584                  choices.append("TRUE") 
 585              else: 
 586                  choices.append("FALSE") 
 587                   
 588               
 589              choices.append(option) 
 590               
 591               
 592          return self._run_zenity(title, ["--list", "--radiolist", "--text", message, "--column", " ", "--column", "Options"] + choices, kwargs) 
  593           
 594           
 595           
 597          """ 
 598          Show a multiple-selection list menu 
 599           
 600          Usage: C{dialog.list_menu_multi(options, title="Choose one or more values", message="Choose one or more values", defaults=[], **kwargs)} 
 601           
 602          @param options: list of options (strings) for the dialog 
 603          @param title: window title for the dialog 
 604          @param message: message displayed above the list 
 605          @param defaults: list of default values to be selected 
 606          @return: a tuple containing the exit code and user choice 
 607          @rtype: C{tuple(int, str)} 
 608          """ 
 609           
 610          choices = [] 
 611           
 612          for option in options: 
 613              if option in defaults: 
 614                  choices.append("TRUE") 
 615              else: 
 616                  choices.append("FALSE") 
 617                   
 618               
 619              choices.append(option) 
 620               
 621               
 622          retCode, output = self._run_zenity(title, ["--list", "--checklist", "--text", message, "--column", " ", "--column", "Options"] + choices, kwargs) 
 623          results = output.split('|') 
 624       
 625           
 626           
 627           
 628           
 629          return retCode, results 
  630           
 631 -    def open_file(self, title="Open File", **kwargs): 
  632          """ 
 633          Show an Open File dialog 
 634           
 635          Usage: C{dialog.open_file(title="Open File", **kwargs)} 
 636           
 637          @param title: window title for the dialog 
 638          @return: a tuple containing the exit code and file path 
 639          @rtype: C{tuple(int, str)} 
 640          """ 
 641           
 642           
 643           
 644          return self._run_zenity(title, ["--file-selection"], kwargs) 
  645           
 646 -    def save_file(self, title="Save As", **kwargs): 
  647          """ 
 648          Show a Save As dialog 
 649           
 650          Usage: C{dialog.save_file(title="Save As", **kwargs)} 
 651           
 652          @param title: window title for the dialog 
 653          @return: a tuple containing the exit code and file path 
 654          @rtype: C{tuple(int, str)} 
 655          """ 
 656           
 657           
 658           
 659          return self._run_zenity(title, ["--file-selection", "--save"], kwargs) 
  660           
 661 -    def choose_directory(self, title="Select Directory", initialDir="~", **kwargs): 
  662          """ 
 663          Show a Directory Chooser dialog 
 664           
 665          Usage: C{dialog.choose_directory(title="Select Directory", **kwargs)} 
 666           
 667          @param title: window title for the dialog 
 668          @return: a tuple containing the exit code and path 
 669          @rtype: C{tuple(int, str)} 
 670          """ 
 671           
 672           
 673           
 674          return self._run_zenity(title, ["--file-selection", "--directory"], kwargs) 
 675           
 676       
 677          """ 
 678          Show a Colour Chooser dialog - not supported by zenity 
 679           
 680          Usage: C{dialog.choose_colour(title="Select Colour")} 
 681           
 682          @param title: window title for the dialog 
 683          """ 
  684           
 685           
 686 -    def calendar(self, title="Choose a date", format="%Y-%m-%d", date="today", **kwargs): 
  687          """ 
 688          Show a calendar dialog 
 689           
 690          Usage: C{dialog.calendar_dialog(title="Choose a date", format="%Y-%m-%d", date="YYYY-MM-DD", **kwargs)} 
 691           
 692          @param title: window title for the dialog 
 693          @param format: format of date to be returned 
 694          @param date: initial date as YYYY-MM-DD, otherwise today 
 695          @return: a tuple containing the exit code and date 
 696          @rtype: C{tuple(int, str)} 
 697          """ 
 698          if re.match(r"[0-9]{4}-[0-9]{2}-[0-9]{2}", date): 
 699              year = date[0:4] 
 700              month = date[5:7] 
 701              day = date[8:10] 
 702              date_args = ["--year=" + year, "--month=" + month, "--day=" + day] 
 703          else: 
 704              date_args = [] 
 705          return self._run_zenity(title, ["--calendar", "--date-format=" + format] + date_args, kwargs) 
   706   
 707       
 709      """ 
 710      Read/write access to the X selection and clipboard - QT version 
 711      """ 
 712       
 714          self.clipBoard = QApplication.clipboard() 
 715          self.app = app 
  716           
 718          """ 
 719          Copy text into the X selection 
 720           
 721          Usage: C{clipboard.fill_selection(contents)} 
 722           
 723          @param contents: string to be placed in the selection 
 724          """ 
 725          self.__execAsync(self.__fillSelection, contents) 
  726           
 728          self.clipBoard.setText(string, QClipboard.Selection) 
 729          self.sem.release() 
  730           
 732          """ 
 733          Read text from the X selection 
 734           
 735          Usage: C{clipboard.get_selection()} 
 736   
 737          @return: text contents of the mouse selection 
 738          @rtype: C{str} 
 739          """ 
 740          self.__execAsync(self.__getSelection) 
 741          return unicode(self.text) 
  742           
 744          self.text = self.clipBoard.text(QClipboard.Selection) 
 745          self.sem.release() 
  746           
 748          """ 
 749          Copy text into the clipboard 
 750           
 751          Usage: C{clipboard.fill_clipboard(contents)} 
 752           
 753          @param contents: string to be placed in the selection 
 754          """ 
 755          self.__execAsync(self.__fillClipboard, contents) 
  756           
 758          self.clipBoard.setText(string, QClipboard.Clipboard) 
 759          self.sem.release()         
  760           
 762          """ 
 763          Read text from the clipboard 
 764           
 765          Usage: C{clipboard.get_clipboard()} 
 766   
 767          @return: text contents of the clipboard 
 768          @rtype: C{str} 
 769          """ 
 770          self.__execAsync(self.__getClipboard) 
 771          return unicode(self.text) 
  772           
 774          self.text = self.clipBoard.text(QClipboard.Clipboard) 
 775          self.sem.release() 
  776           
 778          self.sem = threading.Semaphore(0) 
 779          self.app.exec_in_main(callback, *args) 
 780          self.sem.acquire()         
   781           
 782           
 784      """ 
 785      Read/write access to the X selection and clipboard - GTK version 
 786      """ 
 787       
 789          self.clipBoard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) 
 790          self.selection = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY) 
 791          self.app = app 
  792           
 794          """ 
 795          Copy text into the X selection 
 796           
 797          Usage: C{clipboard.fill_selection(contents)} 
 798           
 799          @param contents: string to be placed in the selection 
 800          """ 
 801           
 802          self.__fillSelection(contents) 
  803           
 805          Gdk.threads_enter() 
 806          self.selection.set_text(string.encode("utf-8")) 
 807          Gdk.threads_leave() 
  808           
 809           
 811          """ 
 812          Read text from the X selection 
 813           
 814          Usage: C{clipboard.get_selection()} 
 815   
 816          @return: text contents of the mouse selection 
 817          @rtype: C{str} 
 818          @raise Exception: if no text was found in the selection 
 819          """ 
 820          self.__execAsync(self.selection.request_text, self.__receive) 
 821          if self.text is not None: 
 822              return self.text.decode("utf-8") 
 823          else: 
 824              raise Exception("No text found in X selection") 
  825           
 827          self.text = text 
 828          self.sem.release() 
  829           
 831          """ 
 832          Copy text into the clipboard 
 833           
 834          Usage: C{clipboard.fill_clipboard(contents)} 
 835           
 836          @param contents: string to be placed in the selection 
 837          """ 
 838          self.__fillClipboard(contents) 
  839           
 841          Gdk.threads_enter() 
 842          self.clipBoard.set_text(string.encode("utf-8")) 
 843          Gdk.threads_leave() 
  844           
 845           
 847          """ 
 848          Read text from the clipboard 
 849           
 850          Usage: C{clipboard.get_clipboard()} 
 851   
 852          @return: text contents of the clipboard 
 853          @rtype: C{str} 
 854          @raise Exception: if no text was found on the clipboard 
 855          """ 
 856          self.__execAsync(self.clipBoard.request_text, self.__receive) 
 857          if self.text is not None: 
 858              return self.text.decode("utf-8") 
 859          else: 
 860              raise Exception("No text found on clipboard") 
  861           
 863          self.sem = threading.Semaphore(0) 
 864          Gdk.threads_enter() 
 865          callback(*args) 
 866          Gdk.threads_leave() 
 867          self.sem.acquire() 
   868   
 869           
 871      """ 
 872      Basic window management using wmctrl 
 873       
 874      Note: in all cases where a window title is required (with the exception of wait_for_focus()),  
 875      two special values of window title are permitted: 
 876       
 877      :ACTIVE: - select the currently active window 
 878      :SELECT: - select the desired window by clicking on it 
 879      """ 
 880       
 882          self.mediator = mediator 
  883           
 885          """ 
 886          Wait for window with the given title to have focus 
 887           
 888          Usage: C{window.wait_for_focus(title, timeOut=5)} 
 889           
 890          If the window becomes active, returns True. Otherwise, returns False if 
 891          the window has not become active by the time the timeout has elapsed. 
 892           
 893          @param title: title to match against (as a regular expression) 
 894          @param timeOut: period (seconds) to wait before giving up 
 895          @rtype: boolean 
 896          """ 
 897          regex = re.compile(title) 
 898          waited = 0 
 899          while waited <= timeOut: 
 900              if regex.match(self.mediator.interface.get_window_title()): 
 901                  return True 
 902               
 903              if timeOut == 0: 
 904                  break  
 905                   
 906              time.sleep(0.3) 
 907              waited += 0.3 
 908               
 909          return False 
  910           
 912          """ 
 913          Wait for window with the given title to be created 
 914           
 915          Usage: C{window.wait_for_exist(title, timeOut=5)} 
 916   
 917          If the window is in existence, returns True. Otherwise, returns False if 
 918          the window has not been created by the time the timeout has elapsed. 
 919           
 920          @param title: title to match against (as a regular expression) 
 921          @param timeOut: period (seconds) to wait before giving up 
 922          @rtype: boolean 
 923          """ 
 924          regex = re.compile(title) 
 925          waited = 0 
 926          while waited <= timeOut: 
 927              retCode, output = self._run_wmctrl(["-l"]) 
 928              for line in output.split('\n'): 
 929                  if regex.match(line[14:].split(' ', 1)[-1]): 
 930                      return True 
 931                       
 932              if timeOut == 0: 
 933                  break  
 934   
 935              time.sleep(0.3) 
 936              waited += 0.3 
 937               
 938          return False 
  939           
 940 -    def activate(self, title, switchDesktop=False, matchClass=False): 
  941          """ 
 942          Activate the specified window, giving it input focus 
 943   
 944          Usage: C{window.activate(title, switchDesktop=False, matchClass=False)} 
 945           
 946          If switchDesktop is False (default), the window will be moved to the current desktop 
 947          and activated. Otherwise, switch to the window's current desktop and activate it there. 
 948           
 949          @param title: window title to match against (as case-insensitive substring match) 
 950          @param switchDesktop: whether or not to switch to the window's current desktop 
 951          @param matchClass: if True, match on the window class instead of the title 
 952          """ 
 953          if switchDesktop: 
 954              args = ["-a", title] 
 955          else: 
 956              args = ["-R", title] 
 957          if matchClass: 
 958              args += ["-x"] 
 959          self._run_wmctrl(args) 
  960           
 961 -    def close(self, title, matchClass=False): 
  962          """ 
 963          Close the specified window gracefully 
 964           
 965          Usage: C{window.close(title, matchClass=False)} 
 966           
 967          @param title: window title to match against (as case-insensitive substring match) 
 968          @param matchClass: if True, match on the window class instead of the title 
 969          """ 
 970          if matchClass: 
 971              self._run_wmctrl(["-c", title, "-x"]) 
 972          else: 
 973              self._run_wmctrl(["-c", title]) 
  974           
 975 -    def resize_move(self, title, xOrigin=-1, yOrigin=-1, width=-1, height=-1, matchClass=False): 
  976          """ 
 977          Resize and/or move the specified window 
 978           
 979          Usage: C{window.close(title, xOrigin=-1, yOrigin=-1, width=-1, height=-1, matchClass=False)} 
 980   
 981          Leaving and of the position/dimension values as the default (-1) will cause that 
 982          value to be left unmodified. 
 983           
 984          @param title: window title to match against (as case-insensitive substring match) 
 985          @param xOrigin: new x origin of the window (upper left corner) 
 986          @param yOrigin: new y origin of the window (upper left corner) 
 987          @param width: new width of the window 
 988          @param height: new height of the window 
 989          @param matchClass: if True, match on the window class instead of the title 
 990          """ 
 991          mvArgs = ["0", str(xOrigin), str(yOrigin), str(width), str(height)] 
 992          if matchClass: 
 993              xArgs = ["-x"] 
 994          else: 
 995              xArgs = [] 
 996          self._run_wmctrl(["-r", title, "-e", ','.join(mvArgs)] + xArgs) 
  997           
 998           
1000          """ 
1001          Move the specified window to the given desktop 
1002           
1003          Usage: C{window.move_to_desktop(title, deskNum, matchClass=False)} 
1004           
1005          @param title: window title to match against (as case-insensitive substring match) 
1006          @param deskNum: desktop to move the window to (note: zero based) 
1007          @param matchClass: if True, match on the window class instead of the title 
1008          """ 
1009          if matchClass: 
1010              xArgs = ["-x"] 
1011          else: 
1012              xArgs = [] 
1013          self._run_wmctrl(["-r", title, "-t", str(deskNum)] + xArgs) 
 1014           
1015           
1017          """ 
1018          Switch to the specified desktop 
1019           
1020          Usage: C{window.switch_desktop(deskNum)} 
1021           
1022          @param deskNum: desktop to switch to (note: zero based) 
1023          """ 
1024          self._run_wmctrl(["-s", str(deskNum)]) 
 1025           
1026 -    def set_property(self, title, action, prop, matchClass=False): 
 1027          """ 
1028          Set a property on the given window using the specified action 
1029   
1030          Usage: C{window.set_property(title, action, prop, matchClass=False)} 
1031           
1032          Allowable actions: C{add, remove, toggle} 
1033          Allowable properties: C{modal, sticky, maximized_vert, maximized_horz, shaded, skip_taskbar, 
1034          skip_pager, hidden, fullscreen, above} 
1035          
1036          @param title: window title to match against (as case-insensitive substring match) 
1037          @param action: one of the actions listed above 
1038          @param prop: one of the properties listed above 
1039          @param matchClass: if True, match on the window class instead of the title 
1040          """ 
1041          if matchClass: 
1042              xArgs = ["-x"] 
1043          else: 
1044              xArgs = [] 
1045          self._run_wmctrl(["-r", title, "-b" + action + ',' + prop] + xArgs) 
 1046           
1048          """ 
1049          Get the geometry of the currently active window 
1050           
1051          Usage: C{window.get_active_geometry()} 
1052           
1053          @return: a 4-tuple containing the x-origin, y-origin, width and height of the window (in pixels) 
1054          @rtype: C{tuple(int, int, int, int)} 
1055          """ 
1056          active = self.mediator.interface.get_window_title() 
1057          result, output = self._run_wmctrl(["-l", "-G"]) 
1058          matchingLine = None 
1059          for line in output.split('\n'): 
1060              if active in line[34:].split(' ', 1)[-1]: 
1061                  matchingLine = line 
1062                   
1063          if matchingLine is not None: 
1064              output = matchingLine.split()[2:6] 
1065              return map(int, output) 
1066          else: 
1067              return None 
 1068   
1070          """ 
1071          Get the visible title of the currently active window 
1072           
1073          Usage: C{window.get_active_title()} 
1074           
1075          @return: the visible title of the currentle active window 
1076          @rtype: C{str} 
1077          """ 
1078          return self.mediator.interface.get_window_title() 
 1079       
1081          """ 
1082          Get the class of the currently active window 
1083           
1084          Usage: C{window.get_active_class()} 
1085           
1086          @return: the class of the currentle active window 
1087          @rtype: C{str} 
1088          """ 
1089          return self.mediator.interface.get_window_class() 
 1090           
1092          p = subprocess.Popen(["wmctrl"] + args, stdout=subprocess.PIPE) 
1093          retCode = p.wait() 
1094          output = p.stdout.read()[:-1]  
1095           
1096          return (retCode, output) 
  1097           
1098           
1100      """ 
1101      Provides access to the internals of AutoKey. 
1102       
1103      Note that any configuration changes made using this API while the configuration window 
1104      is open will not appear until it is closed and re-opened. 
1105      """ 
1106       
1107 -    def __init__(self, configManager, runner): 
 1108          self.configManager = configManager 
1109          self.runner = runner 
1110          self.monitor = configManager.app.monitor 
1111          self.__returnValue = '' 
 1112           
1114          """ 
1115          Retrieve a folder by its title 
1116           
1117          Usage: C{engine.get_folder(title)} 
1118           
1119          Note that if more than one folder has the same title, only the first match will be 
1120          returned. 
1121          """ 
1122          for folder in self.configManager.allFolders: 
1123              if folder.title == title: 
1124                  return folder 
1125          return None 
 1126           
1128          """ 
1129          Create a text phrase 
1130           
1131          Usage: C{engine.create_phrase(folder, description, contents)} 
1132           
1133          A new phrase with no abbreviation or hotkey is created in the specified folder 
1134           
1135          @param folder: folder to place the abbreviation in, retrieved using C{engine.get_folder()} 
1136          @param description: description for the phrase 
1137          @param contents: the expansion text 
1138          """ 
1139          self.monitor.suspend() 
1140          p = model.Phrase(description, contents) 
1141          folder.add_item(p) 
1142          p.persist() 
1143          self.monitor.unsuspend() 
1144          self.configManager.config_altered(False) 
 1145           
1147          """ 
1148          Create a text abbreviation 
1149           
1150          Usage: C{engine.create_abbreviation(folder, description, abbr, contents)} 
1151           
1152          When the given abbreviation is typed, it will be replaced with the given 
1153          text. 
1154           
1155          @param folder: folder to place the abbreviation in, retrieved using C{engine.get_folder()} 
1156          @param description: description for the phrase 
1157          @param abbr: the abbreviation that will trigger the expansion 
1158          @param contents: the expansion text 
1159          @raise Exception: if the specified abbreviation is not unique 
1160          """ 
1161          if not self.configManager.check_abbreviation_unique(abbr, None, None): 
1162              raise Exception("The specified abbreviation is already in use") 
1163           
1164          self.monitor.suspend() 
1165          p = model.Phrase(description, contents) 
1166          p.modes.append(model.TriggerMode.ABBREVIATION) 
1167          p.abbreviations = [abbr] 
1168          folder.add_item(p) 
1169          p.persist() 
1170          self.monitor.unsuspend() 
1171          self.configManager.config_altered(False) 
 1172           
1173 -    def create_hotkey(self, folder, description, modifiers, key, contents): 
 1174          """ 
1175          Create a text hotkey 
1176           
1177          Usage: C{engine.create_hotkey(folder, description, modifiers, key, contents)} 
1178           
1179          When the given hotkey is pressed, it will be replaced with the given 
1180          text. Modifiers must be given as a list of strings, with the following 
1181          values permitted: 
1182           
1183          <ctrl> 
1184          <alt> 
1185          <super> 
1186          <hyper> 
1187          <shift> 
1188           
1189          The key must be an unshifted character (i.e. lowercase) 
1190           
1191          @param folder: folder to place the abbreviation in, retrieved using C{engine.get_folder()} 
1192          @param description: description for the phrase 
1193          @param modifiers: modifiers to use with the hotkey (as a list) 
1194          @param key: the hotkey 
1195          @param contents: the expansion text 
1196          @raise Exception: if the specified hotkey is not unique 
1197          """ 
1198          modifiers.sort() 
1199          if not self.configManager.check_hotkey_unique(modifiers, key, None, None): 
1200              raise Exception("The specified hotkey and modifier combination is already in use") 
1201           
1202          self.monitor.suspend() 
1203          p = model.Phrase(description, contents) 
1204          p.modes.append(model.TriggerMode.HOTKEY) 
1205          p.set_hotkey(modifiers, key) 
1206          folder.add_item(p) 
1207          p.persist() 
1208          self.monitor.unsuspend() 
1209          self.configManager.config_altered(False) 
 1210   
1212          """ 
1213          Run an existing script using its description to look it up 
1214           
1215          Usage: C{engine.run_script(description)} 
1216           
1217          @param description: description of the script to run 
1218          @raise Exception: if the specified script does not exist 
1219          """ 
1220          targetScript = None 
1221          for item in self.configManager.allItems: 
1222              if item.description == description and isinstance(item, model.Script): 
1223                  targetScript = item 
1224   
1225          if targetScript is not None: 
1226              self.runner.run_subscript(targetScript) 
1227          else: 
1228              raise Exception("No script with description '%s' found" % description) 
 1229               
1231          """ 
1232          Used internally by AutoKey for phrase macros 
1233          """ 
1234          self.__macroArgs = args["args"].split(',') 
1235           
1236          try: 
1237              self.run_script(args["name"]) 
1238          except Exception, e: 
1239              self.set_return_value("{ERROR: %s}" % str(e)) 
 1240               
1242          """ 
1243          Get the arguments supplied to the current script via its macro 
1244   
1245          Usage: C{engine.get_macro_arguments()} 
1246           
1247          @return: the arguments 
1248          @rtype: C{list(str())} 
1249          """ 
1250          return self.__macroArgs 
 1251               
1253          """ 
1254          Store a return value to be used by a phrase macro 
1255           
1256          Usage: C{engine.set_return_value(val)} 
1257           
1258          @param val: value to be stored 
1259          """ 
1260          self.__returnValue = val 
 1261           
1263          """ 
1264          Used internally by AutoKey for phrase macros 
1265          """ 
1266          ret = self.__returnValue 
1267          self.__returnValue = '' 
1268          return ret 
  1269