| Package lib ::
        Module scripting |  | 
   1   
   2   
   3   
   4   
   5   
   6   
   7   
   8   
   9   
  10   
  11   
  12   
  13   
  14   
  15   
  16   
  17   
  18   
  19  import subprocess, threading, time, re 
  20   
  21   
  22   
  23   
  24   
  25   
  26   
  27   
  29      """ 
  30      Provides access to the keyboard for event generation. 
  31      """ 
  32       
  34          self.mediator = mediator 
   35           
  37          """ 
  38          Send a sequence of keys via keyboard events 
  39           
  40          Usage: C{keyboard.send_keys(keyString)} 
  41           
  42          @param keyString: string of keys (including special keys) to send 
  43          """ 
  44          self.mediator.interface.begin_send() 
  45          self.mediator.send_string(keyString.decode("utf-8")) 
  46          self.mediator.interface.finish_send() 
   47           
  49          """ 
  50          Send a keyboard event 
  51           
  52          Usage: C{keyboard.send_key(key, repeat=1)} 
  53           
  54          @param key: they key to be sent (e.g. "s" or "<enter>") 
  55          @param repeat: number of times to repeat the key event 
  56          """         
  57          for x in xrange(repeat): 
  58              self.mediator.send_key(key.decode("utf-8")) 
  59          self.mediator.flush() 
   60           
  62          """ 
  63          Send a key down event 
  64           
  65          Usage: C{keyboard.press_key(key)} 
  66           
  67          The key will be treated as down until a matching release_key() is sent. 
  68          @param key: they key to be pressed (e.g. "s" or "<enter>") 
  69          """ 
  70          self.mediator.press_key(key.decode("utf-8")) 
   71           
  73          """ 
  74          Send a key up event 
  75           
  76          Usage: C{keyboard.release_key(key)} 
  77           
  78          If the specified key was not made down using press_key(), the event will be  
  79          ignored. 
  80          @param key: they key to be released (e.g. "s" or "<enter>") 
  81          """ 
  82          self.mediator.release_key(key.decode("utf-8"))         
   83   
  85          """ 
  86          Fake a keypress 
  87   
  88          Usage: C{keyboard.fake_keypress(key, repeat=1)} 
  89   
  90          Uses XTest to 'fake' a keypress. This is useful to send keypresses to some 
  91          applications which won't respond to keyboard.send_key() 
  92   
  93          @param key: they key to be sent (e.g. "s" or "<enter>") 
  94          @param repeat: number of times to repeat the key event 
  95          """ 
  96          for x in xrange(repeat): 
  97              self.mediator.fake_keypress(key.decode("utf-8")) 
    98           
  99           
 100   
 102      """ 
 103      Provides access to send mouse clicks 
 104      """ 
 106          self.mediator = mediator     
  107       
 109          """ 
 110          Send a mouse click relative to the active window 
 111           
 112          Usage: C{mouse.click_relative(x, y, button)} 
 113           
 114          @param x: x-coordinate in pixels, relative to upper left corner of window 
 115          @param y: y-coordinate in pixels, relative to upper left corner of window 
 116          @param button: mouse button to simulate (left=1, middle=2, right=3) 
 117          """ 
 118          self.mediator.send_mouse_click(x, y, button, True) 
  119           
 121          """ 
 122          Send a mouse click relative to the screen (absolute) 
 123           
 124          Usage: C{mouse.click_absolute(x, y, button)} 
 125           
 126          @param x: x-coordinate in pixels, relative to upper left corner of window 
 127          @param y: y-coordinate in pixels, relative to upper left corner of window 
 128          @param button: mouse button to simulate (left=1, middle=2, right=3) 
 129          """ 
 130          self.mediator.send_mouse_click(x, y, button, False) 
   131               
 132               
 134      """ 
 135      Allows persistent storage of values between invocations of the script. 
 136      """ 
 137       
 139          """ 
 140          Store a value 
 141           
 142          Usage: C{store.set_value(key, value)} 
 143          """ 
 144          self[key] = value 
  145           
 147          """ 
 148          Get a value 
 149           
 150          Usage: C{store.get_value(key)} 
 151          """ 
 152          return self[key]         
  153           
 155          """ 
 156          Remove a value 
 157           
 158          Usage: C{store.remove_value(key)} 
 159          """ 
 160          del self[key] 
   161           
 163      """ 
 164      Provides a simple interface for the display of some basic dialogs to collect information from the user. 
 165       
 166      This version uses KDialog to integrate well with KDE. 
 167   
 168      A note on exit codes: an exit code of 0 indicates that the user clicked OK. 
 169      """ 
 170       
 172          p = subprocess.Popen(["kdialog", "--title", title] + args, stdout=subprocess.PIPE) 
 173          retCode = p.wait() 
 174          output = p.stdout.read()[:-1]  
 175           
 176          return (retCode, output) 
  177           
 191           
 192 -    def password_dialog(self, title="Enter password", message="Enter password"): 
  193          """ 
 194          Show a password input dialog 
 195           
 196          Usage: C{dialog.password_dialog(title="Enter password", message="Enter password")} 
 197           
 198          @param title: window title for the dialog 
 199          @param message: message displayed above the password input box 
 200          @return: a tuple containing the exit code and user input 
 201          @rtype: C{tuple(int, str)} 
 202          """ 
 203          return self.__runKdialog(title, ["--password", message])         
  204           
 206          """ 
 207          Show a combobox menu 
 208           
 209          Usage: C{dialog.combo_menu(options, title="Choose an option", message="Choose an option")} 
 210           
 211          @param options: list of options (strings) for the dialog 
 212          @param title: window title for the dialog 
 213          @param message: message displayed above the combobox 
 214          @return: a tuple containing the exit code and user choice 
 215          @rtype: C{tuple(int, str)} 
 216          """ 
 217          return self.__runKdialog(title, ["--combobox", message] + options) 
  218           
 220          """ 
 221          Show a single-selection list menu 
 222           
 223          Usage: C{dialog.list_menu(options, title="Choose a value", message="Choose a value", default=None)} 
 224           
 225          @param options: list of options (strings) for the dialog 
 226          @param title: window title for the dialog 
 227          @param message: message displayed above the list 
 228          @param default: default value to be selected 
 229          @return: a tuple containing the exit code and user choice 
 230          @rtype: C{tuple(int, str)} 
 231          """ 
 232           
 233          choices = [] 
 234          optionNum = 0 
 235          for option in options: 
 236              choices.append(str(optionNum)) 
 237              choices.append(option) 
 238              if option == default: 
 239                  choices.append("on") 
 240              else: 
 241                  choices.append("off") 
 242              optionNum += 1 
 243               
 244          retCode, result = self.__runKdialog(title, ["--radiolist", message] + choices) 
 245          choice = options[int(result)] 
 246           
 247          return retCode, choice         
  248           
 250          """ 
 251          Show a multiple-selection list menu 
 252           
 253          Usage: C{dialog.list_menu_multi(options, title="Choose one or more values", message="Choose one or more values", defaults=[])} 
 254           
 255          @param options: list of options (strings) for the dialog 
 256          @param title: window title for the dialog 
 257          @param message: message displayed above the list 
 258          @param defaults: list of default values to be selected 
 259          @return: a tuple containing the exit code and user choice 
 260          @rtype: C{tuple(int, str)} 
 261          """ 
 262           
 263          choices = [] 
 264          optionNum = 0 
 265          for option in options: 
 266              choices.append(str(optionNum)) 
 267              choices.append(option) 
 268              if option in defaults: 
 269                  choices.append("on") 
 270              else: 
 271                  choices.append("off") 
 272              optionNum += 1 
 273               
 274          retCode, output = self.__runKdialog(title, ["--separate-output", "--checklist", message] + choices) 
 275          results = output.split() 
 276       
 277          choices = [] 
 278          for index in results: 
 279              choices.append(options[int(index)]) 
 280           
 281          return retCode, choices 
  282           
 283 -    def open_file(self, title="Open File", initialDir="~", fileTypes="*|All Files", rememberAs=None): 
  284          """ 
 285          Show an Open File dialog 
 286           
 287          Usage: C{dialog.open_file(title="Open File", initialDir="~", fileTypes="*|All Files", rememberAs=None)} 
 288           
 289          @param title: window title for the dialog 
 290          @param initialDir: starting directory for the file dialog 
 291          @param fileTypes: file type filter expression 
 292          @param rememberAs: gives an ID to this file dialog, allowing it to open at the last used path next time 
 293          @return: a tuple containing the exit code and file path 
 294          @rtype: C{tuple(int, str)} 
 295          """ 
 296          if rememberAs is not None: 
 297              return self.__runKdialog(title, ["--getopenfilename", initialDir, fileTypes, ":" + rememberAs]) 
 298          else: 
 299              return self.__runKdialog(title, ["--getopenfilename", initialDir, fileTypes]) 
  300           
 301 -    def save_file(self, title="Save As", initialDir="~", fileTypes="*|All Files", rememberAs=None): 
  302          """ 
 303          Show a Save As dialog 
 304           
 305          Usage: C{dialog.save_file(title="Save As", initialDir="~", fileTypes="*|All Files", rememberAs=None)} 
 306           
 307          @param title: window title for the dialog 
 308          @param initialDir: starting directory for the file dialog 
 309          @param fileTypes: file type filter expression 
 310          @param rememberAs: gives an ID to this file dialog, allowing it to open at the last used path next time 
 311          @return: a tuple containing the exit code and file path 
 312          @rtype: C{tuple(int, str)} 
 313          """ 
 314          if rememberAs is not None: 
 315              return self.__runKdialog(title, ["--getsavefilename", initialDir, fileTypes, ":" + rememberAs]) 
 316          else: 
 317              return self.__runKdialog(title, ["--getsavefilename", initialDir, fileTypes]) 
  318   
 319 -    def choose_directory(self, title="Select Directory", initialDir="~", rememberAs=None): 
  320          """ 
 321          Show a Directory Chooser dialog 
 322           
 323          Usage: C{dialog.choose_directory(title="Select Directory", initialDir="~", rememberAs=None)} 
 324           
 325          @param title: window title for the dialog 
 326          @param initialDir: starting directory for the directory chooser dialog 
 327          @param rememberAs: gives an ID to this file dialog, allowing it to open at the last used path next time 
 328          @return: a tuple containing the exit code and chosen path 
 329          @rtype: C{tuple(int, str)} 
 330          """ 
 331          if rememberAs is not None: 
 332              return self.__runKdialog(title, ["--getexistingdirectory", initialDir, ":" + rememberAs]) 
 333          else: 
 334              return self.__runKdialog(title, ["--getexistingdirectory", initialDir]) 
  335           
 337          """ 
 338          Show a Colour Chooser dialog 
 339           
 340          Usage: C{dialog.choose_colour(title="Select Colour")} 
 341           
 342          @param title: window title for the dialog 
 343          @return: a tuple containing the exit code and colour 
 344          @rtype: C{tuple(int, str)} 
 345          """ 
 346          return self.__runKdialog(title, ["--getcolor"]) 
   347           
 348           
 350      """ 
 351      Simplified access to some system commands. 
 352      """     
 353       
 355          """ 
 356          Execute a shell command 
 357   
 358          Set getOutput to False if the command does not exit and return immediately. Otherwise 
 359          AutoKey will not respond to any hotkeys/abbreviations etc until the process started 
 360          by the command exits. 
 361           
 362          Usage: C{system.exec_command(command, getOutput=True)} 
 363           
 364          @param command: command to be executed (including any arguments) - e.g. "ls -l" 
 365          @param getOutput: whether to capture the (stdout) output of the command 
 366          @raise subprocess.CalledProcessError: if the command returns a non-zero exit code 
 367          """ 
 368          if getOutput: 
 369              p = subprocess.Popen(command, shell=True, bufsize=-1, stdout=subprocess.PIPE) 
 370              retCode = p.wait() 
 371              output = p.stdout.read()[:-1] 
 372              if retCode != 0: 
 373                  raise subprocess.CalledProcessError(retCode, output) 
 374              else: 
 375                  return output 
 376          else: 
 377              subprocess.Popen(command, shell=True, bufsize=-1) 
  378       
 380          """ 
 381          Create a file with contents 
 382           
 383          Usage: C{system.create_file(fileName, contents="")} 
 384           
 385          @param fileName: full path to the file to be created 
 386          @param contents: contents to insert into the file 
 387          """ 
 388          f = open(fileName, "w") 
 389          f.write(contents) 
 390          f.close() 
   391           
 392           
 394      """ 
 395      Provides a simple interface for the display of some basic dialogs to collect information from the user. 
 396       
 397      This version uses Zenity to integrate well with GNOME. 
 398   
 399      A note on exit codes: an exit code of 0 indicates that the user clicked OK. 
 400      """ 
 401       
 403          p = subprocess.Popen(["zenity", "--title", title] + args, stdout=subprocess.PIPE) 
 404          retCode = p.wait() 
 405          output = p.stdout.read()[:-1]  
 406           
 407          return (retCode, output) 
  408           
 422           
 423 -    def password_dialog(self, title="Enter password", message="Enter password"): 
  424          """ 
 425          Show a password input dialog 
 426           
 427          Usage: C{dialog.password_dialog(title="Enter password", message="Enter password")} 
 428           
 429          @param title: window title for the dialog 
 430          @param message: message displayed above the password input box 
 431          @return: a tuple containing the exit code and user input 
 432          @rtype: C{tuple(int, str)} 
 433          """ 
 434          return self.__runZenity(title, ["--entry", "--text", message, "--hide-text"]) 
 435           
 436       
 437          """ 
 438          Show a combobox menu - not supported by zenity 
 439           
 440          Usage: C{dialog.combo_menu(options, title="Choose an option", message="Choose an option")} 
 441           
 442          @param options: list of options (strings) for the dialog 
 443          @param title: window title for the dialog 
 444          @param message: message displayed above the combobox       
 445          """ 
  446           
 447           
 449          """ 
 450          Show a single-selection list menu 
 451           
 452          Usage: C{dialog.list_menu(options, title="Choose a value", message="Choose a value", default=None)} 
 453           
 454          @param options: list of options (strings) for the dialog 
 455          @param title: window title for the dialog 
 456          @param message: message displayed above the list 
 457          @param default: default value to be selected 
 458          @return: a tuple containing the exit code and user choice 
 459          @rtype: C{tuple(int, str)} 
 460          """ 
 461           
 462          choices = [] 
 463           
 464          for option in options: 
 465              if option == default: 
 466                  choices.append("TRUE") 
 467              else: 
 468                  choices.append("FALSE") 
 469                   
 470               
 471              choices.append(option) 
 472               
 473               
 474          return self.__runZenity(title, ["--list", "--radiolist", "--text", message, "--column", " ", "--column", "Options"] + choices) 
  475           
 476           
 477           
 479          """ 
 480          Show a multiple-selection list menu 
 481           
 482          Usage: C{dialog.list_menu_multi(options, title="Choose one or more values", message="Choose one or more values", defaults=[])} 
 483           
 484          @param options: list of options (strings) for the dialog 
 485          @param title: window title for the dialog 
 486          @param message: message displayed above the list 
 487          @param defaults: list of default values to be selected 
 488          @return: a tuple containing the exit code and user choice 
 489          @rtype: C{tuple(int, str)} 
 490          """ 
 491           
 492          choices = [] 
 493           
 494          for option in options: 
 495              if option in defaults: 
 496                  choices.append("TRUE") 
 497              else: 
 498                  choices.append("FALSE") 
 499                   
 500               
 501              choices.append(option) 
 502               
 503               
 504          retCode, output = self.__runZenity(title, ["--list", "--checklist", "--text", message, "--column", " ", "--column", "Options"] + choices) 
 505          results = output.split('|') 
 506       
 507           
 508           
 509           
 510           
 511          return retCode, results 
  512           
 514          """ 
 515          Show an Open File dialog 
 516           
 517          Usage: C{dialog.open_file(title="Open File")} 
 518           
 519          @param title: window title for the dialog 
 520          @return: a tuple containing the exit code and file path 
 521          @rtype: C{tuple(int, str)} 
 522          """ 
 523           
 524           
 525           
 526          return self.__runZenity(title, ["--file-selection"]) 
  527           
 529          """ 
 530          Show a Save As dialog 
 531           
 532          Usage: C{dialog.save_file(title="Save As")} 
 533           
 534          @param title: window title for the dialog 
 535          @return: a tuple containing the exit code and file path 
 536          @rtype: C{tuple(int, str)} 
 537          """ 
 538           
 539           
 540           
 541          return self.__runZenity(title, ["--file-selection", "--save"]) 
  542           
 544          """ 
 545          Show a Directory Chooser dialog 
 546           
 547          Usage: C{dialog.choose_directory(title="Select Directory")} 
 548           
 549          @param title: window title for the dialog 
 550          @return: a tuple containing the exit code and path 
 551          @rtype: C{tuple(int, str)} 
 552          """ 
 553           
 554           
 555           
 556          return self.__runZenity(title, ["--file-selection", "--directory"]) 
 557           
 558       
 559          """ 
 560          Show a Colour Chooser dialog - not supported by zenity 
 561           
 562          Usage: C{dialog.choose_colour(title="Select Colour")} 
 563           
 564          @param title: window title for the dialog 
 565          """ 
  566           
 567           
 568 -    def calendar(self, title="Choose a date", format="%Y-%m-%d", date="today"): 
  569          """ 
 570          Show a calendar dialog 
 571           
 572          Usage: C{dialog.calendar_dialog(title="Choose a date", format="%Y-%m-%d", date="YYYY-MM-DD")} 
 573           
 574          @param title: window title for the dialog 
 575          @param format: format of date to be returned 
 576          @param date: initial date as YYYY-MM-DD, otherwise today 
 577          @return: a tuple containing the exit code and date 
 578          @rtype: C{tuple(int, str)} 
 579          """ 
 580          if re.match(r"[0-9]{4}-[0-9]{2}-[0-9]{2}", date): 
 581              year = date[0:4] 
 582              month = date[5:7] 
 583              day = date[8:10] 
 584              date_args = ["--year=" + year, "--month=" + month, "--day=" + day] 
 585          else: 
 586              date_args = [] 
 587          return self.__runZenity(title, ["--calendar", "--date-format=" + format] + date_args) 
   588   
 589       
 591      """ 
 592      Read/write access to the X selection and clipboard - QT version 
 593      """ 
 594       
 596          self.clipBoard = QApplication.clipboard() 
 597          self.app = app 
  598           
 600          """ 
 601          Copy text into the X selection 
 602           
 603          Usage: C{clipboard.fill_selection(contents)} 
 604           
 605          @param contents: string to be placed in the selection 
 606          """ 
 607          self.__execAsync(self.__fillSelection, contents) 
  608           
 610          self.clipBoard.setText(string, QClipboard.Selection) 
 611          self.sem.release() 
  612           
 614          """ 
 615          Read text from the X selection 
 616           
 617          Usage: C{clipboard.get_selection()} 
 618   
 619          @return: text contents of the mouse selection 
 620          @rtype: C{str} 
 621          """ 
 622          self.__execAsync(self.__getSelection) 
 623          return str(self.text) 
  624           
 626          self.text = self.clipBoard.text(QClipboard.Selection) 
 627          self.sem.release() 
  628           
 630          """ 
 631          Copy text into the clipboard 
 632           
 633          Usage: C{clipboard.fill_clipboard(contents)} 
 634           
 635          @param contents: string to be placed in the selection 
 636          """ 
 637          self.__execAsync(self.__fillClipboard, contents) 
  638           
 640          self.clipBoard.setText(string, QClipboard.Clipboard) 
 641          self.sem.release()         
  642           
 644          """ 
 645          Read text from the clipboard 
 646           
 647          Usage: C{clipboard.get_clipboard()} 
 648   
 649          @return: text contents of the clipboard 
 650          @rtype: C{str} 
 651          """ 
 652          self.__execAsync(self.__getClipboard) 
 653          return str(self.text) 
  654           
 656          self.text = self.clipBoard.text(QClipboard.Clipboard) 
 657          self.sem.release() 
  658           
 660          self.sem = threading.Semaphore(0) 
 661          self.app.exec_in_main(callback, *args) 
 662          self.sem.acquire()         
   663           
 664           
 666      """ 
 667      Read/write access to the X selection and clipboard - GTK version 
 668      """ 
 669       
 671          self.clipBoard = gtk.Clipboard() 
 672          self.selection = gtk.Clipboard(selection="PRIMARY") 
 673          self.app = app 
  674           
 676          """ 
 677          Copy text into the X selection 
 678           
 679          Usage: C{clipboard.fill_selection(contents)} 
 680           
 681          @param contents: string to be placed in the selection 
 682          """ 
 683           
 684          self.__fillSelection(contents) 
  685           
 687          gtk.gdk.threads_enter() 
 688          self.selection.set_text(string.encode("utf-8")) 
 689          gtk.gdk.threads_leave() 
  690           
 691           
 693          """ 
 694          Read text from the X selection 
 695           
 696          Usage: C{clipboard.get_selection()} 
 697   
 698          @return: text contents of the mouse selection 
 699          @rtype: C{str} 
 700          @raise Exception: if no text was found in the selection 
 701          """ 
 702          self.__execAsync(self.selection.request_text, self.__receive) 
 703          if self.text is not None: 
 704              return self.text.decode("utf-8") 
 705          else: 
 706              raise Exception("No text found in X selection") 
  707           
 709          self.text = text 
 710          self.sem.release() 
  711           
 713          """ 
 714          Copy text into the clipboard 
 715           
 716          Usage: C{clipboard.fill_clipboard(contents)} 
 717           
 718          @param contents: string to be placed in the selection 
 719          """ 
 720          self.__fillClipboard(contents) 
  721           
 723          gtk.gdk.threads_enter() 
 724          self.clipBoard.set_text(string.encode("utf-8")) 
 725          gtk.gdk.threads_leave() 
  726           
 727           
 729          """ 
 730          Read text from the clipboard 
 731           
 732          Usage: C{clipboard.get_clipboard()} 
 733   
 734          @return: text contents of the clipboard 
 735          @rtype: C{str} 
 736          @raise Exception: if no text was found on the clipboard 
 737          """ 
 738          self.__execAsync(self.clipBoard.request_text, self.__receive) 
 739          if self.text is not None: 
 740              return self.text.decode("utf-8") 
 741          else: 
 742              raise Exception("No text found on clipboard") 
  743           
 745          self.sem = threading.Semaphore(0) 
 746          gtk.gdk.threads_enter() 
 747          callback(*args) 
 748          gtk.gdk.threads_leave() 
 749          self.sem.acquire() 
   750   
 751           
 753      """ 
 754      Basic window management using wmctrl 
 755       
 756      Note: in all cases where a window title is required (with the exception of wait_for_focus()),  
 757      two special values of window title are permitted: 
 758       
 759      :ACTIVE: - select the currently active window 
 760      :SELECT: - select the desired window by clicking on it 
 761      """ 
 762       
 764          self.mediator = mediator 
  765           
 767          """ 
 768          Wait for window with the given title to have focus 
 769           
 770          Usage: C{window.wait_for_focus(title, timeOut=5)} 
 771           
 772          If the window becomes active, returns True. Otherwise, returns False if 
 773          the window has not become active by the time the timeout has elapsed. 
 774           
 775          @param title: title to match against (as a regular expression) 
 776          @param timeOut: period (seconds) to wait before giving up 
 777          @rtype: boolean 
 778          """ 
 779          regex = re.compile(title) 
 780          waited = 0 
 781          while waited < timeOut: 
 782              if regex.match(self.mediator.interface.get_window_title()): 
 783                  return True 
 784              time.sleep(0.3) 
 785              waited += 0.3 
 786               
 787          return False 
  788           
 790          """ 
 791          Wait for window with the given title to be created 
 792           
 793          Usage: C{window.wait_for_exist(title, timeOut=5)} 
 794   
 795          If the window is in existence, returns True. Otherwise, returns False if 
 796          the window has not been created by the time the timeout has elapsed. 
 797           
 798          @param title: title to match against (as a regular expression) 
 799          @param timeOut: period (seconds) to wait before giving up 
 800          @rtype: boolean 
 801          """ 
 802          regex = re.compile(title) 
 803          waited = 0 
 804          while waited < timeOut: 
 805              retCode, output = self.__runWmctrl(["-l"]) 
 806              for line in output.split('\n'): 
 807                  if regex.match(line[14:].split(' ', 1)[-1]): 
 808                      return True 
 809   
 810              time.sleep(0.3) 
 811              waited += 0.3 
 812               
 813          return False 
  814           
 815 -    def activate(self, title, switchDesktop=False): 
  816          """ 
 817          Activate the specified window, giving it input focus 
 818   
 819          Usage: C{window.activate(title, switchDesktop=False)} 
 820           
 821          If switchDesktop is False (default), the window will be moved to the current desktop 
 822          and activated. Otherwise, switch to the window's current desktop and activate it there. 
 823           
 824          @param title: window title to match against (as case-insensitive substring match) 
 825          @param switchDesktop: whether or not to switch to the window's current desktop 
 826          """ 
 827          if switchDesktop: 
 828              args = ["-a", title] 
 829          else: 
 830              args = ["-R", title] 
 831          self.__runWmctrl(args) 
  832           
 834          """ 
 835          Close the specified window gracefully 
 836           
 837          Usage: C{window.close(title)} 
 838           
 839          @param title: window title to match against (as case-insensitive substring match) 
 840          """ 
 841          self.__runWmctrl(["-c", title]) 
  842           
 843 -    def resize_move(self, title, xOrigin=-1, yOrigin=-1, width=-1, height=-1): 
  844          """ 
 845          Resize and/or move the specified window 
 846           
 847          Usage: C{window.close(title, xOrigin=-1, yOrigin=-1, width=-1, height=-1)} 
 848   
 849          Leaving and of the position/dimension values as the default (-1) will cause that 
 850          value to be left unmodified. 
 851           
 852          @param title: window title to match against (as case-insensitive substring match) 
 853          @param xOrigin: new x origin of the window (upper left corner) 
 854          @param yOrigin: new y origin of the window (upper left corner) 
 855          @param width: new width of the window 
 856          @param height: new height of the window 
 857          """ 
 858          mvArgs = ["0", str(xOrigin), str(yOrigin), str(width), str(height)] 
 859          self.__runWmctrl(["-r", title, "-e", ','.join(mvArgs)]) 
  860           
 861           
 863          """ 
 864          Move the specified window to the given desktop 
 865           
 866          Usage: C{window.move_to_desktop(title, deskNum)} 
 867           
 868          @param title: window title to match against (as case-insensitive substring match) 
 869          @param deskNum: desktop to move the window to (note: zero based) 
 870          """ 
 871          self.__runWmctrl(["-r", title, "-t", str(deskNum)]) 
  872           
 873           
 875          """ 
 876          Switch to the specified desktop 
 877           
 878          Usage: C{window.switch_desktop(deskNum)} 
 879           
 880          @param deskNum: desktop to switch to (note: zero based) 
 881          """ 
 882          self.__runWmctrl(["-s", str(deskNum)]) 
  883           
 885          """ 
 886          Set a property on the given window using the specified action 
 887   
 888          Usage: C{window.set_property(title, title, action, prop)} 
 889           
 890          Allowable actions: C{add, remove, toggle} 
 891          Allowable properties: C{modal, sticky, maximized_vert, maximized_horz, shaded, skip_taskbar, 
 892          skip_pager, hidden, fullscreen, above} 
 893          
 894          @param title: window title to match against (as case-insensitive substring match) 
 895          @param action: one of the actions listed above 
 896          @param prop: one of the properties listed above 
 897          """ 
 898          self.__runWmctrl(["-r", title, "-b" + action + ',' + prop]) 
  899           
 901          """ 
 902          Get the geometry of the currently active window 
 903           
 904          Usage: C{window.get_active_geometry()} 
 905           
 906          @return: a 4-tuple containing the x-origin, y-origin, width and height of the window (in pixels) 
 907          @rtype: C{tuple(int, int, int, int)} 
 908          """ 
 909          active = self.mediator.interface.get_window_title() 
 910          result, output = self.__runWmctrl(["-l", "-G"]) 
 911          matchingLine = None 
 912          for line in output.split('\n'): 
 913              if active in line[34:].split(' ', 1)[-1]: 
 914                  matchingLine = line 
 915                   
 916          if matchingLine is not None: 
 917              output = matchingLine[14:].split(' ')[0:3] 
 918              return map(int, output) 
 919          else: 
 920              return None 
  921           
 923          p = subprocess.Popen(["wmctrl"] + args, stdout=subprocess.PIPE) 
 924          retCode = p.wait() 
 925          output = p.stdout.read()[:-1]  
 926           
 927          return (retCode, output) 
   928           
 929           
 931      """ 
 932      Provides access to the internals of AutoKey. 
 933       
 934      Note that any configuration changes made using this API while the configuration window 
 935      is open will not appear until it is closed and re-opened. 
 936      """ 
 937       
 938 -    def __init__(self, configManager, runner): 
  939          self.configManager = configManager 
 940          self.runner = runner 
  941           
 943          """ 
 944          Retrieve a folder by its title 
 945           
 946          Usage: C{engine.get_folder(title)} 
 947           
 948          Note that if more than one folder has the same title, only the first match will be 
 949          returned. 
 950          """ 
 951          for folder in self.configManager.allFolders: 
 952              if folder.title == title: 
 953                  return folder 
 954          return None 
  955           
 957          """ 
 958          Create a text phrase 
 959           
 960          Usage: C{engine.create_phrase(folder, description, contents)} 
 961           
 962          A new phrase with no abbreviation or hotkey is created in the specified folder 
 963           
 964          @param folder: folder to place the abbreviation in, retrieved using C{engine.get_folder()} 
 965          @param description: description for the phrase 
 966          @param contents: the expansion text 
 967          """ 
 968          p = model.Phrase(description, contents) 
 969          folder.add_item(p) 
 970          self.configManager.config_altered()             
  971           
 973          """ 
 974          Create a text abbreviation 
 975           
 976          Usage: C{engine.create_abbreviation(folder, description, abbr, contents)} 
 977           
 978          When the given abbreviation is typed, it will be replaced with the given 
 979          text. 
 980           
 981          @param folder: folder to place the abbreviation in, retrieved using C{engine.get_folder()} 
 982          @param description: description for the phrase 
 983          @param abbr: the abbreviation that will trigger the expansion 
 984          @param contents: the expansion text 
 985          @raise Exception: if the specified abbreviation is not unique 
 986          """ 
 987          if not self.configManager.check_abbreviation_unique(abbr, None): 
 988              raise Exception("The specified abbreviation is already in use") 
 989           
 990          p = model.Phrase(description, contents) 
 991          p.modes.append(model.TriggerMode.ABBREVIATION) 
 992          p.abbreviation = abbr 
 993          folder.add_item(p) 
 994          self.configManager.config_altered() 
  995           
 996 -    def create_hotkey(self, folder, description, modifiers, key, contents): 
  997          """ 
 998          Create a text hotkey. 
 999           
1000          Usage: C{engine.create_hotkey(folder, description, modifiers, key, contents)} 
1001           
1002          When the given hotkey is pressed, it will be replaced with the given 
1003          text. Modifiers must be given as a list of strings, with the following 
1004          values permitted: 
1005           
1006          <ctrl> 
1007          <alt> 
1008          <super> 
1009          <shift> 
1010           
1011          The key must be an unshifted character (i.e. lowercase) 
1012           
1013          @param folder: folder to place the abbreviation in, retrieved using C{engine.get_folder()} 
1014          @param description: description for the phrase 
1015          @param modifiers: modifiers to use with the hotkey (as a list) 
1016          @param key: the hotkey 
1017          @param contents: the expansion text 
1018          @raise Exception: if the specified hotkey is not unique 
1019          """ 
1020          modifiers.sort() 
1021          if not self.configManager.check_hotkey_unique(modifiers, key, None): 
1022              raise Exception("The specified hotkey and modifier combination is already in use") 
1023           
1024          p = model.Phrase(description, contents) 
1025          p.modes.append(model.TriggerMode.HOTKEY) 
1026          p.set_hotkey(modifiers, key) 
1027          folder.add_item(p) 
1028          self.configManager.config_altered() 
 1029   
1031          """ 
1032          Run an existing script using its description to look it up 
1033           
1034          Usage: C{engine.run_script(description)} 
1035           
1036          @param description: description of the script to run 
1037          @raise Exception: if the specified script does not exist 
1038          """ 
1039          targetScript = None 
1040          for item in self.configManager.allItems: 
1041              if item.description == description and isinstance(item, Script): 
1042                  targetScript = item 
1043   
1044          if targetScript is not None: 
1045              self.runner.execute(targetScript, "") 
1046          else: 
1047              raise Exception("No script with description '%s' found" % description) 
  1048