1 |
import pygtk |
2 |
pygtk.require('2.0') |
3 |
import gtk |
4 |
import gtk.glade |
5 |
import pango |
6 |
|
7 |
CHANGED_COLOR = "#FFFF88" |
8 |
SOLVERPARAM_BOOL_TRUE = "Yes" |
9 |
SOLVERPARAM_BOOL_FALSE = "No" |
10 |
|
11 |
#====================================================== |
12 |
# SOLVER PARAMETERS WINDOW |
13 |
|
14 |
class SolverParametersWindow: |
15 |
def __init__(self,browser): |
16 |
self.browser = browser |
17 |
self.reporter = self.browser.reporter |
18 |
self.sim = self.browser.sim |
19 |
self.params = self.sim.getSolverParameters(); |
20 |
|
21 |
_xml = gtk.glade.XML(browser.glade_file,"paramswin") |
22 |
self.window = _xml.get_widget("paramswin") |
23 |
self.window.set_transient_for(self.browser.window) |
24 |
|
25 |
self.paramdescription = _xml.get_widget("paramdescription") |
26 |
self.solvername = _xml.get_widget("solvername") |
27 |
|
28 |
_xml.signal_autoconnect(self) |
29 |
|
30 |
self.solvername.set_text(self.sim.getSolver().getName()) |
31 |
|
32 |
self.paramsview = _xml.get_widget("paramsview") |
33 |
self.otank = {} |
34 |
self.paramstore = gtk.TreeStore(str,str,str,bool,str,int) |
35 |
self.paramsview.set_model(self.paramstore) |
36 |
|
37 |
# name column |
38 |
_renderer0 = gtk.CellRendererText() |
39 |
_col0 = gtk.TreeViewColumn("Name", _renderer0, text=0, background=4, weight=5) |
40 |
self.paramsview.append_column(_col0) |
41 |
|
42 |
# value column: 'editable' set by column 3 of the model data. |
43 |
_renderer1 = gtk.CellRendererText() |
44 |
_renderer1.connect('edited',self.on_paramsview_edited) |
45 |
_col1 = gtk.TreeViewColumn("Value", _renderer1, text=1, editable=3, background=4) |
46 |
self.paramsview.append_column(_col1) |
47 |
|
48 |
# range column |
49 |
_renderer2 = gtk.CellRendererText() |
50 |
_col2 = gtk.TreeViewColumn("Range", _renderer2, text=2, background=4) |
51 |
self.paramsview.append_column(_col2) |
52 |
|
53 |
self.populate() |
54 |
|
55 |
self.paramsview.expand_all() |
56 |
|
57 |
#def on_paramswin_key_press_event(self,widget,event): |
58 |
# if event.keyval == ESCAPE_KEY: |
59 |
# if not gtk.gdk.events_pending(): |
60 |
# self.do_destroy() |
61 |
|
62 |
def on_paramsview_row_activated(self,treeview,path,view_column,*args,**kwargs): |
63 |
# get back the object we just clicked |
64 |
|
65 |
if not self.otank.has_key(path): |
66 |
return |
67 |
|
68 |
_iter,_param = self.otank[path] |
69 |
|
70 |
if _param.isBool(): |
71 |
newvalue = not _param.getBoolValue() |
72 |
_param.setBoolValue(newvalue) |
73 |
if newvalue: |
74 |
self.paramstore.set_value(_iter,1,SOLVERPARAM_BOOL_TRUE) |
75 |
else: |
76 |
self.paramstore.set_value(_iter,1,SOLVERPARAM_BOOL_FALSE) |
77 |
self.paramstore.set_value(_iter,4, CHANGED_COLOR) |
78 |
|
79 |
def on_paramsview_button_press_event(self,widget,event): |
80 |
if event.button == 1: |
81 |
_x = int(event.x) |
82 |
_y = int(event.y) |
83 |
_time = event.time |
84 |
_pathinfo = self.paramsview.get_path_at_pos(_x, _y) |
85 |
if _pathinfo != None: |
86 |
_path, _col, _cellx, _celly = _pathinfo |
87 |
if not self.otank.has_key(_path): |
88 |
return |
89 |
_iter, _param = self.otank[_path] |
90 |
|
91 |
# update the description field |
92 |
self.paramdescription.set_text(_param.getDescription()) |
93 |
|
94 |
if _param.isStr(): |
95 |
_menu = gtk.Menu(); |
96 |
_head = gtk.ImageMenuItem("Options",True) |
97 |
_head.show() |
98 |
_head.set_sensitive(False) |
99 |
_img = gtk.Image() |
100 |
_img.set_from_file('icons/folder-open.png') |
101 |
_head.set_image(_img) |
102 |
_menu.append(_head) |
103 |
_sep = gtk.SeparatorMenuItem(); _sep.show() |
104 |
_menu.append(_sep); |
105 |
|
106 |
_item = None; |
107 |
for i in _param.getStrOptions(): |
108 |
_item = gtk.RadioMenuItem(group=_item, label=i); |
109 |
if i == _param.getStrValue(): |
110 |
_item.set_active(True) |
111 |
else: |
112 |
_item.set_active(False) |
113 |
_item.show() |
114 |
_item.connect('activate', self.on_menu_activate, _param, _iter, i); |
115 |
_menu.append(_item) |
116 |
|
117 |
_menu.show() |
118 |
_menu.popup(None, None, None, event.button, _time) |
119 |
|
120 |
def on_menu_activate(self, menuitem, param, iter, newvalue): |
121 |
if param.getStrValue() != newvalue: |
122 |
param.setStrValue(newvalue) |
123 |
self.paramstore.set_value(iter, 1, newvalue) |
124 |
self.paramstore.set_value(iter, 4, CHANGED_COLOR) |
125 |
else: |
126 |
print "NOT CHANGED" |
127 |
|
128 |
def on_paramsview_cursor_changed(self, *args, **kwargs): |
129 |
_path, _col = self.paramsview.get_cursor() |
130 |
if not self.otank.has_key(_path): |
131 |
self.paramdescription.set_text("") |
132 |
return |
133 |
_iter, _param = self.otank[_path] |
134 |
self.paramdescription.set_text(_param.getDescription()) |
135 |
#self.paramsview.set_cursor(_path,self.paramsview.get_column(1)); |
136 |
|
137 |
def on_paramsview_edited(self, renderer, path, newtext, **kwargs): |
138 |
# get back the Instance object we just edited (having to use this seems like a bug) |
139 |
path = tuple( map(int,path.split(":")) ) |
140 |
|
141 |
if not self.otank.has_key(path): |
142 |
raise RuntimeError("cell_edited_callback: invalid path '%s'" % path) |
143 |
return |
144 |
|
145 |
_iter,_param = self.otank[path] |
146 |
# you can only edit real, int, str: |
147 |
|
148 |
_changed = False |
149 |
if _param.isInt(): |
150 |
newvalue = int(newtext) |
151 |
if _param.isBounded(): |
152 |
if newvalue > _param.getIntUpperBound(): |
153 |
self.doErrorDialog() |
154 |
return False |
155 |
if newvalue < _param.getIntLowerBound(): |
156 |
self.doErrorDialog() |
157 |
return False |
158 |
if _param.getIntValue() != newvalue: |
159 |
_param.setIntValue(newvalue) |
160 |
_changed = True |
161 |
elif _param.isReal(): |
162 |
newvalue = float(newtext) |
163 |
if _param.isBounded(): |
164 |
if newvalue > _param.getRealUpperBound(): |
165 |
self.doErrorDialog() |
166 |
return False |
167 |
if newvalue < _param.getRealLowerBound(): |
168 |
self.doErrorDialog() |
169 |
return False |
170 |
if _param.getRealValue() != newvalue: |
171 |
_param.setRealValue(newvalue) |
172 |
_changed = True |
173 |
elif _param.isStr(): |
174 |
newvalue = str(newtext) |
175 |
if _param.getStrValue() != newvalue: |
176 |
_param.setStrValue(newvalue) |
177 |
_changed = True |
178 |
|
179 |
if _changed: |
180 |
self.paramstore.set_value(_iter, 1, newvalue) |
181 |
self.paramstore.set_value(_iter, 4, CHANGED_COLOR) |
182 |
else: |
183 |
print "NO CHANGE" |
184 |
|
185 |
def create_row_data(self,p): |
186 |
_row = [p.getLabel()]; |
187 |
if p.isStr(): |
188 |
_row.extend([p.getStrValue(), str(len(p.getStrOptions()))+" options", False]); |
189 |
elif p.isBool(): |
190 |
if p.getBoolValue(): |
191 |
_val = SOLVERPARAM_BOOL_TRUE |
192 |
else: |
193 |
_val = SOLVERPARAM_BOOL_FALSE |
194 |
_row.extend([_val,"",False]) |
195 |
elif p.isReal(): |
196 |
if not p.isBounded(): |
197 |
_row.extend([str(p.getRealValue()), "",True]) |
198 |
else: |
199 |
_row.extend([str(p.getRealValue()), "[ "+str(p.getRealLowerBound())+", "+str(p.getRealUpperBound())+" ]",True]) |
200 |
elif p.isInt(): |
201 |
if not p.isBounded(): |
202 |
_row.extend([str(p.getIntValue()), "", True]) |
203 |
else: |
204 |
_row.extend([str(p.getIntValue()), "[ "+str(p.getIntLowerBound())+", "+str(p.getIntUpperBound())+" ]", True]) |
205 |
|
206 |
else: |
207 |
raise RuntimeError("invalid type") |
208 |
|
209 |
_row.extend(["white",pango.WEIGHT_NORMAL]) |
210 |
return _row; |
211 |
|
212 |
def populate(self): |
213 |
# Fill the paramstore with data |
214 |
|
215 |
data = {} |
216 |
for i in self.params: |
217 |
if not data.has_key(i.getPage()): |
218 |
data[i.getPage()] = {} |
219 |
data[i.getPage()][i.getNumber()] = i; |
220 |
|
221 |
_pagenum = 1; |
222 |
for _page in sorted(data.keys()): |
223 |
if len(data[_page].keys()): |
224 |
_pageiter = self.paramstore.append( None, ["Page "+str(_pagenum), "", "", False, "white", pango.WEIGHT_BOLD]) |
225 |
for _number in sorted(data[_page].keys()): |
226 |
_param = data[_page][_number] |
227 |
_piter = self.paramstore.append( _pageiter, self.create_row_data(_param) ) |
228 |
_path = self.paramstore.get_path(_piter) |
229 |
self.otank[ _path ] = (_piter, _param) |
230 |
_pagenum = _pagenum + 1 |
231 |
|
232 |
def doErrorDialog(self,msg=None): |
233 |
_dialog = gtk.Dialog("Out of bounds", parent=self.window, flags=gtk.DIALOG_MODAL, buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK) ) |
234 |
if msg: |
235 |
_label = gtk.Label(msg) |
236 |
else: |
237 |
_label = gtk.Label("Please enter a value that is within the\ndisplayed upper and lower bounds") |
238 |
|
239 |
_dialog.vbox.pack_start(_label, True, True, 0) |
240 |
_label.show() |
241 |
_dialog.run() |
242 |
_dialog.destroy() |
243 |
|
244 |
def show(self): |
245 |
self.window.show() |
246 |
|
247 |
def on_paramswin_response(self,response,*args): |
248 |
if response == gtk.RESPONSE_OK: |
249 |
self.sim.setSolverParameters(self.params); |
250 |
elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_CLOSE: |
251 |
pass |
252 |
|
253 |
self.do_destroy() |
254 |
|
255 |
def on_paramswin_destroy(self,*args,**kwargs): |
256 |
self.do_destroy() |
257 |
|
258 |
def do_destroy(self): |
259 |
self.window.hide() |
260 |
del(self.window) |
261 |
del(self.params) |