1 from gi.repository
import Gtk
as gtk
2 from gi.repository
import Gdk
as gdk
3 from gi.repository
import GObject
as gobject
22 self.
window = gtk.Window(gtk.WindowType.TOPLEVEL)
23 self.window.set_title(
'WH-Frequency Counter')
24 self.window.set_border_width(10)
25 self.window.set_default_size(730, 400)
27 self.
logger = logging.getLogger(__name__)
31 segments = self.trs_parser.parse(progress_update_fcn=progress_dialog.set_fraction, progress_next_phase_fcn=progress_dialog.next_phase, validate=
False, seg_filters=[])
36 map(
lambda seg: self.output.add_item(seg), segments)
40 progress_dialog.ensure_finish()
42 scrolled_win = gtk.ScrolledWindow()
43 scrolled_win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
44 scrolled_win.add(treeview)
46 export_button = UIUtils.create_button(
'Export Results', UIUtils.BUTTON_ICONS.EXPORT)
47 export_button.connect(
'clicked',
lambda widget: self.
_export_results(treeview))
49 close_button = UIUtils.create_button(
'Close', UIUtils.BUTTON_ICONS.CLOSE)
50 close_button.connect(
'clicked',
lambda w: self.window.destroy())
52 add_button = UIUtils.create_button(
'Add Count Column', UIUtils.BUTTON_ICONS.ADD)
53 add_button.connect(
'clicked',
lambda w: self.
_add_count_col(treeview))
55 self.
remove_button = UIUtils.create_button(
'Remove Count Column', UIUtils.BUTTON_ICONS.REMOVE)
59 options_frame = gtk.Frame(label=
'Options')
60 options_vbox = gtk.VBox()
69 options_frame.add(options_vbox)
72 self.statusbar.set_has_resize_grip(
False)
73 self.
num_whq = treeview.get_model().iter_n_children(
None)
78 bbox = gtk.HButtonBox()
79 bbox.pack_start(export_button,
True,
False, 0)
80 bbox.pack_start(add_button,
True,
False, 0)
82 bbox.pack_start(close_button,
True,
False, 0)
84 vbox.pack_start(scrolled_win,
True,
True, 0)
85 vbox.pack_start(self.
statusbar,
False,
False, 0)
86 vbox.pack_end(bbox,
False,
False, 0)
87 vbox.pack_end(options_frame,
False,
False, 0)
90 self.window.show_all()
93 return map(
lambda word: [word.capitalize(), word, 0],
'who what why when where how'.split() )
96 tree_model = self.
_build_list_store(link_segs=self.linked_checkbox.get_active(), prev_store=treeview.get_model(), show_context=self.context_checkbox.get_active())
97 treeview.set_model(tree_model)
100 tree_model = self.
_build_list_store(link_segs=self.linked_checkbox.get_active(), prev_store=
None, show_context=self.context_checkbox.get_active())
101 treeview.set_model(tree_model)
102 self.
num_whq = treeview.get_model().iter_n_children(
None)
106 self.remove_button.set_sensitive(len(self.
count_cols) > 0)
109 dialog = gtk.Dialog(title=
'Remove Count Column',
110 buttons=(gtk.STOCK_CANCEL, gtk.ResponseType.CANCEL, gtk.STOCK_OK, gtk.ResponseType.OK))
111 dialog.set_default_response(gtk.ResponseType.OK)
113 vbox = dialog.get_content_area()
115 list_store = gtk.ListStore(gobject.TYPE_STRING)
120 combo = gtk.ComboBox(model=list_store)
121 renderer = gtk.CellRendererText()
122 combo.pack_start(renderer,
True,
True, 0)
123 combo.add_attribute(renderer,
'text', 0)
127 hbox.pack_start(gtk.Label(
'Select Column:'),
True,
True, 0)
128 hbox.pack_start(combo,
True,
True, 0)
130 vbox.pack_start(hbox,
True,
True, 0)
133 response = dialog.run()
135 if response == gtk.ResponseType.CANCEL:
139 elif response == gtk.ResponseType.OK:
140 col_index = combo.get_active()
146 progress_dialog =
ProgressDialog(
'Removing Column...', [
'Rebuilding UI...'])
147 progress_dialog.show()
149 tree_model = self.
_build_list_store(link_segs=self.linked_checkbox.get_active(), prev_store=treeview.get_model(), show_context=self.context_checkbox.get_active())
151 old_col = treeview.get_column(6 + col_index)
152 treeview.remove_column(old_col)
156 while i < tree_model.get_n_columns():
157 col = treeview.get_column(i)
158 renderer = col.get_cell_renderers()[0]
159 col.set_attributes(renderer, text=i)
162 treeview.set_model(tree_model)
167 progress_dialog.ensure_finish()
170 dialog = gtk.Dialog(title=
'Add Count Column',
171 buttons=(gtk.STOCK_CANCEL, gtk.ResponseType.CANCEL, gtk.STOCK_OK, gtk.ResponseType.OK))
172 dialog.set_default_response(gtk.ResponseType.OK)
174 vbox = dialog.get_content_area()
178 name_label = gtk.Label(
'Column Name:')
180 grid.attach(name_label, 0, 0, 1, 1, 3)
182 name_entry = gtk.Entry()
184 grid.attach(name_entry, 1, 0, 1, 1, 3)
186 regex_label = gtk.Label(
'Search term:')
188 grid.attach(regex_label, 0, 1, 1, 1, 3)
190 regex_entry = gtk.Entry()
192 grid.attach(regex_entry, 1, 1, 1, 1, 3)
194 vbox.pack_start(grid,
True,
True, 0)
199 response = dialog.run()
200 if response == gtk.ResponseType.CANCEL:
204 elif response == gtk.ResponseType.OK:
205 name = name_entry.get_text()
206 regex = regex_entry.get_text()
213 self.count_cols.append( [name, regex, 0] )
215 progress_dialog =
ProgressDialog(
'Adding New Column...', [
'Counting occurrances...'])
216 progress_dialog.show()
217 list_store = self.
_build_list_store(link_segs=self.linked_checkbox.get_active(), prev_store=treeview.get_model(), show_context=self.context_checkbox.get_active())
218 progress_dialog.ensure_finish()
220 treeview.set_model(list_store)
221 col = gtk.TreeViewColumn(name, gtk.CellRendererText(), text=list_store.get_n_columns() - 1)
222 treeview.append_column(col)
227 except Exception
as error:
228 if isinstance(error, sre_constants.error):
229 error_dialog = gtk.MessageDialog(buttons=(gtk.ButtonType.OK), message_format=
'The regular expression that has been entered is invalid.')
231 error_dialog.destroy()
233 error_dialog = gtk.MessageDialog(buttons=(gtk.ButtonType.OK), message_format=
'The application has encountered an internal error. Please contact your local programmer to assign blame.')
235 error_dialog.destroy()
239 progress_dialog.destroy()
241 self.logger.error(
'Exception in add_column():\n %s\nStacktrace: %s' % (error, traceback.format_exc()))
244 context_id = self.statusbar.get_context_id(
'num_whq')
245 self.statusbar.pop(context_id)
246 totals =
'Totals: WHQ Count: %d' % (self.
num_whq)
249 totals +=
', %s: %d' % (col[0], col[2])
251 self.statusbar.push(context_id, totals)
267 start_time = (
'%0.2f' % (start_time))
if start_time !=
None else ''
268 end_time = (
'%0.2f' % (end_time))
if end_time !=
None else ''
272 '%s - %s' % (start_time, end_time),
282 while i < len(utter.seg.utters)
and utter_index < 0:
283 if utter.seg.utters[i] == utter:
294 return '(%s)\n%s\n(%s)' % (bwd_phrase, cur_phrase, fwd_phrase)
298 seg_index = start_utter.seg.num
304 i_in_bounds =
lambda i: i >= 0
305 init_j =
lambda i, seg: utter_index
if i == seg_index
else len(seg.utters) - 1
306 j_in_bounds =
lambda j, seg: j >= 0
308 i_in_bounds =
lambda i: i < len(self.filter_manager.get_segs())
309 init_j =
lambda i, seg: utter_index
if i == seg_index
else 0
310 j_in_bounds =
lambda j, seg: j < len(seg.utters)
313 while i_in_bounds(i)
and not phrase:
314 seg = self.filter_manager.get_seg_by_num(i)
316 while j_in_bounds(j, seg)
and not phrase:
317 phrase = seg.utters[j].trans_phrase
325 segments = self.output.get_filtered_items()
326 list_store = gtk.ListStore(gobject.TYPE_INT,
337 utter_chains = FilterManager.get_chains(segments)
338 for head
in utter_chains:
341 trans_phrase = cur.trans_phrase
342 speaker_str = DBConstants.SPEAKER_CODES.get_option(cur.speaker.get_codeinfo().get_code()).desc
if cur.speaker
else '(Unknown)'
343 target_str = DBConstants.TRANS_CODES[1].get_option(cur.trans_codes[1]).desc
if cur.trans_codes
else '(Unknown)'
349 trans_phrase +=
'\n->%s' % (cur.trans_phrase)
351 speaker_str +=
', %s' % (DBConstants.SPEAKER_CODES.get_option(cur.speaker.get_codeinfo().get_code()).desc)
353 target_str +=
', %s' % (DBConstants.TRANS_CODES[1].get_option(cur.trans_codes[1]).desc)
357 tail = FilterManager.get_endpoint(FilterManager.ENDPOINT_TYPES.TAIL, head)
362 whq_count = prev_store[row_num][5]
if prev_store
else 1
363 row = self.
_build_list_store_row(head.id, head.start, tail.end, trans_phrase, speaker_str, target_str, whq_count)
366 count = len(re.findall(self.
count_cols[j][1], trans_phrase))
371 list_store.append(row)
375 for i
in range(len(segments)):
376 for utter
in segments[i].utters:
377 trans_phrase = utter.trans_phrase
381 whq_count = prev_store[row_num][5]
if prev_store
else 1
382 speaker_str = DBConstants.SPEAKER_CODES.get_option(utter.speaker.speaker_codeinfo.get_code()).desc
if utter.speaker
else '(Unknown)'
383 target_str = DBConstants.TRANS_CODES[1].get_option(utter.trans_codes[1]).desc
if utter.trans_codes
else '(Unknown)'
384 row = self.
_build_list_store_row(utter.id, utter.start, utter.end, trans_phrase, speaker_str, target_str, whq_count)
387 count = len(re.findall(self.
count_cols[j][1], utter.trans_phrase.lower()))
392 list_store.append(row)
399 treeview = gtk.TreeView(list_store)
402 col = gtk.TreeViewColumn(
'ID', gtk.CellRendererText(), text=0)
403 col.set_visible(
False)
404 col.set_resizable(
True)
405 treeview.append_column(col)
407 col_names = [
'Time',
'Phrase',
'Speakers',
'Target Listeners']
408 for i
in range(len(col_names)):
409 col = gtk.TreeViewColumn(col_names[i], gtk.CellRendererText(), text=(i + 1))
410 col.set_resizable(
True)
411 treeview.append_column(col)
413 spin_renderer = gtk.CellRendererSpin()
414 adj = gtk.Adjustment(value=1, lower=0, upper=100, page_incr=5, step_incr=1, page_size=0)
415 spin_renderer.set_property(
'adjustment', adj)
416 spin_renderer.set_property(
'editable',
True)
417 spin_renderer.connect(
'edited', self.
_update_row, treeview)
418 col = gtk.TreeViewColumn(
'WHQ Count', spin_renderer, text=(len(col_names) + 1))
419 col.set_resizable(
True)
420 treeview.append_column(col)
423 col = gtk.TreeViewColumn(self.
count_cols[i][0], gtk.CellRendererText(), text=(len(col_names) + 2 + i))
424 col.set_resizable(
True)
425 treeview.append_column(col)
432 if gdk.keyval_name(event.keyval).lower() ==
'tab':
433 (model, paths) = treeview.get_selection().get_selected_rows()
434 total_rows = model.iter_n_children(
None)
435 if paths
and paths[0][0] + 1 < total_rows:
436 treeview.set_cursor(paths[0][0] + 1, focus_column=treeview.get_column(3), start_editing=
True)
440 model = treeview.get_model()
441 old_val = int(model[path][5])
443 self.
num_whq += (new_val - old_val)
445 model[path][5] = new_val
449 dialog = gtk.FileChooserDialog(title=
'Save',
450 action=gtk.FileChooserAction.SAVE,
451 buttons=(gtk.STOCK_CANCEL, gtk.ResponseType.CANCEL, gtk.STOCK_SAVE, gtk.ResponseType.OK))
452 dialog.set_default_response(gtk.ResponseType.OK)
453 dialog.add_filter(UIUtils.CSV_FILE_FILTER)
454 dialog.add_filter(UIUtils.ALL_FILE_FILTER)
457 content_area = dialog.get_content_area()
458 open_now_checkbox = gtk.CheckButton(
'Open Immediately')
459 open_now_checkbox.set_active(
True)
460 align = gtk.Alignment(xalign=1.0, yalign=1.0)
461 align.add(open_now_checkbox)
462 content_area.pack_end(align,
False,
False, 0)
463 open_now_checkbox.show()
466 response = dialog.run()
467 if response == gtk.ResponseType.CANCEL:
469 elif response == gtk.ResponseType.OK:
470 filename = dialog.get_filename()
471 open_now = open_now_checkbox.get_active()
474 count_col_headers, count_col_vals, count_col_totals = zip(*self.
count_cols)
if self.
count_cols else [[]] * 3
475 exporter =
FreqExporter(filename, self.trs_parser.filename)
477 exporter.write_header_row(count_col_headers)
478 list_store = treeview.get_model()
479 tree_it = list_store.get_iter_first()
482 phrase = list_store.get_value(tree_it, 2).replace(
'\n',
' ').replace(
'\r',
'')
483 time_str = list_store.get_value(tree_it, 1)
484 speakers_str = list_store.get_value(tree_it, 3)
or '(Unknown)'
485 targets_str = list_store.get_value(tree_it, 4)
or '(Unknown)'
486 num_utters = int(list_store.get_value(tree_it, 5))
489 while i < list_store.get_n_columns():
490 count_col_vals.append( int(list_store.get_value(tree_it, i)) )
493 exporter.write_count_row(time_str, phrase, speakers_str, targets_str, num_utters, count_col_vals)
495 tree_it = list_store.iter_next(tree_it)
497 exporter.finish(self.
num_whq, count_col_totals)
500 subprocess.Popen([
'%s' % DBConstants.SETTINGS.SPREADSHEET_PATH, filename])
502 result_dialog = gtk.MessageDialog(buttons=gtk.ButtonType.OK, message_format=
'Results exported successfully.')
504 result_dialog.destroy()