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