Mercurial > code > home > repos > light9
comparison flax/CueFaders.py @ 168:f8b5cb5fbeed
- CueFader is hopefully done:
- CueFader is hopefully done:
- The TimedGoButton accepts a wheel to change the times. You can also
enter times directly.
- TimedGoButton really has a default starting time of 2 now. (there was
a variable attached to the wrong widget before)
- We send DMX levels with dmxclient now.
- Autoload Times is a new option.
- We load times from the next cue if Autoload Times is true.
- Time predictions in the LabelledScale are slightly better. You still
can change the time of an active fade.
- Cue cache and DMX level computing now have their own functions, which
get called at (hopefully) All The Right Times.
- There are even some docs now!
- Cues: sub_level parsing is better, will only throw out one line if
it encounters problems (instead of the rest of the cue)
- CueList: lots of 0 vs. None bugs fixed.
- TkCueList: stores a reference to the controlling fader so it can alert
it about changed cues.
- CueEditron: You can edit sub_levels now.
- cuelist1 was edited, checking it in for consistency's sake
author | dmcc |
---|---|
date | Wed, 09 Jul 2003 03:59:40 +0000 |
parents | 79bc84310e80 |
children | ba83a312d8b1 |
comparison
equal
deleted
inserted
replaced
167:79bc84310e80 | 168:f8b5cb5fbeed |
---|---|
1 from __future__ import division, nested_scopes | 1 from __future__ import division, nested_scopes |
2 import Tix as Tk | 2 import Tix as Tk |
3 import time | 3 import time |
4 from TreeDict import TreeDict, allow_class_to_be_pickled | 4 from TreeDict import TreeDict, allow_class_to_be_pickled |
5 from TLUtility import enumerate | 5 from TLUtility import enumerate |
6 import Submaster | 6 import Submaster, dmxclient |
7 | 7 |
8 cue_state_indicator_colors = { | 8 cue_state_indicator_colors = { |
9 # bg fg | 9 # bg fg |
10 'prev' : ('blue', 'white'), | 10 'prev' : ('blue', 'white'), |
11 'cur' : ('yellow', 'black'), | 11 'cur' : ('yellow', 'black'), |
73 self.scale_to_fade = scale_to_fade | 73 self.scale_to_fade = scale_to_fade |
74 self.button = Tk.Button(self, text=name, command=self.start_fade, **kw) | 74 self.button = Tk.Button(self, text=name, command=self.start_fade, **kw) |
75 self.button.pack(fill='both', expand=1, side='left') | 75 self.button.pack(fill='both', expand=1, side='left') |
76 | 76 |
77 self.timer_var = Tk.DoubleVar() | 77 self.timer_var = Tk.DoubleVar() |
78 self.timer_entry = Tk.Control(self, step=0.5, min=0, integer=0) | 78 self.timer_entry = Tk.Control(self, step=0.5, min=0, integer=0, |
79 self.timer_entry.entry.configure(textvariable=self.timer_var, width=5, | 79 variable=self.timer_var, selectmode='immediate') |
80 bg='black', fg='white') | 80 for widget in (self.timer_entry, self.timer_entry.entry, |
81 self.timer_entry.incr, self.timer_entry.decr, self.button, self): | |
82 widget.bind("<4>", self.wheelscroll) | |
83 widget.bind("<5>", self.wheelscroll) | |
84 self.timer_entry.entry.configure(width=5, bg='black', fg='white') | |
81 self.timer_entry.pack(fill='y', side='left') | 85 self.timer_entry.pack(fill='y', side='left') |
86 self.timer_var.set(2) | |
82 self.disabled = (self.button['state'] == 'disabled') | 87 self.disabled = (self.button['state'] == 'disabled') |
83 self.fading = 0 | 88 self.fading = 0 |
89 def wheelscroll(self, event): | |
90 """Mouse wheel increments or decrements timer.""" | |
91 if event.num == 4: # scroll up | |
92 self.timer_entry.increment() | |
93 else: # scroll down | |
94 self.timer_entry.decrement() | |
84 def start_fade(self, end_level=1): | 95 def start_fade(self, end_level=1): |
85 try: | 96 try: |
86 fade_time = float(self.timer_var.get()) | 97 fade_time = float(self.timer_var.get()) |
87 except ValueError: | 98 except ValueError: |
88 # since we use a control now, i don't think we need to worry about | 99 # since we use a control now, i don't think we need to worry about |
89 # validation any more. | 100 # validation any more. |
90 print "can't fade -- bad time" | 101 print ">>> Can't fade -- bad time", self.timer_var.get() |
91 return | 102 return |
92 | 103 |
93 self.start_time = time.time() | 104 self.start_time = time.time() |
94 self.start_level = self.scale_to_fade.scale_var.get() | 105 self.start_level = self.scale_to_fade.scale_var.get() |
95 self.end_level = end_level | 106 self.end_level = end_level |
128 | 139 |
129 class CueFader(Tk.Frame): | 140 class CueFader(Tk.Frame): |
130 def __init__(self, master, cuelist): | 141 def __init__(self, master, cuelist): |
131 Tk.Frame.__init__(self, master, bg='black') | 142 Tk.Frame.__init__(self, master, bg='black') |
132 self.cuelist = cuelist | 143 self.cuelist = cuelist |
133 self.auto_shift = Tk.IntVar() | 144 self.cuelist.set_fader(self) |
134 self.auto_shift.set(1) | 145 |
146 self.last_levels_sent = 0 | |
147 self.current_dmx_levels = [0] * 68 | |
148 self.after(0, self.send_dmx_levels_loop) # start DMX sending loop | |
135 | 149 |
136 # this is a mechanism to stop Tk from autoshifting too much. | 150 # this is a mechanism to stop Tk from autoshifting too much. |
137 # if this variable is true, the mouse button is down. we don't want | 151 # if this variable is true, the mouse button is down. we don't want |
138 # to shift until they release it. when it is released, we will | 152 # to shift until they release it. when it is released, we will |
139 # set it to false and then call autoshift. | 153 # set it to false and then call autoshift. |
148 self.set_prev_button = Tk.Button(topframe, text='Set Prev', | 162 self.set_prev_button = Tk.Button(topframe, text='Set Prev', |
149 command=lambda: cuelist.set_selection_as_prev(), | 163 command=lambda: cuelist.set_selection_as_prev(), |
150 fg='white', bg='blue') | 164 fg='white', bg='blue') |
151 self.set_prev_button.pack(side='left') | 165 self.set_prev_button.pack(side='left') |
152 | 166 |
167 self.auto_shift = Tk.IntVar() | |
168 self.auto_shift.set(1) | |
169 | |
153 self.auto_shift_checkbutton = Tk.Checkbutton(topframe, | 170 self.auto_shift_checkbutton = Tk.Checkbutton(topframe, |
154 variable=self.auto_shift, text='Autoshift', | 171 variable=self.auto_shift, text='Autoshift', |
155 command=self.toggle_autoshift, bg='black', fg='white', | 172 command=self.toggle_autoshift, bg='black', fg='white', |
156 highlightbackground='black') | 173 highlightbackground='black') |
157 self.auto_shift_checkbutton.pack(fill='both', side='left') | 174 self.auto_shift_checkbutton.pack(fill='both', side='left') |
175 | |
176 self.auto_load_times = Tk.IntVar() | |
177 self.auto_load_times.set(1) | |
178 | |
179 self.auto_load_times_checkbutton = Tk.Checkbutton(topframe, | |
180 variable=self.auto_load_times, text='Autoload Times', | |
181 command=self.toggle_autoshift, bg='black', fg='white', | |
182 highlightbackground='black') | |
183 self.auto_load_times_checkbutton.pack(fill='both', side='left') | |
158 | 184 |
159 self.set_next_button = Tk.Button(topframe, text='Set Next', | 185 self.set_next_button = Tk.Button(topframe, text='Set Next', |
160 command=lambda: cuelist.set_selection_as_next(), | 186 command=lambda: cuelist.set_selection_as_next(), |
161 fg='white', bg='red') | 187 fg='white', bg='red') |
162 self.set_next_button.pack(side='left') | 188 self.set_next_button.pack(side='left') |
186 self.shift_buttons[name] = shift | 212 self.shift_buttons[name] = shift |
187 self.go_buttons[name] = go | 213 self.go_buttons[name] = go |
188 | 214 |
189 scale.scale_var.trace('w', \ | 215 scale.scale_var.trace('w', \ |
190 lambda x, y, z, name=name, scale=scale: self.xfade(name, scale)) | 216 lambda x, y, z, name=name, scale=scale: self.xfade(name, scale)) |
217 go.timer_var.trace('w', | |
218 lambda x, y, z, scale=scale: scale.update_value_label()) | |
191 | 219 |
192 def button_press(event, name=name, scale=scale): | 220 def button_press(event, name=name, scale=scale): |
193 self.no_shifts_until_release = 1 # prevent shifts until release | 221 self.no_shifts_until_release = 1 # prevent shifts until release |
194 def button_release(event, name=name, scale=scale): | 222 def button_release(event, name=name, scale=scale): |
195 self.no_shifts_until_release = 0 | 223 self.no_shifts_until_release = 0 |
196 self.autoshift(name, scale) | 224 self.autoshift(name, scale) |
197 | 225 |
198 scale.scale.bind("<ButtonPress>", button_press) | 226 scale.scale.bind("<ButtonPress>", button_press) |
199 scale.scale.bind("<ButtonRelease>", button_release) | 227 scale.scale.bind("<ButtonRelease>", button_release) |
200 faderframe.pack(side='bottom', fill='both', expand=1) | 228 faderframe.pack(side='bottom', fill='both', expand=1) |
229 | |
230 self.current_dir = 'Next' | |
201 self.cues_as_subs = {} | 231 self.cues_as_subs = {} |
232 self.update_cue_cache() | |
233 def reload_cue_times(self): | |
234 prev, cur, next = self.cuelist.get_current_cues() | |
235 self.go_buttons['Next'].set_time(next.time) | |
236 def update_cue_cache(self): | |
237 """Rebuilds subs from the current cues. As this is expensive, we don't | |
238 do it unless necessary (i.e. whenever we shift or a cue is edited)""" | |
239 # load the subs to fade between | |
240 for cue, name in zip(self.cuelist.get_current_cues(), | |
241 ('Prev', 'Cur', 'Next')): | |
242 self.cues_as_subs[name] = cue.get_levels_as_sub() | |
243 self.compute_dmx_levels() | |
244 def compute_dmx_levels(self): | |
245 """Compute the DMX levels to send. This should get called whenever the | |
246 DMX levels could change: either during a crossfade or when a cue is | |
247 edited. Since this is called when we know that a change might occur, | |
248 we will send the new levels too.""" | |
249 cur_sub = self.cues_as_subs.get('Cur') | |
250 if cur_sub: | |
251 scale = self.scales[self.current_dir] | |
252 scale_val = scale.scale_var.get() | |
253 | |
254 other_sub = self.cues_as_subs[self.current_dir] | |
255 current_levels_as_sub = cur_sub.crossfade(other_sub, scale_val) | |
256 self.current_dmx_levels = current_levels_as_sub.get_dmx_list() | |
257 self.send_dmx_levels() | |
258 def send_dmx_levels(self): | |
259 # print "send_dmx_levels", self.current_dmx_levels | |
260 dmxclient.outputlevels(self.current_dmx_levels) | |
261 self.last_levels_sent = time.time() | |
262 def send_dmx_levels_loop(self): | |
263 diff = time.time() - self.last_levels_sent | |
264 if diff >= 2: # too long since last send | |
265 self.send_dmx_levels() | |
266 self.after(200, self.send_dmx_levels_loop) | |
267 else: | |
268 self.after(int((2 - diff) * 100), self.send_dmx_levels_loop) | |
202 def get_scale_desc(self, val, name): | 269 def get_scale_desc(self, val, name): |
270 """Returns a description to the TimedGoButton""" | |
203 go_button = self.go_buttons.get(name) | 271 go_button = self.go_buttons.get(name) |
204 if go_button: | 272 if go_button: |
205 time = go_button.get_time() | 273 time = go_button.get_time() |
206 return "%0.2f%%, %0.1fs left" % (val, time - ((val / 100.0) * time)) | 274 return "%0.2f%%, %0.1fs left" % (val, time - ((val / 100.0) * time)) |
207 else: | 275 else: |
219 | 287 |
220 for scale_name, scale in self.scales.items(): | 288 for scale_name, scale in self.scales.items(): |
221 scale.scale.set(0) | 289 scale.scale.set(0) |
222 self.cuelist.shift((-1, 1)[name == 'Next']) | 290 self.cuelist.shift((-1, 1)[name == 'Next']) |
223 | 291 |
224 # now load the subs to fade between | 292 self.update_cue_cache() |
225 for cue, name in zip(self.cuelist.get_current_cues(), | 293 if self.auto_load_times.get(): |
226 ('Prev', 'Cur', 'Next')): | 294 self.reload_cue_times() |
227 self.cues_as_subs[name] = cue.get_levels_as_sub() | |
228 print "cues_as_subs", self.cues_as_subs | |
229 def autoshift(self, name, scale): | 295 def autoshift(self, name, scale): |
230 scale_val = scale.scale_var.get() | 296 scale_val = scale.scale_var.get() |
231 | 297 |
232 if scale_val == 1: | 298 if scale_val == 1: |
233 if self.auto_shift.get(): | 299 if self.auto_shift.get(): |
252 else: | 318 else: |
253 # undo above work | 319 # undo above work |
254 self.scales[d].enable() | 320 self.scales[d].enable() |
255 self.go_buttons[d].enable() | 321 self.go_buttons[d].enable() |
256 | 322 |
257 cur_sub = self.cues_as_subs.get('Cur') | 323 self.current_dir = name |
258 if cur_sub: | 324 self.compute_dmx_levels() |
259 other_sub = self.cues_as_subs[name] | |
260 # print 'fade between %s and %s (%.2f)' % (cur_sub, other_sub, scale_val) | |
261 self.current_levels_as_sub = cur_sub.crossfade(other_sub, scale_val) | |
262 print "current levels", self.current_levels_as_sub.get_dmx_list() | |
263 # print | |
264 def opposite_direction(self, d): | 325 def opposite_direction(self, d): |
265 if d == 'Next': | 326 if d == 'Next': |
266 return 'Prev' | 327 return 'Prev' |
267 else: | 328 else: |
268 return 'Next' | 329 return 'Next' |
280 """Get this Cue as a combined Submaster, normalized. This method | 341 """Get this Cue as a combined Submaster, normalized. This method |
281 should not be called constantly, since it is somewhat expensive. It | 342 should not be called constantly, since it is somewhat expensive. It |
282 will reload the submasters from disk, combine all subs together, and | 343 will reload the submasters from disk, combine all subs together, and |
283 then compute the normalized form.""" | 344 then compute the normalized form.""" |
284 subdict = {} | 345 subdict = {} |
285 try: | 346 for line in self.sub_levels.split(','): |
286 print self, self.sub_levels | 347 try: |
287 for line in self.sub_levels.split(','): | |
288 line = line.strip() | 348 line = line.strip() |
289 # print 'line', line | 349 if not line: |
350 continue | |
290 sub, scale = line.split(':') | 351 sub, scale = line.split(':') |
291 # print 'sub', sub, 'scale', scale | |
292 sub = sub.strip() | 352 sub = sub.strip() |
293 scale = float(scale) | 353 scale = float(scale) |
294 subdict[sub] = scale | 354 subdict[sub] = scale |
295 # print 'subdict', subdict | 355 except ValueError: |
296 except (ValueError, AttributeError): | 356 print "Parsing error for '%s' in %s" % (self.sub_levels, self) |
297 print "parsing error when computing sub for", self | |
298 | 357 |
299 s = Submaster.Submasters() | 358 s = Submaster.Submasters() |
300 newsub = Submaster.sub_maxes(*[s[sub] * scale | 359 newsub = Submaster.sub_maxes(*[s[sub] * scale |
301 for sub, scale in subdict.items()]) | 360 for sub, scale in subdict.items()]) |
302 return newsub.get_normalized_copy() | 361 return newsub.get_normalized_copy() |
345 def set_next(self, index): | 404 def set_next(self, index): |
346 self.next_pointer = index | 405 self.next_pointer = index |
347 def set_prev(self, index): | 406 def set_prev(self, index): |
348 self.prev_pointer = index | 407 self.prev_pointer = index |
349 def bound_index(self, index): | 408 def bound_index(self, index): |
350 if not self.cues: | 409 if not self.cues or index < 0: |
351 return None | 410 return None |
352 else: | 411 else: |
353 return max(0, min(index, len(self.cues) - 1)) | 412 return min(index, len(self.cues) - 1) |
354 def get_current_cue_indices(self): | 413 def get_current_cue_indices(self): |
414 """Returns a list of the indices of three cues: the previous cue, | |
415 the current cue, and the next cue.""" | |
355 cur = self.current_cue_index | 416 cur = self.current_cue_index |
356 return [self.bound_index(index) for index in | 417 return [self.bound_index(index) for index in |
357 (self.prev_pointer or cur - 1, | 418 (self.prev_pointer or cur - 1, |
358 cur, | 419 cur, |
359 self.next_pointer or cur + 1)] | 420 self.next_pointer or cur + 1)] |
360 def get_current_cues(self): | 421 def get_current_cues(self): |
422 """Returns a list of three cues: the previous cue, the current cue, | |
423 and the next cue.""" | |
361 return [self.get_cue_by_index(index) | 424 return [self.get_cue_by_index(index) |
362 for index in self.get_current_cue_indices()] | 425 for index in self.get_current_cue_indices()] |
363 def get_cue_by_index(self, index): | 426 def get_cue_by_index(self, index): |
364 if index: | 427 try: |
365 return self.cues[self.bound_index(index)] | 428 return self.cues[self.bound_index(index)] |
366 else: | 429 except TypeError: |
367 return empty_cue | 430 return empty_cue |
368 def __del__(self): | 431 def __del__(self): |
369 self.save() | 432 self.save() |
370 def save(self): | 433 def save(self): |
371 print "Saving cues to", self.filename | 434 print "Saving cues to", self.filename |
377 | 440 |
378 class TkCueList(CueList, Tk.Frame): | 441 class TkCueList(CueList, Tk.Frame): |
379 def __init__(self, master, filename): | 442 def __init__(self, master, filename): |
380 CueList.__init__(self, filename) | 443 CueList.__init__(self, filename) |
381 Tk.Frame.__init__(self, master, bg='black') | 444 Tk.Frame.__init__(self, master, bg='black') |
445 self.fader = None | |
382 | 446 |
383 self.edit_tl = Tk.Toplevel() | 447 self.edit_tl = Tk.Toplevel() |
384 self.editor = CueEditron(self.edit_tl, changed_callback=self.redraw_cue) | 448 self.editor = CueEditron(self.edit_tl, |
449 changed_callback=self.cue_changed) | |
385 self.editor.pack(fill='both', expand=1) | 450 self.editor.pack(fill='both', expand=1) |
386 | 451 |
387 def edit_cue(index): | 452 def edit_cue(index): |
388 index = int(index) | 453 index = int(index) |
389 self.editor.set_cue_to_edit(self.cues[index]) | 454 self.editor.set_cue_to_edit(self.cues[index]) |
409 | 474 |
410 self.cue_label_windows = {} | 475 self.cue_label_windows = {} |
411 for count, cue in enumerate(self.cues): | 476 for count, cue in enumerate(self.cues): |
412 self.display_cue(count, cue) | 477 self.display_cue(count, cue) |
413 self.update_cue_indicators() | 478 self.update_cue_indicators() |
479 def set_fader(self, fader): | |
480 self.fader = fader | |
414 def wheelscroll(self, evt): | 481 def wheelscroll(self, evt): |
415 """Perform mouse wheel scrolling""" | 482 """Perform mouse wheel scrolling""" |
416 amount = 2 | 483 if evt.num == 4: # scroll down |
417 if evt.num == 4: | |
418 amount = -2 | 484 amount = -2 |
485 else: # scroll up | |
486 amount = 2 | |
419 self.hlist.yview('scroll', amount, 'units') | 487 self.hlist.yview('scroll', amount, 'units') |
420 def redraw_cue(self, cue): | 488 def cue_changed(self, cue): |
421 path = self.cues.index(cue) | 489 path = self.cues.index(cue) |
422 for col, header in enumerate(self.columns): | 490 for col, header in enumerate(self.columns): |
423 try: | 491 try: |
424 text = getattr(cue, header) | 492 text = getattr(cue, header) |
425 except AttributeError: | 493 except AttributeError: |
427 | 495 |
428 if col == 0: | 496 if col == 0: |
429 self.cue_label_windows[path]['text'] = text | 497 self.cue_label_windows[path]['text'] = text |
430 else: | 498 else: |
431 self.hlist.item_configure(path, col, text=text) | 499 self.hlist.item_configure(path, col, text=text) |
500 | |
501 if cue in self.get_current_cues() and self.fader: | |
502 self.fader.update_cue_cache() | |
503 self.fader.reload_cue_times() | |
432 def display_cue(self, path, cue): | 504 def display_cue(self, path, cue): |
433 for col, header in enumerate(self.columns): | 505 for col, header in enumerate(self.columns): |
434 try: | 506 try: |
435 text = getattr(cue, header) | 507 text = getattr(cue, header) |
436 except AttributeError: | 508 except AttributeError: |
450 self.hlist.item_create(path, col, text=text) | 522 self.hlist.item_create(path, col, text=text) |
451 def reset_cue_indicators(self, cue_indices=None): | 523 def reset_cue_indicators(self, cue_indices=None): |
452 """If cue_indices is None, we'll reset all of them.""" | 524 """If cue_indices is None, we'll reset all of them.""" |
453 cue_indices = cue_indices or self.cue_label_windows.keys() | 525 cue_indices = cue_indices or self.cue_label_windows.keys() |
454 for key in cue_indices: | 526 for key in cue_indices: |
527 if key is None: | |
528 continue | |
455 window = self.cue_label_windows[key] | 529 window = self.cue_label_windows[key] |
456 window.configure(fg='white', bg='black') | 530 window.configure(fg='white', bg='black') |
457 def update_cue_indicators(self): | 531 def update_cue_indicators(self): |
458 states = dict(zip(self.get_current_cue_indices(), | 532 states = dict(zip(self.get_current_cue_indices(), |
459 ('prev', 'cur', 'next'))) | 533 ('prev', 'cur', 'next'))) |
460 | 534 |
461 for count, state in states.items(): | 535 for count, state in states.items(): |
536 if count is None: | |
537 continue | |
462 window = self.cue_label_windows[count] | 538 window = self.cue_label_windows[count] |
463 bg, fg = cue_state_indicator_colors[state] | 539 bg, fg = cue_state_indicator_colors[state] |
464 window.configure(bg=bg, fg=fg) | 540 window.configure(bg=bg, fg=fg) |
465 def shift(self, diff): | 541 def shift(self, diff): |
466 self.reset_cue_indicators(self.get_current_cue_indices()) | 542 self.reset_cue_indicators(self.get_current_cue_indices()) |
467 CueList.shift(self, diff) | 543 CueList.shift(self, diff) |
468 self.update_cue_indicators() | 544 self.update_cue_indicators() |
469 # try to see all indices, but next takes priority over all, and cur | 545 # try to see all indices, but next takes priority over all, and cur |
470 # over prev | 546 # over prev |
471 for index in self.get_current_cue_indices(): | 547 for index in self.get_current_cue_indices(): |
472 self.hlist.see(index) | 548 if index is not None: |
549 self.hlist.see(index) | |
473 def select_callback(self, index): | 550 def select_callback(self, index): |
474 new_next = int(index) | 551 new_next = int(index) |
475 self.set_next(new_next) | 552 self.set_next(new_next) |
476 def set_next(self, index): | 553 def set_next(self, index): |
477 prev, cur, next = self.get_current_cue_indices() | 554 prev, cur, next = self.get_current_cue_indices() |
512 self.master.title("Editing '%s'" % self.cue.name) | 589 self.master.title("Editing '%s'" % self.cue.name) |
513 except AttributeError: | 590 except AttributeError: |
514 pass | 591 pass |
515 def setup_editing_forms(self): | 592 def setup_editing_forms(self): |
516 self.variables = {} | 593 self.variables = {} |
517 for row, field in enumerate(('name', 'time', 'page', 'desc', 'sub_levels')): | 594 for row, field in enumerate(('name', 'time', 'page', 'desc', |
595 'sub_levels')): | |
518 lab = Tk.Label(self, text=field, fg='white', bg='black') | 596 lab = Tk.Label(self, text=field, fg='white', bg='black') |
519 lab.grid(row=row, column=0, sticky='nsew') | 597 lab.grid(row=row, column=0, sticky='nsew') |
520 | 598 |
521 entryvar = Tk.StringVar() | 599 entryvar = Tk.StringVar() |
522 entry = Tk.Entry(self, fg='white', bg='black', | 600 entry = Tk.Entry(self, fg='white', bg='black', |
535 | 613 |
536 entryvar.trace('w', field_changed) | 614 entryvar.trace('w', field_changed) |
537 self.columnconfigure(1, weight=1) | 615 self.columnconfigure(1, weight=1) |
538 def fill_in_cue_info(self): | 616 def fill_in_cue_info(self): |
539 self.enable_callbacks = 0 | 617 self.enable_callbacks = 0 |
540 for row, field in enumerate(('name', 'time', 'page', 'desc', 'sub_levels')): | 618 for row, field in enumerate(('name', 'time', 'page', 'desc', |
619 'sub_levels')): | |
541 text = '' | 620 text = '' |
542 if self.cue: | 621 if self.cue: |
543 try: | 622 try: |
544 text = getattr(self.cue, field) | 623 text = getattr(self.cue, field) |
545 except AttributeError: | 624 except AttributeError: |