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