1 """GTK components for L{qubx.table}.
2
3 Copyright 2008-2014 Research Foundation State University of New York
4 This file is part of QUB Express.
5
6 QUB Express is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 QUB Express is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License,
17 named LICENSE.txt, in the QUB Express program directory. If not, see
18 <http://www.gnu.org/licenses/>.
19
20 """
21
22 from cStringIO import StringIO
23 import qubx.notebook
24 import qubx.notebookGTK
25 import qubx.pyenv
26 import qubx.pyenvGTK
27 from qubx.util_types import *
28 from qubx.GTK import *
29 from qubx.table import *
30 import qubx.accept
31 import qubx.table
32 import gobject
33 import gtk
34 from gtk import gdk
35 from qubx.pyenvGTK import prompt_entry
36 from qubx.toolspace import ColorInfo
37
38 COLOR_TABLE_FILE_MENU = ('tableGTK.file_menu', (0,1,0,1))
39 ColorInfo[COLOR_TABLE_FILE_MENU[0]].label = 'Tables file menu'
40 COLOR_MNU_CHECKED = ('tableGTK.checked_menu', (1, .7, 0, 1))
41 ColorInfo[COLOR_MNU_CHECKED[0]].label = 'Tables check-column menu'
42
44 traceback.print_stack()
45 print
46 gobject.idle_add(*args, **kw)
47 qubx.table.run_later = gobject.idle_add
48
50 """View/controller for a L{qubx.table.Table}.
51
52 @ivar showing: (def True) if False, OnSelect edits are via dialog
53 @ivar table: L{qubx.table.Table}
54 @ivar OnEdit: L{WeakEvent}(label) in case you want to seal an L{qubx.undo.UndoStack}
55 @ivar OnSortColumnChanged: L{WeakEvent}(TableView)
56 """
57
58 __explore_featured = ['global_name', 'OnEdit', 'OnSortColumnChanged', 'showing', 'table', 'model', '_ix_of_col',
59 'dispose', 'sorted_ix', 'raw_ix', 'get_column_ix', 'set_index_widget']
60
61 - def __init__(self, table, global_name=''):
100 if self.table.sortable:
101 return self.model.convert_child_path_to_path((raw,))[0]
102 else:
103 return raw
105 if self.table.sortable:
106 return self.model.convert_path_to_child_path((sorted,))[0]
107 else:
108 return sorted
110 """Returns the index of the named column; adds the column if none."""
111 try:
112 return self._ix_of_name[nm]
113 except:
114 col_options = {}
115 if (nm == '__ix_checked') or (self.table.accept[nm] in (bool, acceptBool)):
116 ix = self._spare_bool.pop()
117 self._bool_names.append(nm)
118 rend = gtk.CellRendererToggle()
119 rend.set_property('activatable', True)
120 self.__col_events.append( (rend, rend.connect('toggled', self.__onToggle, ix)) )
121 else:
122 ix = self._spare.pop()
123 rend = gtk.CellRendererText()
124 if self.table.choices[nm] is None:
125 rend.set_property('editable', True)
126 self.__col_events.append( (rend, rend.connect('editing_started', self._onEditingStarted, ix)) )
127 if self.table.accept[nm] != qubx.accept.acceptNothing:
128 self.__col_events.append( (rend, rend.connect('edited', self._onEdit, ix)) )
129 col_options['text'] = ix
130 try:
131 units = self.table.units[nm]
132 except:
133 units = ""
134 nmu = nm if (not units) else '%s [%s]' % (nm, units)
135 col = gtk.TreeViewColumn(gtk_literally(nmu), rend, **col_options)
136 if isinstance(rend, gtk.CellRendererToggle):
137 col.add_attribute( rend, "active", ix)
138 if nm == '__ix_checked':
139 self.table.add_notebook_item('Pick columns...', qubx.notebookGTK.NbSubTablePicker(self.table, self.table.global_name and ("%s.notebook['Pick columns...']"%self.table.global_name) or "", self.table.nb_get_caption))
140 hdr = gtk.HBox()
141 hdr.show()
142 self.mnuChecked = gtk.Menu()
143 btn = qubx.toolspace.Button_Popup(self.mnuChecked, COLOR_MNU_CHECKED, 'Act on all checked rows...', self.ref(self.__onPopupChecked))
144 btn.show()
145 hdr.pack_start(btn, False, True)
146 self.btnChecked = btn
147 btn = qubx.notebookGTK.Button_Notebook(scale=0.75)
148 btn.items = self.table.notebook_items
149 btn.show()
150 hdr.pack_start(btn, False, True)
151 self.btnNotebook = btn
152 col.set_widget(hdr)
153 self.tvcol_checked, self.tvcol_event = col, col.connect('clicked', self.__onClickMenus)
154
155 self.nbTable = self.table.notebook['Default']
156 elif self.table.sortable:
157 self.model.set_sort_func(ix, self.__sort_func, ix)
158 col.set_sort_column_id(ix)
159 self.__sort_cols.append(ix)
160 self.append_column(col)
161 self._col_of_name[nm] = col
162 self._ix_of_name[nm] = ix
163 self._name_of_col[ix] = nm
164 self._used_col.append(ix)
165 self._ix_of_col[col] = ix
166 if self.table.sortable and (ix == 0):
167 self.model.set_sort_column_id(0, gtk.SORT_ASCENDING)
168 return ix
170 field = self._name_of_col[col_ix]
171 val1, val2 = (self.table[model.get_path(it)[0], field] for it in (iter1, iter2))
172 if val1 < val2:
173 return -1
174 elif val1 == val2:
175 return 0
176 return 1
178 x, y, mods = self.btnNotebook.window.get_pointer()
179 if x < 0:
180 self.btnChecked.do_popup()
181 else:
182 self.btnNotebook.do_popup()
197 self.OnSortColumnChanged(self)
228 self._row = self.raw_ix(int(path_string))
229 self._col = col
230
231 - def _onEdit(self, cell, path_string, new_text, col):
245 i = self.raw_ix(int(path_string))
246 field = self._name_of_col[col]
247 if field == '__ix_checked':
248 val = not self.table.checked[i]
249 if self.table.global_name:
250 qubx.pyenv.env.scriptable_if_matching('%s.set_checked(%i, %s)' % (self.table.global_name, i, repr(val)),
251 [(self.table.global_name, self.table)])
252 self.table.set_checked(i, val)
253 else:
254 val = not self.table[i, field]
255 if self.table.global_name:
256 qubx.pyenv.env.scriptable_if_matching('%s[%i, %s] = %s' % (self.table.global_name, i, repr(field), repr(val)),
257 [(self.table.global_name, self.table)])
258 self.table[i, field] = val
259 self.OnEdit('table edit')
260 - def _onFocus(self, selfy, event, focused):
263 if self.__waiting_first_cursor_change:
264 self.__waiting_first_cursor_change = False
265 return
266 if self._ext_sel:
267 return
268 if not focused:
269
270 return
271 path, col = self.get_cursor()
272 if path is None:
273 self._row = None
274 else:
275 self._row = self.raw_ix(path[0])
276 if col is None:
277 pass
278 else:
279 self._col = self._ix_of_col[col]
280 field = (not (self._col is None)) and self._name_of_col[self._col] or None
281 if self.__select_changed_cursor:
282 self.__select_changed_cursor = False
283 else:
284 self.table.select(self._row, field, sender=self)
286 if (path is None) or (col is None):
287 return
288 field = (not (self._col is None)) and self._name_of_col[self._col] or None
289 self.table.OnDoubleClick(self.raw_ix(path[0]), field)
300 col = self._col_of_name[name]
301 ix = self._ix_of_name[name]
302 self.remove_column(col)
303 del self._col_of_name[name]
304 del self._ix_of_name[name]
305 del self._name_of_col[ix]
306 self._used_col.remove(ix)
307 if name in self._bool_names:
308 self._bool_names.remove(name)
309 self._spare_bool.append(ix)
310 else:
311 self._spare.append(ix)
313 t = self.table
314 def getitem(c):
315 if not (c in self._name_of_col):
316 if c < t.max_fields:
317 return ""
318 else:
319 return False
320 field = self._name_of_col[c]
321 if field == '__ix_checked':
322 return t.checked[i]
323 elif field in self._bool_names:
324 return t.get(i, field)
325 else:
326 return t.format[field](t.get(i, field))
327 row = [getitem(c) for c in xrange(t.max_fields + t.max_bools)]
328 self.model_raw.insert(i, row)
330 self.model_raw.remove(self.model_raw.get_iter((i,)))
331 if self._row == i:
332 self.table.select(None, sender=self)
333 - def _onSet(self, i, field, val, prev, undoing=False):
341 if (sender != self) and (0 <= i < len(self.model)):
342 if self.showing:
343 self._ext_sel = True
344 self.grab_focus()
345 col = field and self._col_of_name[field]
346
347 self._ext_sel = False
348 self.__select_changed_cursor = True
349 gobject.idle_add(self.set_cursor, (self.sorted_ix(i),), col, True)
350 elif field:
351 new_val = prompt_entry("%s[%i] = " % (field, i), self.table[i, field], self.table.accept[field], self.table.format[field],
352 "%s - Editing %s" % (qubx.global_namespace.QubX.appname, self.table.label))
353 if not (new_val is None):
354 qubx.pyenv.env.scriptable_if_matching('%s[%i, %s] = %s' %
355 (self.table.global_name, i, repr(field), repr(new_val)),
356 [(self.table.global_name, self.table)])
357 self.table[i, field] = new_val
358 self.OnEdit('table edit')
359
361 self.model_raw.set_value(self.model_raw.get_iter((i,)), self.__ix_checked, checked)
374 - def _onChoice(self, item, path, field, choice):
378 self.mnuChecked.foreach(lambda item: self.mnuChecked.remove(item))
379 build_menuitem('Un-check all', self.ref(self.__onClickUncheck), menu=self.mnuChecked)
380 build_menuitem('Check rows if...', self.ref(self.__onClickCheckIf), menu=self.mnuChecked)
381 build_menuitem('Invert selection', self.ref(self.__onClickInvert), menu=self.mnuChecked)
382 build_menuitem('Delete rows', self.ref(self.__onClickDel), menu=self.mnuChecked)
383 for field in self.table.fields:
384 if (field == 'Index') or (self.table.accept[field] == acceptNothing):
385 continue
386 build_menuitem('Edit %s...' % field, self.ref(bind(self.__onClickEdit, field)), menu=self.mnuChecked)
387 return True
421 t = self.table
422 chk_ixs = [i for i in xrange(t.size) if t.checked[i]]
423 if not chk_ixs:
424 qubx.GTK.ShowMessage("Please mark some rows first.", title='Editing %s - no rows chosen' % field)
425 return
426 old_val = t[chk_ixs[0], field]
427 new_val = prompt_entry('Set "%s" of all checked rows to' % field, old_val, t.accept[field], t.format[field],
428 "%s - Editing %s" % (qubx.global_namespace.QubX.appname, self.table.label))
429 if not (new_val is None):
430 qubx.pyenv.env.scriptable_if_matching("""for i in xrange(%s.size):
431 if %s.checked[i]:
432 %s[i, %s] = %s""" % (t.global_name, t.global_name, t.global_name, repr(field), repr(new_val)),
433 [(t.global_name, t)])
434 for ix in chk_ixs:
435 t[ix, field] = new_val
436 - def check_rows_if(self, copy_rows_type=None, group=None, inverse=False, criteria=None):
437 crt, grp, inv, cta = prompt_check_rows(self.table, copy_rows_type, group, inverse, criteria)
438 if crt is None:
439 return
440 QubX = qubx.global_namespace.QubX
441 if self.table.global_name:
442 if crt == COPY_ROWS_ALL:
443 qubx.pyenv.env.scriptable_if_matching('%s.check_rows_if(copy_rows_type=COPY_ROWS_ALL)'
444 % self.table.global_name,
445 [(self.table.global_name, self.table)])
446 elif crt == COPY_ROWS_GROUP:
447 qubx.pyenv.env.scriptable_if_matching('%s.check_rows_if(copy_rows_type=COPY_ROWS_GROUP, group=%s, inverse=%s)'
448 % (self.table.global_name,
449 repr(grp), repr(inv)),
450 [(self.table.global_name, self.table)])
451 elif crt == COPY_ROWS_CRITERIA:
452 qubx.pyenv.env.scriptable_if_matching('%s.check_rows_if(copy_rows_type=COPY_ROWS_CRITERIA, criteria=%s)'
453 % (self.table.global_name,
454 repr(cta)),
455 [(self.table.global_name, self.table)])
456 elif crt == COPY_ROWS_CHECKED:
457 qubx.pyenv.env.scriptable_if_matching('%s.check_rows_if(copy_rows_type=COPY_ROWS_CHECKED)'
458 % self.table.global_name,
459 [(self.table.global_name, self.table)])
460 self.table.check_rows_if(copy_rows_type=crt, group=grp, inverse=inv, criteria=cta)
461
462
464 """A row of controls for the top of some L{TableView}s."""
465
466 __explore_featured = ['ADD', 'REMOVE', 'ADD_FIELD', 'CLOSE', 'FILE_MENU', 'COPY_ROWS', 'CALCULATE', 'PLOT',
467 'table', 'undoStack', 'OnClickClose', 'actions', 'need_sel', 'add_row', 'remove_row',
468 'add_field', 'copy_rows', 'calculate', 'plot', 'acceptExpr', 'save']
469
470 ADD = 1
471 REMOVE = 2
472 ADD_FIELD = 3
473 CLOSE = 4
474 FILE_MENU = 5
475 COPY_ROWS = 6
476 CALCULATE = 7
477 PLOT = 8
478 - def __init__(self, table, undoStack=None, *args):
479 """
480 @param table: L{qubx.table.Table}
481 @param undoStack: assuming there is already a L{qubx.table.TableUndo}(table, undoStack), any edits from here will be sealed
482 @param ...: constants ADD or REMOVE (buttons), any string (label), any gtk.Widget, or pair label, action (button that calls action())
483 """
484 gtk.HBox.__init__(self)
485 self.__ref = Reffer()
486 self.table = table
487 self.undoStack = undoStack
488 self.OnClickClose = WeakEvent()
489 self.actions = {}
490 self.need_sel = []
491 for x in args:
492 if isinstance(x, str):
493 pack_label(x, self)
494 elif isinstance(x, gtk.Widget):
495 pack_item(x, self)
496 elif x == self.ADD:
497 x = ('Add row', self.add_row)
498 elif x == self.REMOVE:
499 x = ('Del row', self.remove_row, True)
500 elif x == self.ADD_FIELD:
501 x = ('Add a column...', self.add_field)
502 elif x == self.COPY_ROWS:
503 x = ('Copy row(s) to Table...', self.copy_rows)
504 elif x == self.CALCULATE:
505 x = ('Calculate...', self.calculate)
506 elif x == self.PLOT:
507 x = ('Plot...', self.plot)
508 if isinstance(x, tuple):
509 txt = x[0]
510 proc = x[1]
511 need_sel = False
512 if len(x) >= 3:
513 need_sel = x[2]
514 btn = pack_button(txt, self, on_click=lambda b: self.actions[b]())
515 self.actions[btn] = proc
516 if need_sel:
517 btn.set_sensitive(False)
518 self.need_sel.append(btn)
519 elif x == self.FILE_MENU:
520 self.mnuFile = gtk.Menu()
521 build_menuitem('New Table...', self.__ref(lambda item: qubx.pyenv.env.globals['QubX'].new_table()), menu=self.mnuFile)
522 build_menuitem('Open...', self.__ref(lambda item: qubx.pyenv.env.globals['QubX'].Data.open()), menu=self.mnuFile)
523 build_menuitem('Save as...', self.__ref(self.__onClickSaveAs), menu=self.mnuFile)
524 item = build_menuitem('Close', self.__ref(lambda b: self.OnClickClose(self, self.table)), menu=self.mnuFile)
525 self.btnFile = pack_item(qubx.toolspace.Button_Popup_PNG(self.mnuFile, os.path.join(qubx.global_namespace.app_path, 'icons', 'folder.png'), "File menu"), self)
526 elif x == self.CLOSE:
527 pack_button('X', self, at_end=True, on_click=lambda b: self.OnClickClose(self, self.table))
528 self.table.OnSelect += self.__ref(self._onSelect)
530 self.row = i
531 have_sel = not (self.row is None)
532 for b in self.need_sel:
533 b.set_sensitive(have_sel)
558 - def copy_rows(self, table_name=None, copy_rows_type=None, group=None, inverse=False, criteria=None):
559 tbn, crt, grp, inv, cta = prompt_copy_rows(self.table, self.table.label, [],
560 table_name, copy_rows_type, group, inverse, criteria)
561 if crt is None:
562 return
563 from_table = self.table
564 QubX = qubx.global_namespace.QubX
565 result = QubX.new_table(tbn, initial_row=False)
566 if self.table.global_name:
567 if crt == COPY_ROWS_ALL:
568 qubx.pyenv.env.scriptable_if_matching('QubX.Tables.find_table(%s).copy_rows_from(%s, copy_rows_type=COPY_ROWS_ALL)'
569 % (repr(tbn),
570 self.table.global_name),
571 [(self.table.global_name, self.table)])
572 elif crt == COPY_ROWS_GROUP:
573 qubx.pyenv.env.scriptable_if_matching('QubX.Tables.find_table(%s).copy_rows_from(%s, copy_rows_type=COPY_ROWS_GROUP, group=%s, inverse=%s)'
574 % (repr(tbn),
575 self.table.global_name,
576 repr(grp), repr(inv)),
577 [(self.table.global_name, self.table)])
578 elif crt == COPY_ROWS_CRITERIA:
579 qubx.pyenv.env.scriptable_if_matching('QubX.Tables.find_table(%s).copy_rows_from(%s, copy_rows_type=COPY_ROWS_CRITERIA, criteria=%s)'
580 % (repr(tbn),
581 self.table.global_name,
582 repr(cta)),
583 [(self.table.global_name, self.table)])
584 elif crt == COPY_ROWS_CHECKED:
585 qubx.pyenv.env.scriptable_if_matching('QubX.Tables.find_table(%s).copy_rows_from(%s, copy_rows_type=COPY_ROWS_CHECKED)'
586 % (repr(tbn),
587 self.table.global_name),
588 [(self.table.global_name, self.table)])
589 result.copy_rows_from(from_table, copy_rows_type=crt, group=grp, inverse=inv, criteria=cta)
590 return result
591 - def calculate(self, field_name=None, expr=None):
592 fn = field_name
593 ex = expr
594 if (fn is None) or (ex is None):
595 if fn is None:
596 fn = 'Output'
597 if ex is None:
598 ex = ''
599 QubX = qubx.pyenv.env.globals['QubX']
600 dlg = gtk.Dialog('%s - Calculate...'%QubX.appname, qubx.GTK.get_active_window(), gtk.DIALOG_MODAL)
601 line = pack_item(gtk.HBox(), dlg.vbox)
602 pack_label('Replace data in column:', line)
603 txtField = pack_item(qubx.GTK.NumEntry(fn, str), line, expand=True)
604 line = pack_item(gtk.HBox(), dlg.vbox)
605 pack_label('with:', line)
606 txtExpr = pack_item(qubx.GTK.NumEntry(ex, self.acceptExpr), line, expand=True)
607 btnHelp = pack_item(qubx.pyenvGTK.HelpTestButton(txtExpr), line)
608 btnHelp.caption = 'Enter a numeric expression in terms of field_name'
609 btnHelp.help_msg = CALCULATE_HELP
610 btnHelp.bind = lambda expr: qubx.pyenv.env.globals.__setitem__('calc_value_of_row', lambda r: calc_expr_values(self.table, expr, [r])[0])
611 btnHelp.write_test = lambda expr: 'print calc_value_of_row(0)'
612 dlg.add_button('Cancel', gtk.RESPONSE_REJECT)
613 dlg.add_button('OK', gtk.RESPONSE_ACCEPT)
614 response = dlg.run()
615 dlg.destroy()
616 if response != gtk.RESPONSE_ACCEPT:
617 return
618 fn = txtField.value
619 ex = txtExpr.value
620 if (not fn) or (not ex):
621 return
622 if self.table.global_name:
623 qubx.pyenv.env.scriptable_if_matching('for i, val in enumerate(%s.calc_expr_values(%s)): %s[i, %s] = val'
624 % (self.table.global_name, repr(ex), self.table.global_name, repr(fn)),
625 [(self.table.global_name, self.table)])
626 for i, val in enumerate(self.table.calc_expr_values(ex)):
627 self.table[i, fn] = val
637 - def save(self, fname):
642
643
646
647 CALCULATE_HELP = """Enter a numeric expression such as
648 Index + 1
649
650 These names are available:
651 field_name -- val. of field in this row; replace spaces with underscores; match capitalization
652 row["field name"] -- same, with spaces
653
654 Expressions use Python syntax. Full documentation is available at www.python.org
655 """ + qubx.pyenv.PYTHON_HELP
656
657
659 __explore_featured = ['update_recent', 'copy_rows_type', 'group', 'inv', 'criteria', 'table', 'get_rows']
660 - def __init__(self, recent_criteria, checked=True):
661 gtk.VBox.__init__(self)
662 self.__ref = Reffer()
663 self.__table = None
664 self.__copy_rows_type = COPY_ROWS_ALL
665 self.__inv = False
666
667 line = pack_item(gtk.HBox(), self)
668 pack_label('Pick rows:', line)
669 line = pack_item(gtk.HBox(), self)
670 self.chkAll = pack_radio('All', line, active=True, on_toggle=bind_with_args_before(self.__onToggle, COPY_ROWS_ALL))
671 if checked:
672 line = pack_item(gtk.HBox(), self)
673 self.chkChecked = pack_radio('Checked', line, group=self.chkAll, on_toggle=bind_with_args_before(self.__onToggle, COPY_ROWS_CHECKED))
674 else:
675 self.chkChecked = None
676 line = pack_item(gtk.HBox(), self)
677 self.chkGroup = pack_radio('Group (color)', line, group=self.chkAll, on_toggle=bind_with_args_before(self.__onToggle, COPY_ROWS_GROUP))
678 self.panGroup = pack_item(gtk.HBox(), line, expand=True)
679 self.chkIn = pack_radio('is', self.panGroup, active=True, on_toggle=bind_with_args_before(self.__onToggleInv, False))
680 pack_label('/', self.panGroup)
681 self.chkNotIn = pack_radio('is not', self.panGroup, group=self.chkIn, on_toggle=bind_with_args_before(self.__onToggleInv, True))
682 txtGroup = self.txtGroup = pack_item(qubx.GTK.NumEntry(1, acceptIntGreaterThan(-1), width_chars=3), self.panGroup)
683 txtGroup.OnChange += self.__ref(self.__onChangeGroup)
684 palette = self.palGroup = pack_item(qubx.toolspace.Palette(vertical=False), line, expand=True)
685 palette.OnClickColor += self.__ref(self.__onClickColor)
686 line = pack_item(gtk.HBox(), self)
687 self.chkCriteria = pack_radio('Criteria:', line, group=self.chkAll, on_toggle=bind_with_args_before(self.__onToggle, COPY_ROWS_CRITERIA))
688 self.criteria_entry = pack_item(qubx.select_charts.CriteriaEntry(recent_criteria), line, expand=True)
689
690 self.__copy_rows_type = None
691 self.copy_rows_type = COPY_ROWS_ALL
692
695
707 copy_rows_type = property(lambda self: self.__copy_rows_type, lambda self, x: self.set_copy_rows_type(x))
711 group = property(lambda self: self.palGroup.color, lambda self, x: self.set_group(x))
715 inv = property(lambda self: self.chkNotIn.get_active(), lambda self, x: self.set_inv(x))
716 criteria = property(lambda self: self.criteria_entry.txtCriteria.value, lambda self, x: self.criteria_entry.txtCriteria.setValue)
724 self.__table = x
725 self.criteria_entry.table = x
726 table = property(lambda self: self.__table, lambda self, x: self.set_table(x))
728 tbl = self.__table
729 if not tbl:
730 return []
731 if self.chkAll.get_active():
732 return list(xrange(tbl.size))
733 elif self.chkGroup.get_active():
734 grp = self.palGroup.color
735 if self.chkNotIn.get_active():
736 inv = lambda x: not x
737 else:
738 inv = lambda x: x
739 return [i for i in xrange(tbl.size) if inv(grp == tbl.get(i, 'Group'))]
740 elif self.chkCriteria.get_active():
741 return self.criteria_entry.get_rows()
747
748
750 a, b = [model.get_path(it)[0] for it in (iter1, iter2)]
751 if a < b: return -1
752 if a == b: return 0
753 return 1
754
755
756 -def prompt_copy_rows(table, base_name, name_choices=[], table_name=None, copy_rows_type=None, group=None, inverse=False, criteria=None):
779 txtTable.OnPopup += on_popup_names
780 picker = pack_item(RowPicker(qubx.settings.SettingsMgr['Select'].active['RecentCriteria']), dlg.vbox)
781 picker.table = table
782 picker.copy_rows_type = crt
783 picker.group = grp
784 picker.inv = inv
785 picker.criteria = cta
786 dlg.add_button('Cancel', gtk.RESPONSE_REJECT)
787 dlg.add_button('OK', gtk.RESPONSE_ACCEPT)
788 response = dlg.run()
789 dlg.destroy()
790 if response != gtk.RESPONSE_ACCEPT:
791 return None, None, None, None, None
792 picker.update_recent()
793 tbn = txtTable.value
794 crt = picker.copy_rows_type
795 grp = picker.group
796 inv = picker.inv
797 cta = picker.criteria
798 return tbn, crt, grp, inv, cta
799
800 -def prompt_check_rows(table, copy_rows_type=None, group=None, inverse=False, criteria=None):
801 crt = copy_rows_type
802 grp = group
803 inv = inverse
804 cta = criteria
805 QubX = qubx.pyenv.env.globals['QubX']
806 if (crt is None) or ((crt == COPY_ROWS_GROUP) and (grp is None)) or ((crt == COPY_ROWS_CRITERIA) and (cta is None)):
807 if crt is None:
808 crt = COPY_ROWS_ALL
809 if grp is None:
810 grp = 1
811 if cta is None:
812 cta = ""
813 dlg = gtk.Dialog('%s - Check rows if...'%QubX.appname, qubx.GTK.get_active_window(), gtk.DIALOG_MODAL)
814 picker = pack_item(RowPicker(qubx.settings.SettingsMgr['Select'].active['RecentCriteria'], checked=False), dlg.vbox)
815 picker.table = table
816 picker.copy_rows_type = crt
817 picker.group = grp
818 picker.inv = inv
819 picker.criteria = cta
820 dlg.add_button('Cancel', gtk.RESPONSE_REJECT)
821 dlg.add_button('OK', gtk.RESPONSE_ACCEPT)
822 response = dlg.run()
823 dlg.destroy()
824 if response != gtk.RESPONSE_ACCEPT:
825 return None, None, None, None
826 picker.update_recent()
827 crt = picker.copy_rows_type
828 grp = picker.group
829 inv = picker.inv
830 cta = picker.criteria
831 return crt, grp, inv, cta
832