1c6bd3a639145b36af22b7d591bb09ff8cbef8c34lmr#!/usr/bin/python 26f669cee054a0bca677a85e8443221354ff218b6lmr""" 36f669cee054a0bca677a85e8443221354ff218b6lmrStep file creator/editor. 46f669cee054a0bca677a85e8443221354ff218b6lmr 56f669cee054a0bca677a85e8443221354ff218b6lmr@copyright: Red Hat Inc 2009 66f669cee054a0bca677a85e8443221354ff218b6lmr@author: mgoldish@redhat.com (Michael Goldish) 76f669cee054a0bca677a85e8443221354ff218b6lmr@version: "20090401" 86f669cee054a0bca677a85e8443221354ff218b6lmr""" 96f669cee054a0bca677a85e8443221354ff218b6lmr 10b635b8669393c91dca1c755067d79da5d9c93e7almrimport pygtk, gtk, os, glob, shutil, sys, logging 11b635b8669393c91dca1c755067d79da5d9c93e7almrimport common, ppm_utils 12b635b8669393c91dca1c755067d79da5d9c93e7almrpygtk.require('2.0') 13b635b8669393c91dca1c755067d79da5d9c93e7almr 146f669cee054a0bca677a85e8443221354ff218b6lmr 156f669cee054a0bca677a85e8443221354ff218b6lmr# General utilities 166f669cee054a0bca677a85e8443221354ff218b6lmr 176f669cee054a0bca677a85e8443221354ff218b6lmrdef corner_and_size_clipped(startpoint, endpoint, limits): 186f669cee054a0bca677a85e8443221354ff218b6lmr c0 = startpoint[:] 196f669cee054a0bca677a85e8443221354ff218b6lmr c1 = endpoint[:] 20861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li if c0[0] < 0: 21861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li c0[0] = 0 22861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li if c0[1] < 0: 23861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li c0[1] = 0 24861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li if c1[0] < 0: 25861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li c1[0] = 0 26861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li if c1[1] < 0: 27861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li c1[1] = 0 28861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li if c0[0] > limits[0] - 1: 29861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li c0[0] = limits[0] - 1 30861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li if c0[1] > limits[1] - 1: 31861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li c0[1] = limits[1] - 1 32861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li if c1[0] > limits[0] - 1: 33861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li c1[0] = limits[0] - 1 34861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li if c1[1] > limits[1] - 1: 35861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li c1[1] = limits[1] - 1 366f669cee054a0bca677a85e8443221354ff218b6lmr return ([min(c0[0], c1[0]), 376f669cee054a0bca677a85e8443221354ff218b6lmr min(c0[1], c1[1])], 386f669cee054a0bca677a85e8443221354ff218b6lmr [abs(c1[0] - c0[0]) + 1, 396f669cee054a0bca677a85e8443221354ff218b6lmr abs(c1[1] - c0[1]) + 1]) 406f669cee054a0bca677a85e8443221354ff218b6lmr 416f669cee054a0bca677a85e8443221354ff218b6lmr 426f669cee054a0bca677a85e8443221354ff218b6lmrdef key_event_to_qemu_string(event): 436f669cee054a0bca677a85e8443221354ff218b6lmr keymap = gtk.gdk.keymap_get_default() 446f669cee054a0bca677a85e8443221354ff218b6lmr keyvals = keymap.get_entries_for_keycode(event.hardware_keycode) 456f669cee054a0bca677a85e8443221354ff218b6lmr keyval = keyvals[0][0] 466f669cee054a0bca677a85e8443221354ff218b6lmr keyname = gtk.gdk.keyval_name(keyval) 476f669cee054a0bca677a85e8443221354ff218b6lmr 486f669cee054a0bca677a85e8443221354ff218b6lmr dict = { "Return": "ret", 496f669cee054a0bca677a85e8443221354ff218b6lmr "Tab": "tab", 506f669cee054a0bca677a85e8443221354ff218b6lmr "space": "spc", 516f669cee054a0bca677a85e8443221354ff218b6lmr "Left": "left", 526f669cee054a0bca677a85e8443221354ff218b6lmr "Right": "right", 536f669cee054a0bca677a85e8443221354ff218b6lmr "Up": "up", 546f669cee054a0bca677a85e8443221354ff218b6lmr "Down": "down", 556f669cee054a0bca677a85e8443221354ff218b6lmr "F1": "f1", 566f669cee054a0bca677a85e8443221354ff218b6lmr "F2": "f2", 576f669cee054a0bca677a85e8443221354ff218b6lmr "F3": "f3", 586f669cee054a0bca677a85e8443221354ff218b6lmr "F4": "f4", 596f669cee054a0bca677a85e8443221354ff218b6lmr "F5": "f5", 606f669cee054a0bca677a85e8443221354ff218b6lmr "F6": "f6", 616f669cee054a0bca677a85e8443221354ff218b6lmr "F7": "f7", 626f669cee054a0bca677a85e8443221354ff218b6lmr "F8": "f8", 636f669cee054a0bca677a85e8443221354ff218b6lmr "F9": "f9", 646f669cee054a0bca677a85e8443221354ff218b6lmr "F10": "f10", 656f669cee054a0bca677a85e8443221354ff218b6lmr "F11": "f11", 666f669cee054a0bca677a85e8443221354ff218b6lmr "F12": "f12", 676f669cee054a0bca677a85e8443221354ff218b6lmr "Escape": "esc", 686f669cee054a0bca677a85e8443221354ff218b6lmr "minus": "minus", 696f669cee054a0bca677a85e8443221354ff218b6lmr "equal": "equal", 706f669cee054a0bca677a85e8443221354ff218b6lmr "BackSpace": "backspace", 716f669cee054a0bca677a85e8443221354ff218b6lmr "comma": "comma", 726f669cee054a0bca677a85e8443221354ff218b6lmr "period": "dot", 736f669cee054a0bca677a85e8443221354ff218b6lmr "slash": "slash", 746f669cee054a0bca677a85e8443221354ff218b6lmr "Insert": "insert", 756f669cee054a0bca677a85e8443221354ff218b6lmr "Delete": "delete", 766f669cee054a0bca677a85e8443221354ff218b6lmr "Home": "home", 776f669cee054a0bca677a85e8443221354ff218b6lmr "End": "end", 786f669cee054a0bca677a85e8443221354ff218b6lmr "Page_Up": "pgup", 796f669cee054a0bca677a85e8443221354ff218b6lmr "Page_Down": "pgdn", 806f669cee054a0bca677a85e8443221354ff218b6lmr "Menu": "menu", 816f669cee054a0bca677a85e8443221354ff218b6lmr "semicolon": "0x27", 826f669cee054a0bca677a85e8443221354ff218b6lmr "backslash": "0x2b", 836f669cee054a0bca677a85e8443221354ff218b6lmr "apostrophe": "0x28", 846f669cee054a0bca677a85e8443221354ff218b6lmr "grave": "0x29", 856f669cee054a0bca677a85e8443221354ff218b6lmr "less": "0x2b", 866f669cee054a0bca677a85e8443221354ff218b6lmr "bracketleft": "0x1a", 876f669cee054a0bca677a85e8443221354ff218b6lmr "bracketright": "0x1b", 886f669cee054a0bca677a85e8443221354ff218b6lmr "Super_L": "0xdc", 896f669cee054a0bca677a85e8443221354ff218b6lmr "Super_R": "0xdb", 906f669cee054a0bca677a85e8443221354ff218b6lmr } 916f669cee054a0bca677a85e8443221354ff218b6lmr 926f669cee054a0bca677a85e8443221354ff218b6lmr if ord('a') <= keyval <= ord('z') or ord('0') <= keyval <= ord('9'): 936f669cee054a0bca677a85e8443221354ff218b6lmr str = keyname 946f669cee054a0bca677a85e8443221354ff218b6lmr elif keyname in dict.keys(): 956f669cee054a0bca677a85e8443221354ff218b6lmr str = dict[keyname] 966f669cee054a0bca677a85e8443221354ff218b6lmr else: 976f669cee054a0bca677a85e8443221354ff218b6lmr return "" 986f669cee054a0bca677a85e8443221354ff218b6lmr 99861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li if event.state & gtk.gdk.CONTROL_MASK: 100861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li str = "ctrl-" + str 101861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li if event.state & gtk.gdk.MOD1_MASK: 102861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li str = "alt-" + str 103861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li if event.state & gtk.gdk.SHIFT_MASK: 104861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li str = "shift-" + str 1056f669cee054a0bca677a85e8443221354ff218b6lmr 1066f669cee054a0bca677a85e8443221354ff218b6lmr return str 1076f669cee054a0bca677a85e8443221354ff218b6lmr 1086f669cee054a0bca677a85e8443221354ff218b6lmr 1096f669cee054a0bca677a85e8443221354ff218b6lmrclass StepMakerWindow: 1106f669cee054a0bca677a85e8443221354ff218b6lmr 1116f669cee054a0bca677a85e8443221354ff218b6lmr # Constructor 1126f669cee054a0bca677a85e8443221354ff218b6lmr 1136f669cee054a0bca677a85e8443221354ff218b6lmr def __init__(self): 1146f669cee054a0bca677a85e8443221354ff218b6lmr # Window 1156f669cee054a0bca677a85e8443221354ff218b6lmr self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) 1166f669cee054a0bca677a85e8443221354ff218b6lmr self.window.set_title("Step Maker Window") 1176f669cee054a0bca677a85e8443221354ff218b6lmr self.window.connect("delete-event", self.delete_event) 1186f669cee054a0bca677a85e8443221354ff218b6lmr self.window.connect("destroy", self.destroy) 1196f669cee054a0bca677a85e8443221354ff218b6lmr self.window.set_default_size(600, 800) 1206f669cee054a0bca677a85e8443221354ff218b6lmr 1216f669cee054a0bca677a85e8443221354ff218b6lmr # Main box (inside a frame which is inside a VBox) 1226f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_vbox = gtk.VBox() 1236f669cee054a0bca677a85e8443221354ff218b6lmr self.window.add(self.menu_vbox) 1246f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_vbox.show() 1256f669cee054a0bca677a85e8443221354ff218b6lmr 1266f669cee054a0bca677a85e8443221354ff218b6lmr frame = gtk.Frame() 1276f669cee054a0bca677a85e8443221354ff218b6lmr frame.set_border_width(10) 1286f669cee054a0bca677a85e8443221354ff218b6lmr frame.set_shadow_type(gtk.SHADOW_NONE) 1296f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_vbox.pack_end(frame) 1306f669cee054a0bca677a85e8443221354ff218b6lmr frame.show() 1316f669cee054a0bca677a85e8443221354ff218b6lmr 1326f669cee054a0bca677a85e8443221354ff218b6lmr self.main_vbox = gtk.VBox(spacing=10) 1336f669cee054a0bca677a85e8443221354ff218b6lmr frame.add(self.main_vbox) 1346f669cee054a0bca677a85e8443221354ff218b6lmr self.main_vbox.show() 1356f669cee054a0bca677a85e8443221354ff218b6lmr 1366f669cee054a0bca677a85e8443221354ff218b6lmr # EventBox 1376f669cee054a0bca677a85e8443221354ff218b6lmr self.scrolledwindow = gtk.ScrolledWindow() 1386f669cee054a0bca677a85e8443221354ff218b6lmr self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, 1396f669cee054a0bca677a85e8443221354ff218b6lmr gtk.POLICY_AUTOMATIC) 1406f669cee054a0bca677a85e8443221354ff218b6lmr self.scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) 1416f669cee054a0bca677a85e8443221354ff218b6lmr self.main_vbox.pack_start(self.scrolledwindow) 1426f669cee054a0bca677a85e8443221354ff218b6lmr self.scrolledwindow.show() 1436f669cee054a0bca677a85e8443221354ff218b6lmr 1446f669cee054a0bca677a85e8443221354ff218b6lmr table = gtk.Table(1, 1) 1456f669cee054a0bca677a85e8443221354ff218b6lmr self.scrolledwindow.add_with_viewport(table) 1466f669cee054a0bca677a85e8443221354ff218b6lmr table.show() 1476f669cee054a0bca677a85e8443221354ff218b6lmr table.realize() 1486f669cee054a0bca677a85e8443221354ff218b6lmr 1496f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box = gtk.EventBox() 1506f669cee054a0bca677a85e8443221354ff218b6lmr table.attach(self.event_box, 0, 1, 0, 1, gtk.EXPAND, gtk.EXPAND) 1516f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.show() 1526f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.realize() 1536f669cee054a0bca677a85e8443221354ff218b6lmr 1546f669cee054a0bca677a85e8443221354ff218b6lmr # Image 1556f669cee054a0bca677a85e8443221354ff218b6lmr self.image = gtk.Image() 1566f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.add(self.image) 1576f669cee054a0bca677a85e8443221354ff218b6lmr self.image.show() 1586f669cee054a0bca677a85e8443221354ff218b6lmr 1596f669cee054a0bca677a85e8443221354ff218b6lmr # Data VBox 1606f669cee054a0bca677a85e8443221354ff218b6lmr self.data_vbox = gtk.VBox(spacing=10) 1616f669cee054a0bca677a85e8443221354ff218b6lmr self.main_vbox.pack_start(self.data_vbox, expand=False) 1626f669cee054a0bca677a85e8443221354ff218b6lmr self.data_vbox.show() 1636f669cee054a0bca677a85e8443221354ff218b6lmr 1646f669cee054a0bca677a85e8443221354ff218b6lmr # User VBox 1656f669cee054a0bca677a85e8443221354ff218b6lmr self.user_vbox = gtk.VBox(spacing=10) 1666f669cee054a0bca677a85e8443221354ff218b6lmr self.main_vbox.pack_start(self.user_vbox, expand=False) 1676f669cee054a0bca677a85e8443221354ff218b6lmr self.user_vbox.show() 1686f669cee054a0bca677a85e8443221354ff218b6lmr 1696f669cee054a0bca677a85e8443221354ff218b6lmr # Screendump ID HBox 1706f669cee054a0bca677a85e8443221354ff218b6lmr box = gtk.HBox(spacing=10) 1716f669cee054a0bca677a85e8443221354ff218b6lmr self.data_vbox.pack_start(box) 1726f669cee054a0bca677a85e8443221354ff218b6lmr box.show() 1736f669cee054a0bca677a85e8443221354ff218b6lmr 1746f669cee054a0bca677a85e8443221354ff218b6lmr label = gtk.Label("Screendump ID:") 1756f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(label, False) 1766f669cee054a0bca677a85e8443221354ff218b6lmr label.show() 1776f669cee054a0bca677a85e8443221354ff218b6lmr 1786f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_screendump = gtk.Entry() 1796f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_screendump.set_editable(False) 1806f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.entry_screendump) 1816f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_screendump.show() 1826f669cee054a0bca677a85e8443221354ff218b6lmr 1836f669cee054a0bca677a85e8443221354ff218b6lmr label = gtk.Label("Time:") 1846f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(label, False) 1856f669cee054a0bca677a85e8443221354ff218b6lmr label.show() 1866f669cee054a0bca677a85e8443221354ff218b6lmr 1876f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_time = gtk.Entry() 1886f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_time.set_editable(False) 1896f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_time.set_width_chars(10) 1906f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.entry_time, False) 1916f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_time.show() 1926f669cee054a0bca677a85e8443221354ff218b6lmr 1936f669cee054a0bca677a85e8443221354ff218b6lmr # Comment HBox 1946f669cee054a0bca677a85e8443221354ff218b6lmr box = gtk.HBox(spacing=10) 1956f669cee054a0bca677a85e8443221354ff218b6lmr self.data_vbox.pack_start(box) 1966f669cee054a0bca677a85e8443221354ff218b6lmr box.show() 1976f669cee054a0bca677a85e8443221354ff218b6lmr 1986f669cee054a0bca677a85e8443221354ff218b6lmr label = gtk.Label("Comment:") 1996f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(label, False) 2006f669cee054a0bca677a85e8443221354ff218b6lmr label.show() 2016f669cee054a0bca677a85e8443221354ff218b6lmr 2026f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_comment = gtk.Entry() 2036f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.entry_comment) 2046f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_comment.show() 2056f669cee054a0bca677a85e8443221354ff218b6lmr 2066f669cee054a0bca677a85e8443221354ff218b6lmr # Sleep HBox 2076f669cee054a0bca677a85e8443221354ff218b6lmr box = gtk.HBox(spacing=10) 2086f669cee054a0bca677a85e8443221354ff218b6lmr self.data_vbox.pack_start(box) 2096f669cee054a0bca677a85e8443221354ff218b6lmr box.show() 2106f669cee054a0bca677a85e8443221354ff218b6lmr 2116f669cee054a0bca677a85e8443221354ff218b6lmr self.check_sleep = gtk.CheckButton("Sleep:") 2126f669cee054a0bca677a85e8443221354ff218b6lmr self.check_sleep.connect("toggled", self.event_check_sleep_toggled) 2136f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.check_sleep, False) 2146f669cee054a0bca677a85e8443221354ff218b6lmr self.check_sleep.show() 2156f669cee054a0bca677a85e8443221354ff218b6lmr 2166f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_sleep = gtk.SpinButton(gtk.Adjustment(0, 0, 50000, 1, 10, 0), 2176f669cee054a0bca677a85e8443221354ff218b6lmr climb_rate=0.0) 2186f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.spin_sleep, False) 2196f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_sleep.show() 2206f669cee054a0bca677a85e8443221354ff218b6lmr 2216f669cee054a0bca677a85e8443221354ff218b6lmr # Barrier HBox 2226f669cee054a0bca677a85e8443221354ff218b6lmr box = gtk.HBox(spacing=10) 2236f669cee054a0bca677a85e8443221354ff218b6lmr self.data_vbox.pack_start(box) 2246f669cee054a0bca677a85e8443221354ff218b6lmr box.show() 2256f669cee054a0bca677a85e8443221354ff218b6lmr 2266f669cee054a0bca677a85e8443221354ff218b6lmr self.check_barrier = gtk.CheckButton("Barrier:") 2276f669cee054a0bca677a85e8443221354ff218b6lmr self.check_barrier.connect("toggled", self.event_check_barrier_toggled) 2286f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.check_barrier, False) 2296f669cee054a0bca677a85e8443221354ff218b6lmr self.check_barrier.show() 2306f669cee054a0bca677a85e8443221354ff218b6lmr 2316f669cee054a0bca677a85e8443221354ff218b6lmr vbox = gtk.VBox() 2326f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(vbox) 2336f669cee054a0bca677a85e8443221354ff218b6lmr vbox.show() 2346f669cee054a0bca677a85e8443221354ff218b6lmr 2356f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_region = gtk.Label("Region:") 2366f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_region.set_alignment(0, 0.5) 2376f669cee054a0bca677a85e8443221354ff218b6lmr vbox.pack_start(self.label_barrier_region) 2386f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_region.show() 2396f669cee054a0bca677a85e8443221354ff218b6lmr 2406f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_md5sum = gtk.Label("MD5:") 2416f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_md5sum.set_alignment(0, 0.5) 2426f669cee054a0bca677a85e8443221354ff218b6lmr vbox.pack_start(self.label_barrier_md5sum) 2436f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_md5sum.show() 2446f669cee054a0bca677a85e8443221354ff218b6lmr 2456f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_timeout = gtk.Label("Timeout:") 2466f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.label_barrier_timeout, False) 2476f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_timeout.show() 2486f669cee054a0bca677a85e8443221354ff218b6lmr 2496f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_barrier_timeout = gtk.SpinButton(gtk.Adjustment(0, 0, 50000, 2506f669cee054a0bca677a85e8443221354ff218b6lmr 1, 10, 0), 2516f669cee054a0bca677a85e8443221354ff218b6lmr climb_rate=0.0) 2526f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.spin_barrier_timeout, False) 2536f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_barrier_timeout.show() 2546f669cee054a0bca677a85e8443221354ff218b6lmr 2556f669cee054a0bca677a85e8443221354ff218b6lmr self.check_barrier_optional = gtk.CheckButton("Optional") 2566f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.check_barrier_optional, False) 2576f669cee054a0bca677a85e8443221354ff218b6lmr self.check_barrier_optional.show() 2586f669cee054a0bca677a85e8443221354ff218b6lmr 2596f669cee054a0bca677a85e8443221354ff218b6lmr # Keystrokes HBox 2606f669cee054a0bca677a85e8443221354ff218b6lmr box = gtk.HBox(spacing=10) 2616f669cee054a0bca677a85e8443221354ff218b6lmr self.data_vbox.pack_start(box) 2626f669cee054a0bca677a85e8443221354ff218b6lmr box.show() 2636f669cee054a0bca677a85e8443221354ff218b6lmr 2646f669cee054a0bca677a85e8443221354ff218b6lmr label = gtk.Label("Keystrokes:") 2656f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(label, False) 2666f669cee054a0bca677a85e8443221354ff218b6lmr label.show() 2676f669cee054a0bca677a85e8443221354ff218b6lmr 2686f669cee054a0bca677a85e8443221354ff218b6lmr frame = gtk.Frame() 2696f669cee054a0bca677a85e8443221354ff218b6lmr frame.set_shadow_type(gtk.SHADOW_IN) 2706f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(frame) 2716f669cee054a0bca677a85e8443221354ff218b6lmr frame.show() 2726f669cee054a0bca677a85e8443221354ff218b6lmr 273861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li self.text_buffer = gtk.TextBuffer() 2746f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_keys = gtk.TextView(self.text_buffer) 2756f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_keys.set_wrap_mode(gtk.WRAP_WORD) 2766f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_keys.connect("key-press-event", self.event_key_press) 2776f669cee054a0bca677a85e8443221354ff218b6lmr frame.add(self.entry_keys) 2786f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_keys.show() 2796f669cee054a0bca677a85e8443221354ff218b6lmr 2806f669cee054a0bca677a85e8443221354ff218b6lmr self.check_manual = gtk.CheckButton("Manual") 2816f669cee054a0bca677a85e8443221354ff218b6lmr self.check_manual.connect("toggled", self.event_manual_toggled) 2826f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.check_manual, False) 2836f669cee054a0bca677a85e8443221354ff218b6lmr self.check_manual.show() 2846f669cee054a0bca677a85e8443221354ff218b6lmr 2856f669cee054a0bca677a85e8443221354ff218b6lmr button = gtk.Button("Clear") 2866f669cee054a0bca677a85e8443221354ff218b6lmr button.connect("clicked", self.event_clear_clicked) 2876f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(button, False) 2886f669cee054a0bca677a85e8443221354ff218b6lmr button.show() 2896f669cee054a0bca677a85e8443221354ff218b6lmr 2906f669cee054a0bca677a85e8443221354ff218b6lmr # Mouse click HBox 2916f669cee054a0bca677a85e8443221354ff218b6lmr box = gtk.HBox(spacing=10) 2926f669cee054a0bca677a85e8443221354ff218b6lmr self.data_vbox.pack_start(box) 2936f669cee054a0bca677a85e8443221354ff218b6lmr box.show() 2946f669cee054a0bca677a85e8443221354ff218b6lmr 2956f669cee054a0bca677a85e8443221354ff218b6lmr label = gtk.Label("Mouse action:") 2966f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(label, False) 2976f669cee054a0bca677a85e8443221354ff218b6lmr label.show() 2986f669cee054a0bca677a85e8443221354ff218b6lmr 2996f669cee054a0bca677a85e8443221354ff218b6lmr self.button_capture = gtk.Button("Capture") 3006f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.button_capture, False) 3016f669cee054a0bca677a85e8443221354ff218b6lmr self.button_capture.show() 3026f669cee054a0bca677a85e8443221354ff218b6lmr 3036f669cee054a0bca677a85e8443221354ff218b6lmr self.check_mousemove = gtk.CheckButton("Move: ...") 3046f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.check_mousemove, False) 3056f669cee054a0bca677a85e8443221354ff218b6lmr self.check_mousemove.show() 3066f669cee054a0bca677a85e8443221354ff218b6lmr 3076f669cee054a0bca677a85e8443221354ff218b6lmr self.check_mouseclick = gtk.CheckButton("Click: ...") 3086f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_start(self.check_mouseclick, False) 3096f669cee054a0bca677a85e8443221354ff218b6lmr self.check_mouseclick.show() 3106f669cee054a0bca677a85e8443221354ff218b6lmr 3116f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_sensitivity = gtk.SpinButton(gtk.Adjustment(1, 1, 100, 1, 10, 3126f669cee054a0bca677a85e8443221354ff218b6lmr 0), 3136f669cee054a0bca677a85e8443221354ff218b6lmr climb_rate=0.0) 3146f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_end(self.spin_sensitivity, False) 3156f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_sensitivity.show() 3166f669cee054a0bca677a85e8443221354ff218b6lmr 3176f669cee054a0bca677a85e8443221354ff218b6lmr label = gtk.Label("Sensitivity:") 3186f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_end(label, False) 3196f669cee054a0bca677a85e8443221354ff218b6lmr label.show() 3206f669cee054a0bca677a85e8443221354ff218b6lmr 3216f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_latency = gtk.SpinButton(gtk.Adjustment(10, 1, 500, 1, 10, 0), 3226f669cee054a0bca677a85e8443221354ff218b6lmr climb_rate=0.0) 3236f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_end(self.spin_latency, False) 3246f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_latency.show() 3256f669cee054a0bca677a85e8443221354ff218b6lmr 3266f669cee054a0bca677a85e8443221354ff218b6lmr label = gtk.Label("Latency:") 3276f669cee054a0bca677a85e8443221354ff218b6lmr box.pack_end(label, False) 3286f669cee054a0bca677a85e8443221354ff218b6lmr label.show() 3296f669cee054a0bca677a85e8443221354ff218b6lmr 3306f669cee054a0bca677a85e8443221354ff218b6lmr self.handler_event_box_press = None 3316f669cee054a0bca677a85e8443221354ff218b6lmr self.handler_event_box_release = None 3326f669cee054a0bca677a85e8443221354ff218b6lmr self.handler_event_box_scroll = None 3336f669cee054a0bca677a85e8443221354ff218b6lmr self.handler_event_box_motion = None 3346f669cee054a0bca677a85e8443221354ff218b6lmr self.handler_event_box_expose = None 3356f669cee054a0bca677a85e8443221354ff218b6lmr 3366f669cee054a0bca677a85e8443221354ff218b6lmr self.window.realize() 3376f669cee054a0bca677a85e8443221354ff218b6lmr self.window.show() 3386f669cee054a0bca677a85e8443221354ff218b6lmr 3396f669cee054a0bca677a85e8443221354ff218b6lmr self.clear_state() 3406f669cee054a0bca677a85e8443221354ff218b6lmr 3416f669cee054a0bca677a85e8443221354ff218b6lmr # Utilities 3426f669cee054a0bca677a85e8443221354ff218b6lmr 3436f669cee054a0bca677a85e8443221354ff218b6lmr def message(self, text, title): 3446f669cee054a0bca677a85e8443221354ff218b6lmr dlg = gtk.MessageDialog(self.window, 3456f669cee054a0bca677a85e8443221354ff218b6lmr gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, 3466f669cee054a0bca677a85e8443221354ff218b6lmr gtk.MESSAGE_INFO, 3476f669cee054a0bca677a85e8443221354ff218b6lmr gtk.BUTTONS_CLOSE, 3486f669cee054a0bca677a85e8443221354ff218b6lmr title) 3496f669cee054a0bca677a85e8443221354ff218b6lmr dlg.set_title(title) 3506f669cee054a0bca677a85e8443221354ff218b6lmr dlg.format_secondary_text(text) 3516f669cee054a0bca677a85e8443221354ff218b6lmr response = dlg.run() 3526f669cee054a0bca677a85e8443221354ff218b6lmr dlg.destroy() 3536f669cee054a0bca677a85e8443221354ff218b6lmr 3546f669cee054a0bca677a85e8443221354ff218b6lmr 3556f669cee054a0bca677a85e8443221354ff218b6lmr def question_yes_no(self, text, title): 3566f669cee054a0bca677a85e8443221354ff218b6lmr dlg = gtk.MessageDialog(self.window, 3576f669cee054a0bca677a85e8443221354ff218b6lmr gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, 3586f669cee054a0bca677a85e8443221354ff218b6lmr gtk.MESSAGE_QUESTION, 3596f669cee054a0bca677a85e8443221354ff218b6lmr gtk.BUTTONS_YES_NO, 3606f669cee054a0bca677a85e8443221354ff218b6lmr title) 3616f669cee054a0bca677a85e8443221354ff218b6lmr dlg.set_title(title) 3626f669cee054a0bca677a85e8443221354ff218b6lmr dlg.format_secondary_text(text) 3636f669cee054a0bca677a85e8443221354ff218b6lmr response = dlg.run() 3646f669cee054a0bca677a85e8443221354ff218b6lmr dlg.destroy() 3656f669cee054a0bca677a85e8443221354ff218b6lmr if response == gtk.RESPONSE_YES: 3666f669cee054a0bca677a85e8443221354ff218b6lmr return True 3676f669cee054a0bca677a85e8443221354ff218b6lmr return False 3686f669cee054a0bca677a85e8443221354ff218b6lmr 3696f669cee054a0bca677a85e8443221354ff218b6lmr 3706f669cee054a0bca677a85e8443221354ff218b6lmr def inputdialog(self, text, title, default_response=""): 3716f669cee054a0bca677a85e8443221354ff218b6lmr # Define a little helper function 3726f669cee054a0bca677a85e8443221354ff218b6lmr def inputdialog_entry_activated(entry): 3736f669cee054a0bca677a85e8443221354ff218b6lmr dlg.response(gtk.RESPONSE_OK) 3746f669cee054a0bca677a85e8443221354ff218b6lmr 3756f669cee054a0bca677a85e8443221354ff218b6lmr # Create the dialog 3766f669cee054a0bca677a85e8443221354ff218b6lmr dlg = gtk.MessageDialog(self.window, 3776f669cee054a0bca677a85e8443221354ff218b6lmr gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, 3786f669cee054a0bca677a85e8443221354ff218b6lmr gtk.MESSAGE_QUESTION, 3796f669cee054a0bca677a85e8443221354ff218b6lmr gtk.BUTTONS_OK_CANCEL, 3806f669cee054a0bca677a85e8443221354ff218b6lmr title) 3816f669cee054a0bca677a85e8443221354ff218b6lmr dlg.set_title(title) 3826f669cee054a0bca677a85e8443221354ff218b6lmr dlg.format_secondary_text(text) 3836f669cee054a0bca677a85e8443221354ff218b6lmr 3846f669cee054a0bca677a85e8443221354ff218b6lmr # Create an entry widget 3856f669cee054a0bca677a85e8443221354ff218b6lmr entry = gtk.Entry() 3866f669cee054a0bca677a85e8443221354ff218b6lmr entry.set_text(default_response) 3876f669cee054a0bca677a85e8443221354ff218b6lmr entry.connect("activate", inputdialog_entry_activated) 3886f669cee054a0bca677a85e8443221354ff218b6lmr dlg.vbox.pack_start(entry) 3896f669cee054a0bca677a85e8443221354ff218b6lmr entry.show() 3906f669cee054a0bca677a85e8443221354ff218b6lmr 3916f669cee054a0bca677a85e8443221354ff218b6lmr # Run the dialog 3926f669cee054a0bca677a85e8443221354ff218b6lmr response = dlg.run() 3936f669cee054a0bca677a85e8443221354ff218b6lmr dlg.destroy() 3946f669cee054a0bca677a85e8443221354ff218b6lmr if response == gtk.RESPONSE_OK: 3956f669cee054a0bca677a85e8443221354ff218b6lmr return entry.get_text() 3966f669cee054a0bca677a85e8443221354ff218b6lmr return None 3976f669cee054a0bca677a85e8443221354ff218b6lmr 3986f669cee054a0bca677a85e8443221354ff218b6lmr 3996f669cee054a0bca677a85e8443221354ff218b6lmr def filedialog(self, title=None, default_filename=None): 4006f669cee054a0bca677a85e8443221354ff218b6lmr chooser = gtk.FileChooserDialog(title=title, parent=self.window, 4016f669cee054a0bca677a85e8443221354ff218b6lmr action=gtk.FILE_CHOOSER_ACTION_OPEN, 4026f669cee054a0bca677a85e8443221354ff218b6lmr buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, 4036f669cee054a0bca677a85e8443221354ff218b6lmr gtk.RESPONSE_OK)) 4046f669cee054a0bca677a85e8443221354ff218b6lmr chooser.resize(700, 500) 4056f669cee054a0bca677a85e8443221354ff218b6lmr if default_filename: 4066f669cee054a0bca677a85e8443221354ff218b6lmr chooser.set_filename(os.path.abspath(default_filename)) 4076f669cee054a0bca677a85e8443221354ff218b6lmr filename = None 4086f669cee054a0bca677a85e8443221354ff218b6lmr response = chooser.run() 4096f669cee054a0bca677a85e8443221354ff218b6lmr if response == gtk.RESPONSE_OK: 4106f669cee054a0bca677a85e8443221354ff218b6lmr filename = chooser.get_filename() 4116f669cee054a0bca677a85e8443221354ff218b6lmr chooser.destroy() 4126f669cee054a0bca677a85e8443221354ff218b6lmr return filename 4136f669cee054a0bca677a85e8443221354ff218b6lmr 4146f669cee054a0bca677a85e8443221354ff218b6lmr 4156f669cee054a0bca677a85e8443221354ff218b6lmr def redirect_event_box_input(self, press=None, release=None, scroll=None, 4166f669cee054a0bca677a85e8443221354ff218b6lmr motion=None, expose=None): 4176f669cee054a0bca677a85e8443221354ff218b6lmr if self.handler_event_box_press != None: \ 4186f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.disconnect(self.handler_event_box_press) 4196f669cee054a0bca677a85e8443221354ff218b6lmr if self.handler_event_box_release != None: \ 4206f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.disconnect(self.handler_event_box_release) 4216f669cee054a0bca677a85e8443221354ff218b6lmr if self.handler_event_box_scroll != None: \ 4226f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.disconnect(self.handler_event_box_scroll) 4236f669cee054a0bca677a85e8443221354ff218b6lmr if self.handler_event_box_motion != None: \ 4246f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.disconnect(self.handler_event_box_motion) 4256f669cee054a0bca677a85e8443221354ff218b6lmr if self.handler_event_box_expose != None: \ 4266f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.disconnect(self.handler_event_box_expose) 4276f669cee054a0bca677a85e8443221354ff218b6lmr self.handler_event_box_press = None 4286f669cee054a0bca677a85e8443221354ff218b6lmr self.handler_event_box_release = None 4296f669cee054a0bca677a85e8443221354ff218b6lmr self.handler_event_box_scroll = None 4306f669cee054a0bca677a85e8443221354ff218b6lmr self.handler_event_box_motion = None 4316f669cee054a0bca677a85e8443221354ff218b6lmr self.handler_event_box_expose = None 4326f669cee054a0bca677a85e8443221354ff218b6lmr if press != None: self.handler_event_box_press = \ 4336f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.connect("button-press-event", press) 4346f669cee054a0bca677a85e8443221354ff218b6lmr if release != None: self.handler_event_box_release = \ 4356f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.connect("button-release-event", release) 4366f669cee054a0bca677a85e8443221354ff218b6lmr if scroll != None: self.handler_event_box_scroll = \ 4376f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.connect("scroll-event", scroll) 4386f669cee054a0bca677a85e8443221354ff218b6lmr if motion != None: self.handler_event_box_motion = \ 4396f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.connect("motion-notify-event", motion) 4406f669cee054a0bca677a85e8443221354ff218b6lmr if expose != None: self.handler_event_box_expose = \ 4416f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.connect_after("expose-event", expose) 4426f669cee054a0bca677a85e8443221354ff218b6lmr 4436f669cee054a0bca677a85e8443221354ff218b6lmr 4446f669cee054a0bca677a85e8443221354ff218b6lmr def get_keys(self): 4456f669cee054a0bca677a85e8443221354ff218b6lmr return self.text_buffer.get_text( 4466f669cee054a0bca677a85e8443221354ff218b6lmr self.text_buffer.get_start_iter(), 4476f669cee054a0bca677a85e8443221354ff218b6lmr self.text_buffer.get_end_iter()) 4486f669cee054a0bca677a85e8443221354ff218b6lmr 4496f669cee054a0bca677a85e8443221354ff218b6lmr 4506f669cee054a0bca677a85e8443221354ff218b6lmr def add_key(self, key): 4516f669cee054a0bca677a85e8443221354ff218b6lmr text = self.get_keys() 4526f669cee054a0bca677a85e8443221354ff218b6lmr if len(text) > 0 and text[-1] != ' ': 4536f669cee054a0bca677a85e8443221354ff218b6lmr text += " " 4546f669cee054a0bca677a85e8443221354ff218b6lmr text += key 4556f669cee054a0bca677a85e8443221354ff218b6lmr self.text_buffer.set_text(text) 4566f669cee054a0bca677a85e8443221354ff218b6lmr 4576f669cee054a0bca677a85e8443221354ff218b6lmr 4586f669cee054a0bca677a85e8443221354ff218b6lmr def clear_keys(self): 4596f669cee054a0bca677a85e8443221354ff218b6lmr self.text_buffer.set_text("") 4606f669cee054a0bca677a85e8443221354ff218b6lmr 4616f669cee054a0bca677a85e8443221354ff218b6lmr 4626f669cee054a0bca677a85e8443221354ff218b6lmr def update_barrier_info(self): 4636f669cee054a0bca677a85e8443221354ff218b6lmr if self.barrier_selected: 4646f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_region.set_text("Selected region: Corner: " + \ 4656f669cee054a0bca677a85e8443221354ff218b6lmr str(tuple(self.barrier_corner)) + \ 4666f669cee054a0bca677a85e8443221354ff218b6lmr " Size: " + \ 4676f669cee054a0bca677a85e8443221354ff218b6lmr str(tuple(self.barrier_size))) 4686f669cee054a0bca677a85e8443221354ff218b6lmr else: 4696f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_region.set_text("No region selected.") 4706f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_md5sum.set_text("MD5: " + self.barrier_md5sum) 4716f669cee054a0bca677a85e8443221354ff218b6lmr 4726f669cee054a0bca677a85e8443221354ff218b6lmr 4736f669cee054a0bca677a85e8443221354ff218b6lmr def update_mouse_click_info(self): 4746f669cee054a0bca677a85e8443221354ff218b6lmr if self.mouse_click_captured: 4756f669cee054a0bca677a85e8443221354ff218b6lmr self.check_mousemove.set_label("Move: " + \ 4766f669cee054a0bca677a85e8443221354ff218b6lmr str(tuple(self.mouse_click_coords))) 4776f669cee054a0bca677a85e8443221354ff218b6lmr self.check_mouseclick.set_label("Click: button %d" % 4786f669cee054a0bca677a85e8443221354ff218b6lmr self.mouse_click_button) 4796f669cee054a0bca677a85e8443221354ff218b6lmr else: 4806f669cee054a0bca677a85e8443221354ff218b6lmr self.check_mousemove.set_label("Move: ...") 4816f669cee054a0bca677a85e8443221354ff218b6lmr self.check_mouseclick.set_label("Click: ...") 4826f669cee054a0bca677a85e8443221354ff218b6lmr 4836f669cee054a0bca677a85e8443221354ff218b6lmr 4846f669cee054a0bca677a85e8443221354ff218b6lmr def clear_state(self, clear_screendump=True): 4856f669cee054a0bca677a85e8443221354ff218b6lmr # Recording time 4866f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_time.set_text("unknown") 4876f669cee054a0bca677a85e8443221354ff218b6lmr if clear_screendump: 4886f669cee054a0bca677a85e8443221354ff218b6lmr # Screendump 4896f669cee054a0bca677a85e8443221354ff218b6lmr self.clear_image() 4906f669cee054a0bca677a85e8443221354ff218b6lmr # Screendump ID 4916f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_screendump.set_text("") 4926f669cee054a0bca677a85e8443221354ff218b6lmr # Comment 4936f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_comment.set_text("") 4946f669cee054a0bca677a85e8443221354ff218b6lmr # Sleep 4956f669cee054a0bca677a85e8443221354ff218b6lmr self.check_sleep.set_active(True) 4966f669cee054a0bca677a85e8443221354ff218b6lmr self.check_sleep.set_active(False) 4976f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_sleep.set_value(10) 4986f669cee054a0bca677a85e8443221354ff218b6lmr # Barrier 4996f669cee054a0bca677a85e8443221354ff218b6lmr self.clear_barrier_state() 5006f669cee054a0bca677a85e8443221354ff218b6lmr # Keystrokes 5016f669cee054a0bca677a85e8443221354ff218b6lmr self.check_manual.set_active(False) 5026f669cee054a0bca677a85e8443221354ff218b6lmr self.clear_keys() 5036f669cee054a0bca677a85e8443221354ff218b6lmr # Mouse actions 5046f669cee054a0bca677a85e8443221354ff218b6lmr self.check_mousemove.set_sensitive(False) 5056f669cee054a0bca677a85e8443221354ff218b6lmr self.check_mouseclick.set_sensitive(False) 5066f669cee054a0bca677a85e8443221354ff218b6lmr self.check_mousemove.set_active(False) 5076f669cee054a0bca677a85e8443221354ff218b6lmr self.check_mouseclick.set_active(False) 5086f669cee054a0bca677a85e8443221354ff218b6lmr self.mouse_click_captured = False 5096f669cee054a0bca677a85e8443221354ff218b6lmr self.mouse_click_coords = [0, 0] 5106f669cee054a0bca677a85e8443221354ff218b6lmr self.mouse_click_button = 0 5116f669cee054a0bca677a85e8443221354ff218b6lmr self.update_mouse_click_info() 5126f669cee054a0bca677a85e8443221354ff218b6lmr 5136f669cee054a0bca677a85e8443221354ff218b6lmr 5146f669cee054a0bca677a85e8443221354ff218b6lmr def clear_barrier_state(self): 5156f669cee054a0bca677a85e8443221354ff218b6lmr self.check_barrier.set_active(True) 5166f669cee054a0bca677a85e8443221354ff218b6lmr self.check_barrier.set_active(False) 5176f669cee054a0bca677a85e8443221354ff218b6lmr self.check_barrier_optional.set_active(False) 5186f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_barrier_timeout.set_value(10) 5196f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_selection_started = False 5206f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_selected = False 5216f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner0 = [0, 0] 5226f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner1 = [0, 0] 5236f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner = [0, 0] 5246f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_size = [0, 0] 5256f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_md5sum = "" 5266f669cee054a0bca677a85e8443221354ff218b6lmr self.update_barrier_info() 5276f669cee054a0bca677a85e8443221354ff218b6lmr 5286f669cee054a0bca677a85e8443221354ff218b6lmr 5296f669cee054a0bca677a85e8443221354ff218b6lmr def set_image(self, w, h, data): 5306f669cee054a0bca677a85e8443221354ff218b6lmr (self.image_width, self.image_height, self.image_data) = (w, h, data) 5316f669cee054a0bca677a85e8443221354ff218b6lmr self.image.set_from_pixbuf(gtk.gdk.pixbuf_new_from_data( 5326f669cee054a0bca677a85e8443221354ff218b6lmr data, gtk.gdk.COLORSPACE_RGB, False, 8, 5336f669cee054a0bca677a85e8443221354ff218b6lmr w, h, w*3)) 5346f669cee054a0bca677a85e8443221354ff218b6lmr hscrollbar = self.scrolledwindow.get_hscrollbar() 5356f669cee054a0bca677a85e8443221354ff218b6lmr hscrollbar.set_range(0, w) 5366f669cee054a0bca677a85e8443221354ff218b6lmr vscrollbar = self.scrolledwindow.get_vscrollbar() 5376f669cee054a0bca677a85e8443221354ff218b6lmr vscrollbar.set_range(0, h) 5386f669cee054a0bca677a85e8443221354ff218b6lmr 5396f669cee054a0bca677a85e8443221354ff218b6lmr 5406f669cee054a0bca677a85e8443221354ff218b6lmr def set_image_from_file(self, filename): 5416f669cee054a0bca677a85e8443221354ff218b6lmr if not ppm_utils.image_verify_ppm_file(filename): 5426f669cee054a0bca677a85e8443221354ff218b6lmr logging.warning("set_image_from_file: Warning: received invalid" 5436f669cee054a0bca677a85e8443221354ff218b6lmr "screendump file") 5446f669cee054a0bca677a85e8443221354ff218b6lmr return self.clear_image() 5456f669cee054a0bca677a85e8443221354ff218b6lmr (w, h, data) = ppm_utils.image_read_from_ppm_file(filename) 5466f669cee054a0bca677a85e8443221354ff218b6lmr self.set_image(w, h, data) 5476f669cee054a0bca677a85e8443221354ff218b6lmr 5486f669cee054a0bca677a85e8443221354ff218b6lmr 5496f669cee054a0bca677a85e8443221354ff218b6lmr def clear_image(self): 5506f669cee054a0bca677a85e8443221354ff218b6lmr self.image.clear() 5516f669cee054a0bca677a85e8443221354ff218b6lmr self.image_width = 0 5526f669cee054a0bca677a85e8443221354ff218b6lmr self.image_height = 0 5536f669cee054a0bca677a85e8443221354ff218b6lmr self.image_data = "" 5546f669cee054a0bca677a85e8443221354ff218b6lmr 5556f669cee054a0bca677a85e8443221354ff218b6lmr 5566f669cee054a0bca677a85e8443221354ff218b6lmr def update_screendump_id(self, data_dir): 5576f669cee054a0bca677a85e8443221354ff218b6lmr if not self.image_data: 5586f669cee054a0bca677a85e8443221354ff218b6lmr return 5596f669cee054a0bca677a85e8443221354ff218b6lmr # Find a proper ID for the screendump 5606f669cee054a0bca677a85e8443221354ff218b6lmr scrdump_md5sum = ppm_utils.image_md5sum(self.image_width, 5616f669cee054a0bca677a85e8443221354ff218b6lmr self.image_height, 5626f669cee054a0bca677a85e8443221354ff218b6lmr self.image_data) 5636f669cee054a0bca677a85e8443221354ff218b6lmr scrdump_id = ppm_utils.find_id_for_screendump(scrdump_md5sum, data_dir) 5646f669cee054a0bca677a85e8443221354ff218b6lmr if not scrdump_id: 5656f669cee054a0bca677a85e8443221354ff218b6lmr # Not found; generate one 5666f669cee054a0bca677a85e8443221354ff218b6lmr scrdump_id = ppm_utils.generate_id_for_screendump(scrdump_md5sum, 5676f669cee054a0bca677a85e8443221354ff218b6lmr data_dir) 5686f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_screendump.set_text(scrdump_id) 5696f669cee054a0bca677a85e8443221354ff218b6lmr 5706f669cee054a0bca677a85e8443221354ff218b6lmr 5716f669cee054a0bca677a85e8443221354ff218b6lmr def get_step_lines(self, data_dir=None): 5726f669cee054a0bca677a85e8443221354ff218b6lmr if self.check_barrier.get_active() and not self.barrier_selected: 5736f669cee054a0bca677a85e8443221354ff218b6lmr self.message("No barrier region selected.", "Error") 5746f669cee054a0bca677a85e8443221354ff218b6lmr return 5756f669cee054a0bca677a85e8443221354ff218b6lmr 5766f669cee054a0bca677a85e8443221354ff218b6lmr str = "step" 5776f669cee054a0bca677a85e8443221354ff218b6lmr 5786f669cee054a0bca677a85e8443221354ff218b6lmr # Add step recording time 5796f669cee054a0bca677a85e8443221354ff218b6lmr if self.entry_time.get_text(): 5806f669cee054a0bca677a85e8443221354ff218b6lmr str += " " + self.entry_time.get_text() 5816f669cee054a0bca677a85e8443221354ff218b6lmr 5826f669cee054a0bca677a85e8443221354ff218b6lmr str += "\n" 5836f669cee054a0bca677a85e8443221354ff218b6lmr 5846f669cee054a0bca677a85e8443221354ff218b6lmr # Add screendump line 5856f669cee054a0bca677a85e8443221354ff218b6lmr if self.image_data: 5866f669cee054a0bca677a85e8443221354ff218b6lmr str += "screendump %s\n" % self.entry_screendump.get_text() 5876f669cee054a0bca677a85e8443221354ff218b6lmr 5886f669cee054a0bca677a85e8443221354ff218b6lmr # Add comment 5896f669cee054a0bca677a85e8443221354ff218b6lmr if self.entry_comment.get_text(): 5906f669cee054a0bca677a85e8443221354ff218b6lmr str += "# %s\n" % self.entry_comment.get_text() 5916f669cee054a0bca677a85e8443221354ff218b6lmr 5926f669cee054a0bca677a85e8443221354ff218b6lmr # Add sleep line 5936f669cee054a0bca677a85e8443221354ff218b6lmr if self.check_sleep.get_active(): 5946f669cee054a0bca677a85e8443221354ff218b6lmr str += "sleep %d\n" % self.spin_sleep.get_value() 5956f669cee054a0bca677a85e8443221354ff218b6lmr 5966f669cee054a0bca677a85e8443221354ff218b6lmr # Add barrier_2 line 5976f669cee054a0bca677a85e8443221354ff218b6lmr if self.check_barrier.get_active(): 5986f669cee054a0bca677a85e8443221354ff218b6lmr str += "barrier_2 %d %d %d %d %s %d" % ( 5996f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_size[0], self.barrier_size[1], 6006f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner[0], self.barrier_corner[1], 6016f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_md5sum, self.spin_barrier_timeout.get_value()) 6026f669cee054a0bca677a85e8443221354ff218b6lmr if self.check_barrier_optional.get_active(): 6036f669cee054a0bca677a85e8443221354ff218b6lmr str += " optional" 6046f669cee054a0bca677a85e8443221354ff218b6lmr str += "\n" 6056f669cee054a0bca677a85e8443221354ff218b6lmr 6066f669cee054a0bca677a85e8443221354ff218b6lmr # Add "Sending keys" comment 6076f669cee054a0bca677a85e8443221354ff218b6lmr keys_to_send = self.get_keys().split() 6086f669cee054a0bca677a85e8443221354ff218b6lmr if keys_to_send: 6096f669cee054a0bca677a85e8443221354ff218b6lmr str += "# Sending keys: %s\n" % self.get_keys() 6106f669cee054a0bca677a85e8443221354ff218b6lmr 6116f669cee054a0bca677a85e8443221354ff218b6lmr # Add key and var lines 6126f669cee054a0bca677a85e8443221354ff218b6lmr for key in keys_to_send: 6136f669cee054a0bca677a85e8443221354ff218b6lmr if key.startswith("$"): 6146f669cee054a0bca677a85e8443221354ff218b6lmr varname = key[1:] 6156f669cee054a0bca677a85e8443221354ff218b6lmr str += "var %s\n" % varname 6166f669cee054a0bca677a85e8443221354ff218b6lmr else: 6176f669cee054a0bca677a85e8443221354ff218b6lmr str += "key %s\n" % key 6186f669cee054a0bca677a85e8443221354ff218b6lmr 6196f669cee054a0bca677a85e8443221354ff218b6lmr # Add mousemove line 6206f669cee054a0bca677a85e8443221354ff218b6lmr if self.check_mousemove.get_active(): 6216f669cee054a0bca677a85e8443221354ff218b6lmr str += "mousemove %d %d\n" % (self.mouse_click_coords[0], 6226f669cee054a0bca677a85e8443221354ff218b6lmr self.mouse_click_coords[1]) 6236f669cee054a0bca677a85e8443221354ff218b6lmr 6246f669cee054a0bca677a85e8443221354ff218b6lmr # Add mouseclick line 6256f669cee054a0bca677a85e8443221354ff218b6lmr if self.check_mouseclick.get_active(): 6266f669cee054a0bca677a85e8443221354ff218b6lmr dict = { 1 : 1, 6276f669cee054a0bca677a85e8443221354ff218b6lmr 2 : 2, 6286f669cee054a0bca677a85e8443221354ff218b6lmr 3 : 4 } 6296f669cee054a0bca677a85e8443221354ff218b6lmr str += "mouseclick %d\n" % dict[self.mouse_click_button] 6306f669cee054a0bca677a85e8443221354ff218b6lmr 6316f669cee054a0bca677a85e8443221354ff218b6lmr # Write screendump and cropped screendump image files 6326f669cee054a0bca677a85e8443221354ff218b6lmr if data_dir and self.image_data: 6336f669cee054a0bca677a85e8443221354ff218b6lmr # Create the data dir if it doesn't exist 6346f669cee054a0bca677a85e8443221354ff218b6lmr if not os.path.exists(data_dir): 6356f669cee054a0bca677a85e8443221354ff218b6lmr os.makedirs(data_dir) 6366f669cee054a0bca677a85e8443221354ff218b6lmr # Get the full screendump filename 6376f669cee054a0bca677a85e8443221354ff218b6lmr scrdump_filename = os.path.join(data_dir, 6386f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_screendump.get_text()) 6396f669cee054a0bca677a85e8443221354ff218b6lmr # Write screendump file if it doesn't exist 6406f669cee054a0bca677a85e8443221354ff218b6lmr if not os.path.exists(scrdump_filename): 6416f669cee054a0bca677a85e8443221354ff218b6lmr try: 6426f669cee054a0bca677a85e8443221354ff218b6lmr ppm_utils.image_write_to_ppm_file(scrdump_filename, 6436f669cee054a0bca677a85e8443221354ff218b6lmr self.image_width, 6446f669cee054a0bca677a85e8443221354ff218b6lmr self.image_height, 6456f669cee054a0bca677a85e8443221354ff218b6lmr self.image_data) 6466f669cee054a0bca677a85e8443221354ff218b6lmr except IOError: 6476f669cee054a0bca677a85e8443221354ff218b6lmr self.message("Could not write screendump file.", "Error") 6486f669cee054a0bca677a85e8443221354ff218b6lmr 6496f669cee054a0bca677a85e8443221354ff218b6lmr #if self.check_barrier.get_active(): 6506f669cee054a0bca677a85e8443221354ff218b6lmr # # Crop image to get the cropped screendump 6516f669cee054a0bca677a85e8443221354ff218b6lmr # (cw, ch, cdata) = ppm_utils.image_crop( 6526f669cee054a0bca677a85e8443221354ff218b6lmr # self.image_width, self.image_height, self.image_data, 6536f669cee054a0bca677a85e8443221354ff218b6lmr # self.barrier_corner[0], self.barrier_corner[1], 6546f669cee054a0bca677a85e8443221354ff218b6lmr # self.barrier_size[0], self.barrier_size[1]) 6556f669cee054a0bca677a85e8443221354ff218b6lmr # cropped_scrdump_md5sum = ppm_utils.image_md5sum(cw, ch, cdata) 6566f669cee054a0bca677a85e8443221354ff218b6lmr # cropped_scrdump_filename = \ 6576f669cee054a0bca677a85e8443221354ff218b6lmr # ppm_utils.get_cropped_screendump_filename(scrdump_filename, 6586f669cee054a0bca677a85e8443221354ff218b6lmr # cropped_scrdump_md5sum) 6596f669cee054a0bca677a85e8443221354ff218b6lmr # # Write cropped screendump file 6606f669cee054a0bca677a85e8443221354ff218b6lmr # try: 6616f669cee054a0bca677a85e8443221354ff218b6lmr # ppm_utils.image_write_to_ppm_file(cropped_scrdump_filename, 6626f669cee054a0bca677a85e8443221354ff218b6lmr # cw, ch, cdata) 6636f669cee054a0bca677a85e8443221354ff218b6lmr # except IOError: 6646f669cee054a0bca677a85e8443221354ff218b6lmr # self.message("Could not write cropped screendump file.", 6656f669cee054a0bca677a85e8443221354ff218b6lmr # "Error") 6666f669cee054a0bca677a85e8443221354ff218b6lmr 6676f669cee054a0bca677a85e8443221354ff218b6lmr return str 6686f669cee054a0bca677a85e8443221354ff218b6lmr 6696f669cee054a0bca677a85e8443221354ff218b6lmr def set_state_from_step_lines(self, str, data_dir, warn=True): 6706f669cee054a0bca677a85e8443221354ff218b6lmr self.clear_state() 6716f669cee054a0bca677a85e8443221354ff218b6lmr 6726f669cee054a0bca677a85e8443221354ff218b6lmr for line in str.splitlines(): 6736f669cee054a0bca677a85e8443221354ff218b6lmr words = line.split() 6746f669cee054a0bca677a85e8443221354ff218b6lmr if not words: 6756f669cee054a0bca677a85e8443221354ff218b6lmr continue 6766f669cee054a0bca677a85e8443221354ff218b6lmr 6776f669cee054a0bca677a85e8443221354ff218b6lmr if line.startswith("#") \ 6786f669cee054a0bca677a85e8443221354ff218b6lmr and not self.entry_comment.get_text() \ 6796f669cee054a0bca677a85e8443221354ff218b6lmr and not line.startswith("# Sending keys:") \ 6806f669cee054a0bca677a85e8443221354ff218b6lmr and not line.startswith("# ----"): 6816f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_comment.set_text(line.strip("#").strip()) 6826f669cee054a0bca677a85e8443221354ff218b6lmr 6836f669cee054a0bca677a85e8443221354ff218b6lmr elif words[0] == "step": 6846f669cee054a0bca677a85e8443221354ff218b6lmr if len(words) >= 2: 6856f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_time.set_text(words[1]) 6866f669cee054a0bca677a85e8443221354ff218b6lmr 6876f669cee054a0bca677a85e8443221354ff218b6lmr elif words[0] == "screendump": 6886f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_screendump.set_text(words[1]) 6896f669cee054a0bca677a85e8443221354ff218b6lmr self.set_image_from_file(os.path.join(data_dir, words[1])) 6906f669cee054a0bca677a85e8443221354ff218b6lmr 6916f669cee054a0bca677a85e8443221354ff218b6lmr elif words[0] == "sleep": 6926f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_sleep.set_value(int(words[1])) 6936f669cee054a0bca677a85e8443221354ff218b6lmr self.check_sleep.set_active(True) 6946f669cee054a0bca677a85e8443221354ff218b6lmr 6956f669cee054a0bca677a85e8443221354ff218b6lmr elif words[0] == "key": 6966f669cee054a0bca677a85e8443221354ff218b6lmr self.add_key(words[1]) 6976f669cee054a0bca677a85e8443221354ff218b6lmr 6986f669cee054a0bca677a85e8443221354ff218b6lmr elif words[0] == "var": 6996f669cee054a0bca677a85e8443221354ff218b6lmr self.add_key("$%s" % words[1]) 7006f669cee054a0bca677a85e8443221354ff218b6lmr 7016f669cee054a0bca677a85e8443221354ff218b6lmr elif words[0] == "mousemove": 7026f669cee054a0bca677a85e8443221354ff218b6lmr self.mouse_click_captured = True 7036f669cee054a0bca677a85e8443221354ff218b6lmr self.mouse_click_coords = [int(words[1]), int(words[2])] 7046f669cee054a0bca677a85e8443221354ff218b6lmr self.update_mouse_click_info() 7056f669cee054a0bca677a85e8443221354ff218b6lmr 7066f669cee054a0bca677a85e8443221354ff218b6lmr elif words[0] == "mouseclick": 7076f669cee054a0bca677a85e8443221354ff218b6lmr self.mouse_click_captured = True 7086f669cee054a0bca677a85e8443221354ff218b6lmr self.mouse_click_button = int(words[1]) 7096f669cee054a0bca677a85e8443221354ff218b6lmr self.update_mouse_click_info() 7106f669cee054a0bca677a85e8443221354ff218b6lmr 7116f669cee054a0bca677a85e8443221354ff218b6lmr elif words[0] == "barrier_2": 7126f669cee054a0bca677a85e8443221354ff218b6lmr # Get region corner and size from step lines 7136f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner = [int(words[3]), int(words[4])] 7146f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_size = [int(words[1]), int(words[2])] 7156f669cee054a0bca677a85e8443221354ff218b6lmr # Get corner0 and corner1 from step lines 7166f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner0 = self.barrier_corner 7176f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner1 = [self.barrier_corner[0] + 7186f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_size[0] - 1, 7196f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner[1] + 7206f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_size[1] - 1] 7216f669cee054a0bca677a85e8443221354ff218b6lmr # Get the md5sum 7226f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_md5sum = words[5] 7236f669cee054a0bca677a85e8443221354ff218b6lmr # Pretend the user selected the region with the mouse 7246f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_selection_started = True 7256f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_selected = True 7266f669cee054a0bca677a85e8443221354ff218b6lmr # Update label widgets according to region information 7276f669cee054a0bca677a85e8443221354ff218b6lmr self.update_barrier_info() 7286f669cee054a0bca677a85e8443221354ff218b6lmr # Check the barrier checkbutton 7296f669cee054a0bca677a85e8443221354ff218b6lmr self.check_barrier.set_active(True) 7306f669cee054a0bca677a85e8443221354ff218b6lmr # Set timeout value 7316f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_barrier_timeout.set_value(int(words[6])) 7326f669cee054a0bca677a85e8443221354ff218b6lmr # Set 'optional' checkbutton state 7336f669cee054a0bca677a85e8443221354ff218b6lmr self.check_barrier_optional.set_active(words[-1] == "optional") 7346f669cee054a0bca677a85e8443221354ff218b6lmr # Update the image widget 7356f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.queue_draw() 7366f669cee054a0bca677a85e8443221354ff218b6lmr 7376f669cee054a0bca677a85e8443221354ff218b6lmr if warn: 7386f669cee054a0bca677a85e8443221354ff218b6lmr # See if the computed md5sum matches the one recorded in 7396f669cee054a0bca677a85e8443221354ff218b6lmr # the file 7406f669cee054a0bca677a85e8443221354ff218b6lmr computed_md5sum = ppm_utils.get_region_md5sum( 7416f669cee054a0bca677a85e8443221354ff218b6lmr self.image_width, self.image_height, 7426f669cee054a0bca677a85e8443221354ff218b6lmr self.image_data, self.barrier_corner[0], 7436f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner[1], self.barrier_size[0], 7446f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_size[1]) 7456f669cee054a0bca677a85e8443221354ff218b6lmr if computed_md5sum != self.barrier_md5sum: 7466f669cee054a0bca677a85e8443221354ff218b6lmr self.message("Computed MD5 sum (%s) differs from MD5" 7476f669cee054a0bca677a85e8443221354ff218b6lmr " sum recorded in steps file (%s)" % 7486f669cee054a0bca677a85e8443221354ff218b6lmr (computed_md5sum, self.barrier_md5sum), 7496f669cee054a0bca677a85e8443221354ff218b6lmr "Warning") 7506f669cee054a0bca677a85e8443221354ff218b6lmr 7516f669cee054a0bca677a85e8443221354ff218b6lmr # Events 7526f669cee054a0bca677a85e8443221354ff218b6lmr 7536f669cee054a0bca677a85e8443221354ff218b6lmr def delete_event(self, widget, event): 7546f669cee054a0bca677a85e8443221354ff218b6lmr pass 7556f669cee054a0bca677a85e8443221354ff218b6lmr 7566f669cee054a0bca677a85e8443221354ff218b6lmr def destroy(self, widget): 7576f669cee054a0bca677a85e8443221354ff218b6lmr gtk.main_quit() 7586f669cee054a0bca677a85e8443221354ff218b6lmr 7596f669cee054a0bca677a85e8443221354ff218b6lmr def event_check_barrier_toggled(self, widget): 7606f669cee054a0bca677a85e8443221354ff218b6lmr if self.check_barrier.get_active(): 7616f669cee054a0bca677a85e8443221354ff218b6lmr self.redirect_event_box_input( 7626f669cee054a0bca677a85e8443221354ff218b6lmr self.event_button_press, 7636f669cee054a0bca677a85e8443221354ff218b6lmr self.event_button_release, 7646f669cee054a0bca677a85e8443221354ff218b6lmr None, 7656f669cee054a0bca677a85e8443221354ff218b6lmr None, 7666f669cee054a0bca677a85e8443221354ff218b6lmr self.event_expose) 7676f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.queue_draw() 7686f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.CROSSHAIR)) 7696f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_region.set_sensitive(True) 7706f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_md5sum.set_sensitive(True) 7716f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_timeout.set_sensitive(True) 7726f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_barrier_timeout.set_sensitive(True) 7736f669cee054a0bca677a85e8443221354ff218b6lmr self.check_barrier_optional.set_sensitive(True) 7746f669cee054a0bca677a85e8443221354ff218b6lmr else: 7756f669cee054a0bca677a85e8443221354ff218b6lmr self.redirect_event_box_input() 7766f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.queue_draw() 7776f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.window.set_cursor(None) 7786f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_region.set_sensitive(False) 7796f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_md5sum.set_sensitive(False) 7806f669cee054a0bca677a85e8443221354ff218b6lmr self.label_barrier_timeout.set_sensitive(False) 7816f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_barrier_timeout.set_sensitive(False) 7826f669cee054a0bca677a85e8443221354ff218b6lmr self.check_barrier_optional.set_sensitive(False) 7836f669cee054a0bca677a85e8443221354ff218b6lmr 7846f669cee054a0bca677a85e8443221354ff218b6lmr def event_check_sleep_toggled(self, widget): 7856f669cee054a0bca677a85e8443221354ff218b6lmr if self.check_sleep.get_active(): 7866f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_sleep.set_sensitive(True) 7876f669cee054a0bca677a85e8443221354ff218b6lmr else: 7886f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_sleep.set_sensitive(False) 7896f669cee054a0bca677a85e8443221354ff218b6lmr 7906f669cee054a0bca677a85e8443221354ff218b6lmr def event_manual_toggled(self, widget): 7916f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_keys.grab_focus() 7926f669cee054a0bca677a85e8443221354ff218b6lmr 7936f669cee054a0bca677a85e8443221354ff218b6lmr def event_clear_clicked(self, widget): 7946f669cee054a0bca677a85e8443221354ff218b6lmr self.clear_keys() 7956f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_keys.grab_focus() 7966f669cee054a0bca677a85e8443221354ff218b6lmr 7976f669cee054a0bca677a85e8443221354ff218b6lmr def event_expose(self, widget, event): 7986f669cee054a0bca677a85e8443221354ff218b6lmr if not self.barrier_selection_started: 7996f669cee054a0bca677a85e8443221354ff218b6lmr return 8006f669cee054a0bca677a85e8443221354ff218b6lmr (corner, size) = corner_and_size_clipped(self.barrier_corner0, 8016f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner1, 8026f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.size_request()) 8036f669cee054a0bca677a85e8443221354ff218b6lmr gc = self.event_box.window.new_gc(line_style=gtk.gdk.LINE_DOUBLE_DASH, 8046f669cee054a0bca677a85e8443221354ff218b6lmr line_width=1) 8056f669cee054a0bca677a85e8443221354ff218b6lmr gc.set_foreground(gc.get_colormap().alloc_color("red")) 8066f669cee054a0bca677a85e8443221354ff218b6lmr gc.set_background(gc.get_colormap().alloc_color("dark red")) 8076f669cee054a0bca677a85e8443221354ff218b6lmr gc.set_dashes(0, (4, 4)) 8086f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.window.draw_rectangle( 8096f669cee054a0bca677a85e8443221354ff218b6lmr gc, False, 8106f669cee054a0bca677a85e8443221354ff218b6lmr corner[0], corner[1], 8116f669cee054a0bca677a85e8443221354ff218b6lmr size[0]-1, size[1]-1) 8126f669cee054a0bca677a85e8443221354ff218b6lmr 8136f669cee054a0bca677a85e8443221354ff218b6lmr def event_drag_motion(self, widget, event): 8146f669cee054a0bca677a85e8443221354ff218b6lmr old_corner1 = self.barrier_corner1 8156f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner1 = [int(event.x), int(event.y)] 8166f669cee054a0bca677a85e8443221354ff218b6lmr (corner, size) = corner_and_size_clipped(self.barrier_corner0, 8176f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner1, 8186f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.size_request()) 8196f669cee054a0bca677a85e8443221354ff218b6lmr (old_corner, old_size) = corner_and_size_clipped(self.barrier_corner0, 8206f669cee054a0bca677a85e8443221354ff218b6lmr old_corner1, 8216f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.size_request()) 8226f669cee054a0bca677a85e8443221354ff218b6lmr corner0 = [min(corner[0], old_corner[0]), min(corner[1], old_corner[1])] 8236f669cee054a0bca677a85e8443221354ff218b6lmr corner1 = [max(corner[0] + size[0], old_corner[0] + old_size[0]), 8246f669cee054a0bca677a85e8443221354ff218b6lmr max(corner[1] + size[1], old_corner[1] + old_size[1])] 8256f669cee054a0bca677a85e8443221354ff218b6lmr size = [corner1[0] - corner0[0] + 1, 8266f669cee054a0bca677a85e8443221354ff218b6lmr corner1[1] - corner0[1] + 1] 8276f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.queue_draw_area(corner0[0], corner0[1], size[0], size[1]) 8286f669cee054a0bca677a85e8443221354ff218b6lmr 8296f669cee054a0bca677a85e8443221354ff218b6lmr def event_button_press(self, widget, event): 8306f669cee054a0bca677a85e8443221354ff218b6lmr (corner, size) = corner_and_size_clipped(self.barrier_corner0, 8316f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner1, 8326f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.size_request()) 8336f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.queue_draw_area(corner[0], corner[1], size[0], size[1]) 8346f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner0 = [int(event.x), int(event.y)] 8356f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner1 = [int(event.x), int(event.y)] 8366f669cee054a0bca677a85e8443221354ff218b6lmr self.redirect_event_box_input( 8376f669cee054a0bca677a85e8443221354ff218b6lmr self.event_button_press, 8386f669cee054a0bca677a85e8443221354ff218b6lmr self.event_button_release, 8396f669cee054a0bca677a85e8443221354ff218b6lmr None, 8406f669cee054a0bca677a85e8443221354ff218b6lmr self.event_drag_motion, 8416f669cee054a0bca677a85e8443221354ff218b6lmr self.event_expose) 8426f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_selection_started = True 8436f669cee054a0bca677a85e8443221354ff218b6lmr 8446f669cee054a0bca677a85e8443221354ff218b6lmr def event_button_release(self, widget, event): 8456f669cee054a0bca677a85e8443221354ff218b6lmr self.redirect_event_box_input( 8466f669cee054a0bca677a85e8443221354ff218b6lmr self.event_button_press, 8476f669cee054a0bca677a85e8443221354ff218b6lmr self.event_button_release, 8486f669cee054a0bca677a85e8443221354ff218b6lmr None, 8496f669cee054a0bca677a85e8443221354ff218b6lmr None, 8506f669cee054a0bca677a85e8443221354ff218b6lmr self.event_expose) 8516f669cee054a0bca677a85e8443221354ff218b6lmr (self.barrier_corner, self.barrier_size) = \ 8526f669cee054a0bca677a85e8443221354ff218b6lmr corner_and_size_clipped(self.barrier_corner0, self.barrier_corner1, 8536f669cee054a0bca677a85e8443221354ff218b6lmr self.event_box.size_request()) 8546f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_md5sum = ppm_utils.get_region_md5sum( 8556f669cee054a0bca677a85e8443221354ff218b6lmr self.image_width, self.image_height, self.image_data, 8566f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_corner[0], self.barrier_corner[1], 8576f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_size[0], self.barrier_size[1]) 8586f669cee054a0bca677a85e8443221354ff218b6lmr self.barrier_selected = True 8596f669cee054a0bca677a85e8443221354ff218b6lmr self.update_barrier_info() 8606f669cee054a0bca677a85e8443221354ff218b6lmr 8616f669cee054a0bca677a85e8443221354ff218b6lmr def event_key_press(self, widget, event): 8626f669cee054a0bca677a85e8443221354ff218b6lmr if self.check_manual.get_active(): 8636f669cee054a0bca677a85e8443221354ff218b6lmr return False 8646f669cee054a0bca677a85e8443221354ff218b6lmr str = key_event_to_qemu_string(event) 8656f669cee054a0bca677a85e8443221354ff218b6lmr self.add_key(str) 8666f669cee054a0bca677a85e8443221354ff218b6lmr return True 8676f669cee054a0bca677a85e8443221354ff218b6lmr 8686f669cee054a0bca677a85e8443221354ff218b6lmr 8696f669cee054a0bca677a85e8443221354ff218b6lmrclass StepEditor(StepMakerWindow): 8706f669cee054a0bca677a85e8443221354ff218b6lmr ui = '''<ui> 8716f669cee054a0bca677a85e8443221354ff218b6lmr <menubar name="MenuBar"> 8721b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menu action="File"> 8731b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menuitem action="Open"/> 8741b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <separator/> 8751b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menuitem action="Quit"/> 8761b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr </menu> 8771b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menu action="Edit"> 8781b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menuitem action="CopyStep"/> 8791b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menuitem action="DeleteStep"/> 8801b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr </menu> 8811b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menu action="Insert"> 8821b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menuitem action="InsertNewBefore"/> 8831b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menuitem action="InsertNewAfter"/> 8841b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <separator/> 8851b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menuitem action="InsertStepsBefore"/> 8861b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menuitem action="InsertStepsAfter"/> 8871b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr </menu> 8881b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menu action="Tools"> 8891b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr <menuitem action="CleanUp"/> 8901b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr </menu> 8916f669cee054a0bca677a85e8443221354ff218b6lmr </menubar> 8921b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr</ui>''' 8936f669cee054a0bca677a85e8443221354ff218b6lmr 8946f669cee054a0bca677a85e8443221354ff218b6lmr # Constructor 8956f669cee054a0bca677a85e8443221354ff218b6lmr 8966f669cee054a0bca677a85e8443221354ff218b6lmr def __init__(self, filename=None): 8976f669cee054a0bca677a85e8443221354ff218b6lmr StepMakerWindow.__init__(self) 8986f669cee054a0bca677a85e8443221354ff218b6lmr 8996f669cee054a0bca677a85e8443221354ff218b6lmr self.steps_filename = None 9006f669cee054a0bca677a85e8443221354ff218b6lmr self.steps = [] 9016f669cee054a0bca677a85e8443221354ff218b6lmr 9026f669cee054a0bca677a85e8443221354ff218b6lmr # Create a UIManager instance 9036f669cee054a0bca677a85e8443221354ff218b6lmr uimanager = gtk.UIManager() 9046f669cee054a0bca677a85e8443221354ff218b6lmr 9056f669cee054a0bca677a85e8443221354ff218b6lmr # Add the accelerator group to the toplevel window 9066f669cee054a0bca677a85e8443221354ff218b6lmr accelgroup = uimanager.get_accel_group() 9076f669cee054a0bca677a85e8443221354ff218b6lmr self.window.add_accel_group(accelgroup) 9086f669cee054a0bca677a85e8443221354ff218b6lmr 9096f669cee054a0bca677a85e8443221354ff218b6lmr # Create an ActionGroup 9101b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr actiongroup = gtk.ActionGroup('StepEditor') 9116f669cee054a0bca677a85e8443221354ff218b6lmr 9126f669cee054a0bca677a85e8443221354ff218b6lmr # Create actions 9136f669cee054a0bca677a85e8443221354ff218b6lmr actiongroup.add_actions([ 9146f669cee054a0bca677a85e8443221354ff218b6lmr ('Quit', gtk.STOCK_QUIT, '_Quit', None, 'Quit the Program', 9156f669cee054a0bca677a85e8443221354ff218b6lmr self.quit), 9166f669cee054a0bca677a85e8443221354ff218b6lmr ('Open', gtk.STOCK_OPEN, '_Open', None, 'Open steps file', 9176f669cee054a0bca677a85e8443221354ff218b6lmr self.open_steps_file), 9181b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr ('CopyStep', gtk.STOCK_COPY, '_Copy current step...', "", 9196f669cee054a0bca677a85e8443221354ff218b6lmr 'Copy current step to user specified position', self.copy_step), 9201b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr ('DeleteStep', gtk.STOCK_DELETE, '_Delete current step', "", 9216f669cee054a0bca677a85e8443221354ff218b6lmr 'Delete current step', self.event_remove_clicked), 9221b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr ('InsertNewBefore', gtk.STOCK_ADD, '_New step before current', "", 9236f669cee054a0bca677a85e8443221354ff218b6lmr 'Insert new step before current step', self.insert_before), 9241b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr ('InsertNewAfter', gtk.STOCK_ADD, 'N_ew step after current', "", 9256f669cee054a0bca677a85e8443221354ff218b6lmr 'Insert new step after current step', self.insert_after), 9266f669cee054a0bca677a85e8443221354ff218b6lmr ('InsertStepsBefore', gtk.STOCK_ADD, '_Steps before current...', 9271b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr "", 'Insert steps (from file) before current step', 9286f669cee054a0bca677a85e8443221354ff218b6lmr self.insert_steps_before), 9291b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr ('InsertStepsAfter', gtk.STOCK_ADD, 'Steps _after current...', "", 9301b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr 'Insert steps (from file) after current step', 9316f669cee054a0bca677a85e8443221354ff218b6lmr self.insert_steps_after), 9321b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr ('CleanUp', gtk.STOCK_DELETE, '_Clean up data directory', "", 9331b99b40fec1cf413f7c5db14a7420fc0468a5f8blmr 'Move unused PPM files to a backup directory', self.cleanup), 9346f669cee054a0bca677a85e8443221354ff218b6lmr ('File', None, '_File'), 9356f669cee054a0bca677a85e8443221354ff218b6lmr ('Edit', None, '_Edit'), 9366f669cee054a0bca677a85e8443221354ff218b6lmr ('Insert', None, '_Insert'), 9376f669cee054a0bca677a85e8443221354ff218b6lmr ('Tools', None, '_Tools') 9386f669cee054a0bca677a85e8443221354ff218b6lmr ]) 9396f669cee054a0bca677a85e8443221354ff218b6lmr 9406f669cee054a0bca677a85e8443221354ff218b6lmr def create_shortcut(name, callback, keyname): 9416f669cee054a0bca677a85e8443221354ff218b6lmr # Create an action 9426f669cee054a0bca677a85e8443221354ff218b6lmr action = gtk.Action(name, None, None, None) 9436f669cee054a0bca677a85e8443221354ff218b6lmr # Connect a callback to the action 9446f669cee054a0bca677a85e8443221354ff218b6lmr action.connect("activate", callback) 9456f669cee054a0bca677a85e8443221354ff218b6lmr actiongroup.add_action_with_accel(action, keyname) 9466f669cee054a0bca677a85e8443221354ff218b6lmr # Have the action use accelgroup 9476f669cee054a0bca677a85e8443221354ff218b6lmr action.set_accel_group(accelgroup) 9486f669cee054a0bca677a85e8443221354ff218b6lmr # Connect the accelerator to the action 9496f669cee054a0bca677a85e8443221354ff218b6lmr action.connect_accelerator() 9506f669cee054a0bca677a85e8443221354ff218b6lmr 9516f669cee054a0bca677a85e8443221354ff218b6lmr create_shortcut("Next", self.event_next_clicked, "Page_Down") 9526f669cee054a0bca677a85e8443221354ff218b6lmr create_shortcut("Previous", self.event_prev_clicked, "Page_Up") 9536f669cee054a0bca677a85e8443221354ff218b6lmr 9546f669cee054a0bca677a85e8443221354ff218b6lmr # Add the actiongroup to the uimanager 9556f669cee054a0bca677a85e8443221354ff218b6lmr uimanager.insert_action_group(actiongroup, 0) 9566f669cee054a0bca677a85e8443221354ff218b6lmr 9576f669cee054a0bca677a85e8443221354ff218b6lmr # Add a UI description 9586f669cee054a0bca677a85e8443221354ff218b6lmr uimanager.add_ui_from_string(self.ui) 9596f669cee054a0bca677a85e8443221354ff218b6lmr 9606f669cee054a0bca677a85e8443221354ff218b6lmr # Create a MenuBar 9616f669cee054a0bca677a85e8443221354ff218b6lmr menubar = uimanager.get_widget('/MenuBar') 9626f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_vbox.pack_start(menubar, False) 9636f669cee054a0bca677a85e8443221354ff218b6lmr 9646f669cee054a0bca677a85e8443221354ff218b6lmr # Remember the Edit menu bar for future reference 9656f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_edit = uimanager.get_widget('/MenuBar/Edit') 9666f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_edit.set_sensitive(False) 9676f669cee054a0bca677a85e8443221354ff218b6lmr 9686f669cee054a0bca677a85e8443221354ff218b6lmr # Remember the Insert menu bar for future reference 9696f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_insert = uimanager.get_widget('/MenuBar/Insert') 9706f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_insert.set_sensitive(False) 9716f669cee054a0bca677a85e8443221354ff218b6lmr 9726f669cee054a0bca677a85e8443221354ff218b6lmr # Remember the Tools menu bar for future reference 9736f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_tools = uimanager.get_widget('/MenuBar/Tools') 9746f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_tools.set_sensitive(False) 9756f669cee054a0bca677a85e8443221354ff218b6lmr 9766f669cee054a0bca677a85e8443221354ff218b6lmr # Next/Previous HBox 9776f669cee054a0bca677a85e8443221354ff218b6lmr hbox = gtk.HBox(spacing=10) 9786f669cee054a0bca677a85e8443221354ff218b6lmr self.user_vbox.pack_start(hbox) 9796f669cee054a0bca677a85e8443221354ff218b6lmr hbox.show() 9806f669cee054a0bca677a85e8443221354ff218b6lmr 9816f669cee054a0bca677a85e8443221354ff218b6lmr self.button_first = gtk.Button(stock=gtk.STOCK_GOTO_FIRST) 9826f669cee054a0bca677a85e8443221354ff218b6lmr self.button_first.connect("clicked", self.event_first_clicked) 9836f669cee054a0bca677a85e8443221354ff218b6lmr hbox.pack_start(self.button_first) 9846f669cee054a0bca677a85e8443221354ff218b6lmr self.button_first.show() 9856f669cee054a0bca677a85e8443221354ff218b6lmr 9866f669cee054a0bca677a85e8443221354ff218b6lmr #self.button_prev = gtk.Button("<< Previous") 9876f669cee054a0bca677a85e8443221354ff218b6lmr self.button_prev = gtk.Button(stock=gtk.STOCK_GO_BACK) 9886f669cee054a0bca677a85e8443221354ff218b6lmr self.button_prev.connect("clicked", self.event_prev_clicked) 9896f669cee054a0bca677a85e8443221354ff218b6lmr hbox.pack_start(self.button_prev) 9906f669cee054a0bca677a85e8443221354ff218b6lmr self.button_prev.show() 9916f669cee054a0bca677a85e8443221354ff218b6lmr 9926f669cee054a0bca677a85e8443221354ff218b6lmr self.label_step = gtk.Label("Step:") 9936f669cee054a0bca677a85e8443221354ff218b6lmr hbox.pack_start(self.label_step, False) 9946f669cee054a0bca677a85e8443221354ff218b6lmr self.label_step.show() 9956f669cee054a0bca677a85e8443221354ff218b6lmr 9966f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_step_num = gtk.Entry() 9976f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_step_num.connect("activate", self.event_entry_step_activated) 9986f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_step_num.set_width_chars(3) 9996f669cee054a0bca677a85e8443221354ff218b6lmr hbox.pack_start(self.entry_step_num, False) 10006f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_step_num.show() 10016f669cee054a0bca677a85e8443221354ff218b6lmr 10026f669cee054a0bca677a85e8443221354ff218b6lmr #self.button_next = gtk.Button("Next >>") 10036f669cee054a0bca677a85e8443221354ff218b6lmr self.button_next = gtk.Button(stock=gtk.STOCK_GO_FORWARD) 10046f669cee054a0bca677a85e8443221354ff218b6lmr self.button_next.connect("clicked", self.event_next_clicked) 10056f669cee054a0bca677a85e8443221354ff218b6lmr hbox.pack_start(self.button_next) 10066f669cee054a0bca677a85e8443221354ff218b6lmr self.button_next.show() 10076f669cee054a0bca677a85e8443221354ff218b6lmr 10086f669cee054a0bca677a85e8443221354ff218b6lmr self.button_last = gtk.Button(stock=gtk.STOCK_GOTO_LAST) 10096f669cee054a0bca677a85e8443221354ff218b6lmr self.button_last.connect("clicked", self.event_last_clicked) 10106f669cee054a0bca677a85e8443221354ff218b6lmr hbox.pack_start(self.button_last) 10116f669cee054a0bca677a85e8443221354ff218b6lmr self.button_last.show() 10126f669cee054a0bca677a85e8443221354ff218b6lmr 10136f669cee054a0bca677a85e8443221354ff218b6lmr # Save HBox 10146f669cee054a0bca677a85e8443221354ff218b6lmr hbox = gtk.HBox(spacing=10) 10156f669cee054a0bca677a85e8443221354ff218b6lmr self.user_vbox.pack_start(hbox) 10166f669cee054a0bca677a85e8443221354ff218b6lmr hbox.show() 10176f669cee054a0bca677a85e8443221354ff218b6lmr 10186f669cee054a0bca677a85e8443221354ff218b6lmr self.button_save = gtk.Button("_Save current step") 10196f669cee054a0bca677a85e8443221354ff218b6lmr self.button_save.connect("clicked", self.event_save_clicked) 10206f669cee054a0bca677a85e8443221354ff218b6lmr hbox.pack_start(self.button_save) 10216f669cee054a0bca677a85e8443221354ff218b6lmr self.button_save.show() 10226f669cee054a0bca677a85e8443221354ff218b6lmr 10236f669cee054a0bca677a85e8443221354ff218b6lmr self.button_remove = gtk.Button("_Delete current step") 10246f669cee054a0bca677a85e8443221354ff218b6lmr self.button_remove.connect("clicked", self.event_remove_clicked) 10256f669cee054a0bca677a85e8443221354ff218b6lmr hbox.pack_start(self.button_remove) 10266f669cee054a0bca677a85e8443221354ff218b6lmr self.button_remove.show() 10276f669cee054a0bca677a85e8443221354ff218b6lmr 10286f669cee054a0bca677a85e8443221354ff218b6lmr self.button_replace = gtk.Button("_Replace screendump") 10296f669cee054a0bca677a85e8443221354ff218b6lmr self.button_replace.connect("clicked", self.event_replace_clicked) 10306f669cee054a0bca677a85e8443221354ff218b6lmr hbox.pack_start(self.button_replace) 10316f669cee054a0bca677a85e8443221354ff218b6lmr self.button_replace.show() 10326f669cee054a0bca677a85e8443221354ff218b6lmr 10336f669cee054a0bca677a85e8443221354ff218b6lmr # Disable unused widgets 10346f669cee054a0bca677a85e8443221354ff218b6lmr self.button_capture.set_sensitive(False) 10356f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_latency.set_sensitive(False) 10366f669cee054a0bca677a85e8443221354ff218b6lmr self.spin_sensitivity.set_sensitive(False) 10376f669cee054a0bca677a85e8443221354ff218b6lmr 10386f669cee054a0bca677a85e8443221354ff218b6lmr # Disable main vbox because no steps file is loaded 10396f669cee054a0bca677a85e8443221354ff218b6lmr self.main_vbox.set_sensitive(False) 10406f669cee054a0bca677a85e8443221354ff218b6lmr 10416f669cee054a0bca677a85e8443221354ff218b6lmr # Set title 10426f669cee054a0bca677a85e8443221354ff218b6lmr self.window.set_title("Step Editor") 10436f669cee054a0bca677a85e8443221354ff218b6lmr 10446f669cee054a0bca677a85e8443221354ff218b6lmr # Events 10456f669cee054a0bca677a85e8443221354ff218b6lmr 10466f669cee054a0bca677a85e8443221354ff218b6lmr def delete_event(self, widget, event): 10476f669cee054a0bca677a85e8443221354ff218b6lmr # Make sure the step is saved (if the user wants it to be) 10486f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 10496f669cee054a0bca677a85e8443221354ff218b6lmr 10506f669cee054a0bca677a85e8443221354ff218b6lmr def event_first_clicked(self, widget): 10516f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps: 10526f669cee054a0bca677a85e8443221354ff218b6lmr return 10536f669cee054a0bca677a85e8443221354ff218b6lmr # Make sure the step is saved (if the user wants it to be) 10546f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 10556f669cee054a0bca677a85e8443221354ff218b6lmr # Go to first step 10566f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(0) 10576f669cee054a0bca677a85e8443221354ff218b6lmr 10586f669cee054a0bca677a85e8443221354ff218b6lmr def event_last_clicked(self, widget): 10596f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps: 10606f669cee054a0bca677a85e8443221354ff218b6lmr return 10616f669cee054a0bca677a85e8443221354ff218b6lmr # Make sure the step is saved (if the user wants it to be) 10626f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 10636f669cee054a0bca677a85e8443221354ff218b6lmr # Go to last step 10646f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(len(self.steps) - 1) 10656f669cee054a0bca677a85e8443221354ff218b6lmr 10666f669cee054a0bca677a85e8443221354ff218b6lmr def event_prev_clicked(self, widget): 10676f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps: 10686f669cee054a0bca677a85e8443221354ff218b6lmr return 10696f669cee054a0bca677a85e8443221354ff218b6lmr # Make sure the step is saved (if the user wants it to be) 10706f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 10716f669cee054a0bca677a85e8443221354ff218b6lmr # Go to previous step 10726f669cee054a0bca677a85e8443221354ff218b6lmr index = self.current_step_index - 1 10736f669cee054a0bca677a85e8443221354ff218b6lmr if self.steps: 10746f669cee054a0bca677a85e8443221354ff218b6lmr index = index % len(self.steps) 10756f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(index) 10766f669cee054a0bca677a85e8443221354ff218b6lmr 10776f669cee054a0bca677a85e8443221354ff218b6lmr def event_next_clicked(self, widget): 10786f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps: 10796f669cee054a0bca677a85e8443221354ff218b6lmr return 10806f669cee054a0bca677a85e8443221354ff218b6lmr # Make sure the step is saved (if the user wants it to be) 10816f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 10826f669cee054a0bca677a85e8443221354ff218b6lmr # Go to next step 10836f669cee054a0bca677a85e8443221354ff218b6lmr index = self.current_step_index + 1 10846f669cee054a0bca677a85e8443221354ff218b6lmr if self.steps: 10856f669cee054a0bca677a85e8443221354ff218b6lmr index = index % len(self.steps) 10866f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(index) 10876f669cee054a0bca677a85e8443221354ff218b6lmr 10886f669cee054a0bca677a85e8443221354ff218b6lmr def event_entry_step_activated(self, widget): 10896f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps: 10906f669cee054a0bca677a85e8443221354ff218b6lmr return 10916f669cee054a0bca677a85e8443221354ff218b6lmr step_index = self.entry_step_num.get_text() 10926f669cee054a0bca677a85e8443221354ff218b6lmr if not step_index.isdigit(): 10936f669cee054a0bca677a85e8443221354ff218b6lmr return 10946f669cee054a0bca677a85e8443221354ff218b6lmr step_index = int(step_index) - 1 10956f669cee054a0bca677a85e8443221354ff218b6lmr if step_index == self.current_step_index: 10966f669cee054a0bca677a85e8443221354ff218b6lmr return 10976f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 10986f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(step_index) 10996f669cee054a0bca677a85e8443221354ff218b6lmr 11006f669cee054a0bca677a85e8443221354ff218b6lmr def event_save_clicked(self, widget): 11016f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps: 11026f669cee054a0bca677a85e8443221354ff218b6lmr return 11036f669cee054a0bca677a85e8443221354ff218b6lmr self.save_step() 11046f669cee054a0bca677a85e8443221354ff218b6lmr 11056f669cee054a0bca677a85e8443221354ff218b6lmr def event_remove_clicked(self, widget): 11066f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps: 11076f669cee054a0bca677a85e8443221354ff218b6lmr return 11086f669cee054a0bca677a85e8443221354ff218b6lmr if not self.question_yes_no("This will modify the steps file." 11096f669cee054a0bca677a85e8443221354ff218b6lmr " Are you sure?", "Remove step?"): 11106f669cee054a0bca677a85e8443221354ff218b6lmr return 11116f669cee054a0bca677a85e8443221354ff218b6lmr # Remove step 11126f669cee054a0bca677a85e8443221354ff218b6lmr del self.steps[self.current_step_index] 11136f669cee054a0bca677a85e8443221354ff218b6lmr # Write changes to file 11146f669cee054a0bca677a85e8443221354ff218b6lmr self.write_steps_file(self.steps_filename) 11156f669cee054a0bca677a85e8443221354ff218b6lmr # Move to previous step 11166f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(self.current_step_index) 11176f669cee054a0bca677a85e8443221354ff218b6lmr 11186f669cee054a0bca677a85e8443221354ff218b6lmr def event_replace_clicked(self, widget): 11196f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps: 11206f669cee054a0bca677a85e8443221354ff218b6lmr return 11216f669cee054a0bca677a85e8443221354ff218b6lmr # Let the user choose a screendump file 11226f669cee054a0bca677a85e8443221354ff218b6lmr current_filename = os.path.join(self.steps_data_dir, 11236f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_screendump.get_text()) 11246f669cee054a0bca677a85e8443221354ff218b6lmr filename = self.filedialog("Choose PPM image file", 11256f669cee054a0bca677a85e8443221354ff218b6lmr default_filename=current_filename) 11266f669cee054a0bca677a85e8443221354ff218b6lmr if not filename: 11276f669cee054a0bca677a85e8443221354ff218b6lmr return 11286f669cee054a0bca677a85e8443221354ff218b6lmr if not ppm_utils.image_verify_ppm_file(filename): 11296f669cee054a0bca677a85e8443221354ff218b6lmr self.message("Not a valid PPM image file.", "Error") 11306f669cee054a0bca677a85e8443221354ff218b6lmr return 11316f669cee054a0bca677a85e8443221354ff218b6lmr self.clear_image() 11326f669cee054a0bca677a85e8443221354ff218b6lmr self.clear_barrier_state() 11336f669cee054a0bca677a85e8443221354ff218b6lmr self.set_image_from_file(filename) 11346f669cee054a0bca677a85e8443221354ff218b6lmr self.update_screendump_id(self.steps_data_dir) 11356f669cee054a0bca677a85e8443221354ff218b6lmr 11366f669cee054a0bca677a85e8443221354ff218b6lmr # Menu actions 11376f669cee054a0bca677a85e8443221354ff218b6lmr 11386f669cee054a0bca677a85e8443221354ff218b6lmr def open_steps_file(self, action): 11396f669cee054a0bca677a85e8443221354ff218b6lmr # Make sure the step is saved (if the user wants it to be) 11406f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 11416f669cee054a0bca677a85e8443221354ff218b6lmr # Let the user choose a steps file 11426f669cee054a0bca677a85e8443221354ff218b6lmr current_filename = self.steps_filename 11436f669cee054a0bca677a85e8443221354ff218b6lmr filename = self.filedialog("Open steps file", 11446f669cee054a0bca677a85e8443221354ff218b6lmr default_filename=current_filename) 11456f669cee054a0bca677a85e8443221354ff218b6lmr if not filename: 11466f669cee054a0bca677a85e8443221354ff218b6lmr return 11476f669cee054a0bca677a85e8443221354ff218b6lmr self.set_steps_file(filename) 11486f669cee054a0bca677a85e8443221354ff218b6lmr 11496f669cee054a0bca677a85e8443221354ff218b6lmr def quit(self, action): 11506f669cee054a0bca677a85e8443221354ff218b6lmr # Make sure the step is saved (if the user wants it to be) 11516f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 11526f669cee054a0bca677a85e8443221354ff218b6lmr # Quit 11536f669cee054a0bca677a85e8443221354ff218b6lmr gtk.main_quit() 11546f669cee054a0bca677a85e8443221354ff218b6lmr 11556f669cee054a0bca677a85e8443221354ff218b6lmr def copy_step(self, action): 11566f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps: 11576f669cee054a0bca677a85e8443221354ff218b6lmr return 11586f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 11596f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(self.current_step_index) 11606f669cee054a0bca677a85e8443221354ff218b6lmr # Get the desired position 11616f669cee054a0bca677a85e8443221354ff218b6lmr step_index = self.inputdialog("Copy step to position:", 11626f669cee054a0bca677a85e8443221354ff218b6lmr "Copy step", 11636f669cee054a0bca677a85e8443221354ff218b6lmr str(self.current_step_index + 2)) 11646f669cee054a0bca677a85e8443221354ff218b6lmr if not step_index: 11656f669cee054a0bca677a85e8443221354ff218b6lmr return 11666f669cee054a0bca677a85e8443221354ff218b6lmr step_index = int(step_index) - 1 11676f669cee054a0bca677a85e8443221354ff218b6lmr # Get the lines of the current step 11686f669cee054a0bca677a85e8443221354ff218b6lmr step = self.steps[self.current_step_index] 11696f669cee054a0bca677a85e8443221354ff218b6lmr # Insert new step at position step_index 11706f669cee054a0bca677a85e8443221354ff218b6lmr self.steps.insert(step_index, step) 11716f669cee054a0bca677a85e8443221354ff218b6lmr # Go to new step 11726f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(step_index) 11736f669cee054a0bca677a85e8443221354ff218b6lmr # Write changes to disk 11746f669cee054a0bca677a85e8443221354ff218b6lmr self.write_steps_file(self.steps_filename) 11756f669cee054a0bca677a85e8443221354ff218b6lmr 11766f669cee054a0bca677a85e8443221354ff218b6lmr def insert_before(self, action): 11776f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps_filename: 11786f669cee054a0bca677a85e8443221354ff218b6lmr return 11796f669cee054a0bca677a85e8443221354ff218b6lmr if not self.question_yes_no("This will modify the steps file." 11806f669cee054a0bca677a85e8443221354ff218b6lmr " Are you sure?", "Insert new step?"): 11816f669cee054a0bca677a85e8443221354ff218b6lmr return 11826f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 11836f669cee054a0bca677a85e8443221354ff218b6lmr step_index = self.current_step_index 11846f669cee054a0bca677a85e8443221354ff218b6lmr # Get the lines of a blank step 11856f669cee054a0bca677a85e8443221354ff218b6lmr self.clear_state() 11866f669cee054a0bca677a85e8443221354ff218b6lmr step = self.get_step_lines() 11876f669cee054a0bca677a85e8443221354ff218b6lmr # Insert new step at position step_index 11886f669cee054a0bca677a85e8443221354ff218b6lmr self.steps.insert(step_index, step) 11896f669cee054a0bca677a85e8443221354ff218b6lmr # Go to new step 11906f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(step_index) 11916f669cee054a0bca677a85e8443221354ff218b6lmr # Write changes to disk 11926f669cee054a0bca677a85e8443221354ff218b6lmr self.write_steps_file(self.steps_filename) 11936f669cee054a0bca677a85e8443221354ff218b6lmr 11946f669cee054a0bca677a85e8443221354ff218b6lmr def insert_after(self, action): 11956f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps_filename: 11966f669cee054a0bca677a85e8443221354ff218b6lmr return 11976f669cee054a0bca677a85e8443221354ff218b6lmr if not self.question_yes_no("This will modify the steps file." 11986f669cee054a0bca677a85e8443221354ff218b6lmr " Are you sure?", "Insert new step?"): 11996f669cee054a0bca677a85e8443221354ff218b6lmr return 12006f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 12016f669cee054a0bca677a85e8443221354ff218b6lmr step_index = self.current_step_index + 1 12026f669cee054a0bca677a85e8443221354ff218b6lmr # Get the lines of a blank step 12036f669cee054a0bca677a85e8443221354ff218b6lmr self.clear_state() 12046f669cee054a0bca677a85e8443221354ff218b6lmr step = self.get_step_lines() 12056f669cee054a0bca677a85e8443221354ff218b6lmr # Insert new step at position step_index 12066f669cee054a0bca677a85e8443221354ff218b6lmr self.steps.insert(step_index, step) 12076f669cee054a0bca677a85e8443221354ff218b6lmr # Go to new step 12086f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(step_index) 12096f669cee054a0bca677a85e8443221354ff218b6lmr # Write changes to disk 12106f669cee054a0bca677a85e8443221354ff218b6lmr self.write_steps_file(self.steps_filename) 12116f669cee054a0bca677a85e8443221354ff218b6lmr 12126f669cee054a0bca677a85e8443221354ff218b6lmr def insert_steps(self, filename, index): 12136f669cee054a0bca677a85e8443221354ff218b6lmr # Read the steps file 12146f669cee054a0bca677a85e8443221354ff218b6lmr (steps, header) = self.read_steps_file(filename) 12156f669cee054a0bca677a85e8443221354ff218b6lmr 12166f669cee054a0bca677a85e8443221354ff218b6lmr data_dir = ppm_utils.get_data_dir(filename) 12176f669cee054a0bca677a85e8443221354ff218b6lmr for step in steps: 12186f669cee054a0bca677a85e8443221354ff218b6lmr self.set_state_from_step_lines(step, data_dir, warn=False) 12196f669cee054a0bca677a85e8443221354ff218b6lmr step = self.get_step_lines(self.steps_data_dir) 12206f669cee054a0bca677a85e8443221354ff218b6lmr 12216f669cee054a0bca677a85e8443221354ff218b6lmr # Insert steps into self.steps 12226f669cee054a0bca677a85e8443221354ff218b6lmr self.steps[index:index] = steps 12236f669cee054a0bca677a85e8443221354ff218b6lmr # Write changes to disk 12246f669cee054a0bca677a85e8443221354ff218b6lmr self.write_steps_file(self.steps_filename) 12256f669cee054a0bca677a85e8443221354ff218b6lmr 12266f669cee054a0bca677a85e8443221354ff218b6lmr def insert_steps_before(self, action): 12276f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps_filename: 12286f669cee054a0bca677a85e8443221354ff218b6lmr return 12296f669cee054a0bca677a85e8443221354ff218b6lmr # Let the user choose a steps file 12306f669cee054a0bca677a85e8443221354ff218b6lmr current_filename = self.steps_filename 12316f669cee054a0bca677a85e8443221354ff218b6lmr filename = self.filedialog("Choose steps file", 12326f669cee054a0bca677a85e8443221354ff218b6lmr default_filename=current_filename) 12336f669cee054a0bca677a85e8443221354ff218b6lmr if not filename: 12346f669cee054a0bca677a85e8443221354ff218b6lmr return 12356f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 12366f669cee054a0bca677a85e8443221354ff218b6lmr 12376f669cee054a0bca677a85e8443221354ff218b6lmr step_index = self.current_step_index 12386f669cee054a0bca677a85e8443221354ff218b6lmr # Insert steps at position step_index 12396f669cee054a0bca677a85e8443221354ff218b6lmr self.insert_steps(filename, step_index) 12406f669cee054a0bca677a85e8443221354ff218b6lmr # Go to new steps 12416f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(step_index) 12426f669cee054a0bca677a85e8443221354ff218b6lmr 12436f669cee054a0bca677a85e8443221354ff218b6lmr def insert_steps_after(self, action): 12446f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps_filename: 12456f669cee054a0bca677a85e8443221354ff218b6lmr return 12466f669cee054a0bca677a85e8443221354ff218b6lmr # Let the user choose a steps file 12476f669cee054a0bca677a85e8443221354ff218b6lmr current_filename = self.steps_filename 12486f669cee054a0bca677a85e8443221354ff218b6lmr filename = self.filedialog("Choose steps file", 12496f669cee054a0bca677a85e8443221354ff218b6lmr default_filename=current_filename) 12506f669cee054a0bca677a85e8443221354ff218b6lmr if not filename: 12516f669cee054a0bca677a85e8443221354ff218b6lmr return 12526f669cee054a0bca677a85e8443221354ff218b6lmr self.verify_save() 12536f669cee054a0bca677a85e8443221354ff218b6lmr 12546f669cee054a0bca677a85e8443221354ff218b6lmr step_index = self.current_step_index + 1 12556f669cee054a0bca677a85e8443221354ff218b6lmr # Insert new steps at position step_index 12566f669cee054a0bca677a85e8443221354ff218b6lmr self.insert_steps(filename, step_index) 12576f669cee054a0bca677a85e8443221354ff218b6lmr # Go to new steps 12586f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(step_index) 12596f669cee054a0bca677a85e8443221354ff218b6lmr 12606f669cee054a0bca677a85e8443221354ff218b6lmr def cleanup(self, action): 12616f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps_filename: 12626f669cee054a0bca677a85e8443221354ff218b6lmr return 12636f669cee054a0bca677a85e8443221354ff218b6lmr if not self.question_yes_no("All unused PPM files will be moved to a" 12646f669cee054a0bca677a85e8443221354ff218b6lmr " backup directory. Are you sure?", 12656f669cee054a0bca677a85e8443221354ff218b6lmr "Clean up data directory?"): 12666f669cee054a0bca677a85e8443221354ff218b6lmr return 12676f669cee054a0bca677a85e8443221354ff218b6lmr # Remember the current step index 12686f669cee054a0bca677a85e8443221354ff218b6lmr current_step_index = self.current_step_index 12696f669cee054a0bca677a85e8443221354ff218b6lmr # Get the backup dir 12706f669cee054a0bca677a85e8443221354ff218b6lmr backup_dir = os.path.join(self.steps_data_dir, "backup") 12716f669cee054a0bca677a85e8443221354ff218b6lmr # Create it if it doesn't exist 12726f669cee054a0bca677a85e8443221354ff218b6lmr if not os.path.exists(backup_dir): 12736f669cee054a0bca677a85e8443221354ff218b6lmr os.makedirs(backup_dir) 12746f669cee054a0bca677a85e8443221354ff218b6lmr # Move all files to the backup dir 12756f669cee054a0bca677a85e8443221354ff218b6lmr for filename in glob.glob(os.path.join(self.steps_data_dir, 12766f669cee054a0bca677a85e8443221354ff218b6lmr "*.[Pp][Pp][Mm]")): 12776f669cee054a0bca677a85e8443221354ff218b6lmr shutil.move(filename, backup_dir) 12786f669cee054a0bca677a85e8443221354ff218b6lmr # Get the used files back 12796f669cee054a0bca677a85e8443221354ff218b6lmr for step in self.steps: 12806f669cee054a0bca677a85e8443221354ff218b6lmr self.set_state_from_step_lines(step, backup_dir, warn=False) 12816f669cee054a0bca677a85e8443221354ff218b6lmr self.get_step_lines(self.steps_data_dir) 12826f669cee054a0bca677a85e8443221354ff218b6lmr # Remove the used files from the backup dir 12836f669cee054a0bca677a85e8443221354ff218b6lmr used_files = os.listdir(self.steps_data_dir) 12846f669cee054a0bca677a85e8443221354ff218b6lmr for filename in os.listdir(backup_dir): 12856f669cee054a0bca677a85e8443221354ff218b6lmr if filename in used_files: 12866f669cee054a0bca677a85e8443221354ff218b6lmr os.unlink(os.path.join(backup_dir, filename)) 12876f669cee054a0bca677a85e8443221354ff218b6lmr # Restore step index 12886f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(current_step_index) 12896f669cee054a0bca677a85e8443221354ff218b6lmr # Inform the user 12906f669cee054a0bca677a85e8443221354ff218b6lmr self.message("All unused PPM files may be found at %s." % 12916f669cee054a0bca677a85e8443221354ff218b6lmr os.path.abspath(backup_dir), 12926f669cee054a0bca677a85e8443221354ff218b6lmr "Clean up data directory") 12936f669cee054a0bca677a85e8443221354ff218b6lmr 12946f669cee054a0bca677a85e8443221354ff218b6lmr # Methods 12956f669cee054a0bca677a85e8443221354ff218b6lmr 12966f669cee054a0bca677a85e8443221354ff218b6lmr def read_steps_file(self, filename): 12976f669cee054a0bca677a85e8443221354ff218b6lmr steps = [] 12986f669cee054a0bca677a85e8443221354ff218b6lmr header = "" 12996f669cee054a0bca677a85e8443221354ff218b6lmr 13006f669cee054a0bca677a85e8443221354ff218b6lmr file = open(filename, "r") 13016f669cee054a0bca677a85e8443221354ff218b6lmr for line in file.readlines(): 13026f669cee054a0bca677a85e8443221354ff218b6lmr words = line.split() 13036f669cee054a0bca677a85e8443221354ff218b6lmr if not words: 13046f669cee054a0bca677a85e8443221354ff218b6lmr continue 13056f669cee054a0bca677a85e8443221354ff218b6lmr if line.startswith("# ----"): 13066f669cee054a0bca677a85e8443221354ff218b6lmr continue 13076f669cee054a0bca677a85e8443221354ff218b6lmr if words[0] == "step": 13086f669cee054a0bca677a85e8443221354ff218b6lmr steps.append("") 13096f669cee054a0bca677a85e8443221354ff218b6lmr if steps: 13106f669cee054a0bca677a85e8443221354ff218b6lmr steps[-1] += line 13116f669cee054a0bca677a85e8443221354ff218b6lmr else: 13126f669cee054a0bca677a85e8443221354ff218b6lmr header += line 13136f669cee054a0bca677a85e8443221354ff218b6lmr file.close() 13146f669cee054a0bca677a85e8443221354ff218b6lmr 13156f669cee054a0bca677a85e8443221354ff218b6lmr return (steps, header) 13166f669cee054a0bca677a85e8443221354ff218b6lmr 13176f669cee054a0bca677a85e8443221354ff218b6lmr def set_steps_file(self, filename): 13186f669cee054a0bca677a85e8443221354ff218b6lmr try: 13196f669cee054a0bca677a85e8443221354ff218b6lmr (self.steps, self.header) = self.read_steps_file(filename) 13206f669cee054a0bca677a85e8443221354ff218b6lmr except (TypeError, IOError): 13216f669cee054a0bca677a85e8443221354ff218b6lmr self.message("Cannot read file %s." % filename, "Error") 13226f669cee054a0bca677a85e8443221354ff218b6lmr return 13236f669cee054a0bca677a85e8443221354ff218b6lmr 13246f669cee054a0bca677a85e8443221354ff218b6lmr self.steps_filename = filename 13256f669cee054a0bca677a85e8443221354ff218b6lmr self.steps_data_dir = ppm_utils.get_data_dir(filename) 13266f669cee054a0bca677a85e8443221354ff218b6lmr # Go to step 0 13276f669cee054a0bca677a85e8443221354ff218b6lmr self.set_step(0) 13286f669cee054a0bca677a85e8443221354ff218b6lmr 13296f669cee054a0bca677a85e8443221354ff218b6lmr def set_step(self, index): 13306f669cee054a0bca677a85e8443221354ff218b6lmr # Limit index to legal boundaries 13316f669cee054a0bca677a85e8443221354ff218b6lmr if index < 0: 13326f669cee054a0bca677a85e8443221354ff218b6lmr index = 0 13336f669cee054a0bca677a85e8443221354ff218b6lmr if index > len(self.steps) - 1: 13346f669cee054a0bca677a85e8443221354ff218b6lmr index = len(self.steps) - 1 13356f669cee054a0bca677a85e8443221354ff218b6lmr 13366f669cee054a0bca677a85e8443221354ff218b6lmr # Enable the menus 13376f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_edit.set_sensitive(True) 13386f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_insert.set_sensitive(True) 13396f669cee054a0bca677a85e8443221354ff218b6lmr self.menu_tools.set_sensitive(True) 13406f669cee054a0bca677a85e8443221354ff218b6lmr 13416f669cee054a0bca677a85e8443221354ff218b6lmr # If no steps exist... 13426f669cee054a0bca677a85e8443221354ff218b6lmr if self.steps == []: 13436f669cee054a0bca677a85e8443221354ff218b6lmr self.current_step_index = index 13446f669cee054a0bca677a85e8443221354ff218b6lmr self.current_step = None 13456f669cee054a0bca677a85e8443221354ff218b6lmr # Set window title 13466f669cee054a0bca677a85e8443221354ff218b6lmr self.window.set_title("Step Editor -- %s" % 13476f669cee054a0bca677a85e8443221354ff218b6lmr os.path.basename(self.steps_filename)) 13486f669cee054a0bca677a85e8443221354ff218b6lmr # Set step entry widget text 13496f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_step_num.set_text("") 13506f669cee054a0bca677a85e8443221354ff218b6lmr # Clear the state of all widgets 13516f669cee054a0bca677a85e8443221354ff218b6lmr self.clear_state() 13526f669cee054a0bca677a85e8443221354ff218b6lmr # Disable the main vbox 13536f669cee054a0bca677a85e8443221354ff218b6lmr self.main_vbox.set_sensitive(False) 13546f669cee054a0bca677a85e8443221354ff218b6lmr return 13556f669cee054a0bca677a85e8443221354ff218b6lmr 13566f669cee054a0bca677a85e8443221354ff218b6lmr self.current_step_index = index 13576f669cee054a0bca677a85e8443221354ff218b6lmr self.current_step = self.steps[index] 13586f669cee054a0bca677a85e8443221354ff218b6lmr # Set window title 13596f669cee054a0bca677a85e8443221354ff218b6lmr self.window.set_title("Step Editor -- %s -- step %d" % 13606f669cee054a0bca677a85e8443221354ff218b6lmr (os.path.basename(self.steps_filename), 13616f669cee054a0bca677a85e8443221354ff218b6lmr index + 1)) 13626f669cee054a0bca677a85e8443221354ff218b6lmr # Set step entry widget text 13636f669cee054a0bca677a85e8443221354ff218b6lmr self.entry_step_num.set_text(str(self.current_step_index + 1)) 13646f669cee054a0bca677a85e8443221354ff218b6lmr # Load the state from the step lines 13656f669cee054a0bca677a85e8443221354ff218b6lmr self.set_state_from_step_lines(self.current_step, self.steps_data_dir) 13666f669cee054a0bca677a85e8443221354ff218b6lmr # Enable the main vbox 13676f669cee054a0bca677a85e8443221354ff218b6lmr self.main_vbox.set_sensitive(True) 13686f669cee054a0bca677a85e8443221354ff218b6lmr # Make sure the step lines in self.current_step are identical to the 13696f669cee054a0bca677a85e8443221354ff218b6lmr # output of self.get_step_lines 13706f669cee054a0bca677a85e8443221354ff218b6lmr self.current_step = self.get_step_lines() 13716f669cee054a0bca677a85e8443221354ff218b6lmr 13726f669cee054a0bca677a85e8443221354ff218b6lmr def verify_save(self): 13736f669cee054a0bca677a85e8443221354ff218b6lmr if not self.steps: 13746f669cee054a0bca677a85e8443221354ff218b6lmr return 13756f669cee054a0bca677a85e8443221354ff218b6lmr # See if the user changed anything 13766f669cee054a0bca677a85e8443221354ff218b6lmr if self.get_step_lines() != self.current_step: 13776f669cee054a0bca677a85e8443221354ff218b6lmr if self.question_yes_no("Step contents have been modified." 13786f669cee054a0bca677a85e8443221354ff218b6lmr " Save step?", "Save changes?"): 13796f669cee054a0bca677a85e8443221354ff218b6lmr self.save_step() 13806f669cee054a0bca677a85e8443221354ff218b6lmr 13816f669cee054a0bca677a85e8443221354ff218b6lmr def save_step(self): 13826f669cee054a0bca677a85e8443221354ff218b6lmr lines = self.get_step_lines(self.steps_data_dir) 13836f669cee054a0bca677a85e8443221354ff218b6lmr if lines != None: 13846f669cee054a0bca677a85e8443221354ff218b6lmr self.steps[self.current_step_index] = lines 13856f669cee054a0bca677a85e8443221354ff218b6lmr self.current_step = lines 13866f669cee054a0bca677a85e8443221354ff218b6lmr self.write_steps_file(self.steps_filename) 13876f669cee054a0bca677a85e8443221354ff218b6lmr 13886f669cee054a0bca677a85e8443221354ff218b6lmr def write_steps_file(self, filename): 13896f669cee054a0bca677a85e8443221354ff218b6lmr file = open(filename, "w") 13906f669cee054a0bca677a85e8443221354ff218b6lmr file.write(self.header) 13916f669cee054a0bca677a85e8443221354ff218b6lmr for step in self.steps: 13926f669cee054a0bca677a85e8443221354ff218b6lmr file.write("# " + "-" * 32 + "\n") 13936f669cee054a0bca677a85e8443221354ff218b6lmr file.write(step) 13946f669cee054a0bca677a85e8443221354ff218b6lmr file.close() 13956f669cee054a0bca677a85e8443221354ff218b6lmr 13966f669cee054a0bca677a85e8443221354ff218b6lmr 13976f669cee054a0bca677a85e8443221354ff218b6lmrif __name__ == "__main__": 13986f669cee054a0bca677a85e8443221354ff218b6lmr se = StepEditor() 13996f669cee054a0bca677a85e8443221354ff218b6lmr if len(sys.argv) > 1: 14006f669cee054a0bca677a85e8443221354ff218b6lmr se.set_steps_file(sys.argv[1]) 14016f669cee054a0bca677a85e8443221354ff218b6lmr gtk.main() 1402