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