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 if common.USING_QT:
21 from PyQt4.QtGui import QClipboard, QApplication
22 else:
23 import gtk
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
198
200 """
201 Provides a simple interface for the display of some basic dialogs to collect information from the user.
202
203 This version uses KDialog to integrate well with KDE. To pass additional arguments to KDialog that are
204 not specifically handled, use keyword arguments. For example, to pass the --geometry argument to KDialog
205 to specify the desired size of the dialog, pass C{geometry="700x400"} as one of the parameters. All
206 keyword arguments must be given as strings.
207
208 A note on exit codes: an exit code of 0 indicates that the user clicked OK.
209 """
210
212 for k, v in kwargs.iteritems():
213 args.append("--" + k)
214 args.append(v)
215
216 p = subprocess.Popen(["kdialog", "--title", title] + args, stdout=subprocess.PIPE)
217 retCode = p.wait()
218 output = p.stdout.read()[:-1]
219
220 return (retCode, output)
221
222 - def info_dialog(self, title="Information", message="", **kwargs):
223 """
224 Show an information dialog
225
226 Usage: C{dialog.info_dialog(title="Information", message="", **kwargs)}
227
228 @param title: window title for the dialog
229 @param message: message displayed in the dialog
230 @return: a tuple containing the exit code and user input
231 @rtype: C{tuple(int, str)}
232 """
233 return self.__runKdialog(title, ["--msgbox", message], kwargs)
234
248
249 - def password_dialog(self, title="Enter password", message="Enter password", **kwargs):
250 """
251 Show a password input dialog
252
253 Usage: C{dialog.password_dialog(title="Enter password", message="Enter password", **kwargs)}
254
255 @param title: window title for the dialog
256 @param message: message displayed above the password input box
257 @return: a tuple containing the exit code and user input
258 @rtype: C{tuple(int, str)}
259 """
260 return self.__runKdialog(title, ["--password", message], kwargs)
261
263 """
264 Show a combobox menu
265
266 Usage: C{dialog.combo_menu(options, title="Choose an option", message="Choose an option", **kwargs)}
267
268 @param options: list of options (strings) for the dialog
269 @param title: window title for the dialog
270 @param message: message displayed above the combobox
271 @return: a tuple containing the exit code and user choice
272 @rtype: C{tuple(int, str)}
273 """
274 return self.__runKdialog(title, ["--combobox", message] + options, kwargs)
275
277 """
278 Show a single-selection list menu
279
280 Usage: C{dialog.list_menu(options, title="Choose a value", message="Choose a value", default=None, **kwargs)}
281
282 @param options: list of options (strings) for the dialog
283 @param title: window title for the dialog
284 @param message: message displayed above the list
285 @param default: default value to be selected
286 @return: a tuple containing the exit code and user choice
287 @rtype: C{tuple(int, str)}
288 """
289
290 choices = []
291 optionNum = 0
292 for option in options:
293 choices.append(str(optionNum))
294 choices.append(option)
295 if option == default:
296 choices.append("on")
297 else:
298 choices.append("off")
299 optionNum += 1
300
301 retCode, result = self.__runKdialog(title, ["--radiolist", message] + choices, kwargs)
302 choice = options[int(result)]
303
304 return retCode, choice
305
307 """
308 Show a multiple-selection list menu
309
310 Usage: C{dialog.list_menu_multi(options, title="Choose one or more values", message="Choose one or more values", defaults=[], **kwargs)}
311
312 @param options: list of options (strings) for the dialog
313 @param title: window title for the dialog
314 @param message: message displayed above the list
315 @param defaults: list of default values to be selected
316 @return: a tuple containing the exit code and user choice
317 @rtype: C{tuple(int, str)}
318 """
319
320 choices = []
321 optionNum = 0
322 for option in options:
323 choices.append(str(optionNum))
324 choices.append(option)
325 if option in defaults:
326 choices.append("on")
327 else:
328 choices.append("off")
329 optionNum += 1
330
331 retCode, output = self.__runKdialog(title, ["--separate-output", "--checklist", message] + choices, kwargs)
332 results = output.split()
333
334 choices = []
335 for index in results:
336 choices.append(options[int(index)])
337
338 return retCode, choices
339
340 - def open_file(self, title="Open File", initialDir="~", fileTypes="*|All Files", rememberAs=None, **kwargs):
341 """
342 Show an Open File dialog
343
344 Usage: C{dialog.open_file(title="Open File", initialDir="~", fileTypes="*|All Files", rememberAs=None, **kwargs)}
345
346 @param title: window title for the dialog
347 @param initialDir: starting directory for the file dialog
348 @param fileTypes: file type filter expression
349 @param rememberAs: gives an ID to this file dialog, allowing it to open at the last used path next time
350 @return: a tuple containing the exit code and file path
351 @rtype: C{tuple(int, str)}
352 """
353 if rememberAs is not None:
354 return self.__runKdialog(title, ["--getopenfilename", initialDir, fileTypes, ":" + rememberAs], kwargs)
355 else:
356 return self.__runKdialog(title, ["--getopenfilename", initialDir, fileTypes], kwargs)
357
358 - def save_file(self, title="Save As", initialDir="~", fileTypes="*|All Files", rememberAs=None, **kwargs):
359 """
360 Show a Save As dialog
361
362 Usage: C{dialog.save_file(title="Save As", initialDir="~", fileTypes="*|All Files", rememberAs=None, **kwargs)}
363
364 @param title: window title for the dialog
365 @param initialDir: starting directory for the file dialog
366 @param fileTypes: file type filter expression
367 @param rememberAs: gives an ID to this file dialog, allowing it to open at the last used path next time
368 @return: a tuple containing the exit code and file path
369 @rtype: C{tuple(int, str)}
370 """
371 if rememberAs is not None:
372 return self.__runKdialog(title, ["--getsavefilename", initialDir, fileTypes, ":" + rememberAs], kwargs)
373 else:
374 return self.__runKdialog(title, ["--getsavefilename", initialDir, fileTypes], kwargs)
375
376 - def choose_directory(self, title="Select Directory", initialDir="~", rememberAs=None, **kwargs):
377 """
378 Show a Directory Chooser dialog
379
380 Usage: C{dialog.choose_directory(title="Select Directory", initialDir="~", rememberAs=None, **kwargs)}
381
382 @param title: window title for the dialog
383 @param initialDir: starting directory for the directory chooser dialog
384 @param rememberAs: gives an ID to this file dialog, allowing it to open at the last used path next time
385 @return: a tuple containing the exit code and chosen path
386 @rtype: C{tuple(int, str)}
387 """
388 if rememberAs is not None:
389 return self.__runKdialog(title, ["--getexistingdirectory", initialDir, ":" + rememberAs], kwargs)
390 else:
391 return self.__runKdialog(title, ["--getexistingdirectory", initialDir], kwargs)
392
394 """
395 Show a Colour Chooser dialog
396
397 Usage: C{dialog.choose_colour(title="Select Colour")}
398
399 @param title: window title for the dialog
400 @return: a tuple containing the exit code and colour
401 @rtype: C{tuple(int, str)}
402 """
403 return self.__runKdialog(title, ["--getcolor"], kwargs)
404
405 - def calendar(self, title="Choose a date", format="%Y-%m-%d", date="today", **kwargs):
406 """
407 Show a calendar dialog
408
409 Usage: C{dialog.calendar_dialog(title="Choose a date", format="%Y-%m-%d", date="YYYY-MM-DD", **kwargs)}
410
411 Note: the format and date parameters are not currently used
412
413 @param title: window title for the dialog
414 @param format: format of date to be returned
415 @param date: initial date as YYYY-MM-DD, otherwise today
416 @return: a tuple containing the exit code and date
417 @rtype: C{tuple(int, str)}
418 """
419 return self.__runKdialog(title, ["--calendar"], kwargs)
420
421
423 """
424 Simplified access to some system commands.
425 """
426
428 """
429 Execute a shell command
430
431 Usage: C{system.exec_command(command, getOutput=True)}
432
433 Set getOutput to False if the command does not exit and return immediately. Otherwise
434 AutoKey will not respond to any hotkeys/abbreviations etc until the process started
435 by the command exits.
436
437 @param command: command to be executed (including any arguments) - e.g. "ls -l"
438 @param getOutput: whether to capture the (stdout) output of the command
439 @raise subprocess.CalledProcessError: if the command returns a non-zero exit code
440 """
441 if getOutput:
442 p = subprocess.Popen(command, shell=True, bufsize=-1, stdout=subprocess.PIPE)
443 retCode = p.wait()
444 output = p.stdout.read()[:-1]
445 if retCode != 0:
446 raise subprocess.CalledProcessError(retCode, output)
447 else:
448 return output
449 else:
450 subprocess.Popen(command, shell=True, bufsize=-1)
451
453 """
454 Create a file with contents
455
456 Usage: C{system.create_file(fileName, contents="")}
457
458 @param fileName: full path to the file to be created
459 @param contents: contents to insert into the file
460 """
461 f = open(fileName, "w")
462 f.write(contents)
463 f.close()
464
465
467 """
468 Provides a simple interface for the display of some basic dialogs to collect information from the user.
469
470 This version uses Zenity to integrate well with GNOME. To pass additional arguments to Zenity that are
471 not specifically handled, use keyword arguments. For example, to pass the --timeout argument to Zenity
472 pass C{timeout="15"} as one of the parameters. All keyword arguments must be given as strings.
473
474 A note on exit codes: an exit code of 0 indicates that the user clicked OK.
475 """
476
478 for k, v in kwargs.iteritems():
479 args.append("--" + k)
480 args.append(v)
481
482 p = subprocess.Popen(["zenity", "--title", title] + args, stdout=subprocess.PIPE)
483 retCode = p.wait()
484 output = p.stdout.read()[:-1]
485
486 return (retCode, output)
487
488 - def info_dialog(self, title="Information", message="", **kwargs):
489 """
490 Show an information dialog
491
492 Usage: C{dialog.info_dialog(title="Information", message="", **kwargs)}
493
494 @param title: window title for the dialog
495 @param message: message displayed in the dialog
496 @return: a tuple containing the exit code and user input
497 @rtype: C{tuple(int, str)}
498 """
499 return self.__runZenity(title, ["--info", "--text", message], kwargs)
500
514
515 - def password_dialog(self, title="Enter password", message="Enter password", **kwargs):
516 """
517 Show a password input dialog
518
519 Usage: C{dialog.password_dialog(title="Enter password", message="Enter password")}
520
521 @param title: window title for the dialog
522 @param message: message displayed above the password input box
523 @return: a tuple containing the exit code and user input
524 @rtype: C{tuple(int, str)}
525 """
526 return self.__runZenity(title, ["--entry", "--text", message, "--hide-text"], kwargs)
527
528
529 """
530 Show a combobox menu - not supported by zenity
531
532 Usage: C{dialog.combo_menu(options, title="Choose an option", message="Choose an option")}
533
534 @param options: list of options (strings) for the dialog
535 @param title: window title for the dialog
536 @param message: message displayed above the combobox
537 """
538
539
541 """
542 Show a single-selection list menu
543
544 Usage: C{dialog.list_menu(options, title="Choose a value", message="Choose a value", default=None, **kwargs)}
545
546 @param options: list of options (strings) for the dialog
547 @param title: window title for the dialog
548 @param message: message displayed above the list
549 @param default: default value to be selected
550 @return: a tuple containing the exit code and user choice
551 @rtype: C{tuple(int, str)}
552 """
553
554 choices = []
555
556 for option in options:
557 if option == default:
558 choices.append("TRUE")
559 else:
560 choices.append("FALSE")
561
562
563 choices.append(option)
564
565
566 return self.__runZenity(title, ["--list", "--radiolist", "--text", message, "--column", " ", "--column", "Options"] + choices, kwargs)
567
568
569
571 """
572 Show a multiple-selection list menu
573
574 Usage: C{dialog.list_menu_multi(options, title="Choose one or more values", message="Choose one or more values", defaults=[], **kwargs)}
575
576 @param options: list of options (strings) for the dialog
577 @param title: window title for the dialog
578 @param message: message displayed above the list
579 @param defaults: list of default values to be selected
580 @return: a tuple containing the exit code and user choice
581 @rtype: C{tuple(int, str)}
582 """
583
584 choices = []
585
586 for option in options:
587 if option in defaults:
588 choices.append("TRUE")
589 else:
590 choices.append("FALSE")
591
592
593 choices.append(option)
594
595
596 retCode, output = self.__runZenity(title, ["--list", "--checklist", "--text", message, "--column", " ", "--column", "Options"] + choices, kwargs)
597 results = output.split('|')
598
599
600
601
602
603 return retCode, results
604
605 - def open_file(self, title="Open File", **kwargs):
606 """
607 Show an Open File dialog
608
609 Usage: C{dialog.open_file(title="Open File", **kwargs)}
610
611 @param title: window title for the dialog
612 @return: a tuple containing the exit code and file path
613 @rtype: C{tuple(int, str)}
614 """
615
616
617
618 return self.__runZenity(title, ["--file-selection"], kwargs)
619
620 - def save_file(self, title="Save As", **kwargs):
621 """
622 Show a Save As dialog
623
624 Usage: C{dialog.save_file(title="Save As", **kwargs)}
625
626 @param title: window title for the dialog
627 @return: a tuple containing the exit code and file path
628 @rtype: C{tuple(int, str)}
629 """
630
631
632
633 return self.__runZenity(title, ["--file-selection", "--save"], kwargs)
634
635 - def choose_directory(self, title="Select Directory", initialDir="~", **kwargs):
636 """
637 Show a Directory Chooser dialog
638
639 Usage: C{dialog.choose_directory(title="Select Directory", **kwargs)}
640
641 @param title: window title for the dialog
642 @return: a tuple containing the exit code and path
643 @rtype: C{tuple(int, str)}
644 """
645
646
647
648 return self.__runZenity(title, ["--file-selection", "--directory"], kwargs)
649
650
651 """
652 Show a Colour Chooser dialog - not supported by zenity
653
654 Usage: C{dialog.choose_colour(title="Select Colour")}
655
656 @param title: window title for the dialog
657 """
658
659
660 - def calendar(self, title="Choose a date", format="%Y-%m-%d", date="today", **kwargs):
661 """
662 Show a calendar dialog
663
664 Usage: C{dialog.calendar_dialog(title="Choose a date", format="%Y-%m-%d", date="YYYY-MM-DD", **kwargs)}
665
666 @param title: window title for the dialog
667 @param format: format of date to be returned
668 @param date: initial date as YYYY-MM-DD, otherwise today
669 @return: a tuple containing the exit code and date
670 @rtype: C{tuple(int, str)}
671 """
672 if re.match(r"[0-9]{4}-[0-9]{2}-[0-9]{2}", date):
673 year = date[0:4]
674 month = date[5:7]
675 day = date[8:10]
676 date_args = ["--year=" + year, "--month=" + month, "--day=" + day]
677 else:
678 date_args = []
679 return self.__runZenity(title, ["--calendar", "--date-format=" + format] + date_args, kwargs)
680
681
683 """
684 Read/write access to the X selection and clipboard - QT version
685 """
686
688 self.clipBoard = QApplication.clipboard()
689 self.app = app
690
692 """
693 Copy text into the X selection
694
695 Usage: C{clipboard.fill_selection(contents)}
696
697 @param contents: string to be placed in the selection
698 """
699 self.__execAsync(self.__fillSelection, contents)
700
702 self.clipBoard.setText(string, QClipboard.Selection)
703 self.sem.release()
704
706 """
707 Read text from the X selection
708
709 Usage: C{clipboard.get_selection()}
710
711 @return: text contents of the mouse selection
712 @rtype: C{str}
713 """
714 self.__execAsync(self.__getSelection)
715 return unicode(self.text)
716
718 self.text = self.clipBoard.text(QClipboard.Selection)
719 self.sem.release()
720
722 """
723 Copy text into the clipboard
724
725 Usage: C{clipboard.fill_clipboard(contents)}
726
727 @param contents: string to be placed in the selection
728 """
729 self.__execAsync(self.__fillClipboard, contents)
730
732 self.clipBoard.setText(string, QClipboard.Clipboard)
733 self.sem.release()
734
736 """
737 Read text from the clipboard
738
739 Usage: C{clipboard.get_clipboard()}
740
741 @return: text contents of the clipboard
742 @rtype: C{str}
743 """
744 self.__execAsync(self.__getClipboard)
745 return unicode(self.text)
746
748 self.text = self.clipBoard.text(QClipboard.Clipboard)
749 self.sem.release()
750
752 self.sem = threading.Semaphore(0)
753 self.app.exec_in_main(callback, *args)
754 self.sem.acquire()
755
756
758 """
759 Read/write access to the X selection and clipboard - GTK version
760 """
761
763 self.clipBoard = gtk.Clipboard()
764 self.selection = gtk.Clipboard(selection="PRIMARY")
765 self.app = app
766
768 """
769 Copy text into the X selection
770
771 Usage: C{clipboard.fill_selection(contents)}
772
773 @param contents: string to be placed in the selection
774 """
775
776 self.__fillSelection(contents)
777
779 gtk.gdk.threads_enter()
780 self.selection.set_text(string.encode("utf-8"))
781 gtk.gdk.threads_leave()
782
783
785 """
786 Read text from the X selection
787
788 Usage: C{clipboard.get_selection()}
789
790 @return: text contents of the mouse selection
791 @rtype: C{str}
792 @raise Exception: if no text was found in the selection
793 """
794 self.__execAsync(self.selection.request_text, self.__receive)
795 if self.text is not None:
796 return self.text.decode("utf-8")
797 else:
798 raise Exception("No text found in X selection")
799
801 self.text = text
802 self.sem.release()
803
805 """
806 Copy text into the clipboard
807
808 Usage: C{clipboard.fill_clipboard(contents)}
809
810 @param contents: string to be placed in the selection
811 """
812 self.__fillClipboard(contents)
813
815 gtk.gdk.threads_enter()
816 self.clipBoard.set_text(string.encode("utf-8"))
817 gtk.gdk.threads_leave()
818
819
821 """
822 Read text from the clipboard
823
824 Usage: C{clipboard.get_clipboard()}
825
826 @return: text contents of the clipboard
827 @rtype: C{str}
828 @raise Exception: if no text was found on the clipboard
829 """
830 self.__execAsync(self.clipBoard.request_text, self.__receive)
831 if self.text is not None:
832 return self.text.decode("utf-8")
833 else:
834 raise Exception("No text found on clipboard")
835
837 self.sem = threading.Semaphore(0)
838 gtk.gdk.threads_enter()
839 callback(*args)
840 gtk.gdk.threads_leave()
841 self.sem.acquire()
842
843
845 """
846 Basic window management using wmctrl
847
848 Note: in all cases where a window title is required (with the exception of wait_for_focus()),
849 two special values of window title are permitted:
850
851 :ACTIVE: - select the currently active window
852 :SELECT: - select the desired window by clicking on it
853 """
854
856 self.mediator = mediator
857
859 """
860 Wait for window with the given title to have focus
861
862 Usage: C{window.wait_for_focus(title, timeOut=5)}
863
864 If the window becomes active, returns True. Otherwise, returns False if
865 the window has not become active by the time the timeout has elapsed.
866
867 @param title: title to match against (as a regular expression)
868 @param timeOut: period (seconds) to wait before giving up
869 @rtype: boolean
870 """
871 regex = re.compile(title)
872 waited = 0
873 while waited <= timeOut:
874 if regex.match(self.mediator.interface.get_window_title()):
875 return True
876
877 if timeOut == 0:
878 break
879
880 time.sleep(0.3)
881 waited += 0.3
882
883 return False
884
886 """
887 Wait for window with the given title to be created
888
889 Usage: C{window.wait_for_exist(title, timeOut=5)}
890
891 If the window is in existence, returns True. Otherwise, returns False if
892 the window has not been created by the time the timeout has elapsed.
893
894 @param title: title to match against (as a regular expression)
895 @param timeOut: period (seconds) to wait before giving up
896 @rtype: boolean
897 """
898 regex = re.compile(title)
899 waited = 0
900 while waited <= timeOut:
901 retCode, output = self.__runWmctrl(["-l"])
902 for line in output.split('\n'):
903 if regex.match(line[14:].split(' ', 1)[-1]):
904 return True
905
906 if timeOut == 0:
907 break
908
909 time.sleep(0.3)
910 waited += 0.3
911
912 return False
913
914 - def activate(self, title, switchDesktop=False, matchClass=False):
915 """
916 Activate the specified window, giving it input focus
917
918 Usage: C{window.activate(title, switchDesktop=False, matchClass=False)}
919
920 If switchDesktop is False (default), the window will be moved to the current desktop
921 and activated. Otherwise, switch to the window's current desktop and activate it there.
922
923 @param title: window title to match against (as case-insensitive substring match)
924 @param switchDesktop: whether or not to switch to the window's current desktop
925 @param matchClass: if True, match on the window class instead of the title
926 """
927 if switchDesktop:
928 args = ["-a", title]
929 else:
930 args = ["-R", title]
931 if matchClass:
932 args += ["-x"]
933 self.__runWmctrl(args)
934
935 - def close(self, title, matchClass=False):
936 """
937 Close the specified window gracefully
938
939 Usage: C{window.close(title, matchClass=False)}
940
941 @param title: window title to match against (as case-insensitive substring match)
942 @param matchClass: if True, match on the window class instead of the title
943 """
944 if matchClass:
945 self.__runWmctrl(["-c", title, "-x"])
946 else:
947 self.__runWmctrl(["-c", title])
948
949 - def resize_move(self, title, xOrigin=-1, yOrigin=-1, width=-1, height=-1, matchClass=False):
950 """
951 Resize and/or move the specified window
952
953 Usage: C{window.close(title, xOrigin=-1, yOrigin=-1, width=-1, height=-1, matchClass=False)}
954
955 Leaving and of the position/dimension values as the default (-1) will cause that
956 value to be left unmodified.
957
958 @param title: window title to match against (as case-insensitive substring match)
959 @param xOrigin: new x origin of the window (upper left corner)
960 @param yOrigin: new y origin of the window (upper left corner)
961 @param width: new width of the window
962 @param height: new height of the window
963 @param matchClass: if True, match on the window class instead of the title
964 """
965 mvArgs = ["0", str(xOrigin), str(yOrigin), str(width), str(height)]
966 if matchClass:
967 xArgs = ["-x"]
968 else:
969 xArgs = []
970 self.__runWmctrl(["-r", title, "-e", ','.join(mvArgs)] + xArgs)
971
972
974 """
975 Move the specified window to the given desktop
976
977 Usage: C{window.move_to_desktop(title, deskNum, matchClass=False)}
978
979 @param title: window title to match against (as case-insensitive substring match)
980 @param deskNum: desktop to move the window to (note: zero based)
981 @param matchClass: if True, match on the window class instead of the title
982 """
983 if matchClass:
984 xArgs = ["-x"]
985 else:
986 xArgs = []
987 self.__runWmctrl(["-r", title, "-t", str(deskNum)] + xArgs)
988
989
991 """
992 Switch to the specified desktop
993
994 Usage: C{window.switch_desktop(deskNum)}
995
996 @param deskNum: desktop to switch to (note: zero based)
997 """
998 self.__runWmctrl(["-s", str(deskNum)])
999
1000 - def set_property(self, title, action, prop, matchClass=False):
1001 """
1002 Set a property on the given window using the specified action
1003
1004 Usage: C{window.set_property(title, action, prop, matchClass=False)}
1005
1006 Allowable actions: C{add, remove, toggle}
1007 Allowable properties: C{modal, sticky, maximized_vert, maximized_horz, shaded, skip_taskbar,
1008 skip_pager, hidden, fullscreen, above}
1009
1010 @param title: window title to match against (as case-insensitive substring match)
1011 @param action: one of the actions listed above
1012 @param prop: one of the properties listed above
1013 @param matchClass: if True, match on the window class instead of the title
1014 """
1015 if matchClass:
1016 xArgs = ["-x"]
1017 else:
1018 xArgs = []
1019 self.__runWmctrl(["-r", title, "-b" + action + ',' + prop] + xArgs)
1020
1022 """
1023 Get the geometry of the currently active window
1024
1025 Usage: C{window.get_active_geometry()}
1026
1027 @return: a 4-tuple containing the x-origin, y-origin, width and height of the window (in pixels)
1028 @rtype: C{tuple(int, int, int, int)}
1029 """
1030 active = self.mediator.interface.get_window_title()
1031 result, output = self.__runWmctrl(["-l", "-G"])
1032 matchingLine = None
1033 for line in output.split('\n'):
1034 if active in line[34:].split(' ', 1)[-1]:
1035 matchingLine = line
1036
1037 if matchingLine is not None:
1038 output = matchingLine.split()[2:6]
1039 return map(int, output)
1040 else:
1041 return None
1042
1044 """
1045 Get the visible title of the currently active window
1046
1047 Usage: C{window.get_active_title()}
1048
1049 @return: the visible title of the currentle active window
1050 @rtype: C{str}
1051 """
1052 return self.mediator.interface.get_window_title()
1053
1055 """
1056 Get the class of the currently active window
1057
1058 Usage: C{window.get_active_class()}
1059
1060 @return: the class of the currentle active window
1061 @rtype: C{str}
1062 """
1063 return self.mediator.interface.get_window_class()
1064
1066 p = subprocess.Popen(["wmctrl"] + args, stdout=subprocess.PIPE)
1067 retCode = p.wait()
1068 output = p.stdout.read()[:-1]
1069
1070 return (retCode, output)
1071
1072
1074 """
1075 Provides access to the internals of AutoKey.
1076
1077 Note that any configuration changes made using this API while the configuration window
1078 is open will not appear until it is closed and re-opened.
1079 """
1080
1081 - def __init__(self, configManager, runner):
1082 self.configManager = configManager
1083 self.runner = runner
1084 self.monitor = configManager.app.monitor
1085 self.__returnValue = ''
1086
1088 """
1089 Retrieve a folder by its title
1090
1091 Usage: C{engine.get_folder(title)}
1092
1093 Note that if more than one folder has the same title, only the first match will be
1094 returned.
1095 """
1096 for folder in self.configManager.allFolders:
1097 if folder.title == title:
1098 return folder
1099 return None
1100
1102 """
1103 Create a text phrase
1104
1105 Usage: C{engine.create_phrase(folder, description, contents)}
1106
1107 A new phrase with no abbreviation or hotkey is created in the specified folder
1108
1109 @param folder: folder to place the abbreviation in, retrieved using C{engine.get_folder()}
1110 @param description: description for the phrase
1111 @param contents: the expansion text
1112 """
1113 self.monitor.suspend()
1114 p = model.Phrase(description, contents)
1115 folder.add_item(p)
1116 p.persist()
1117 self.monitor.unsuspend()
1118 self.configManager.config_altered(False)
1119
1121 """
1122 Create a text abbreviation
1123
1124 Usage: C{engine.create_abbreviation(folder, description, abbr, contents)}
1125
1126 When the given abbreviation is typed, it will be replaced with the given
1127 text.
1128
1129 @param folder: folder to place the abbreviation in, retrieved using C{engine.get_folder()}
1130 @param description: description for the phrase
1131 @param abbr: the abbreviation that will trigger the expansion
1132 @param contents: the expansion text
1133 @raise Exception: if the specified abbreviation is not unique
1134 """
1135 if not self.configManager.check_abbreviation_unique(abbr, None, None):
1136 raise Exception("The specified abbreviation is already in use")
1137
1138 self.monitor.suspend()
1139 p = model.Phrase(description, contents)
1140 p.modes.append(model.TriggerMode.ABBREVIATION)
1141 p.abbreviations = [abbr]
1142 folder.add_item(p)
1143 p.persist()
1144 self.monitor.unsuspend()
1145 self.configManager.config_altered(False)
1146
1147 - def create_hotkey(self, folder, description, modifiers, key, contents):
1148 """
1149 Create a text hotkey
1150
1151 Usage: C{engine.create_hotkey(folder, description, modifiers, key, contents)}
1152
1153 When the given hotkey is pressed, it will be replaced with the given
1154 text. Modifiers must be given as a list of strings, with the following
1155 values permitted:
1156
1157 <ctrl>
1158 <alt>
1159 <super>
1160 <hyper>
1161 <shift>
1162
1163 The key must be an unshifted character (i.e. lowercase)
1164
1165 @param folder: folder to place the abbreviation in, retrieved using C{engine.get_folder()}
1166 @param description: description for the phrase
1167 @param modifiers: modifiers to use with the hotkey (as a list)
1168 @param key: the hotkey
1169 @param contents: the expansion text
1170 @raise Exception: if the specified hotkey is not unique
1171 """
1172 modifiers.sort()
1173 if not self.configManager.check_hotkey_unique(modifiers, key, None, None):
1174 raise Exception("The specified hotkey and modifier combination is already in use")
1175
1176 self.monitor.suspend()
1177 p = model.Phrase(description, contents)
1178 p.modes.append(model.TriggerMode.HOTKEY)
1179 p.set_hotkey(modifiers, key)
1180 folder.add_item(p)
1181 p.persist()
1182 self.monitor.unsuspend()
1183 self.configManager.config_altered(False)
1184
1186 """
1187 Run an existing script using its description to look it up
1188
1189 Usage: C{engine.run_script(description)}
1190
1191 @param description: description of the script to run
1192 @raise Exception: if the specified script does not exist
1193 """
1194 targetScript = None
1195 for item in self.configManager.allItems:
1196 if item.description == description and isinstance(item, model.Script):
1197 targetScript = item
1198
1199 if targetScript is not None:
1200 self.runner.run_subscript(targetScript)
1201 else:
1202 raise Exception("No script with description '%s' found" % description)
1203
1205 """
1206 Used internally by AutoKey for phrase macros
1207 """
1208 self.__macroArgs = args["args"].split(',')
1209
1210 try:
1211 self.run_script(args["name"])
1212 except Exception, e:
1213 self.set_return_value("{ERROR: %s}" % str(e))
1214
1216 """
1217 Get the arguments supplied to the current script via its macro
1218
1219 Usage: C{engine.get_macro_arguments()}
1220
1221 @return: the arguments
1222 @rtype: C{list(str())}
1223 """
1224 return self.__macroArgs
1225
1227 """
1228 Store a return value to be used by a phrase macro
1229
1230 Usage: C{engine.set_return_value(val)}
1231
1232 @param val: value to be stored
1233 """
1234 self.__returnValue = val
1235
1237 """
1238 Used internally by AutoKey for phrase macros
1239 """
1240 ret = self.__returnValue
1241 self.__returnValue = ''
1242 return ret
1243