add test for arithmetic operations and iteration
[oscopy/ivan.git] / oscopy_gui / dialogs.py
blob8df1f8e8cc2299228f7308a580f986568171faca
1 import os
2 import gobject
3 import gtk
4 import vte
5 import pty
6 import sys
7 import readline
8 import math
10 from oscopy import factors_to_names, abbrevs_to_factors
12 class Enter_Units_Dialog(object):
13 def __init__(self):
14 self._dlg = None
15 self._entry_xunits = None
16 self._entry_yunits = None
17 self._scale_factors = gtk.ListStore(gobject.TYPE_STRING,
18 gobject.TYPE_STRING)
19 sorted_list = factors_to_names.keys()
20 sorted_list.sort()
21 for factor in sorted_list:
22 self._scale_factors.append((factors_to_names[factor][0],
23 factors_to_names[factor][1]))
25 def display(self, units, xy, scale_factors):
27 sorted_list = factors_to_names.keys()
28 sorted_list.sort()
30 self._dlg = gtk.Dialog('Enter graph units',
31 flags=gtk.DIALOG_NO_SEPARATOR,
32 buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
33 gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
34 self._dlg.set_default_response(gtk.RESPONSE_ACCEPT)
35 table = gtk.Table(2, 3, False)
36 table.set_col_spacing(0, 12)
37 table.set_col_spacing(1, 12)
38 # Label, scale factor and entry for X axis
39 label_xunits = gtk.Label(xy[0])
40 align = gtk.Alignment(0, 0.5)
41 align.add(label_xunits)
42 table.attach(align, 0, 1, 0, 1)
43 self._entry_xunits = gtk.Entry()
44 self._entry_xunits.set_text(units[0])
45 self._entry_xunits.set_width_chars(7)
46 self._entry_xunits.set_activates_default(True)
47 table.attach(self._entry_xunits, 2, 3, 0, 1)
48 self._combox_fact = gtk.ComboBox(self._scale_factors)
49 self._combox_fact.set_active(sorted_list.index(scale_factors[0]))
50 cell = gtk.CellRendererText()
51 self._combox_fact.pack_start(cell, True)
52 self._combox_fact.add_attribute(cell, 'text', 1)
53 table.attach(self._combox_fact, 1, 2, 0, 1)
55 # Label, scale factor and entry for Y axis
56 label_yunits = gtk.Label(xy[1])
57 align = gtk.Alignment(0, 0.5)
58 align.add(label_yunits)
59 table.attach(align, 0, 1, 1, 2)
60 self._entry_yunits = gtk.Entry()
61 self._entry_yunits.set_text(units[1])
62 self._entry_yunits.set_width_chars(7)
63 self._entry_yunits.set_activates_default(True)
64 table.attach(self._entry_yunits, 2, 3, 1, 2)
65 self._comboy_fact = gtk.ComboBox(self._scale_factors)
66 self._comboy_fact.set_active(sorted_list.index(scale_factors[1]))
67 cell = gtk.CellRendererText()
68 self._comboy_fact.pack_start(cell, True)
69 self._comboy_fact.add_attribute(cell, 'text', 1)
70 table.attach(self._comboy_fact, 1, 2, 1, 2)
71 self._dlg.vbox.pack_start(table)
73 self._dlg.show_all()
75 def run(self):
76 units = ()
77 scale_factors = []
78 resp = self._dlg.run()
79 if resp == gtk.RESPONSE_ACCEPT:
80 units = (self._entry_xunits.get_text(),
81 self._entry_yunits.get_text())
82 x_factor_index = self._combox_fact.get_active_iter()
83 y_factor_index = self._comboy_fact.get_active_iter()
84 scale_factors = [self._scale_factors.get(x_factor_index, 0)[0],
85 self._scale_factors.get(y_factor_index, 0)[0]]
86 self._dlg.destroy()
87 return units, scale_factors
89 class Enter_Range_Dialog(object):
90 def __init__(self):
91 self._dlg = None
92 self._entries = None
94 def display(self, r, xy, scale_factors, units):
95 self._dlg = gtk.Dialog('Enter graph range',
96 flags=gtk.DIALOG_NO_SEPARATOR,
97 buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
98 gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
99 self._dlg.set_default_response(gtk.RESPONSE_ACCEPT)
101 self._entries = []
102 minmax = ['From', 'To']
104 hbox = gtk.HBox(False)
105 for col in range(0, 2):
106 frame = gtk.Frame('')
107 frame.get_label_widget().set_markup('<b>'+ xy[col] +'</b>')
108 frame.set_shadow_type(gtk.SHADOW_NONE)
109 table = gtk.Table(1, 3, False)
110 entries_row = []
111 for row in range(0, 2):
112 label = gtk.Label(minmax[row])
113 align_lbl = gtk.Alignment(0, 0.5)
114 align_lbl.add(label)
115 step = abs(float(r[col][0] - r[col][1]))/100.0
116 print step
117 adj = gtk.Adjustment(r[col][row], -1e99, 1e99,
118 step, step * 10.0, 0)
119 entry = gtk.SpinButton(adj, 1,
120 int(math.ceil(abs(math.log10(step)))))
121 entry.set_activates_default(True)
122 units_label = gtk.Label(factors_to_names[scale_factors[col]][0]
123 + units[col])
124 align_units = gtk.Alignment(0, 0.5)
125 align_units.add(units_label)
126 table.attach(align_lbl, 0, 1, row, row + 1, xpadding=3)
127 table.attach(entry, 1, 2, row, row + 1, xpadding=3)
128 table.attach(align_units, 2, 3, row, row + 1, xpadding=3)
129 table.set_row_spacing(row, 6)
130 entries_row.append(entry)
131 self._entries.append(entries_row)
132 box = gtk.HBox(False)
133 box.pack_start(table, False, False, 12)
134 frame.add(box)
135 hbox.pack_start(frame, False, False, 0)
136 self._dlg.vbox.pack_start(hbox, False, False, 6)
138 self._dlg.show_all()
140 def run(self):
141 r = []
142 resp = self._dlg.run()
143 if resp == gtk.RESPONSE_ACCEPT:
144 r = [str(self._entries[0][0].get_value()),
145 str(self._entries[0][1].get_value()),
146 str(self._entries[1][0].get_value()),
147 str(self._entries[1][1].get_value())]
148 self._dlg.destroy()
149 return r
151 DEFAULT_NETLISTER_COMMAND = 'gnetlist -g spice-sdb -s -o %s.net %s.sch'
152 DEFAULT_SIMULATOR_COMMAND = 'gnucap -b %s.net'
154 class Run_Netlister_and_Simulate_Dialog(object):
155 def __init__(self):
156 self._dlg = None
157 pass
159 def _make_check_entry(self, name, do_run, commands, default_command):
160 # returns a tuple (check_button, combo_box_entry)
161 combo = gtk.combo_box_entry_new_text()
162 if not commands:
163 commands = [default_command]
164 for cmd in commands:
165 combo.append_text(cmd)
166 combo.set_active(0)
167 combo.set_sensitive(do_run)
169 btn = gtk.CheckButton('Run %s:' % name)
170 btn.set_active(do_run)
171 btn.connect('toggled', self._check_button_toggled, combo)
172 return btn, combo
174 def display(self, actions):
175 self._dlg = gtk.Dialog("Run netlister and simulate",
176 flags=gtk.DIALOG_NO_SEPARATOR,
177 buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
178 gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
179 self._dlg.set_default_response(gtk.RESPONSE_ACCEPT)
181 # netlister part
182 box = gtk.HBox()
183 do_run, commands = actions['run_netlister']
184 btn, combo = self._make_check_entry('netlister', do_run, commands,
185 DEFAULT_NETLISTER_COMMAND)
186 self._ckbutton_netl, self._entry_netl = btn, combo
187 box.pack_start(btn, False, False, 12)
188 box.pack_start(combo, True, True)
189 self._dlg.vbox.pack_start(box, False, False, 6)
191 # simulator part
192 box = gtk.HBox()
193 do_run, commands = actions['run_simulator']
194 btn, combo = self._make_check_entry('simulator', do_run, commands,
195 DEFAULT_SIMULATOR_COMMAND)
196 self._ckbutton_sim, self._entry_sim = btn, combo
197 box.pack_start(btn, False, False, 12)
198 box.pack_start(combo, True, True)
199 self._dlg.vbox.pack_start(box, False, False, 6)
201 group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
202 group.add_widget(self._ckbutton_netl)
203 group.add_widget(self._ckbutton_sim)
205 frame = gtk.Frame('')
206 frame.get_label_widget().set_markup('<b>Options</b>')
207 frame.set_shadow_type(gtk.SHADOW_NONE)
208 vbox = gtk.VBox()
209 box = gtk.HBox(False, 12)
210 label = gtk.Label()
211 label.set_markup('Run from directory:')
212 box.pack_start(label, False, False, 12)
213 dialog = gtk.FileChooserDialog('Choose directory',
214 None,
215 gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
216 buttons=(gtk.STOCK_CANCEL,
217 gtk.RESPONSE_REJECT,
218 gtk.STOCK_OK,
219 gtk.RESPONSE_ACCEPT))
220 dialog.set_filename(actions['run_from'])
221 self._filechoose = gtk.FileChooserButton(dialog)
222 box.pack_start(self._filechoose)
223 vbox.pack_start(box, False)
224 box = gtk.HBox()
225 self._ckbutton_upd = gtk.CheckButton('Update readers once terminated')
226 self._ckbutton_upd.set_active(actions['update'])
227 box.pack_start(self._ckbutton_upd, False, False, 12)
228 vbox.pack_start(box, False, False, 6)
229 frame.add(vbox)
230 self._dlg.vbox.pack_start(frame, False, False, 6)
232 self._dlg.resize(400, 100)
233 self._dlg.show_all()
235 def _collect_data(self):
236 # make sure that the command to run is always the first
237 # element of the list (more recent commands are at the
238 # beginning of the list) and eliminate duplicates
239 netlister_cmds = [row[0] for row in self._entry_netl.get_model()]
240 if self._entry_netl.get_active_text() in netlister_cmds:
241 netlister_cmds.remove(self._entry_netl.get_active_text())
242 netlister_cmds.insert(0, self._entry_netl.get_active_text())
244 simulator_cmds = [row[0] for row in self._entry_sim.get_model()]
245 if self._entry_sim.get_active_text() in simulator_cmds:
246 simulator_cmds.remove(self._entry_sim.get_active_text())
247 simulator_cmds.insert(0, self._entry_sim.get_active_text())
249 actions = {}
250 actions['run_netlister'] = (self._ckbutton_netl.get_active(), netlister_cmds)
251 actions['run_simulator'] = (self._ckbutton_sim.get_active(), simulator_cmds)
252 actions['update'] = self._ckbutton_upd.get_active()
253 actions['run_from'] = self._filechoose.get_filename()
254 return actions
256 def run(self):
257 actions = None
258 if self._dlg.run() == gtk.RESPONSE_ACCEPT:
259 actions = self._collect_data()
260 self._dlg.destroy()
261 return actions
263 def _check_button_toggled(self, button, entry):
264 entry.set_sensitive(button.get_active())
266 class TerminalWindow(gtk.Window):
267 def __init__(self, prompt, intro, hist_file, app_exec):
268 gtk.Window.__init__(self)
269 # History file
270 self.hist_file = hist_file
272 # Readline configuration
273 if not os.path.exists(self.hist_file):
274 f = open(self.hist_file, "w")
275 f.write("figlist")
276 f.close()
277 readline.read_history_file(self.hist_file)
279 self.prompt = prompt
280 self.intro = intro
281 self._term = None
282 self._app_exec = app_exec
283 self._term_hist_item = readline.get_current_history_length() + 1
285 def create(self):
286 cmdw = self
287 if self._term is None:
288 self._term = vte.Terminal()
289 self._term.set_cursor_blinks(True)
290 self._term.set_emulation('xterm')
291 self._term.set_font_from_string('monospace 9')
292 self._term.set_scrollback_lines(1000)
293 self._term.connect('focus-in-event', self._term_focus_in)
294 master, slave = pty.openpty()
295 self._term.set_pty(master)
296 sys.stdout.close()
297 sys.stderr.close()
298 sys.stdout = sys.stderr = os.fdopen(slave, "w")
299 print self.intro
301 scrollbar = gtk.VScrollbar()
302 scrollbar.set_adjustment(self._term.get_adjustment())
304 termbox = gtk.HBox()
305 termbox.pack_start(self._term)
306 termbox.pack_start(scrollbar)
308 entrybox = gtk.HBox(False)
309 label = gtk.Label('Command:')
310 self._entry = gtk.Entry()
311 self._entry.connect('activate', self._entry_activate)
312 self._entry.connect('key-press-event', self._entry_key_pressed)
313 entrybox.pack_start(label, False, False, 12)
314 entrybox.pack_start(self._entry, True, True, 12)
316 box = gtk.VBox()
317 box.pack_start(termbox)
318 box.pack_start(entrybox)
320 cmdw.add(box)
322 def _term_focus_in(self, widget, event):
323 self._entry.grab_focus()
325 def _entry_activate(self, entry, data=None):
326 if isinstance(entry, gtk.Entry):
327 line = entry.get_text()
328 if line is not None:
329 print self.prompt + line
330 self._app_exec(line)
331 readline.add_history(line)
332 self._term_hist_item = readline.get_current_history_length() + 1
333 entry.set_text('')
335 def _entry_key_pressed(self, entry, event):
336 if gtk.gdk.keyval_name(event.keyval) == "Up":
337 line = readline.get_history_item(self._term_hist_item - 1)
338 if line is not None:
339 self._term_hist_item = self._term_hist_item - 1
340 entry.set_text(line)
341 return True
342 elif gtk.gdk.keyval_name(event.keyval) == "Down":
343 line = readline.get_history_item(self._term_hist_item + 1)
344 if line is not None:
345 self._term_hist_item = self._term_hist_item + 1
346 entry.set_text(line)
347 return True