def __init__(self, path, parent, t0, okclicked_cb): '''Builds and display the edit t0 window''' super(EditT0Win, self).__init__(Gtk.WindowType.TOPLEVEL) self.okclicked_cb = okclicked_cb self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_title('fsTimer - ' + os.path.basename(path)) self.set_position(Gtk.WindowPosition.CENTER) self.set_transient_for(parent) self.set_modal(True) self.connect('delete_event', lambda b, jnk: self.hide()) label = Gtk.Label("""This is the starting time in seconds.\ \nAdd or subtract seconds from this number to adjust the start time by that many seconds.\ \nNote that this will NOT affect times that have already been marked, only future times.""" ) self.t0box = Gtk.Entry() self.t0box.set_text(str(t0)) hbox = Gtk.HBox(False, 8) btnOK = GtkStockButton('ok', "OK") btnOK.connect('clicked', self.okclicked) btnCANCEL = GtkStockButton('close', "Cancel") btnCANCEL.connect('clicked', lambda jnk: self.hide()) hbox.pack_start(btnOK, False, False, 0) hbox.pack_start(btnCANCEL, False, False, 0) hbox_lbl = Gtk.HBox(False, 0) hbox_lbl.pack_start(label, False, False, 10) vbox = Gtk.VBox(False, 8) vbox.pack_start(hbox_lbl, False, False, 20) vbox.pack_start(self.t0box, False, False, 0) vbox.pack_start(hbox, False, False, 0) self.add(vbox) self.show_all()
def __init__(self, path, parent, t0, okclicked_cb): '''Builds and display the edit t0 window''' super(EditT0Win, self).__init__(Gtk.WindowType.TOPLEVEL) self.okclicked_cb = okclicked_cb self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_title('fsTimer - ' + os.path.basename(path)) self.set_position(Gtk.WindowPosition.CENTER) self.set_transient_for(parent) self.set_modal(True) self.connect('delete_event', lambda b, jnk: self.hide()) label = Gtk.Label("""This is the starting time in seconds.\ \nAdd or subtract seconds from this number to adjust the start time by that many seconds.\ \nNote that this will NOT affect times that have already been marked, only future times.""") self.t0box = Gtk.Entry() self.t0box.set_text(str(t0)) hbox = Gtk.HBox(False, 8) btnOK = GtkStockButton('ok',"OK") btnOK.connect('clicked', self.okclicked) btnCANCEL = GtkStockButton('close',"Cancel") btnCANCEL.connect('clicked', lambda jnk: self.hide()) hbox.pack_start(btnOK, False, False, 0) hbox.pack_start(btnCANCEL, False, False, 0) hbox_lbl = Gtk.HBox(False, 0) hbox_lbl.pack_start(label, False, False, 10) vbox = Gtk.VBox(False, 8) vbox.pack_start(hbox_lbl, False, False, 20) vbox.pack_start(self.t0box, False, False, 0) vbox.pack_start(hbox, False, False, 0) self.add(vbox) self.show_all()
def __init__(self, path, fields, fieldsdic): '''Builds and display the importation window''' super(ImportPreRegWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.path = path self.fields = fields self.fieldsdic = fieldsdic self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) fname = os.path.abspath( os.path.join( os.path.dirname(os.path.abspath(__file__)), '../data/icon.png')) self.set_icon_from_file(fname) self.set_title('fsTimer - ' + os.path.basename(path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.hide()) self.set_border_width(10) self.set_size_request(600, 400) # Start with some intro text. label1 = Gtk.Label( label=('Select a pre-registration csv file to import.\n\n' 'If the spreadsheet has accented or non-Latin characters, it must be in utf-8,\n' 'see Section 2.2 of the documentation for instructions.')) #Continue to the load file. btnFILE = GtkStockButton('open',"Open") ## Textbuffer textbuffer = Gtk.TextBuffer() try: textbuffer.create_tag("blue", foreground="blue") textbuffer.create_tag("red", foreground="red") except TypeError: pass textview = Gtk.TextView() textview.set_buffer(textbuffer) textview.set_editable(False) textview.set_cursor_visible(False) textsw = Gtk.ScrolledWindow() textsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) textsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) textsw.add(textview) textalgn = Gtk.Alignment.new(0, 0, 1, 1) textalgn.add(textsw) hbox2 = Gtk.HBox(False, 5) btnFILE.connect('clicked', self.select_preregistration, textbuffer) btn_algn = Gtk.Alignment.new(1, 0, 1, 0) hbox2.pack_start(btnFILE, False, False, 0) hbox2.pack_start(btn_algn, True, True, 0) ## buttons btnOK = GtkStockButton('ok',"OK") btnOK.connect('clicked', lambda b: self.hide()) cancel_algn = Gtk.Alignment.new(0, 0, 1, 0) hbox3 = Gtk.HBox(False, 10) hbox3.pack_start(cancel_algn, True, True, 0) hbox3.pack_start(btnOK, False, False, 0) vbox = Gtk.VBox(False, 0) vbox.pack_start(label1, False, False, 5) vbox.pack_start(hbox2, False, True, 5) vbox.pack_start(textalgn, True, True, 5) vbox.pack_start(hbox3, False, False, 0) self.add(vbox) self.show_all()
def __init__(self, path, parent, errors, fields, timedict, allok_cb): '''Builds and display the compilation error window''' super(CompilationErrorsWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.path = path self.errors = errors self.fields = fields self.timedict = timedict self.allok_cb = allok_cb self.corerrorswin = None self.corerrorlist = None self.corerrortreeview = None self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(parent) self.set_modal(True) self.set_title('fsTimer - ' + os.path.basename(path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.hide()) self.set_border_width(10) self.set_size_request(450, 300) # make a liststore with all of the overloaded IDs (that is, # the keys of errors) and put it in a scrolled window comperrorsw = Gtk.ScrolledWindow() comperrorsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) comperrorsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.errorlist = Gtk.ListStore(str) self.errortreeview = Gtk.TreeView() rendererText = Gtk.CellRendererText() column = Gtk.TreeViewColumn('Overloaded IDs', rendererText, text=0) column.set_sort_column_id(0) self.errortreeview.append_column(column) # add on the IDs from errors for errorid in errors.keys(): self.errorlist.append([errorid]) self.errortreeview.set_model(self.errorlist) comperrorsw.add(self.errortreeview) errvbox1 = Gtk.VBox(False, 8) errvbox1.pack_start( Gtk.Label( 'These IDs were assigned to multiple entries.\nThey will be left unassigned.', True, True, 0), False, False, 0) errvbox1.pack_start(comperrorsw, True, True, 0) vbox1align = Gtk.Alignment.new(0, 0, 1, 1) vbox1align.add(errvbox1) # buttons btnVIEW = Gtk.Button('View ID entries') btnVIEW.connect('clicked', self.view_entries_clicked) btnOK = GtkStockButton('ok', 'OK') btnOK.connect('clicked', self.ok_error) errvbalign = Gtk.Alignment.new(1, 0, 0, 0) vbox2 = Gtk.VBox(False, 10) vbox2.pack_start(errvbalign, True, True, 0) vbox2.pack_start(btnVIEW, False, False, 0) vbox2.pack_start(btnOK, False, False, 0) hbox = Gtk.HBox(False, 10) hbox.pack_start(vbox1align, False, False, 0) hbox.pack_start(vbox2, False, False, 0) self.add(hbox) self.show_all()
def __init__(self, path, timing, okclicked_cb): '''Builds and display the compilation error window''' super(PreTimeWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.path = path self.timing = timing self.okclicked_cb = okclicked_cb self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) fname = os.path.abspath( os.path.join( os.path.dirname(os.path.abspath(__file__)), '../data/icon.png')) self.set_icon_from_file(fname) self.set_title('fsTimer - Project '+os.path.basename(self.path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.hide()) self.set_border_width(10) # Start with some intro text. btnFILE = Gtk.Button('Choose file') btnFILE.connect('clicked', self.choose_timingdict) self.pretimefilelabel = Gtk.Label(label='') self.pretimefilelabel.set_markup('<span color="blue">Select a timing dictionary.</span>') self.entry1 = Gtk.Entry() self.entry1.set_max_length(6) self.entry1.set_text('0') label2 = Gtk.Label('Specify a "pass" ID, not assigned to any racer') self.timebtncombobox = Gtk.ComboBoxText() self.timebtnlist = [' ', '.', '/'] timebtndescr = ['Spacebar (" ")', 'Period (".")', 'Forward slash ("/")'] for descr in timebtndescr: self.timebtncombobox.append_text(descr) self.timebtncombobox.set_active(0) label3 = Gtk.Label(label='Specify the key for marking times. It must not be in any of the IDs.') hbox3 = Gtk.HBox(False, 10) hbox3.pack_start(self.timebtncombobox, False, False, 8) hbox3.pack_start(label3, False, False, 8) btnCANCEL = GtkStockButton('close',"Close") btnCANCEL.connect('clicked', lambda b: self.hide()) pretimebtnOK = GtkStockButton('ok',"OK") pretimebtnOK.connect('clicked', self.okclicked) btmhbox = Gtk.HBox(False, 8) btmhbox.pack_start(pretimebtnOK, False, False, 8) btmhbox.pack_start(btnCANCEL, False, False, 8) btmalign = Gtk.Alignment.new(1, 0, 0, 0) btmalign.add(btmhbox) hbox = Gtk.HBox(False, 10) hbox.pack_start(btnFILE, False, False, 8) hbox.pack_start(self.pretimefilelabel, False, False, 8) hbox2 = Gtk.HBox(False, 10) hbox2.pack_start(self.entry1, False, False, 8) hbox2.pack_start(label2, False, False, 8) vbox = Gtk.VBox(False, 10) vbox.pack_start(hbox, False, False, 8) vbox.pack_start(hbox2, False, False, 8) vbox.pack_start(hbox3, False, False, 8) vbox.pack_start(btmalign, False, False, 8) self.add(vbox) self.show_all()
def __init__(self, path, parent, errors, fields, timedict, allok_cb): '''Builds and display the compilation error window''' super(CompilationErrorsWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.path = path self.errors = errors self.fields = fields self.timedict = timedict self.allok_cb = allok_cb self.corerrorswin = None self.corerrorlist = None self.corerrortreeview = None self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(parent) self.set_modal(True) self.set_title('fsTimer - ' + os.path.basename(path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.hide()) self.set_border_width(10) self.set_size_request(450, 300) # make a liststore with all of the overloaded IDs (that is, # the keys of errors) and put it in a scrolled window comperrorsw = Gtk.ScrolledWindow() comperrorsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) comperrorsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.errorlist = Gtk.ListStore(str) self.errortreeview = Gtk.TreeView() rendererText = Gtk.CellRendererText() column = Gtk.TreeViewColumn('Overloaded IDs', rendererText, text=0) column.set_sort_column_id(0) self.errortreeview.append_column(column) # add on the IDs from errors for errorid in errors.keys(): self.errorlist.append([errorid]) self.errortreeview.set_model(self.errorlist) comperrorsw.add(self.errortreeview) errvbox1 = Gtk.VBox(False, 8) errvbox1.pack_start(Gtk.Label('These IDs were assigned to multiple entries.\nThey will be left unassigned.', True, True, 0), False, False, 0) errvbox1.pack_start(comperrorsw, True, True, 0) vbox1align = Gtk.Alignment.new(0, 0, 1, 1) vbox1align.add(errvbox1) # buttons btnVIEW = Gtk.Button('View ID entries') btnVIEW.connect('clicked', self.view_entries_clicked) btnOK = GtkStockButton('ok','OK') btnOK.connect('clicked', self.ok_error) errvbalign = Gtk.Alignment.new(1, 0, 0, 0) vbox2 = Gtk.VBox(False, 10) vbox2.pack_start(errvbalign, True, True, 0) vbox2.pack_start(btnVIEW, False, False, 0) vbox2.pack_start(btnOK, False, False, 0) hbox = Gtk.HBox(False, 10) hbox.pack_start(vbox1align, False, False, 0) hbox.pack_start(vbox2, False, False, 0) self.add(hbox) self.show_all()
def __init__(self, path, set_registration_file_cb, handle_registration_cb): '''Builds and display the window handling preregistration set the computers registration ID, and optionally choose a pre-registration json''' super(PreRegistrationWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.path = path self.set_registration_file_cb = set_registration_file_cb self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) fname = os.path.abspath( os.path.join(os.path.dirname(os.path.abspath(__file__)), '../data/icon.png')) self.set_icon_from_file(fname) self.set_title('fsTimer - ' + os.path.basename(path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.hide()) self.set_border_width(10) # Start with some intro text. prereglabel1 = Gtk.Label( 'Give a unique number to each computer used for registration.\nSelect a pre-registration file, if available.' ) # Continue to the spinner preregtable = Gtk.Table(3, 2, False) preregtable.set_row_spacings(5) preregtable.set_col_spacings(5) preregtable.set_border_width(10) regid = Gtk.Adjustment(value=1, lower=1, upper=99, step_incr=1) regid_btn = Gtk.SpinButton(digits=0, climb_rate=0) regid_btn.set_adjustment(regid) preregtable.attach(regid_btn, 0, 1, 0, 1) preregtable.attach( Gtk.Label(label="This computer's registration number"), 1, 2, 0, 1) preregbtnFILE = Gtk.Button('Select pre-registration') preregbtnFILE.connect('clicked', self.file_selected) preregtable.attach(preregbtnFILE, 0, 1, 2, 3) self.preregfilelabel = Gtk.Label(label='') self.preregfilelabel.set_markup( '<span color="blue">No pre-registration selected.</span>') preregtable.attach(self.preregfilelabel, 1, 2, 2, 3) ## buttons prereghbox = Gtk.HBox(True, 0) preregbtnOK = GtkStockButton('ok', "OK") preregbtnOK.connect('clicked', self.preregister_ok_cb, regid_btn, handle_registration_cb) preregbtnCANCEL = GtkStockButton('close', "Close") preregbtnCANCEL.connect('clicked', lambda b: self.hide()) prereghbox.pack_start(preregbtnOK, False, False, 5) prereghbox.pack_start(preregbtnCANCEL, False, False, 5) #Vbox preregvbox = Gtk.VBox(False, 0) preregbtnhalign = Gtk.Alignment.new(1, 0, 0, 0) preregbtnhalign.add(prereghbox) preregvbox.pack_start(prereglabel1, False, False, 5) preregvbox.pack_start(preregtable, False, False, 5) preregvbox.pack_start(preregbtnhalign, False, False, 5) self.add(preregvbox) self.show_all()
def regfield_new_entrybox(self, jnk_unused, name, maxchar, treeiter, typ): '''Handled click on the New entrybox button''' self.winnewentry = Gtk.Window(Gtk.WindowType.TOPLEVEL) self.winnewentry.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.winnewentry.set_transient_for(self) self.winnewentry.set_modal(True) self.winnewentry.set_title('fsTimer - New {} entry'.format(typ)) self.winnewentry.set_position(Gtk.WindowPosition.CENTER) self.winnewentry.set_border_width(20) self.winnewentry.connect('delete_event', lambda b, jnk_unused: self.winnewentry.hide()) if typ == 'text': descr = ('text', 'text') elif typ == 'number': descr = ('number', 'integer') label0 = Gtk.Label( label=('A {} entry allows for any {} to be entered,\n' 'up to the number of characters specified below.'.format( *descr))) label1 = Gtk.Label(label='Field name:') nameentry = Gtk.Entry() nameentry.set_max_length(50) nameentry.set_text(name) hbox1 = Gtk.HBox(False, 10) hbox1.pack_start(label1, False, False, 0) hbox1.pack_start(nameentry, False, False, 0) label2 = Gtk.Label(label='Max characters:') maxcharadj = Gtk.Adjustment(value=1, lower=1, upper=120, step_incr=1) maxcharbtn = Gtk.SpinButton(digits=0, climb_rate=0) maxcharbtn.set_adjustment(maxcharadj) maxcharbtn.set_value(int(maxchar)) hbox2 = Gtk.HBox(False, 10) hbox2.pack_start(label2, False, False, 0) hbox2.pack_start(maxcharbtn, False, False, 0) label3 = Gtk.Label(label='') btnOK = GtkStockButton('ok', "OK") btnOK.connect('clicked', self.winnewentryOK, treeiter, nameentry, maxcharbtn, label3, typ) btnCANCEL = GtkStockButton('close', "Cancel") btnCANCEL.connect('clicked', lambda b: self.winnewentry.hide()) cancel_algn = Gtk.Alignment.new(0, 0, 0, 0) cancel_algn.add(btnCANCEL) hbox3 = Gtk.HBox(False, 10) hbox3.pack_start(cancel_algn, True, True, 0) hbox3.pack_start(btnOK, False, False, 0) vbox = Gtk.VBox(False, 10) vbox.pack_start(label0, False, False, 0) vbox.pack_start(hbox1, False, False, 0) vbox.pack_start(hbox2, False, False, 0) vbox.pack_start(label3, False, False, 0) vbox.pack_start(hbox3, False, False, 0) self.winnewentry.add(vbox) self.winnewentry.show_all() return
def __init__(self, set_projecttype_cb, parent): '''Creates new project window''' super(NewProjectWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(parent) self.set_modal(True) self.set_title('fsTimer - New project') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.connect('delete_event', lambda b, jnk_unused: self.hide()) # Now create the vbox. vbox = Gtk.VBox(False, 10) self.add(vbox) # Now add the text. label_0 = Gtk.Label('Enter a name for the new project.\nOnly letters, numbers, and underscore.') # And an error, if needed.. self.label_1 = Gtk.Label() self.label_1.set_line_wrap(True) # And the text entry self.entry = Gtk.Entry() self.entry.set_max_length(32) # Select a file to import, if desired label_2 = Gtk.Label('Select a project to import settings from (optional)') # A combobox to select the project combobox = Gtk.ComboBoxText() projectlist = ["-- No import --"] rootdir = normpath(join(dirname(abspath(__file__)),'../../')) projectlist.extend([i for i in os.listdir(rootdir) if os.path.isdir(join(rootdir,i)) and os.path.exists(join(rootdir,i+'/'+i+'.reg'))]) #List the folders in pwd that contain a .reg registration file projectlist.sort() for project in projectlist: combobox.append_text(project) combobox.set_active(0) # And an hbox with 2 buttons hbox_1 = Gtk.HBox(False, 0) btnCANCEL = GtkStockButton('close',"Close") btnCANCEL.connect('clicked', lambda btn: self.hide()) alignCANCEL = Gtk.Alignment.new(0, 0, 0, 0) alignCANCEL.add(btnCANCEL) btnNEXT = GtkStockButton('forward',"Next") btnNEXT.connect('clicked', self.nextClicked, set_projecttype_cb, projectlist, combobox) alignNEXT = Gtk.Alignment.new(1, 0, 1, 0) alignNEXT.add(btnNEXT) btnNEXT.set_sensitive(False) # And populate self.entry.connect("changed", self.lock_btn_title, btnNEXT) hbox_1.pack_start(alignCANCEL, True, True, 0) hbox_1.pack_start(alignNEXT, False, False, 0) vbox.pack_start(label_0, False, False, 0) vbox.pack_start(self.entry, False, False, 0) vbox.pack_start(self.label_1, False, False, 0) vbox.pack_start(label_2, False, False, 0) vbox.pack_start(combobox, False, False, 0) vbox.pack_start(hbox_1, False, False, 0) self.show_all()
def regfield_new_entrybox(self, jnk_unused, name, maxchar, treeiter, typ): '''Handled click on the New entrybox button''' self.winnewentry = Gtk.Window(Gtk.WindowType.TOPLEVEL) self.winnewentry.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.winnewentry.set_transient_for(self) self.winnewentry.set_modal(True) self.winnewentry.set_title('fsTimer - New {} entry'.format(typ)) self.winnewentry.set_position(Gtk.WindowPosition.CENTER) self.winnewentry.set_border_width(20) self.winnewentry.connect( 'delete_event', lambda b, jnk_unused: self.winnewentry.hide()) if typ == 'text': descr = ('text', 'text') elif typ == 'number': descr = ('number', 'integer') label0 = Gtk.Label(label=( 'A {} entry allows for any {} to be entered,\n' 'up to the number of characters specified below.'.format(*descr))) label1 = Gtk.Label(label='Field name:') nameentry = Gtk.Entry() nameentry.set_max_length(50) nameentry.set_text(name) hbox1 = Gtk.HBox(False, 10) hbox1.pack_start(label1, False, False, 0) hbox1.pack_start(nameentry, False, False, 0) label2 = Gtk.Label(label='Max characters:') maxcharadj = Gtk.Adjustment( value=1, lower=1, upper=120, step_incr=1) maxcharbtn = Gtk.SpinButton(digits=0, climb_rate=0) maxcharbtn.set_adjustment(maxcharadj) maxcharbtn.set_value(int(maxchar)) hbox2 = Gtk.HBox(False, 10) hbox2.pack_start(label2, False, False, 0) hbox2.pack_start(maxcharbtn, False, False, 0) label3 = Gtk.Label(label='') btnOK = GtkStockButton('ok', "OK") btnOK.connect('clicked', self.winnewentryOK, treeiter, nameentry, maxcharbtn, label3, typ) btnCANCEL = GtkStockButton('close',"Cancel") btnCANCEL.connect('clicked', lambda b: self.winnewentry.hide()) cancel_algn = Gtk.Alignment.new(0, 0, 0, 0) cancel_algn.add(btnCANCEL) hbox3 = Gtk.HBox(False, 10) hbox3.pack_start(cancel_algn, True, True, 0) hbox3.pack_start(btnOK, False, False, 0) vbox = Gtk.VBox(False, 10) vbox.pack_start(label0, False, False, 0) vbox.pack_start(hbox1, False, False, 0) vbox.pack_start(hbox2, False, False, 0) vbox.pack_start(label3, False, False, 0) vbox.pack_start(hbox3, False, False, 0) self.winnewentry.add(vbox) self.winnewentry.show_all() return
def __init__(self, path, set_registration_file_cb, handle_registration_cb): '''Builds and display the window handling preregistration set the computers registration ID, and optionally choose a pre-registration json''' super(PreRegistrationWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.path = path self.set_registration_file_cb = set_registration_file_cb self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) fname = os.path.abspath( os.path.join( os.path.dirname(os.path.abspath(__file__)), '../data/icon.png')) self.set_icon_from_file(fname) self.set_title('fsTimer - ' + os.path.basename(path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.hide()) self.set_border_width(10) # Start with some intro text. prereglabel1 = Gtk.Label('Give a unique number to each computer used for registration.\nSelect a pre-registration file, if available.') # Continue to the spinner preregtable = Gtk.Table(3, 2, False) preregtable.set_row_spacings(5) preregtable.set_col_spacings(5) preregtable.set_border_width(10) regid = Gtk.Adjustment(value=1, lower=1, upper=99, step_incr=1) regid_btn = Gtk.SpinButton(digits=0, climb_rate=0) regid_btn.set_adjustment(regid) preregtable.attach(regid_btn, 0, 1, 0, 1) preregtable.attach(Gtk.Label(label="This computer's registration number"), 1, 2, 0, 1) preregbtnFILE = Gtk.Button('Select pre-registration') preregbtnFILE.connect('clicked', self.file_selected) preregtable.attach(preregbtnFILE, 0, 1, 2, 3) self.preregfilelabel = Gtk.Label(label='') self.preregfilelabel.set_markup('<span color="blue">No pre-registration selected.</span>') preregtable.attach(self.preregfilelabel, 1, 2, 2, 3) ## buttons prereghbox = Gtk.HBox(True, 0) preregbtnOK = GtkStockButton('ok',"OK") preregbtnOK.connect('clicked', self.preregister_ok_cb, regid_btn, handle_registration_cb) preregbtnCANCEL = GtkStockButton('close',"Close") preregbtnCANCEL.connect('clicked', lambda b: self.hide()) prereghbox.pack_start(preregbtnOK, False, False, 5) prereghbox.pack_start(preregbtnCANCEL, False, False, 5) #Vbox preregvbox = Gtk.VBox(False, 0) preregbtnhalign = Gtk.Alignment.new(1, 0, 0, 0) preregbtnhalign.add(prereghbox) preregvbox.pack_start(prereglabel1, False, False, 5) preregvbox.pack_start(preregtable, False, False, 5) preregvbox.pack_start(preregbtnhalign, False, False, 5) self.add(preregvbox) self.show_all()
def regfield_new_combobox(self, jnk_unused, name, options, treeiter): '''Handled click on the New combobox button''' self.winnewcombo = Gtk.Window(Gtk.WindowType.TOPLEVEL) self.winnewcombo.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.winnewcombo.set_transient_for(self) self.winnewcombo.set_modal(True) self.winnewcombo.set_title('fsTimer - New selection box') self.winnewcombo.set_position(Gtk.WindowPosition.CENTER) self.winnewcombo.set_border_width(20) self.winnewcombo.connect('delete_event', lambda b, jnk_unused: self.winnewcombo.hide()) label0 = Gtk.Label(label=('A selection box allows the value to be ' 'one of a few options.')) label1 = Gtk.Label(label='Field name:') nameentry = Gtk.Entry() nameentry.set_max_length(50) nameentry.set_text(name) hbox1 = Gtk.HBox(False, 10) hbox1.pack_start(label1, False, False, 0) hbox1.pack_start(nameentry, False, False, 0) label2 = Gtk.Label('Options, separated by commas:') optionentry = Gtk.Entry() optionentry.set_max_length(50) optionentry.set_text(options) hbox2 = Gtk.HBox(False, 10) hbox2.pack_start(label2, False, False, 0) hbox2.pack_start(optionentry, False, False, 0) label3 = Gtk.Label(label='') btnOK = GtkStockButton('ok', "OK") btnOK.connect('clicked', self.winnewcomboOK, treeiter, nameentry, optionentry, label3) btnCANCEL = GtkStockButton('close', "Cancel") btnCANCEL.connect('clicked', lambda b: self.winnewcombo.hide()) cancel_algn = Gtk.Alignment.new(0, 0, 0, 0) cancel_algn.add(btnCANCEL) hbox3 = Gtk.HBox(False, 10) hbox3.pack_start(cancel_algn, True, True, 0) hbox3.pack_start(btnOK, False, False, 0) vbox = Gtk.VBox(False, 10) vbox.pack_start(label0, False, False, 0) vbox.pack_start(hbox1, False, False, 0) vbox.pack_start(hbox2, False, False, 0) vbox.pack_start(label3, False, False, 0) vbox.pack_start(hbox3, False, False, 0) self.winnewcombo.add(vbox) self.winnewcombo.show_all() return
def regfield_new_combobox(self, jnk_unused, name, options, treeiter): '''Handled click on the New combobox button''' self.winnewcombo = Gtk.Window(Gtk.WindowType.TOPLEVEL) self.winnewcombo.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.winnewcombo.set_transient_for(self) self.winnewcombo.set_modal(True) self.winnewcombo.set_title('fsTimer - New selection box') self.winnewcombo.set_position(Gtk.WindowPosition.CENTER) self.winnewcombo.set_border_width(20) self.winnewcombo.connect( 'delete_event', lambda b, jnk_unused: self.winnewcombo.hide()) label0 = Gtk.Label(label=('A selection box allows the value to be ' 'one of a few options.')) label1 = Gtk.Label(label='Field name:') nameentry = Gtk.Entry() nameentry.set_max_length(50) nameentry.set_text(name) hbox1 = Gtk.HBox(False, 10) hbox1.pack_start(label1, False, False, 0) hbox1.pack_start(nameentry, False, False, 0) label2 = Gtk.Label('Options, separated by commas:') optionentry = Gtk.Entry() optionentry.set_max_length(50) optionentry.set_text(options) hbox2 = Gtk.HBox(False, 10) hbox2.pack_start(label2, False, False, 0) hbox2.pack_start(optionentry, False, False, 0) label3 = Gtk.Label(label='') btnOK = GtkStockButton('ok',"OK") btnOK.connect('clicked', self.winnewcomboOK, treeiter, nameentry, optionentry, label3) btnCANCEL = GtkStockButton('close',"Cancel") btnCANCEL.connect('clicked', lambda b: self.winnewcombo.hide()) cancel_algn = Gtk.Alignment.new(0, 0, 0, 0) cancel_algn.add(btnCANCEL) hbox3 = Gtk.HBox(False, 10) hbox3.pack_start(cancel_algn, True, True, 0) hbox3.pack_start(btnOK, False, False, 0) vbox = Gtk.VBox(False, 10) vbox.pack_start(label0,False,False,0) vbox.pack_start(hbox1, False, False, 0) vbox.pack_start(hbox2, False, False, 0) vbox.pack_start(label3, False, False, 0) vbox.pack_start(hbox3, False, False, 0) self.winnewcombo.add(vbox) self.winnewcombo.show_all() return
def __init__(self, parent, okclicked_cb): '''Builds and display the window for editing block of times''' super(EditBlockTimesWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.okclicked_cb = okclicked_cb self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(parent) self.set_modal(True) self.set_title('fsTimer - Edit times') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.connect('delete_event', lambda b, jnk: self.hide()) label0 = Gtk.Label(label='') label0.set_markup( '<span color="red">WARNING: Changes to times cannot be automatically undone</span>\nIf you change the times and forget the old values, they will be gone forever.' ) label1 = Gtk.Label( label= 'Time (h:mm:ss) to be added or subtracted from all selected times:' ) self.radiobutton = Gtk.RadioButton(group=None, label="ADD") self.radiobutton.set_active(True) radiobutton2 = Gtk.RadioButton(group=self.radiobutton, label="SUBTRACT") self.entrytime = Gtk.Entry() self.entrytime.set_max_length(7) self.entrytime.set_text('0:00:00') hbox1 = Gtk.HBox(False, 10) hbox1.pack_start(self.radiobutton, False, False, 0) hbox1.pack_start(radiobutton2, False, False, 0) hbox1.pack_start(self.entrytime, False, False, 0) btnOK = GtkStockButton('ok', "OK") btnOK.connect('clicked', self.okclicked) btnCANCEL = GtkStockButton('close', "Cancel") btnCANCEL.connect('clicked', lambda b: self.hide()) cancel_algn = Gtk.Alignment.new(0, 0, 0, 0) cancel_algn.add(btnCANCEL) hbox2 = Gtk.HBox(False, 10) hbox2.pack_start(cancel_algn, True, True, 0) hbox2.pack_start(btnOK, False, False, 0) vbox = Gtk.VBox(False, 10) vbox.pack_start(label0, False, False, 10) vbox.pack_start(label1, False, False, 10) vbox.pack_start(hbox1, False, False, 0) vbox.pack_start(hbox2, False, False, 0) self.add(vbox) self.show_all()
def __init__(self, timewin, old_id, old_time, clickedok_cb): '''Builds and display the window for editing a single time''' super(EditTimeWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.timewin = timewin self.clickedok_cb = clickedok_cb self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(timewin) self.set_modal(True) self.set_title('fsTimer - Edit time') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.connect('delete_event', lambda b, jnk: self.hide()) label0 = Gtk.Label(label='') label0.set_markup( '<span color="red">WARNING: Changes to these values cannot be automatically undone</span>\nIf you change the time and forget the old one, it will be gone forever.' ) label1 = Gtk.Label(label='ID:') self.entryid = Gtk.Entry() self.entryid.set_max_length(6) self.entryid.set_text(old_id) hbox1 = Gtk.HBox(False, 10) hbox1.pack_start(label1, False, False, 0) hbox1.pack_start(self.entryid, False, False, 0) label2 = Gtk.Label(label='Time:') self.entrytime = Gtk.Entry() self.entrytime.set_max_length(25) self.entrytime.set_text(old_time) hbox2 = Gtk.HBox(False, 10) hbox2.pack_start(label2, False, False, 0) hbox2.pack_start(self.entrytime, False, False, 0) btnOK = GtkStockButton('ok', "OK") btnOK.connect('clicked', self.winedittimeOK) btnCANCEL = GtkStockButton('close', "Cancel") btnCANCEL.connect('clicked', lambda b: self.hide()) cancel_algn = Gtk.Alignment.new(0, 0, 0, 0) cancel_algn.add(btnCANCEL) hbox3 = Gtk.HBox(False, 10) hbox3.pack_start(cancel_algn, True, True, 0) hbox3.pack_start(btnOK, False, False, 0) vbox = Gtk.VBox(False, 10) vbox.pack_start(label0, False, False, 10) vbox.pack_start(hbox1, False, False, 0) vbox.pack_start(hbox2, False, False, 0) vbox.pack_start(hbox3, False, False, 0) self.add(vbox) self.show_all()
def __init__(self, timewin, old_id, old_time, clickedok_cb): '''Builds and display the window for editing a single time''' super(EditTimeWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.timewin = timewin self.clickedok_cb = clickedok_cb self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(timewin) self.set_modal(True) self.set_title('fsTimer - Edit time') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.connect('delete_event', lambda b, jnk: self.hide()) label0 = Gtk.Label(label='') label0.set_markup('<span color="red">WARNING: Changes to these values cannot be automatically undone</span>\nIf you change the time and forget the old one, it will be gone forever.') label1 = Gtk.Label(label='ID:') self.entryid = Gtk.Entry() self.entryid.set_max_length(6) self.entryid.set_text(old_id) hbox1 = Gtk.HBox(False, 10) hbox1.pack_start(label1, False, False, 0) hbox1.pack_start(self.entryid, False, False, 0) label2 = Gtk.Label(label='Time:') self.entrytime = Gtk.Entry() self.entrytime.set_max_length(25) self.entrytime.set_text(old_time) hbox2 = Gtk.HBox(False, 10) hbox2.pack_start(label2, False, False, 0) hbox2.pack_start(self.entrytime, False, False, 0) btnOK = GtkStockButton('ok',"OK") btnOK.connect('clicked', self.winedittimeOK) btnCANCEL = GtkStockButton('close',"Cancel") btnCANCEL.connect('clicked', lambda b: self.hide()) cancel_algn = Gtk.Alignment.new(0, 0, 0, 0) cancel_algn.add(btnCANCEL) hbox3 = Gtk.HBox(False, 10) hbox3.pack_start(cancel_algn, True, True, 0) hbox3.pack_start(btnOK, False, False, 0) vbox = Gtk.VBox(False, 10) vbox.pack_start(label0, False, False, 10) vbox.pack_start(hbox1, False, False, 0) vbox.pack_start(hbox2, False, False, 0) vbox.pack_start(hbox3, False, False, 0) self.add(vbox) self.show_all()
def __init__(self, load_project_cb, create_project_cb): '''Builds and display the introduction window''' super(IntroWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) icon_fname = normpath(join(dirname(abspath(__file__)),'../data/icon.png')) self.set_icon_from_file(icon_fname) self.set_title('fsTimer') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.connect('delete_event', Gtk.main_quit) # Create the vbox that will contain everything vbox = Gtk.VBox(False, 10) self.add(vbox) # Main logo logo = Gtk.Image() logo.set_from_file(normpath(join(dirname(abspath(__file__)),'../data/fstimer_logo.png'))) # Welcome text label0 = Gtk.Label(label='') label = Gtk.Label('Select an existing project, or begin a new project.') # A combobox to select the project combobox = Gtk.ComboBoxText() projectlist = [' -- Select an existing project --'] rootdir = normpath(join(dirname(abspath(__file__)),'../../')) projectlist.extend([i for i in os.listdir(rootdir) if os.path.isdir(join(rootdir,i)) and os.path.exists(join(rootdir,i+'/'+i+'.reg'))]) #List the folders in pwd that contain a .reg registration file projectlist.sort() for project in projectlist: combobox.append_text(project) combobox.set_active(0) #An hbox for the buttons. hbox = Gtk.HBox(False, 0) #And build the buttons btnNEW = GtkStockButton('new','New') btnNEW.connect('clicked', create_project_cb) btnOK = GtkStockButton('ok','OK') btnOK.connect('clicked', load_project_cb, combobox, projectlist) btnOK.set_sensitive(False) #Set combobox to lock btnOK, so we can't press OK until we have selected a project combobox.connect('changed', self.lock_btnOK, combobox, btnOK) btnCANCEL = GtkStockButton('close','Close') btnCANCEL.connect('clicked', Gtk.main_quit) #Now fill the hbox. hbox.pack_start(btnCANCEL, True, True, 0) hbox.pack_start(btnNEW, True, True, 50) hbox.pack_start(btnOK, True, True, 0) #Now build the vbox vbox.pack_start(logo, False, False, 0) vbox.pack_start(label0, False, False, 0) vbox.pack_start(label, False, False, 0) vbox.pack_start(combobox, False, False, 0) vbox.pack_start(hbox, False, False, 0) #And show everything. self.show_all()
def __init__(self, fields, fieldsdic, divisions, back_clicked_cb, next_clicked_cb, parent, edit): '''Creates divisions window''' super(DivisionsWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.divisions = divisions self.fields = fields self.fieldsdic = fieldsdic self.winnewdiv = None self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(parent) self.set_modal(True) self.set_title('fsTimer - Divisions') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.set_size_request(800, 500) self.connect('delete_event', lambda b, jnk_unused: self.hide()) # Now create the vbox. vbox = Gtk.VBox(False, 10) self.add(vbox) # Now add the text. label2_0 = Gtk.Label( "Specify the divisions for reporting divisional places.\n" "Press 'Forward' to continue with the default settings, or make " "edits below.\n\nDivisions can be any combination of number entry" " and selection box fields.") # Make the liststore, with columns: # name | (... combobox and entrybox_int fields...) # To do this we first count the number of fields ndivfields = len([field for field in fields if fieldsdic[field]['type'] in ['combobox', 'entrybox_int']]) self.divmodel = Gtk.ListStore(*[str for i_unused in range(ndivfields + 1)]) #We will put the liststore in a treeview self.divview = Gtk.TreeView() #Add each of the columns Columns = {} Columns[1] = Gtk.TreeViewColumn( 'Division name', Gtk.CellRendererText(), text=0) self.divview.append_column(Columns[1]) # The fields textcount = 1 for field in fields: if fieldsdic[field]['type'] in ['combobox', 'entrybox_int']: Columns[field] = Gtk.TreeViewColumn( field, Gtk.CellRendererText(), text=textcount) textcount += 1 self.divview.append_column(Columns[field]) #Now we populate the model with the default fields divmodelrows = {} for div in self.divisions: divmodelrow = self.get_divmodelrow(div) self.divmodel.append(divmodelrow) #Done there. self.divview.set_model(self.divmodel) selection = self.divview.get_selection() #And put it in a scrolled window, in an alignment divsw = Gtk.ScrolledWindow() divsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) divsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) divsw.add(self.divview) divalgn = Gtk.Alignment.new(0, 0, 1, 1) divalgn.add(divsw) #Now we put the buttons on the side. vbox2 = Gtk.VBox(False, 10) btnUP = GtkStockButton('up','Up') btnUP.connect('clicked', self.div_up, selection) vbox2.pack_start(btnUP, False, False, 0) btnDOWN = GtkStockButton('down','Down') btnDOWN.connect('clicked', self.div_down, selection) vbox2.pack_start(btnDOWN, False, False, 0) btnEDIT = GtkStockButton('edit','Edit') btnEDIT.connect('clicked', self.div_edit, selection) vbox2.pack_start(btnEDIT, False, False, 0) btnREMOVE = GtkStockButton('remove','Remove') btnREMOVE.connect('clicked', self.div_remove, selection) vbox2.pack_start(btnREMOVE, False, False, 0) btnNEW = GtkStockButton('new','New') btnNEW.connect('clicked', self.div_new, ('', {}), None) vbox2.pack_start(btnNEW, False, False, 0) btnCOPY = GtkStockButton('copy','Copy') btnCOPY.connect('clicked', self.div_copy, selection) vbox2.pack_start(btnCOPY, False, False, 0) #And an hbox for the fields and the buttons hbox4 = Gtk.HBox(False, 0) hbox4.pack_start(divalgn, True, True, 10) hbox4.pack_start(vbox2, False, False, 0) ##And an hbox with 3 buttons hbox3 = Gtk.HBox(False, 0) btnCANCEL = GtkStockButton('close', 'Close') btnCANCEL.connect('clicked', lambda btn: self.hide()) alignCANCEL = Gtk.Alignment.new(0, 0, 0, 0) alignCANCEL.add(btnCANCEL) btnBACK = GtkStockButton('back', 'Back') if edit: btnBACK.set_sensitive(False) else: btnBACK.connect('clicked', back_clicked_cb) btnNEXT = GtkStockButton('forward', 'Next') btnNEXT.connect('clicked', next_clicked_cb, edit) ##And populate hbox3.pack_start(alignCANCEL, True, True, 0) hbox3.pack_start(btnBACK, False, False, 2) hbox3.pack_start(btnNEXT, False, False, 0) alignText = Gtk.Alignment.new(0, 0, 0, 0) alignText.add(label2_0) vbox.pack_start(alignText, False, False, 0) vbox.pack_start(hbox4, True, True, 0) vbox.pack_start(hbox3, False, False, 10) self.show_all()
def __init__(self, path, timing, okclicked_cb): '''Builds and display the compilation error window''' super(PreTimeWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.path = path self.timing = timing self.okclicked_cb = okclicked_cb self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) fname = os.path.abspath( os.path.join(os.path.dirname(os.path.abspath(__file__)), '../data/icon.png')) self.set_icon_from_file(fname) self.set_title('fsTimer - Project ' + os.path.basename(self.path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.hide()) self.set_border_width(10) # Start with some intro text. btnFILE = Gtk.Button('Choose file') btnFILE.connect('clicked', self.choose_timingdict) self.pretimefilelabel = Gtk.Label(label='') self.pretimefilelabel.set_markup( '<span color="blue">Select a timing dictionary.</span>') self.entry1 = Gtk.Entry() self.entry1.set_max_length(6) self.entry1.set_text('0') label2 = Gtk.Label('Specify a "pass" ID, not assigned to any racer') self.timebtncombobox = Gtk.ComboBoxText() self.timebtnlist = [' ', '.', '/'] timebtndescr = [ 'Spacebar (" ")', 'Period (".")', 'Forward slash ("/")' ] for descr in timebtndescr: self.timebtncombobox.append_text(descr) self.timebtncombobox.set_active(0) label3 = Gtk.Label( label= 'Specify the key for marking times. It must not be in any of the IDs.' ) hbox3 = Gtk.HBox(False, 10) hbox3.pack_start(self.timebtncombobox, False, False, 8) hbox3.pack_start(label3, False, False, 8) btnCANCEL = GtkStockButton('close', "Close") btnCANCEL.connect('clicked', lambda b: self.hide()) pretimebtnOK = GtkStockButton('ok', "OK") pretimebtnOK.connect('clicked', self.okclicked) btmhbox = Gtk.HBox(False, 8) btmhbox.pack_start(pretimebtnOK, False, False, 8) btmhbox.pack_start(btnCANCEL, False, False, 8) btmalign = Gtk.Alignment.new(1, 0, 0, 0) btmalign.add(btmhbox) hbox = Gtk.HBox(False, 10) hbox.pack_start(btnFILE, False, False, 8) hbox.pack_start(self.pretimefilelabel, False, False, 8) hbox2 = Gtk.HBox(False, 10) hbox2.pack_start(self.entry1, False, False, 8) hbox2.pack_start(label2, False, False, 8) vbox = Gtk.VBox(False, 10) vbox.pack_start(hbox, False, False, 8) vbox.pack_start(hbox2, False, False, 8) vbox.pack_start(hbox3, False, False, 8) vbox.pack_start(btmalign, False, False, 8) self.add(vbox) self.show_all()
def __init__(self, pytimer, timebtn): '''Builds and display the compilation error window''' super(TimingWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.path = pytimer.path self.projecttype = pytimer.projecttype self.fields = pytimer.fields self.fieldsdic = pytimer.fieldsdic self.write_timing_cb = pytimer.write_updated_timing self.timebtn = timebtn self.rawtimes = pytimer.rawtimes self.timing = pytimer.timing self.numlaps = pytimer.numlaps self.wineditblocktime = None self.winedittime = None self.t0win = None self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(pytimer.rootwin) self.set_modal(True) self.set_title('fsTimer - ' + os.path.basename(self.path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.done_timing(b)) self.set_border_width(10) self.set_size_request(450, 450) # We will put the timing info in a liststore in a scrolledwindow self.timemodel = Gtk.ListStore(str, str) # We will put the liststore in a treeview self.timeview = Gtk.TreeView() column = Gtk.TreeViewColumn('ID', Gtk.CellRendererText(), text=0) self.timeview.append_column(column) column = Gtk.TreeViewColumn('Time', Gtk.CellRendererText(), text=1) self.timeview.append_column(column) #An extra column if it is a handicap race if self.projecttype == 'handicap': renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn('Corrected Time', renderer) column.set_cell_data_func(renderer, self.print_corrected_time) self.timeview.append_column(column) #Another extra column if it is a lap race if self.numlaps > 1: renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn('Completed laps', renderer) column.set_cell_data_func(renderer, self.print_completed_laps) self.timeview.append_column(column) self.timeview.set_model(self.timemodel) self.timeview.connect('size-allocate', self.scroll_times) treeselection = self.timeview.get_selection() # make it multiple selecting treeselection.set_mode(Gtk.SelectionMode.MULTIPLE) # And put it in a scrolled window, in an alignment self.timesw = Gtk.ScrolledWindow() self.timesw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) self.timesw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.timesw.add(self.timeview) timealgn = Gtk.Alignment.new(0, 0, 1, 1) timealgn.add(self.timesw) self.entrybox = Gtk.Entry() self.entrybox.set_max_length(40) self.offset = 0 #this is len(times) - len(ids) self.entrybox.connect('activate', self.record_time) self.entrybox.connect('changed', self.check_for_newtime) # And we will save our file self.timestr = re.sub(' +', '_', time.ctime()).replace(':', '') #we save with the current time in the filename so no chance of being overwritten accidentally # Now lets go on to boxes tophbox = Gtk.HBox() # our default t0, and the stuff on top for setting/edit t0 self.t0 = 0. btn_t0 = Gtk.Button('Start!') btn_t0.connect('clicked', self.set_t0) # time display self.clocklabel = Gtk.Label() self.clocklabel.modify_font(Pango.FontDescription("sans 20")) self.clocklabel.set_markup(time_format(0)) tophbox.pack_start(btn_t0, False, False, 10) tophbox.pack_start(self.clocklabel, False, False, 10) timevbox1 = Gtk.VBox(False, 8) timevbox1.pack_start(tophbox, False, False, 0) timevbox1.pack_start(timealgn, True, True, 0) timevbox1.pack_start( Gtk.Label('Select box below in order to mark times:'), False, False, 0) timevbox1.pack_start(self.entrybox, False, False, 0) # we will keep track of how many racers are still out. self.racers_reg = [] for i_unused in range(self.numlaps): self.racers_reg.append(set([k for k in self.timing.keys()])) self.racers_total = len(self.racers_reg[0]) self.racers_in = [0] * self.numlaps self.lapcounter = defaultdict(int) self.racerslabel = Gtk.Label() self.update_racers_label() timevbox1.pack_start(self.racerslabel, False, False, 0) vbox1align = Gtk.Alignment.new(0, 0, 1, 1) vbox1align.add(timevbox1) # buttons on the right side #First an options button that will actually be a menu options_menu = Gtk.Menu() menu_editreg = Gtk.MenuItem('Edit registration data') menu_editreg.connect_object("activate", self.edit_reg, None) menu_editreg.show() options_menu.append(menu_editreg) menu_resett0 = Gtk.MenuItem('Restart clock') menu_resett0.connect_object("activate", self.restart_t0, None) menu_resett0.show() options_menu.append(menu_resett0) menu_editt0 = Gtk.MenuItem('Edit starting time') menu_editt0.connect_object("activate", self.edit_t0, None) menu_editt0.show() options_menu.append(menu_editt0) menu_savecsv = Gtk.MenuItem('Save results to CSV') menu_savecsv.connect_object("activate", self.print_csv, pytimer) menu_savecsv.show() options_menu.append(menu_savecsv) menu_resume = Gtk.MenuItem('Load saved timing session') menu_resume.connect_object("activate", self.resume_times, None, False) #False is for not merging menu_resume.show() options_menu.append(menu_resume) menu_merge = Gtk.MenuItem('Merge in saved IDs or times') menu_merge.connect_object("activate", self.resume_times, None, True) #True is for merging menu_merge.show() options_menu.append(menu_merge) btnOPTIONS = Gtk.Button('Options') btnOPTIONS.connect_object("event", self.options_btn, options_menu) options_align = Gtk.Alignment.new(1, 0.1, 1, 0) options_align.add(btnOPTIONS) #Then the block of editing buttons btnDROPID = Gtk.Button('Drop ID') btnDROPID.connect('clicked', self.timing_rm_ID) btnDROPTIME = Gtk.Button('Drop time') btnDROPTIME.connect('clicked', self.timing_rm_time) btnEDIT = GtkStockButton('edit', "Edit") btnEDIT.connect('clicked', self.edit_time) edit_vbox = Gtk.VBox(True, 8) edit_vbox.pack_start(btnDROPID, False, False, 0) edit_vbox.pack_start(btnDROPTIME, False, False, 0) edit_vbox.pack_start(btnEDIT, False, False, 0) edit_align = Gtk.Alignment.new(1, 0, 1, 0) edit_align.add(edit_vbox) #Then the print and save buttons btnPRINT = Gtk.Button('Printouts') btnPRINT.connect('clicked', self.print_html, pytimer) btnSAVE = GtkStockButton('save', "Save") btnSAVE.connect('clicked', self.save_times) save_vbox = Gtk.VBox(True, 8) save_vbox.pack_start(btnPRINT, False, False, 0) save_vbox.pack_start(btnSAVE, False, False, 0) save_align = Gtk.Alignment.new(1, 1, 1, 0) save_align.add(save_vbox) #And finally the finish button btnOK = GtkStockButton('close', "Close") btnOK.connect('clicked', self.done_timing) done_align = Gtk.Alignment.new(1, 0.7, 1, 0) done_align.add(btnOK) vsubbox = Gtk.VBox(True, 0) vsubbox.pack_start(options_align, True, True, 0) vsubbox.pack_start(edit_align, True, True, 0) vsubbox.pack_start(save_align, True, True, 0) vsubbox.pack_start(done_align, True, True, 0) vspacer = Gtk.Alignment.new(1, 1, 0, 0) vspacer.add(vsubbox) timehbox = Gtk.HBox(False, 8) timehbox.pack_start(vbox1align, True, True, 0) timehbox.pack_start(vspacer, False, False, 0) self.add(timehbox) self.show_all()
class RegistrationWin(Gtk.Window): '''Handling of the window dedicated to registration''' def __init__(self, path, fields, fieldsdic, prereg, projecttype, save_registration_cb, parent_win=None, autosave=True, save_label=''): '''Builds and display the registration window''' super(RegistrationWin, self).__init__(Gtk.WindowType.TOPLEVEL) if parent_win: self.set_transient_for(parent_win) self.set_modal(True) self.fields = fields self.fieldsdic = fieldsdic self.prereg = prereg self.ids = set() self.projecttype = projecttype self.save_registration_cb = save_registration_cb self.autosave = autosave self.editreg_win = None self.editregfields = None # First we define the registration model. # We will setup a liststore that is wrapped in a treemodelfilter # that is wrapped in a treemodelsort that is put in a treeview # that is put in a scrolled window. Eesh. self.regmodel = Gtk.ListStore(*[str for field in self.fields]) self.modelfilter = self.regmodel.filter_new() self.modelfiltersorted = Gtk.TreeModelSort(self.modelfilter) self.treeview = Gtk.TreeView() # Now we define each column in the treeview for (colid, field) in enumerate(fields): column = Gtk.TreeViewColumn(field, Gtk.CellRendererText(), text=colid) column.set_sort_column_id(colid) self.treeview.append_column(column) # Now we populate the model with the pre-registration info, if any for reg in prereg: self.regmodel.append([reg[field] for field in fields]) if reg['ID']: self.ids.add(reg['ID']) # This is the string that we filter based on. self.searchstr = '' self.modelfilter.set_visible_func(self.visible_filter) self.treeview.set_model(self.modelfiltersorted) self.treeview.set_enable_search(False) # Now let us actually build the window self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) fname = os.path.abspath( os.path.join( os.path.dirname(os.path.abspath(__file__)), '../data/icon.png')) self.set_icon_from_file(fname) self.set_title('fsTimer - ' + os.path.basename(path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.close_clicked(jnk)) self.set_border_width(10) self.set_size_request(850, 450) #Now the filter entrybox filterbox = Gtk.HBox(False, 8) filterbox.pack_start(Gtk.Label('Filter by ', True, True, 0), False, False, 0) self.filter_combo = Gtk.ComboBoxText() for field in self.fields: self.filter_combo.append_text(field) self.filter_combo.set_active(0) filterbox.pack_start(self.filter_combo, False, False, 0) filterbox.pack_start(Gtk.Label(':'), False, False, 0) self.filterentry = Gtk.Entry() self.filterentry.set_max_length(40) self.filterentry.connect('changed', self.filter_apply) self.filterbtnCLEAR = GtkStockButton('clear',"Clear") self.filterbtnCLEAR.connect('clicked', self.filter_clear) self.filterbtnCLEAR.set_sensitive(False) filterbox.pack_start(self.filterentry, False, False, 0) filterbox.pack_start(self.filterbtnCLEAR, False, False, 0) # Now the scrolled window that contains the treeview regsw = Gtk.ScrolledWindow() regsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) regsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) regsw.add(self.treeview) # And a message that says if we have saved or not. self.regstatus = Gtk.Label(label=save_label) # Some boxes for all the stuff on the left regvbox1 = Gtk.VBox(False, 8) regvbox1.pack_start(filterbox, False, False, 0) regvbox1.pack_start(regsw, True, True, 0) regvbox1.pack_start(self.regstatus, False, False, 0) vbox1align = Gtk.Alignment.new(0, 0, 1, 1) vbox1align.add(regvbox1) # And boxes/table for the buttons on the right regtable = Gtk.Table(2, 1, False) regtable.set_row_spacings(5) regtable.set_col_spacings(5) regtable.set_border_width(5) btnEDIT = GtkStockButton('edit',"Edit") btnEDIT.connect('clicked', self.edit_clicked) btnREMOVE = GtkStockButton('remove',"Remove") btnREMOVE.connect('clicked', self.rm_clicked) btnNEW = GtkStockButton('new',"New") btnNEW.connect('clicked', self.new_clicked) btnSAVE = GtkStockButton('save',"Save") btnSAVE.connect('clicked', self.save_clicked) btnOK = GtkStockButton('close',"Close") btnOK.connect('clicked', self.close_clicked) vsubbox = Gtk.VBox(False, 8) vsubbox.pack_start(btnSAVE, False, False, 0) regvspacer = Gtk.Alignment.new(1, 1, 0, 0) regvspacer.add(vsubbox) regtable.attach(regvspacer, 0, 1, 1, 2) regvbox2 = Gtk.VBox(False, 8) regvbox2.pack_start(btnNEW, False, False, 0) regvbox2.pack_start(btnEDIT, False, False, 0) regvbox2.pack_start(btnREMOVE, False, False, 30) regvbalign = Gtk.Alignment.new(1, 0, 0, 0) regvbalign.add(regvbox2) regtable.attach(regvbalign, 0, 1, 0, 1) #Now we pack everything together reghbox = Gtk.HBox(False, 8) reghbox.pack_start(vbox1align, True, True, 0) reghbox.pack_start(regtable, False, False, 0) # Add in the close button on the bottom vbox_all = Gtk.VBox(False, 0) vbox_all.pack_start(reghbox, True, True, 0) donespacer = Gtk.Alignment.new(0, 0, 0, 0) donespacer.add(btnOK) vbox_all.pack_start(donespacer, False, False, 5) self.add(vbox_all) # And show. self.show_all() def visible_filter(self, model, titer, data): '''This is the filter function. It checks if self.searchstr is contained in column matching self.filter_combo case insensitive''' if self.searchstr: col_idx = self.filter_combo.get_active() if not model.get_value(titer, col_idx): return False else: return self.searchstr.lower() in model.get_value(titer, col_idx).lower() else: return True def filter_apply(self, jnk_unused): ''' handles modification of the content of the filter box sets self.searchstr to the current entrybox contents and refilter''' self.searchstr = self.filterentry.get_text() self.filterbtnCLEAR.set_sensitive(True) self.modelfilter.refilter() def filter_clear(self, jnk_unused): '''handles clearing of the filter box. Clears self.searchstr and refilter''' self.searchstr = '' self.filterentry.set_text('') self.filterbtnCLEAR.set_sensitive(False) self.modelfilter.refilter() def edit_clicked(self, jnk_unused): '''handles click on the 'edit' button on the registration window''' selection = self.treeview.get_selection() treeiter = selection.get_selected()[1] # if no selection, do nothing. if treeiter: # Grab the current information. current_info = {} for (colid, field) in enumerate(self.fields): current_info[field] = self.modelfiltersorted.get_value(treeiter, colid) # Find where this is in self.prereg preregiter = self.prereg.index(current_info) # Generate the window self.edit_registration(treeiter, preregiter, current_info) def rm_clicked(self, jnk_unused): '''Handling click on the 'remove' button of the registration window Throws up an 'are you sure' dialog box, and delete if yes''' selection = self.treeview.get_selection() treeiter = selection.get_selected()[1] # if nothing is selected, do nothing. if treeiter: rmreg_dialog = MsgDialog(self, 'warning', ['yes', 'no'], 'Really delete?', 'Are you sure you want to delete this entry?\nThis cannot be undone.') rmreg_dialog.set_default_response(Gtk.ResponseType.NO) response = rmreg_dialog.run() rmreg_dialog.destroy() if response == Gtk.ResponseType.YES: # Grab the current information. current_info = {} for (colid, field) in enumerate(self.fields): current_info[field] = self.modelfiltersorted.get_value(treeiter, colid) # Find where this is in self.prereg preregiter = self.prereg.index(current_info) # converts the treeiter from sorted to filter to model, and remove self.regmodel.remove(self.modelfilter.convert_iter_to_child_iter(self.modelfiltersorted.convert_iter_to_child_iter(treeiter))) try: self.ids.remove(current_info['ID']) except: pass self.prereg.pop(preregiter) # The latest stuff has no longer been saved. self.regstatus.set_markup('') def new_clicked(self, jnk_unused): '''Handles click on the 'new' button on the registration window Creates the editreg window with a None treeiter and clear initial values.''' self.edit_registration(None, None, None) def save_clicked(self, jnk_unused): '''Handles click on the 'save' button on the registration window. We do a json dump of self.prereg''' filename, success = self.save_registration_cb() if success: self.regstatus.set_markup('<span color="blue">Registration saved to %s</span>' % filename) return True else: self.regstatus.set_markup('<span color="red">Registration NOT saved: %s</span>' % filename) return False def close_clicked(self, jnk_unused): '''Handles click on the 'close' button on the registration window. Throws up a 'do you want to save' dialog, and close the window''' okreg_dialog = MsgDialog(self, 'question', ['yes', 'no'], 'Save?', 'Do you want to save before finishing?\nUnsaved data will be lost.') okreg_dialog.set_default_response(Gtk.ResponseType.YES) response = okreg_dialog.run() okreg_dialog.destroy() if response == Gtk.ResponseType.YES: # this will save save_res = self.save_clicked(None) if not save_res: return self.hide() # Clear the file setting from pre-reg, in case pre-reg is # re-run without selecting a file del self.prereg[:] def edit_registration(self, treeiter, preregiter, current_info): '''handles creation/modification of a registration entry. Converts the treeiter from the treemodelsort to the liststore.''' if treeiter: treeiter = self.modelfilter.convert_iter_to_child_iter(self.modelfiltersorted.convert_iter_to_child_iter(treeiter)) # Define the window self.editreg_win = Gtk.Window(Gtk.WindowType.TOPLEVEL) self.editreg_win.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.editreg_win.set_title('Registration entry') self.editreg_win.set_transient_for(self) self.editreg_win.set_modal(True) self.editreg_win.set_position(Gtk.WindowPosition.CENTER) self.editreg_win.connect('delete_event', lambda b, jnk_unused: self.editreg_win.hide()) self.editreg_win.set_border_width(10) #An hbox for the buttons editreghbox = Gtk.HBox(False, 8) editregbtnOK = GtkStockButton('ok',"OK") editregbtnCANCEL = GtkStockButton('close',"Cancel") editregbtnCANCEL.connect('clicked', lambda b: self.editreg_win.hide()) editreghbox.pack_start(editregbtnOK, False, False, 5) editreghbox.pack_start(editregbtnCANCEL, False, False, 5) # fill in current_info if available. self.editregfields = {} for field in self.fields: # Determine which type of entry is appropriate, create it and fill it. # Entrybox if self.fieldsdic[field]['type'] in ['entrybox', 'entrybox_int']: self.editregfields[field] = Gtk.Entry() self.editregfields[field].set_max_length(self.fieldsdic[field]['max']) if current_info: self.editregfields[field].set_text(current_info[field]) # Combobox elif self.fieldsdic[field]['type'] == 'combobox': self.editregfields[field] = Gtk.ComboBoxText() self.editregfields[field].append_text('') for val in self.fieldsdic[field]['options']: self.editregfields[field].append_text(val) if current_info: try: indx = self.fieldsdic[field]['options'].index(current_info[field]) self.editregfields[field].set_active(indx+1) except ValueError: self.editregfields[field].set_active(0) #this catches if current_inf[field] is not a valid value. It is probably blank. Otherwise this is an issue, but we will force it blank. else: self.editregfields[field].set_active(0) # Set up the vbox editregvbox = Gtk.VBox(False, 8) # We will make a smaller hbox for each of the fields. hboxes = {} for field in self.fields: hboxes[field] = Gtk.HBox(False, 15) hboxes[field].pack_start(Gtk.Label(field+':', True, True, 0), False, False, 0) #Pack the label hboxes[field].pack_start(self.editregfields[field], False, False, 0) #Pack the button/entry/.. if self.projecttype == 'handicap' and field == 'Handicap': label_hd = Gtk.Label(label='hh:mm:ss') hboxes[field].pack_start(label_hd, False, False, 0) if field == 'ID': label_id = Gtk.Label('Must be unique') hboxes[field].pack_start(label_id, False, False, 0) editregvbox.pack_start(hboxes[field], False, False, 0) #Pack this hbox into the big vbox. #Pack and show if self.projecttype == 'handicap': editregbtnOK.connect('clicked', self.validate_entry, treeiter, preregiter, label_hd, label_id) else: editregbtnOK.connect('clicked', self.validate_entry, treeiter, preregiter, None, label_id) editregvbox.pack_start(editreghbox, False, False, 5) self.editreg_win.add(editregvbox) self.editreg_win.show_all() def validate_entry(self, jnk_unused, treeiter, preregiter, label_hd, label_id): '''Handles a click on the 'ok' button of the entry edition window. Reads out the input information, and writes the changes to the treemodel''' #First check if we have entered a handicap, and if so, make sure it is valid if self.projecttype == 'handicap': sduration = self.editregfields['Handicap'].get_text() if sduration != '': try: timePattern = r'((?P<days>-?\d+) day(s)?, )?((?P<hours>\d+):)?'r'(?P<minutes>\d+):(?P<seconds>\d+)' re.match(timePattern, sduration).groupdict(0) except AttributeError: label_hd.set_markup('<span color="red">hh:mm:ss</span>') return # If that was OK, we go through each field and grab the new value. new_vals = {} for field in self.fields: #Entrybox if self.fieldsdic[field]['type'] in ['entrybox', 'entrybox_int']: new_vals[field] = self.editregfields[field].get_text() #Combobox elif self.fieldsdic[field]['type'] == 'combobox': indx = self.editregfields[field].get_active() if indx == 0: new_vals[field] = '' else: new_vals[field] = self.fieldsdic[field]['options'][indx-1] # Make sure we don't have a duplicate ID, unless we are editing and leave it the same. if treeiter and new_vals['ID'] == self.prereg[preregiter]['ID']: pass # No need for an ID check, it was already done. elif new_vals['ID'] in self.ids: label_id.set_markup('<span color="red">{} has already been used</span>'.format(new_vals['ID'])) return # Now we replace or append in the treemodel and in prereg if treeiter: # Remove the old ID from the id store, and add the new value if self.prereg[preregiter]['ID']: self.ids.remove(self.prereg[preregiter]['ID']) # Update the tree and prereg for (colid, field) in enumerate(self.fields): self.regmodel.set_value(treeiter, colid, new_vals[field]) self.prereg[preregiter] = new_vals else: self.regmodel.append([new_vals[field] for field in self.fields]) self.prereg.append(new_vals) # Add the new ID to the id store if new_vals['ID']: self.ids.add(new_vals['ID']) # The saved status is unsaved self.regstatus.set_markup('') # Filter results by the current filter field, for this value self.filterentry.set_text(new_vals[self.filter_combo.get_active_text()]) # Save if self.autosave: self.save_clicked(None) # we're done self.editreg_win.hide()
def __init__(self, fields, fieldsdic, printfields, back_clicked_cb, next_clicked_cb, parent, edit): '''Creates print fields window''' super(PrintFieldsWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(parent) self.set_modal(True) self.set_size_request(600, 600) self.set_title('fsTimer - Choose results fields') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.connect('delete_event', lambda b, jnk: self.hide()) self.printfields = printfields self.fields = fields self.fieldsdic = fieldsdic # Now create the vbox. vbox = Gtk.VBox(False, 2) self.add(vbox) # Now add the text. label1_0 = Gtk.Label( "Choose the fields to show on the results printout.\nPress 'Forward' to continue with the default settings, or make edits below.\n" ) label1_1 = Gtk.Label() label1_1.set_markup('<b>Registration fields</b>') vbox.pack_start(label1_0, False, False, 0) vbox.pack_start(label1_1, False, False, 0) reg_sw = Gtk.ScrolledWindow() reg_sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) reg_sw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) vbox_btn = Gtk.VBox(False, 2) btnlist = [] for field in self.fields: btnlist.append(Gtk.CheckButton(field)) if field in self.printfields: btnlist[-1].set_active(True) else: btnlist[-1].set_active(False) vbox_btn.pack_start(btnlist[-1], True, True, 0) reg_sw.add_with_viewport(vbox_btn) vbox.pack_start(reg_sw, True, True, 5) label1_2 = Gtk.Label() label1_2.set_markup('<b>Computed results</b>') vbox.pack_start(label1_2, False, False, 0) btn_time = Gtk.CheckButton('Time') if 'Time' in self.printfields: btn_time.set_active(True) # Pace buttons btn_pace = Gtk.CheckButton('Pace') label_pace = Gtk.Label(' Distance:') entry_pace = Gtk.Entry() entry_pace.set_max_length(5) entry_pace.set_width_chars(5) # Fill it in if 'Pace' in self.printfields: btn_pace.set_active(True) entry_pace.set_text( str(float(self.printfields['Pace'].split('/')[1]))) hbox_pace = Gtk.HBox(False, 5) hbox_pace.pack_start(btn_pace, False, False, 0) hbox_pace.pack_start(label_pace, False, False, 2) hbox_pace.pack_start(entry_pace, False, False, 2) vbox.pack_start(btn_time, False, False, 0) vbox.pack_start(hbox_pace, False, False, 0) vbox.pack_start( Gtk.Label("\nCustom expressions ({Time} is in seconds):"), False, False, 0) self.customview = Gtk.TreeView() # Make the model, a liststore with columns str, bool, str self.custommodel = Gtk.ListStore(str, str) for field in self.printfields: if field not in self.fields and field not in ['Time', 'Pace']: self.custommodel.append((field, self.printfields[field])) self.customview.set_model(self.custommodel) selection = self.customview.get_selection() # Add following columns to the treeview : # field name | expression name_renderer = Gtk.CellRendererText() name_renderer.set_property("editable", True) name_renderer.connect("edited", self.name_edit) column = Gtk.TreeViewColumn('Name', name_renderer, text=0) self.customview.append_column(column) code_renderer = Gtk.CellRendererText() code_renderer.set_property("editable", True) code_renderer.connect("edited", self.code_edit) column = Gtk.TreeViewColumn('Expression', code_renderer, text=1) self.customview.append_column(column) # Create scrolled window, in an alignment customsw = Gtk.ScrolledWindow() customsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) customsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) customsw.add(self.customview) customalgn = Gtk.Alignment.new(0, 0, 1, 1) customalgn.add(customsw) # Now we put the buttons on the side. vbox2 = Gtk.VBox(False, 10) btnREMOVE = GtkStockButton('remove', "Remove") btnREMOVE.connect('clicked', self.custom_remove, selection) vbox2.pack_start(btnREMOVE, False, False, 0) btnNEW = GtkStockButton('new', "New") btnNEW.connect('clicked', self.custom_new, selection) vbox2.pack_start(btnNEW, False, False, 0) # And an hbox for the fields and the buttons hbox4 = Gtk.HBox(False, 0) hbox4.pack_start(customalgn, True, True, 10) hbox4.pack_start(vbox2, False, False, 0) vbox_comp = Gtk.VBox(False, 0) vbox_comp.pack_start(hbox4, True, True, 0) vbox.pack_start(vbox_comp, False, False, 0) # And an hbox with 2 buttons hbox = Gtk.HBox(False, 0) btnCANCEL = GtkStockButton('close', "Close") btnCANCEL.connect('clicked', lambda btn: self.hide()) alignCANCEL = Gtk.Alignment.new(0, 0, 0, 0) alignCANCEL.add(btnCANCEL) btnBACK = GtkStockButton('back', "Back") btnBACK.connect('clicked', back_clicked_cb, btnlist, btn_time, btn_pace, entry_pace, self.printfields) btnNEXT = GtkStockButton('forward', "Next") btnNEXT.connect('clicked', next_clicked_cb, btnlist, btn_time, btn_pace, entry_pace, self.printfields, edit) ##And populate hbox.pack_start(alignCANCEL, True, True, 0) hbox.pack_start(btnBACK, False, False, 2) hbox.pack_start(btnNEXT, False, False, 0) vbox.pack_start(hbox, False, False, 8) self.show_all()
def view_entries_clicked(self, jnk_unused): '''Handles click on View Id entries Loads a new window that will list the registration entries overloaded. Then gives an option to keep one of the registration entries''' selection = self.errortreeview.get_selection() treeiter = selection.get_selected()[1] if treeiter: current_id = self.errorlist.get_value(treeiter, 0) # Define the new window self.corerrorswin = Gtk.Window(Gtk.WindowType.TOPLEVEL) self.corerrorswin.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.corerrorswin.set_transient_for(self) self.corerrorswin.set_modal(True) self.corerrorswin.set_title('fsTimer - ' + os.path.basename(self.path)) self.corerrorswin.set_position(Gtk.WindowPosition.CENTER) self.corerrorswin.connect('delete_event', lambda b, jnk: self.corerrorswin.hide()) self.corerrorswin.set_border_width(10) self.corerrorswin.set_size_request(800, 300) # This will be a liststore in a treeview in a scrolled window, as usual corerrorsw = Gtk.ScrolledWindow() corerrorsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) corerrorsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.corerrorlist = Gtk.ListStore(*[str for field in self.fields]) self.corerrortreeview = Gtk.TreeView() # Now define each column in the treeview # Take these from self.fields for (colid, field) in enumerate(self.fields): column = Gtk.TreeViewColumn(field, Gtk.CellRendererText(), text=colid) column.set_sort_column_id(colid) self.corerrortreeview.append_column(column) # Add in the info from self.errors for reg in self.errors[current_id]: self.corerrorlist.append([reg[field] for field in self.fields]) self.corerrortreeview.set_model(self.corerrorlist) corerrorsw.add(self.corerrortreeview) errvbox1 = Gtk.VBox(False, 8) errvbox1.pack_start(Gtk.Label('''These entries share the same ID. Use "Keep entry" to associate an entry with the ID. Otherwise, press "OK" to continue, no entry will be associated with this ID.'''), False, False, 0) errvbox1.pack_start(corerrorsw, True, True, 0) vbox1align = Gtk.Alignment.new(0, 0, 1, 1) vbox1align.add(errvbox1) #Now build a table for the buttons errtable = Gtk.Table(2, 1, False) errtable.set_row_spacings(5) errtable.set_col_spacings(5) errtable.set_border_width(5) btnKEEP = Gtk.Button('Keep entry') btnKEEP.connect('clicked', self.keep_correct, current_id, treeiter) btnCANCEL = GtkStockButton('close','Close') btnCANCEL.connect('clicked', lambda b: self.corerrorswin.hide()) vsubbox = Gtk.VBox(False, 8) vsubbox.pack_start(btnCANCEL, False, False, 0) errvspacer = Gtk.Alignment.new(1, 1, 0, 0) errvspacer.add(vsubbox) errtable.attach(errvspacer, 0, 1, 1, 2) errvbox2 = Gtk.VBox(False, 8) errvbox2.pack_start(btnKEEP, False, False, 0) errvbalign = Gtk.Alignment.new(1, 0, 0, 0) errvbalign.add(errvbox2) errtable.attach(errvbalign, 0, 1, 0, 1) errhbox = Gtk.HBox(False, 8) errhbox.pack_start(vbox1align, True, True, 0) errhbox.pack_start(errtable, False, False, 0) self.corerrorswin.add(errhbox) self.corerrorswin.show_all()
def div_new(self, jnk_unused, divtupl, treeiter): '''handles a click on NEW button''' self.winnewdiv = Gtk.Window(Gtk.WindowType.TOPLEVEL) self.winnewdiv.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.winnewdiv.set_transient_for(self) self.winnewdiv.set_modal(True) self.winnewdiv.set_title('fsTimer - New division') self.winnewdiv.set_position(Gtk.WindowPosition.CENTER) self.winnewdiv.set_border_width(20) self.winnewdiv.connect( 'delete_event', lambda b, jnk_unused: self.winnewdiv.hide()) #Prepare for packing. vbox = Gtk.VBox(False, 10) windescr = Gtk.Label( 'Use the checkboxes to select which fields to use to define this ' 'division,\nand then select the corresponding value to be used ' 'for this division.') vbox.pack_start(windescr, False, False, 0) HBoxes = {} CheckButtons = {} ComboBoxes = {} minadjs = {} minbtns = {} maxadjs = {} maxbtns = {} #Process the input divnamein = divtupl[0] divdic = divtupl[1] #First name of the divisional. divnamelbl = Gtk.Label(label='Division name:') divnameentry = Gtk.Entry() divnameentry.set_max_length(80) divnameentry.set_width_chars(40) divnameentry.set_text(divnamein) # set to initial value HBoxes[1] = Gtk.HBox(False, 10) # int key won't collide with a field HBoxes[1].pack_start(divnamelbl, False, False, 0) HBoxes[1].pack_start(divnameentry, False, False, 0) vbox.pack_start(HBoxes[1], False, False, 0) #And now all of the fields for field in self.fields: if self.fieldsdic[field]['type'] == 'combobox': #Add it. CheckButtons[field] = Gtk.CheckButton(label=field + ':') ComboBoxes[field] = Gtk.ComboBoxText() for option in self.fieldsdic[field]['options']: ComboBoxes[field].append_text(option) if field in divdic and divdic[field]: CheckButtons[field].set_active(True) # check box ComboBoxes[field].set_active( self.fieldsdic[field]['options'].index( divdic[field])) #Put it in an HBox HBoxes[field] = Gtk.HBox(False, 10) HBoxes[field].pack_start(CheckButtons[field], False, False, 0) HBoxes[field].pack_start(ComboBoxes[field], False, False, 0) vbox.pack_start(HBoxes[field], False, False, 0) elif self.fieldsdic[field]['type'] == 'entrybox_int': CheckButtons[field] = Gtk.CheckButton(label=field + ':') if field in divdic: CheckButtons[field].set_active(True) minadjs[field] = Gtk.Adjustment( value=divdic[field][0], step_incr=1, lower=-10000, upper=10000) maxadjs[field] = Gtk.Adjustment( value=divdic[field][1], step_incr=1, lower=-10000, upper=10000) else: minadjs[field] = Gtk.Adjustment(value=0, step_incr=1, lower=-10000, upper=10000) maxadjs[field] = Gtk.Adjustment(value=120, step_incr=1, lower=-10000, upper=10000) minlbl = Gtk.Label(label='From:') minbtns[field] = Gtk.SpinButton(digits=0, climb_rate=0) minbtns[field].set_adjustment(minadjs[field]) maxlbl = Gtk.Label(label='Through:') maxbtns[field] = Gtk.SpinButton(digits=0, climb_rate=0) maxbtns[field].set_adjustment(maxadjs[field]) #Make an hbox of it. HBoxes[field] = Gtk.HBox(False, 10) HBoxes[field].pack_start(CheckButtons[field], False, False, 0) HBoxes[field].pack_start(minlbl, False, False, 0) HBoxes[field].pack_start(minbtns[field], False, False, 0) HBoxes[field].pack_start(maxlbl, False, False, 0) HBoxes[field].pack_start(maxbtns[field], False, False, 0) vbox.pack_start(HBoxes[field], False, False, 0) #On to the bottom buttons btnOK = GtkStockButton('ok','OK') btnOK.connect('clicked', self.winnewdivOK, treeiter, CheckButtons, ComboBoxes, minbtns, maxbtns, divnameentry) btnCANCEL = GtkStockButton('close','Cancel') btnCANCEL.connect('clicked', lambda b: self.winnewdiv.hide()) cancel_algn = Gtk.Alignment.new(0, 0, 0, 0) cancel_algn.add(btnCANCEL) hbox3 = Gtk.HBox(False, 10) hbox3.pack_start(cancel_algn, True, True, 0) hbox3.pack_start(btnOK, False, False, 0) vbox.pack_start(hbox3, False, False, 0) self.winnewdiv.add(vbox) self.winnewdiv.show_all()
def __init__(self, fields, fieldsdic, projecttype, back_clicked_cb, next_clicked_cb, parent): '''Creates fields definition window''' super(DefineFieldsWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.fields = fields self.fieldsdic = fieldsdic self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.winnewcombo = None self.winnewentry = None self.set_transient_for(parent) self.set_modal(True) self.set_title('fsTimer - Fields') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.set_size_request(600, 400) self.connect('delete_event', lambda b, jnk_unused: self.hide()) #Specify the fields that are required and so will be locked. if projecttype == 'handicap': self.reqfields = ['ID', 'Handicap'] else: self.reqfields = ['ID'] ##Now create the vbox. vbox1 = Gtk.VBox(False, 10) self.add(vbox1) ##Now add the text. label2_0 = Gtk.Label( "Specify the information to be collected during registration.\n" "Press 'Forward' to continue with the default settings, or make " "edits below.") #Now we put in a liststore with the settings. We start with the default settings. #Make the liststore, with 3 columns (title, type, settings) self.regfieldsmodel = Gtk.ListStore(str, str, str) #We will put the liststore in a treeview self.regfieldview = Gtk.TreeView() column = Gtk.TreeViewColumn('Field', Gtk.CellRendererText(), text=0) self.regfieldview.append_column(column) column = Gtk.TreeViewColumn('Type', Gtk.CellRendererText(), text=1) self.regfieldview.append_column(column) column = Gtk.TreeViewColumn('Settings', Gtk.CellRendererText(), text=2) self.regfieldview.append_column(column) #Now we populate the model with the default fields for field in fields: if fieldsdic[field]['type'] == 'entrybox': self.regfieldsmodel.append([field, 'Text entry', 'max characters: '+str(fieldsdic[field]['max'])]) elif fieldsdic[field]['type'] == 'entrybox_int': self.regfieldsmodel.append([field, 'Number entry', 'max characters: '+str(fieldsdic[field]['max'])]) elif fieldsdic[field]['type'] == 'combobox': optstr = '' for opt in fieldsdic[field]['options']: optstr += opt + ', ' optstr = optstr[:-2] #drop the last ', ' self.regfieldsmodel.append([field, 'Selection box', 'options: '+optstr]) self.regfieldview.set_model(self.regfieldsmodel) selection = self.regfieldview.get_selection() #And put it in a scrolled window, in an alignment regfieldsw = Gtk.ScrolledWindow() regfieldsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) regfieldsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) regfieldsw.add(self.regfieldview) regfieldalgn = Gtk.Alignment.new(0, 0, 1, 1) regfieldalgn.add(regfieldsw) #Now we put the buttons on the side. vbox2 = Gtk.VBox(False, 10) btnUP = GtkStockButton('up',"Up") btnUP.connect('clicked', self.regfield_up, selection) vbox2.pack_start(btnUP, False, False, 0) btnDOWN = GtkStockButton('down',"Down") btnDOWN.connect('clicked', self.regfield_down, selection) vbox2.pack_start(btnDOWN, False, False, 0) btnEDIT = GtkStockButton('edit',"Edit") btnEDIT.connect('clicked', self.regfield_edit, selection) vbox2.pack_start(btnEDIT, False, False, 0) btnREMOVE = GtkStockButton('remove',"Remove") btnREMOVE.connect('clicked', self.regfield_remove, selection) vbox2.pack_start(btnREMOVE, False, False, 0) btnNEWentry = Gtk.Button('New text entry') btnNEWentry.connect('clicked', self.regfield_new_entrybox, '', 20, None, 'text') vbox2.pack_start(btnNEWentry, False, False, 0) btnNEWentry = Gtk.Button('New number entry') btnNEWentry.connect('clicked', self.regfield_new_entrybox, '', 3, None, 'number') vbox2.pack_start(btnNEWentry, False, False, 0) btnNEWcombo = Gtk.Button('New selection box') btnNEWcombo.connect('clicked', self.regfield_new_combobox, '', '', None) vbox2.pack_start(btnNEWcombo, False, False, 0) selection.connect('changed', self.regfield_lock_required_fields, btnREMOVE, btnEDIT) #And an hbox for the fields and the buttons hbox4 = Gtk.HBox(False, 0) hbox4.pack_start(regfieldalgn, True, True, 10) hbox4.pack_start(vbox2, False, False, 0) ##And an hbox with 3 buttons hbox3 = Gtk.HBox(False, 0) btnCANCEL = GtkStockButton('close',"Close") btnCANCEL.connect('clicked', lambda btn: self.hide()) alignCANCEL = Gtk.Alignment.new(0, 0, 0, 0) alignCANCEL.add(btnCANCEL) btnBACK = GtkStockButton('back',"Back") btnBACK.connect('clicked', back_clicked_cb) btnNEXT = GtkStockButton('forward',"Next") btnNEXT.connect('clicked', next_clicked_cb) ##And populate hbox3.pack_start(alignCANCEL, True, True, 0) hbox3.pack_start(btnBACK, False, False, 2) hbox3.pack_start(btnNEXT, False, False, 0) vbox1.pack_start(label2_0, False, False, 0) vbox1.pack_start(hbox4, True, True, 0) vbox1.pack_start(hbox3, False, False, 10) self.show_all()
def propose_advanced_import(self, csv_fields, textbuffer1): '''Propose advanced import mechanism where project fields can be build from the csv ones using python expressions''' self.advancedwin = Gtk.Window(Gtk.WindowType.TOPLEVEL) self.advancedwin.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.advancedwin.set_transient_for(self) self.advancedwin.set_modal(True) self.advancedwin.set_title('fsTimer - CSV import') self.advancedwin.set_position(Gtk.WindowPosition.CENTER) self.advancedwin.set_border_width(20) self.advancedwin.set_size_request(600, 400) self.advancedwin.connect('delete_event', lambda b, jnk_unused: self.advancedwin.hide()) # top label toplabel = Gtk.Label("For each field, specify the corresponding CSV column.\n") # Treeview with 3 columns : field, combobox and free text self.fieldview = Gtk.TreeView() self.fieldview.set_grid_lines(Gtk.TreeViewGridLines.BOTH) # Associated model with 5 columns : the 4th one is a boolean indicating # whether the 3rd one (Advanced mapping) should be sensitive self.fieldsmodel = Gtk.ListStore(str, str, str, bool) for field in self.fields: self.fieldsmodel.append([field, field if field in csv_fields else '-- select --', '', False]) self.fieldview.set_model(self.fieldsmodel) # build first column (project field) column = Gtk.TreeViewColumn('Field', Gtk.CellRendererText(), text=0) self.fieldview.append_column(column) # vuild 2nd column (csv field to be used, as a combo box) combo_renderer = Gtk.CellRendererCombo() liststore_csv_fields = Gtk.ListStore(str) liststore_csv_fields.append(['-- Leave empty --']) for field in csv_fields: liststore_csv_fields.append([field]) liststore_csv_fields.append(['-- Advanced expression --']) combo_renderer.set_property("model", liststore_csv_fields) combo_renderer.set_property("text-column", 0) combo_renderer.set_property("editable", True) combo_renderer.set_property("has-entry", False) column = Gtk.TreeViewColumn('CSV column', combo_renderer, text=1) self.fieldview.append_column(column) # build the 3rd column (Advanced mapping) advanced_renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn('Advanced mapping', advanced_renderer, text=2, sensitive=3, editable=3) self.fieldview.append_column(column) # handler for the combo changes combo_renderer.connect("edited", self.combo_changed) advanced_renderer.connect("edited", self.text_changed) # And put it in a scrolled window, in an alignment fieldsw = Gtk.ScrolledWindow() fieldsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) fieldsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) fieldsw.add(self.fieldview) fieldalgn = Gtk.Alignment.new(0, 0, 1, 1) fieldalgn.add(fieldsw) # a text buffer for errors textbuffer2 = Gtk.TextBuffer() try: textbuffer2.create_tag("red", foreground="red") textbuffer2.create_tag("blue", foreground="blue") except TypeError: pass textview = Gtk.TextView() textview.set_buffer(textbuffer2) textview.set_editable(False) textview.set_cursor_visible(False) # hbox for the buttons hbox = Gtk.HBox(False, 0) btnCANCEL = GtkStockButton('close',"Cancel") btnCANCEL.connect('clicked', self.advanced_import_cancel, textbuffer1) btnOK = GtkStockButton('ok',"OK") btnOK.connect('clicked', self.advanced_import_ok, textbuffer1, textbuffer2) alignOK = Gtk.Alignment.new(1, 0, 0, 0) alignOK.add(btnOK) hbox.pack_start(btnCANCEL, False, True, 0) hbox.pack_start(alignOK, True, True, 0) # populate vbox = Gtk.VBox(False, 10) vbox.pack_start(toplabel, False, False, 0) vbox.pack_start(fieldalgn, True, True, 0) vbox.pack_start(textview, False, False, 0) vbox.pack_start(hbox, False, False, 10) self.advancedwin.add(vbox) self.advancedwin.show_all()
def __init__(self, fields, fieldsdic, projecttype, back_clicked_cb, next_clicked_cb, parent): '''Creates fields definition window''' super(DefineFieldsWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.fields = fields self.fieldsdic = fieldsdic self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.winnewcombo = None self.winnewentry = None self.set_transient_for(parent) self.set_modal(True) self.set_title('fsTimer - Fields') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.set_size_request(600, 400) self.connect('delete_event', lambda b, jnk_unused: self.hide()) #Specify the fields that are required and so will be locked. if projecttype == 'handicap': self.reqfields = ['ID', 'Handicap'] else: self.reqfields = ['ID'] ##Now create the vbox. vbox1 = Gtk.VBox(False, 10) self.add(vbox1) ##Now add the text. label2_0 = Gtk.Label( "Specify the information to be collected during registration.\n" "Press 'Forward' to continue with the default settings, or make " "edits below.") #Now we put in a liststore with the settings. We start with the default settings. #Make the liststore, with 3 columns (title, type, settings) self.regfieldsmodel = Gtk.ListStore(str, str, str) #We will put the liststore in a treeview self.regfieldview = Gtk.TreeView() column = Gtk.TreeViewColumn('Field', Gtk.CellRendererText(), text=0) self.regfieldview.append_column(column) column = Gtk.TreeViewColumn('Type', Gtk.CellRendererText(), text=1) self.regfieldview.append_column(column) column = Gtk.TreeViewColumn('Settings', Gtk.CellRendererText(), text=2) self.regfieldview.append_column(column) #Now we populate the model with the default fields for field in fields: if fieldsdic[field]['type'] == 'entrybox': self.regfieldsmodel.append([ field, 'Text entry', 'max characters: ' + str(fieldsdic[field]['max']) ]) elif fieldsdic[field]['type'] == 'entrybox_int': self.regfieldsmodel.append([ field, 'Number entry', 'max characters: ' + str(fieldsdic[field]['max']) ]) elif fieldsdic[field]['type'] == 'combobox': optstr = '' for opt in fieldsdic[field]['options']: optstr += opt + ', ' optstr = optstr[:-2] #drop the last ', ' self.regfieldsmodel.append( [field, 'Selection box', 'options: ' + optstr]) self.regfieldview.set_model(self.regfieldsmodel) selection = self.regfieldview.get_selection() #And put it in a scrolled window, in an alignment regfieldsw = Gtk.ScrolledWindow() regfieldsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) regfieldsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) regfieldsw.add(self.regfieldview) regfieldalgn = Gtk.Alignment.new(0, 0, 1, 1) regfieldalgn.add(regfieldsw) #Now we put the buttons on the side. vbox2 = Gtk.VBox(False, 10) btnUP = GtkStockButton('up', "Up") btnUP.connect('clicked', self.regfield_up, selection) vbox2.pack_start(btnUP, False, False, 0) btnDOWN = GtkStockButton('down', "Down") btnDOWN.connect('clicked', self.regfield_down, selection) vbox2.pack_start(btnDOWN, False, False, 0) btnEDIT = GtkStockButton('edit', "Edit") btnEDIT.connect('clicked', self.regfield_edit, selection) vbox2.pack_start(btnEDIT, False, False, 0) btnREMOVE = GtkStockButton('remove', "Remove") btnREMOVE.connect('clicked', self.regfield_remove, selection) vbox2.pack_start(btnREMOVE, False, False, 0) btnNEWentry = Gtk.Button('New text entry') btnNEWentry.connect('clicked', self.regfield_new_entrybox, '', 20, None, 'text') vbox2.pack_start(btnNEWentry, False, False, 0) btnNEWentry = Gtk.Button('New number entry') btnNEWentry.connect('clicked', self.regfield_new_entrybox, '', 3, None, 'number') vbox2.pack_start(btnNEWentry, False, False, 0) btnNEWcombo = Gtk.Button('New selection box') btnNEWcombo.connect('clicked', self.regfield_new_combobox, '', '', None) vbox2.pack_start(btnNEWcombo, False, False, 0) selection.connect('changed', self.regfield_lock_required_fields, btnREMOVE, btnEDIT) #And an hbox for the fields and the buttons hbox4 = Gtk.HBox(False, 0) hbox4.pack_start(regfieldalgn, True, True, 10) hbox4.pack_start(vbox2, False, False, 0) ##And an hbox with 3 buttons hbox3 = Gtk.HBox(False, 0) btnCANCEL = GtkStockButton('close', "Close") btnCANCEL.connect('clicked', lambda btn: self.hide()) alignCANCEL = Gtk.Alignment.new(0, 0, 0, 0) alignCANCEL.add(btnCANCEL) btnBACK = GtkStockButton('back', "Back") btnBACK.connect('clicked', back_clicked_cb) btnNEXT = GtkStockButton('forward', "Next") btnNEXT.connect('clicked', next_clicked_cb) ##And populate hbox3.pack_start(alignCANCEL, True, True, 0) hbox3.pack_start(btnBACK, False, False, 2) hbox3.pack_start(btnNEXT, False, False, 0) vbox1.pack_start(label2_0, False, False, 0) vbox1.pack_start(hbox4, True, True, 0) vbox1.pack_start(hbox3, False, False, 10) self.show_all()
def __init__(self, rankings, divisions, printfields, back_clicked_cb, next_clicked_cb, parent, edit): '''Creates divisions window''' super(RankingsWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.rankings = rankings self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(parent) self.set_modal(True) self.set_title('fsTimer - Rankings') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.set_size_request(600, 400) self.connect('delete_event', lambda b, jnk_unused: self.hide()) # top label top_label = Gtk.Label( 'Select which field the results will be ranked by.\nYou can use any one of the results fields defined on the previous window.' ) self.fieldslist = list(printfields.keys()) try: self.indx = self.fieldslist.index(self.rankings['Overall']) except ValueError: self.indx = 0 #overall_align = Gtk.Alignment.new(0, 0, 0, 0) #overall_align.add(Gtk.Label('Rank overall results by: ')) ov_hbox = Gtk.HBox(False, 5) ov_hbox.pack_start(Gtk.Label('Rank overall results by:'), False, False, 0) # Prep the combobox combobox = Gtk.ComboBoxText() for field in self.fieldslist: combobox.append_text(field) combobox.set_active(self.indx) combobox.connect('changed', self.overall_edit) ov_hbox.pack_start(combobox, False, False, 0) apply_btn = Gtk.Button('Apply to divisions') apply_btn.connect('clicked', self.apply_to_divs) ov_hbox.pack_start(apply_btn, False, False, 5) # Create a treeview and add columns self.rankingview = Gtk.TreeView() # Make the model, a liststore with columns str, str self.rankingmodel = Gtk.ListStore(str, str) for div in divisions: indx_div = self.fieldslist.index(self.rankings[div[0]]) self.rankingmodel.append([div[0], self.fieldslist[indx_div]]) self.rankingview.set_model(self.rankingmodel) selection = self.rankingview.get_selection() # Add following columns to the treeview : # Division | Ranking field ranking_renderer = Gtk.CellRendererText() ranking_renderer.set_property("editable", False) column = Gtk.TreeViewColumn('Division', ranking_renderer, text=0) self.rankingview.append_column(column) #Prepare the combobox liststore liststore_fields = Gtk.ListStore(str) for field in self.fieldslist: liststore_fields.append([field]) combo_renderer = Gtk.CellRendererCombo() combo_renderer.set_property("editable", True) combo_renderer.set_property("model", liststore_fields) combo_renderer.set_property("text-column", 0) combo_renderer.set_property("has-entry", False) combo_renderer.connect("edited", self.ranking_edit) column = Gtk.TreeViewColumn('Rank by:', combo_renderer, text=1) self.rankingview.append_column(column) # Create scrolled window, in an alignment rankingsw = Gtk.ScrolledWindow() rankingsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) rankingsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) rankingsw.add(self.rankingview) rankingalgn = Gtk.Alignment.new(0, 0, 1, 1) rankingalgn.add(rankingsw) # And an hbox for the fields and the buttons hbox4 = Gtk.HBox(False, 0) hbox4.pack_start(rankingalgn, True, True, 10) # Add an hbox with 3 buttons hbox3 = Gtk.HBox(False, 0) btnCANCEL = GtkStockButton('close', "Close") btnCANCEL.connect('clicked', lambda btn: self.hide()) alignCANCEL = Gtk.Alignment.new(0, 0, 0, 0) alignCANCEL.add(btnCANCEL) btnBACK = GtkStockButton('back', "Back") btnBACK.connect('clicked', back_clicked_cb) btnNEXT = GtkStockButton('forward', "Next") btnNEXT.connect('clicked', next_clicked_cb, edit) # Populate hbox3.pack_start(alignCANCEL, True, True, 0) hbox3.pack_start(btnBACK, False, False, 2) hbox3.pack_start(btnNEXT, False, False, 0) vbox = Gtk.VBox(False, 0) vbox.pack_start(top_label, False, False, 0) vbox.pack_start(ov_hbox, False, False, 15) vbox.pack_start(hbox4, True, True, 0) vbox.pack_start(hbox3, False, False, 10) self.add(vbox) self.show_all()
def __init__(self, path, merge_cb): '''Builds and display the compilation window''' super(CompilationWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.path = path self.merge_cb = merge_cb self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) fname = os.path.abspath( os.path.join( os.path.dirname(os.path.abspath(__file__)), '../data/icon.png')) self.set_icon_from_file(fname) self.set_title('fsTimer - ' + os.path.basename(path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.hide()) self.set_border_width(10) self.set_size_request(600, 450) # We will use a liststore to hold the filenames of the # registrations to be merged, and put the liststore in a scrolledwindow compregsw = Gtk.ScrolledWindow() compregsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) compregsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.reglist = Gtk.ListStore(str) self.comptreeview = Gtk.TreeView() rendererText = Gtk.CellRendererText() column = Gtk.TreeViewColumn('Registration files', rendererText, text=0) column.set_sort_column_id(0) self.comptreeview.append_column(column) self.comptreeview.set_model(self.reglist) compregsw.add(self.comptreeview) # We have text below the window to explain what is happening during merging self.comblabel = [] for i in range(3): label = Gtk.Label(label='') label.set_alignment(0, 0.5) self.comblabel.append(label) # Pack it all regvbox1 = Gtk.VBox(False, 8) regvbox1.pack_start(Gtk.Label('Select all of the registration files to compile', True, True, 0), False, False, 0) regvbox1.pack_start(compregsw, True, True, 0) for i in range(3): regvbox1.pack_start(self.comblabel[i], False, False, 0) vbox1align = Gtk.Alignment.new(0, 0, 1, 1) vbox1align.add(regvbox1) # The buttons in a table regtable = Gtk.Table(2, 1, False) regtable.set_row_spacings(5) regtable.set_col_spacings(5) regtable.set_border_width(5) btnREMOVE = GtkStockButton('remove','Remove') btnREMOVE.connect('clicked', self.rm_clicked) btnADD = GtkStockButton('add','Add') btnADD.connect('clicked', self.add_clicked) btnMERGE = Gtk.Button('Compile') btnMERGE.connect('clicked', self.merge_clicked) btnOK = GtkStockButton('close','Close') btnOK.connect('clicked', lambda jnk: self.hide()) vsubbox = Gtk.VBox(False, 8) vsubbox.pack_start(btnMERGE, False, False, 0) vsubbox.pack_start(btnOK, False, False, 0) regvspacer = Gtk.Alignment.new(1, 1, 0, 0) regvspacer.add(vsubbox) regtable.attach(regvspacer, 0, 1, 1, 2) regvbox2 = Gtk.VBox(False, 8) regvbox2.pack_start(btnREMOVE, False, False, 0) regvbox2.pack_start(btnADD, False, False, 0) regvbalign = Gtk.Alignment.new(1, 0, 0, 0) regvbalign.add(regvbox2) regtable.attach(regvbalign, 0, 1, 0, 1) reghbox = Gtk.HBox(False, 8) reghbox.pack_start(vbox1align, True, True, 0) reghbox.pack_start(regtable, False, False, 0) #Add and show self.add(reghbox) self.show_all()
def view_entries_clicked(self, jnk_unused): '''Handles click on View Id entries Loads a new window that will list the registration entries overloaded. Then gives an option to keep one of the registration entries''' selection = self.errortreeview.get_selection() treeiter = selection.get_selected()[1] if treeiter: current_id = self.errorlist.get_value(treeiter, 0) # Define the new window self.corerrorswin = Gtk.Window(Gtk.WindowType.TOPLEVEL) self.corerrorswin.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.corerrorswin.set_transient_for(self) self.corerrorswin.set_modal(True) self.corerrorswin.set_title('fsTimer - ' + os.path.basename(self.path)) self.corerrorswin.set_position(Gtk.WindowPosition.CENTER) self.corerrorswin.connect('delete_event', lambda b, jnk: self.corerrorswin.hide()) self.corerrorswin.set_border_width(10) self.corerrorswin.set_size_request(800, 300) # This will be a liststore in a treeview in a scrolled window, as usual corerrorsw = Gtk.ScrolledWindow() corerrorsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) corerrorsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.corerrorlist = Gtk.ListStore(*[str for field in self.fields]) self.corerrortreeview = Gtk.TreeView() # Now define each column in the treeview # Take these from self.fields for (colid, field) in enumerate(self.fields): column = Gtk.TreeViewColumn(field, Gtk.CellRendererText(), text=colid) column.set_sort_column_id(colid) self.corerrortreeview.append_column(column) # Add in the info from self.errors for reg in self.errors[current_id]: self.corerrorlist.append([reg[field] for field in self.fields]) self.corerrortreeview.set_model(self.corerrorlist) corerrorsw.add(self.corerrortreeview) errvbox1 = Gtk.VBox(False, 8) errvbox1.pack_start( Gtk.Label('''These entries share the same ID. Use "Keep entry" to associate an entry with the ID. Otherwise, press "OK" to continue, no entry will be associated with this ID.''' ), False, False, 0) errvbox1.pack_start(corerrorsw, True, True, 0) vbox1align = Gtk.Alignment.new(0, 0, 1, 1) vbox1align.add(errvbox1) #Now build a table for the buttons errtable = Gtk.Table(2, 1, False) errtable.set_row_spacings(5) errtable.set_col_spacings(5) errtable.set_border_width(5) btnKEEP = Gtk.Button('Keep entry') btnKEEP.connect('clicked', self.keep_correct, current_id, treeiter) btnCANCEL = GtkStockButton('close', 'Close') btnCANCEL.connect('clicked', lambda b: self.corerrorswin.hide()) vsubbox = Gtk.VBox(False, 8) vsubbox.pack_start(btnCANCEL, False, False, 0) errvspacer = Gtk.Alignment.new(1, 1, 0, 0) errvspacer.add(vsubbox) errtable.attach(errvspacer, 0, 1, 1, 2) errvbox2 = Gtk.VBox(False, 8) errvbox2.pack_start(btnKEEP, False, False, 0) errvbalign = Gtk.Alignment.new(1, 0, 0, 0) errvbalign.add(errvbox2) errtable.attach(errvbalign, 0, 1, 0, 1) errhbox = Gtk.HBox(False, 8) errhbox.pack_start(vbox1align, True, True, 0) errhbox.pack_start(errtable, False, False, 0) self.corerrorswin.add(errhbox) self.corerrorswin.show_all()
def edit_registration(self, treeiter, preregiter, current_info): '''handles creation/modification of a registration entry. Converts the treeiter from the treemodelsort to the liststore.''' if treeiter: treeiter = self.modelfilter.convert_iter_to_child_iter(self.modelfiltersorted.convert_iter_to_child_iter(treeiter)) # Define the window self.editreg_win = Gtk.Window(Gtk.WindowType.TOPLEVEL) self.editreg_win.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.editreg_win.set_title('Registration entry') self.editreg_win.set_transient_for(self) self.editreg_win.set_modal(True) self.editreg_win.set_position(Gtk.WindowPosition.CENTER) self.editreg_win.connect('delete_event', lambda b, jnk_unused: self.editreg_win.hide()) self.editreg_win.set_border_width(10) #An hbox for the buttons editreghbox = Gtk.HBox(False, 8) editregbtnOK = GtkStockButton('ok',"OK") editregbtnCANCEL = GtkStockButton('close',"Cancel") editregbtnCANCEL.connect('clicked', lambda b: self.editreg_win.hide()) editreghbox.pack_start(editregbtnOK, False, False, 5) editreghbox.pack_start(editregbtnCANCEL, False, False, 5) # fill in current_info if available. self.editregfields = {} for field in self.fields: # Determine which type of entry is appropriate, create it and fill it. # Entrybox if self.fieldsdic[field]['type'] in ['entrybox', 'entrybox_int']: self.editregfields[field] = Gtk.Entry() self.editregfields[field].set_max_length(self.fieldsdic[field]['max']) if current_info: self.editregfields[field].set_text(current_info[field]) # Combobox elif self.fieldsdic[field]['type'] == 'combobox': self.editregfields[field] = Gtk.ComboBoxText() self.editregfields[field].append_text('') for val in self.fieldsdic[field]['options']: self.editregfields[field].append_text(val) if current_info: try: indx = self.fieldsdic[field]['options'].index(current_info[field]) self.editregfields[field].set_active(indx+1) except ValueError: self.editregfields[field].set_active(0) #this catches if current_inf[field] is not a valid value. It is probably blank. Otherwise this is an issue, but we will force it blank. else: self.editregfields[field].set_active(0) # Set up the vbox editregvbox = Gtk.VBox(False, 8) # We will make a smaller hbox for each of the fields. hboxes = {} for field in self.fields: hboxes[field] = Gtk.HBox(False, 15) hboxes[field].pack_start(Gtk.Label(field+':', True, True, 0), False, False, 0) #Pack the label hboxes[field].pack_start(self.editregfields[field], False, False, 0) #Pack the button/entry/.. if self.projecttype == 'handicap' and field == 'Handicap': label_hd = Gtk.Label(label='hh:mm:ss') hboxes[field].pack_start(label_hd, False, False, 0) if field == 'ID': label_id = Gtk.Label('Must be unique') hboxes[field].pack_start(label_id, False, False, 0) editregvbox.pack_start(hboxes[field], False, False, 0) #Pack this hbox into the big vbox. #Pack and show if self.projecttype == 'handicap': editregbtnOK.connect('clicked', self.validate_entry, treeiter, preregiter, label_hd, label_id) else: editregbtnOK.connect('clicked', self.validate_entry, treeiter, preregiter, None, label_id) editregvbox.pack_start(editreghbox, False, False, 5) self.editreg_win.add(editregvbox) self.editreg_win.show_all()
def __init__(self, pytimer, timebtn): '''Builds and display the compilation error window''' super(TimingWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.path = pytimer.path self.projecttype = pytimer.projecttype self.fields = pytimer.fields self.fieldsdic = pytimer.fieldsdic self.write_timing_cb = pytimer.write_updated_timing self.timebtn = timebtn self.rawtimes = pytimer.rawtimes self.timing = pytimer.timing self.numlaps = pytimer.numlaps self.wineditblocktime = None self.winedittime = None self.t0win = None self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(pytimer.rootwin) self.set_modal(True) self.set_title('fsTimer - ' + os.path.basename(self.path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.done_timing(b)) self.set_border_width(10) self.set_size_request(450, 450) # We will put the timing info in a liststore in a scrolledwindow self.timemodel = Gtk.ListStore(str, str) # We will put the liststore in a treeview self.timeview = Gtk.TreeView() column = Gtk.TreeViewColumn('ID', Gtk.CellRendererText(), text=0) self.timeview.append_column(column) column = Gtk.TreeViewColumn('Time', Gtk.CellRendererText(), text=1) self.timeview.append_column(column) #An extra column if it is a handicap race if self.projecttype == 'handicap': renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn('Corrected Time', renderer) column.set_cell_data_func(renderer, self.print_corrected_time) self.timeview.append_column(column) #Another extra column if it is a lap race if self.numlaps > 1: renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn('Completed laps', renderer) column.set_cell_data_func(renderer, self.print_completed_laps) self.timeview.append_column(column) self.timeview.set_model(self.timemodel) self.timeview.connect('size-allocate', self.scroll_times) treeselection = self.timeview.get_selection() # make it multiple selecting treeselection.set_mode(Gtk.SelectionMode.MULTIPLE) # And put it in a scrolled window, in an alignment self.timesw = Gtk.ScrolledWindow() self.timesw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) self.timesw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.timesw.add(self.timeview) timealgn = Gtk.Alignment.new(0, 0, 1, 1) timealgn.add(self.timesw) self.entrybox = Gtk.Entry() self.entrybox.set_max_length(40) self.offset = 0 #this is len(times) - len(ids) self.entrybox.connect('activate', self.record_time) self.entrybox.connect('changed', self.check_for_newtime) # And we will save our file self.timestr = re.sub(' +', '_', time.ctime()).replace(':', '') #we save with the current time in the filename so no chance of being overwritten accidentally # Now lets go on to boxes tophbox = Gtk.HBox() # our default t0, and the stuff on top for setting/edit t0 self.t0 = 0. btn_t0 = Gtk.Button('Start!') btn_t0.connect('clicked', self.set_t0) # time display self.clocklabel = Gtk.Label() self.clocklabel.modify_font(Pango.FontDescription("sans 20")) self.clocklabel.set_markup(time_format(0)) tophbox.pack_start(btn_t0, False, False, 10) tophbox.pack_start(self.clocklabel, False, False, 10) timevbox1 = Gtk.VBox(False, 8) timevbox1.pack_start(tophbox, False, False, 0) timevbox1.pack_start(timealgn, True, True, 0) timevbox1.pack_start(Gtk.Label('Select box below in order to mark times:'), False, False, 0) timevbox1.pack_start(self.entrybox, False, False, 0) # we will keep track of how many racers are still out. self.racers_reg = [] for i_unused in range(self.numlaps): self.racers_reg.append(set([k for k in self.timing.keys()])) self.racers_total = len(self.racers_reg[0]) self.racers_in = [0] * self.numlaps self.lapcounter = defaultdict(int) self.racerslabel = Gtk.Label() self.update_racers_label() timevbox1.pack_start(self.racerslabel, False, False, 0) vbox1align = Gtk.Alignment.new(0, 0, 1, 1) vbox1align.add(timevbox1) # buttons on the right side #First an options button that will actually be a menu options_menu = Gtk.Menu() menu_editreg = Gtk.MenuItem('Edit registration data') menu_editreg.connect_object("activate", self.edit_reg, None) menu_editreg.show() options_menu.append(menu_editreg) menu_resett0 = Gtk.MenuItem('Restart clock') menu_resett0.connect_object("activate", self.restart_t0, None) menu_resett0.show() options_menu.append(menu_resett0) menu_editt0 = Gtk.MenuItem('Edit starting time') menu_editt0.connect_object("activate", self.edit_t0, None) menu_editt0.show() options_menu.append(menu_editt0) menu_savecsv = Gtk.MenuItem('Save results to CSV') menu_savecsv.connect_object("activate", self.print_csv, pytimer) menu_savecsv.show() options_menu.append(menu_savecsv) menu_resume = Gtk.MenuItem('Load saved timing session') menu_resume.connect_object("activate", self.resume_times, None, False) #False is for not merging menu_resume.show() options_menu.append(menu_resume) menu_merge = Gtk.MenuItem('Merge in saved IDs or times') menu_merge.connect_object("activate", self.resume_times, None, True) #True is for merging menu_merge.show() options_menu.append(menu_merge) btnOPTIONS = Gtk.Button('Options') btnOPTIONS.connect_object("event", self.options_btn, options_menu) options_align = Gtk.Alignment.new(1, 0.1, 1, 0) options_align.add(btnOPTIONS) #Then the block of editing buttons btnDROPID = Gtk.Button('Drop ID') btnDROPID.connect('clicked', self.timing_rm_ID) btnDROPTIME = Gtk.Button('Drop time') btnDROPTIME.connect('clicked', self.timing_rm_time) btnEDIT = GtkStockButton('edit',"Edit") btnEDIT.connect('clicked', self.edit_time) edit_vbox = Gtk.VBox(True, 8) edit_vbox.pack_start(btnDROPID, False, False, 0) edit_vbox.pack_start(btnDROPTIME, False, False, 0) edit_vbox.pack_start(btnEDIT, False, False, 0) edit_align = Gtk.Alignment.new(1, 0, 1, 0) edit_align.add(edit_vbox) #Then the print and save buttons btnPRINT = Gtk.Button('Printouts') btnPRINT.connect('clicked', self.print_html, pytimer) btnSAVE = GtkStockButton('save',"Save") btnSAVE.connect('clicked', self.save_times) save_vbox = Gtk.VBox(True, 8) save_vbox.pack_start(btnPRINT, False, False, 0) save_vbox.pack_start(btnSAVE, False, False, 0) save_align = Gtk.Alignment.new(1, 1, 1, 0) save_align.add(save_vbox) #And finally the finish button btnOK = GtkStockButton('close',"Close") btnOK.connect('clicked', self.done_timing) done_align = Gtk.Alignment.new(1, 0.7, 1, 0) done_align.add(btnOK) vsubbox = Gtk.VBox(True, 0) vsubbox.pack_start(options_align, True, True, 0) vsubbox.pack_start(edit_align, True, True, 0) vsubbox.pack_start(save_align, True, True, 0) vsubbox.pack_start(done_align, True, True, 0) vspacer = Gtk.Alignment.new(1, 1, 0, 0) vspacer.add(vsubbox) timehbox = Gtk.HBox(False, 8) timehbox.pack_start(vbox1align, True, True, 0) timehbox.pack_start(vspacer, False, False, 0) self.add(timehbox) self.show_all()
def __init__(self, path, fields, fieldsdic, prereg, projecttype, save_registration_cb, parent_win=None, autosave=True, save_label=''): '''Builds and display the registration window''' super(RegistrationWin, self).__init__(Gtk.WindowType.TOPLEVEL) if parent_win: self.set_transient_for(parent_win) self.set_modal(True) self.fields = fields self.fieldsdic = fieldsdic self.prereg = prereg self.ids = set() self.projecttype = projecttype self.save_registration_cb = save_registration_cb self.autosave = autosave self.editreg_win = None self.editregfields = None # First we define the registration model. # We will setup a liststore that is wrapped in a treemodelfilter # that is wrapped in a treemodelsort that is put in a treeview # that is put in a scrolled window. Eesh. self.regmodel = Gtk.ListStore(*[str for field in self.fields]) self.modelfilter = self.regmodel.filter_new() self.modelfiltersorted = Gtk.TreeModelSort(self.modelfilter) self.treeview = Gtk.TreeView() # Now we define each column in the treeview for (colid, field) in enumerate(fields): column = Gtk.TreeViewColumn(field, Gtk.CellRendererText(), text=colid) column.set_sort_column_id(colid) self.treeview.append_column(column) # Now we populate the model with the pre-registration info, if any for reg in prereg: self.regmodel.append([reg[field] for field in fields]) if reg['ID']: self.ids.add(reg['ID']) # This is the string that we filter based on. self.searchstr = '' self.modelfilter.set_visible_func(self.visible_filter) self.treeview.set_model(self.modelfiltersorted) self.treeview.set_enable_search(False) # Now let us actually build the window self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) fname = os.path.abspath( os.path.join( os.path.dirname(os.path.abspath(__file__)), '../data/icon.png')) self.set_icon_from_file(fname) self.set_title('fsTimer - ' + os.path.basename(path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.close_clicked(jnk)) self.set_border_width(10) self.set_size_request(850, 450) #Now the filter entrybox filterbox = Gtk.HBox(False, 8) filterbox.pack_start(Gtk.Label('Filter by ', True, True, 0), False, False, 0) self.filter_combo = Gtk.ComboBoxText() for field in self.fields: self.filter_combo.append_text(field) self.filter_combo.set_active(0) filterbox.pack_start(self.filter_combo, False, False, 0) filterbox.pack_start(Gtk.Label(':'), False, False, 0) self.filterentry = Gtk.Entry() self.filterentry.set_max_length(40) self.filterentry.connect('changed', self.filter_apply) self.filterbtnCLEAR = GtkStockButton('clear',"Clear") self.filterbtnCLEAR.connect('clicked', self.filter_clear) self.filterbtnCLEAR.set_sensitive(False) filterbox.pack_start(self.filterentry, False, False, 0) filterbox.pack_start(self.filterbtnCLEAR, False, False, 0) # Now the scrolled window that contains the treeview regsw = Gtk.ScrolledWindow() regsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) regsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) regsw.add(self.treeview) # And a message that says if we have saved or not. self.regstatus = Gtk.Label(label=save_label) # Some boxes for all the stuff on the left regvbox1 = Gtk.VBox(False, 8) regvbox1.pack_start(filterbox, False, False, 0) regvbox1.pack_start(regsw, True, True, 0) regvbox1.pack_start(self.regstatus, False, False, 0) vbox1align = Gtk.Alignment.new(0, 0, 1, 1) vbox1align.add(regvbox1) # And boxes/table for the buttons on the right regtable = Gtk.Table(2, 1, False) regtable.set_row_spacings(5) regtable.set_col_spacings(5) regtable.set_border_width(5) btnEDIT = GtkStockButton('edit',"Edit") btnEDIT.connect('clicked', self.edit_clicked) btnREMOVE = GtkStockButton('remove',"Remove") btnREMOVE.connect('clicked', self.rm_clicked) btnNEW = GtkStockButton('new',"New") btnNEW.connect('clicked', self.new_clicked) btnSAVE = GtkStockButton('save',"Save") btnSAVE.connect('clicked', self.save_clicked) btnOK = GtkStockButton('close',"Close") btnOK.connect('clicked', self.close_clicked) vsubbox = Gtk.VBox(False, 8) vsubbox.pack_start(btnSAVE, False, False, 0) regvspacer = Gtk.Alignment.new(1, 1, 0, 0) regvspacer.add(vsubbox) regtable.attach(regvspacer, 0, 1, 1, 2) regvbox2 = Gtk.VBox(False, 8) regvbox2.pack_start(btnNEW, False, False, 0) regvbox2.pack_start(btnEDIT, False, False, 0) regvbox2.pack_start(btnREMOVE, False, False, 30) regvbalign = Gtk.Alignment.new(1, 0, 0, 0) regvbalign.add(regvbox2) regtable.attach(regvbalign, 0, 1, 0, 1) #Now we pack everything together reghbox = Gtk.HBox(False, 8) reghbox.pack_start(vbox1align, True, True, 0) reghbox.pack_start(regtable, False, False, 0) # Add in the close button on the bottom vbox_all = Gtk.VBox(False, 0) vbox_all.pack_start(reghbox, True, True, 0) donespacer = Gtk.Alignment.new(0, 0, 0, 0) donespacer.add(btnOK) vbox_all.pack_start(donespacer, False, False, 5) self.add(vbox_all) # And show. self.show_all()
def __init__(self, project_types, projecttype, numlaps, variablelaps, back_clicked_cb, next_clicked_cb, parent): '''Creates project type window''' super(ProjectTypeWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(parent) self.set_modal(True) self.set_title('fsTimer - Project type') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.connect('delete_event', lambda b, jnk_unused: self.hide()) # Now create the vbox. vbox = Gtk.VBox(False, 50) self.add(vbox) ##First is the project type label_0 = Gtk.Label(label='Select the race type.') rbs = {} rbs[0] = Gtk.RadioButton( group=None, label='Standard.\t All runners begin at the same time.') rbs[1] = Gtk.RadioButton( group=rbs[0], label=('Handicap.\t Some runners are assigned a handicap and ' 'start the race later.')) #Set the correct button active rbs[project_types.index(projecttype)].set_active(True) ##Second are other race settigns. label_1 = Gtk.Label(label='Multi-lap races:') check_button = Gtk.CheckButton( label='Lap timing - Check the box and specify the number of laps:') check_button2 = Gtk.CheckButton( label='Racers complete variable number of laps') check_button2.set_sensitive(False) check_button.connect('toggled', self.lock_check_button2, check_button, check_button2) numlapsadj = Gtk.Adjustment(value=2, lower=2, upper=10, step_incr=1) numlapsbtn = Gtk.SpinButton(digits=0, climb_rate=0) numlapsbtn.set_adjustment(numlapsadj) #Activate the button as needed if numlaps > 1: check_button.set_active(True) numlapsadj.set_value(numlaps) if variablelaps: check_button2.set_active(True) else: check_button.set_active(False) numlapsadj.set_value(2) #Pop these in an hbox hbox_0 = Gtk.HBox(False, 0) hbox_0.pack_start(check_button, False, False, 8) hbox_0.pack_start(numlapsbtn, False, False, 8) # The next button hbox_05 = Gtk.HBox(False, 0) hbox_05.pack_start(check_button2, False, False, 8) # And an hbox with 2 buttons hbox_1 = Gtk.HBox(False, 0) btnCANCEL = GtkStockButton('close', "Close") btnCANCEL.connect('clicked', lambda btn: self.hide()) alignCANCEL = Gtk.Alignment.new(0, 0, 0, 0) alignCANCEL.add(btnCANCEL) btnBACK = GtkStockButton('back', "Back") btnBACK.connect('clicked', back_clicked_cb) btnNEXT = GtkStockButton('forward', "Next") btnNEXT.connect('clicked', next_clicked_cb, rbs, check_button, check_button2, numlapsbtn) alignNEXT = Gtk.Alignment.new(1, 0, 1, 0) alignNEXT.add(btnNEXT) alignBACK = Gtk.Alignment.new(1, 0, 1, 0) alignBACK.add(btnBACK) # And populate hbox_1.pack_start(alignCANCEL, True, True, 0) hbox_1.pack_start(alignBACK, False, False, 0) hbox_1.pack_start(alignNEXT, False, False, 0) vbox1 = Gtk.VBox(False, 10) vbox2 = Gtk.VBox(False, 10) vbox1.pack_start(label_0, False, False, 0) vbox1.pack_start(rbs[0], False, False, 0) vbox1.pack_start(rbs[1], False, False, 0) vbox2.pack_start(label_1, False, False, 0) vbox2.pack_start(hbox_0, False, False, 0) vbox2.pack_start(hbox_05, False, False, 0) vbox2.pack_start(hbox_1, False, False, 0) vbox.pack_start(vbox1, False, False, 0) vbox.pack_start(vbox2, False, False, 0) self.show_all()
def __init__(self, rankings, divisions, printfields, back_clicked_cb, next_clicked_cb, parent, edit): '''Creates divisions window''' super(RankingsWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.rankings = rankings self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(parent) self.set_modal(True) self.set_title('fsTimer - Rankings') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.set_size_request(600, 400) self.connect('delete_event', lambda b, jnk_unused: self.hide()) # top label top_label = Gtk.Label('Select which field the results will be ranked by.\nYou can use any one of the results fields defined on the previous window.') self.fieldslist = list(printfields.keys()) try: self.indx = self.fieldslist.index(self.rankings['Overall']) except ValueError: self.indx = 0 #overall_align = Gtk.Alignment.new(0, 0, 0, 0) #overall_align.add(Gtk.Label('Rank overall results by: ')) ov_hbox = Gtk.HBox(False, 5) ov_hbox.pack_start(Gtk.Label('Rank overall results by:'), False, False, 0) # Prep the combobox combobox = Gtk.ComboBoxText() for field in self.fieldslist: combobox.append_text(field) combobox.set_active(self.indx) combobox.connect('changed', self.overall_edit) ov_hbox.pack_start(combobox, False, False, 0) apply_btn = Gtk.Button('Apply to divisions') apply_btn.connect('clicked', self.apply_to_divs) ov_hbox.pack_start(apply_btn, False, False, 5) # Create a treeview and add columns self.rankingview = Gtk.TreeView() # Make the model, a liststore with columns str, str self.rankingmodel = Gtk.ListStore(str, str) for div in divisions: indx_div = self.fieldslist.index(self.rankings[div[0]]) self.rankingmodel.append([div[0], self.fieldslist[indx_div]]) self.rankingview.set_model(self.rankingmodel) selection = self.rankingview.get_selection() # Add following columns to the treeview : # Division | Ranking field ranking_renderer = Gtk.CellRendererText() ranking_renderer.set_property("editable", False) column = Gtk.TreeViewColumn('Division', ranking_renderer, text=0) self.rankingview.append_column(column) #Prepare the combobox liststore liststore_fields = Gtk.ListStore(str) for field in self.fieldslist: liststore_fields.append([field]) combo_renderer = Gtk.CellRendererCombo() combo_renderer.set_property("editable", True) combo_renderer.set_property("model", liststore_fields) combo_renderer.set_property("text-column", 0) combo_renderer.set_property("has-entry", False) combo_renderer.connect("edited", self.ranking_edit) column = Gtk.TreeViewColumn('Rank by:', combo_renderer, text=1) self.rankingview.append_column(column) # Create scrolled window, in an alignment rankingsw = Gtk.ScrolledWindow() rankingsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) rankingsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) rankingsw.add(self.rankingview) rankingalgn = Gtk.Alignment.new(0, 0, 1, 1) rankingalgn.add(rankingsw) # And an hbox for the fields and the buttons hbox4 = Gtk.HBox(False, 0) hbox4.pack_start(rankingalgn, True, True, 10) # Add an hbox with 3 buttons hbox3 = Gtk.HBox(False, 0) btnCANCEL = GtkStockButton('close',"Close") btnCANCEL.connect('clicked', lambda btn: self.hide()) alignCANCEL = Gtk.Alignment.new(0, 0, 0, 0) alignCANCEL.add(btnCANCEL) btnBACK = GtkStockButton('back',"Back") btnBACK.connect('clicked', back_clicked_cb) btnNEXT = GtkStockButton('forward',"Next") btnNEXT.connect('clicked', next_clicked_cb, edit) # Populate hbox3.pack_start(alignCANCEL, True, True, 0) hbox3.pack_start(btnBACK, False, False, 2) hbox3.pack_start(btnNEXT, False, False, 0) vbox = Gtk.VBox(False, 0) vbox.pack_start(top_label, False, False, 0) vbox.pack_start(ov_hbox, False, False, 15) vbox.pack_start(hbox4, True, True, 0) vbox.pack_start(hbox3, False, False, 10) self.add(vbox) self.show_all()
def __init__(self, path, show_about_cb, importprereg_cb, prereg_cb, compreg_cb, pretime_cb, edit_cb): '''Creates the root window with choices for the tasks''' super(RootWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) fname = os.path.abspath( os.path.join( os.path.dirname(os.path.abspath(__file__)), '../data/icon.png')) self.set_icon_from_file(fname) self.set_title('fsTimer - ' + os.path.basename(path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', Gtk.main_quit) self.set_border_width(0) # Generate the menubar mb = Gtk.MenuBar() helpmenu = Gtk.Menu() helpm = Gtk.MenuItem('Menu') helpm.set_submenu(helpmenu) menuedit = MenuItemIcon('edit', 'Edit project settings', edit_cb, True) helpmenu.append(menuedit) menuhelp = MenuItemIcon('help', 'Documentation', lambda x: webbrowser.open_new('http://fstimer.org/documentation/documentation_sec2.htm')) helpmenu.append(menuhelp) menuabout = MenuItemIcon('about', 'About', show_about_cb, self) helpmenu.append(menuabout) mb.append(helpm) ### Frame rootframe = Gtk.Frame(label='al') rootframe_label = Gtk.Label(label='') rootframe_label.set_markup('<b>fsTimer - ' + os.path.basename(path) + '</b>') rootframe.set_label_widget(rootframe_label) rootframe.set_border_width(20) #And now fill the frame with a table roottable = Gtk.Table(4, 2, False) roottable.set_row_spacings(20) roottable.set_col_spacings(20) roottable.set_border_width(10) #And internal buttons rootbtnPREREG = Gtk.Button('Import') rootbtnPREREG.connect('clicked', importprereg_cb) rootlabelPREREG = Gtk.Label(label='') rootlabelPREREG.set_alignment(0, 0.5) rootlabelPREREG.set_markup('Import registration info from spreadsheet.') rootbtnREG = Gtk.Button('Register') rootbtnREG.connect('clicked', prereg_cb) rootlabelREG = Gtk.Label(label='') rootlabelREG.set_alignment(0, 0.5) rootlabelREG.set_markup('Register racer information and assign ID numbers.') rootbtnCOMP = Gtk.Button('Compile') rootbtnCOMP.connect('clicked', compreg_cb) rootlabelCOMP = Gtk.Label(label='') rootlabelCOMP.set_alignment(0, 0.5) rootlabelCOMP.set_markup('Compile registration file(s)') rootbtnTIME = Gtk.Button('Time') rootbtnTIME.connect('clicked', pretime_cb) rootlabelTIME = Gtk.Label(label='') rootlabelTIME.set_alignment(0, 0.5) rootlabelTIME.set_markup('Record race times on the day of the race.') roottable.attach(rootbtnPREREG, 0, 1, 0, 1) roottable.attach(rootlabelPREREG, 1, 2, 0, 1) roottable.attach(rootbtnREG, 0, 1, 1, 2) roottable.attach(rootlabelREG, 1, 2, 1, 2) roottable.attach(rootbtnCOMP, 0, 1, 2, 3) roottable.attach(rootlabelCOMP, 1, 2, 2, 3) roottable.attach(rootbtnTIME, 0, 1, 3, 4) roottable.attach(rootlabelTIME, 1, 2, 3, 4) rootframe.add(roottable) ### Buttons roothbox = Gtk.HBox(True, 0) rootbtnQUIT = GtkStockButton('close',"Quit") rootbtnQUIT.connect('clicked', Gtk.main_quit) roothbox.pack_start(rootbtnQUIT, False, False, 5) #Vbox rootvbox = Gtk.VBox(False, 0) btnhalign = Gtk.Alignment.new(1, 0, 0, 0) btnhalign.add(roothbox) rootvbox.pack_start(mb, False, False, 0) rootvbox.pack_start(rootframe, True, True, 0) rootvbox.pack_start(btnhalign, False, False, 5) self.add(rootvbox) self.show_all()
def __init__(self, path, merge_cb): '''Builds and display the compilation window''' super(CompilationWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.path = path self.merge_cb = merge_cb self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) fname = os.path.abspath( os.path.join(os.path.dirname(os.path.abspath(__file__)), '../data/icon.png')) self.set_icon_from_file(fname) self.set_title('fsTimer - ' + os.path.basename(path)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('delete_event', lambda b, jnk: self.hide()) self.set_border_width(10) self.set_size_request(600, 450) # We will use a liststore to hold the filenames of the # registrations to be merged, and put the liststore in a scrolledwindow compregsw = Gtk.ScrolledWindow() compregsw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) compregsw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.reglist = Gtk.ListStore(str) self.comptreeview = Gtk.TreeView() rendererText = Gtk.CellRendererText() column = Gtk.TreeViewColumn('Registration files', rendererText, text=0) column.set_sort_column_id(0) self.comptreeview.append_column(column) self.comptreeview.set_model(self.reglist) compregsw.add(self.comptreeview) # We have text below the window to explain what is happening during merging self.comblabel = [] for i in range(3): label = Gtk.Label(label='') label.set_alignment(0, 0.5) self.comblabel.append(label) # Pack it all regvbox1 = Gtk.VBox(False, 8) regvbox1.pack_start( Gtk.Label('Select all of the registration files to compile', True, True, 0), False, False, 0) regvbox1.pack_start(compregsw, True, True, 0) for i in range(3): regvbox1.pack_start(self.comblabel[i], False, False, 0) vbox1align = Gtk.Alignment.new(0, 0, 1, 1) vbox1align.add(regvbox1) # The buttons in a table regtable = Gtk.Table(2, 1, False) regtable.set_row_spacings(5) regtable.set_col_spacings(5) regtable.set_border_width(5) btnREMOVE = GtkStockButton('remove', 'Remove') btnREMOVE.connect('clicked', self.rm_clicked) btnADD = GtkStockButton('add', 'Add') btnADD.connect('clicked', self.add_clicked) btnMERGE = Gtk.Button('Compile') btnMERGE.connect('clicked', self.merge_clicked) btnOK = GtkStockButton('close', 'Close') btnOK.connect('clicked', lambda jnk: self.hide()) vsubbox = Gtk.VBox(False, 8) vsubbox.pack_start(btnMERGE, False, False, 0) vsubbox.pack_start(btnOK, False, False, 0) regvspacer = Gtk.Alignment.new(1, 1, 0, 0) regvspacer.add(vsubbox) regtable.attach(regvspacer, 0, 1, 1, 2) regvbox2 = Gtk.VBox(False, 8) regvbox2.pack_start(btnREMOVE, False, False, 0) regvbox2.pack_start(btnADD, False, False, 0) regvbalign = Gtk.Alignment.new(1, 0, 0, 0) regvbalign.add(regvbox2) regtable.attach(regvbalign, 0, 1, 0, 1) reghbox = Gtk.HBox(False, 8) reghbox.pack_start(vbox1align, True, True, 0) reghbox.pack_start(regtable, False, False, 0) #Add and show self.add(reghbox) self.show_all()
def __init__(self, project_types, projecttype, numlaps, variablelaps, back_clicked_cb, next_clicked_cb, parent): '''Creates project type window''' super(ProjectTypeWin, self).__init__(Gtk.WindowType.TOPLEVEL) self.modify_bg(Gtk.StateType.NORMAL, fstimer.gui.bgcolor) self.set_transient_for(parent) self.set_modal(True) self.set_title('fsTimer - Project type') self.set_position(Gtk.WindowPosition.CENTER) self.set_border_width(20) self.connect('delete_event', lambda b, jnk_unused: self.hide()) # Now create the vbox. vbox = Gtk.VBox(False, 50) self.add(vbox) ##First is the project type label_0 = Gtk.Label(label='Select the race type.') rbs = {} rbs[0] = Gtk.RadioButton( group=None, label='Standard.\t All runners begin at the same time.') rbs[1] = Gtk.RadioButton( group=rbs[0], label=('Handicap.\t Some runners are assigned a handicap and ' 'start the race later.')) #Set the correct button active rbs[project_types.index(projecttype)].set_active(True) ##Second are other race settigns. label_1 = Gtk.Label(label='Multi-lap races:') check_button = Gtk.CheckButton( label='Lap timing - Check the box and specify the number of laps:') check_button2 = Gtk.CheckButton( label='Racers complete variable number of laps') check_button2.set_sensitive(False) check_button.connect('toggled', self.lock_check_button2, check_button, check_button2) numlapsadj = Gtk.Adjustment(value=2, lower=2, upper=10, step_incr=1) numlapsbtn = Gtk.SpinButton(digits=0, climb_rate=0) numlapsbtn.set_adjustment(numlapsadj) #Activate the button as needed if numlaps > 1: check_button.set_active(True) numlapsadj.set_value(numlaps) if variablelaps: check_button2.set_active(True) else: check_button.set_active(False) numlapsadj.set_value(2) #Pop these in an hbox hbox_0 = Gtk.HBox(False, 0) hbox_0.pack_start(check_button, False, False, 8) hbox_0.pack_start(numlapsbtn, False, False, 8) # The next button hbox_05 = Gtk.HBox(False, 0) hbox_05.pack_start(check_button2, False, False, 8) # And an hbox with 2 buttons hbox_1 = Gtk.HBox(False, 0) btnCANCEL = GtkStockButton('close',"Close") btnCANCEL.connect('clicked', lambda btn: self.hide()) alignCANCEL = Gtk.Alignment.new(0, 0, 0, 0) alignCANCEL.add(btnCANCEL) btnBACK = GtkStockButton('back',"Back") btnBACK.connect('clicked', back_clicked_cb) btnNEXT = GtkStockButton('forward',"Next") btnNEXT.connect('clicked', next_clicked_cb, rbs, check_button, check_button2, numlapsbtn) alignNEXT = Gtk.Alignment.new(1, 0, 1, 0) alignNEXT.add(btnNEXT) alignBACK = Gtk.Alignment.new(1, 0, 1, 0) alignBACK.add(btnBACK) # And populate hbox_1.pack_start(alignCANCEL, True, True, 0) hbox_1.pack_start(alignBACK, False, False, 0) hbox_1.pack_start(alignNEXT, False, False, 0) vbox1 = Gtk.VBox(False, 10) vbox2 = Gtk.VBox(False, 10) vbox1.pack_start(label_0, False, False, 0) vbox1.pack_start(rbs[0], False, False, 0) vbox1.pack_start(rbs[1], False, False, 0) vbox2.pack_start(label_1, False, False, 0) vbox2.pack_start(hbox_0, False, False, 0) vbox2.pack_start(hbox_05, False, False, 0) vbox2.pack_start(hbox_1, False, False, 0) vbox.pack_start(vbox1, False, False, 0) vbox.pack_start(vbox2, False, False, 0) self.show_all()