def __init__(self, parent, id=wx.ID_ANY): wx.Panel.__init__(self, parent, id) self.SetBackgroundColour(wx.WHITE) self.hbs = wx.BoxSizer(wx.HORIZONTAL) self.titleLabel = wx.StaticText(self, label=u'{}:'.format( _('Unmatched RFID Tags'))) self.excelButton = wx.Button(self, label=_('Export to Excel')) self.excelButton.Bind(wx.EVT_BUTTON, self.onExcel) self.ganttChart = GanttChartPanel.GanttChartPanel(self) self.ganttChart.getNowTimeCallback = GetNowTime self.hbs.Add(self.titleLabel, flag=wx.TOP | wx.BOTTOM | wx.LEFT | wx.ALIGN_CENTRE_VERTICAL, border=4) self.hbs.AddStretchSpacer() self.hbs.Add(self.excelButton, flag=wx.ALL | wx.ALIGN_CENTRE_VERTICAL | wx.ALIGN_RIGHT, border=4) bs = wx.BoxSizer(wx.VERTICAL) bs.Add(self.hbs, flag=wx.GROW | wx.HORIZONTAL) bs.Add(self.ganttChart, 1, wx.GROW | wx.ALL, 5) self.SetSizer(bs) bs.SetSizeHints(self)
def __init__( self, parent, id = wx.ID_ANY ): wx.Panel.__init__(self, parent, id) self.numSelect = None self.entry = None self.numBefore = None self.numAfter = None self.refreshTimer = None self.hbs = wx.BoxSizer(wx.HORIZONTAL) self.categoryLabel = wx.StaticText( self, label = _('Category:') ) self.categoryChoice = wx.Choice( self ) self.Bind( wx.EVT_CHOICE, self.doChooseCategory, self.categoryChoice ) self.groupByStartWave = wx.CheckBox( self, label=_('Group by Start Wave') ) self.Bind( wx.EVT_CHECKBOX, self.doGroupByStartWave, self.groupByStartWave ) self.statsLabel = wx.StaticText( self ) self.hbs.Add( self.categoryLabel, flag=wx.TOP | wx.BOTTOM | wx.LEFT | wx.ALIGN_CENTRE_VERTICAL, border=4 ) self.hbs.Add( self.categoryChoice, flag=wx.ALL | wx.ALIGN_CENTRE_VERTICAL, border=4 ) self.hbs.Add( self.groupByStartWave, flag=wx.ALL | wx.ALIGN_CENTRE_VERTICAL | wx.EXPAND, border=4 ) self.hbs.Add( self.statsLabel, flag=wx.ALL | wx.ALIGN_CENTRE_VERTICAL | wx.EXPAND, border=4 ) self.ganttChart = GanttChartPanel.GanttChartPanel( self ) self.ganttChart.dClickCallback = UpdateSetNum self.ganttChart.rClickCallback = self.onRightClick #self.ganttChart.lClickCallback = self.onLeftClick self.ganttChart.getNowTimeCallback = GetNowTime bs = wx.BoxSizer(wx.VERTICAL) bs.Add(self.hbs, flag=wx.GROW|wx.HORIZONTAL) bs.Add(self.ganttChart, 1, wx.GROW|wx.ALL, 5) self.SetSizer(bs) bs.SetSizeHints(self) self.SetDoubleBuffered( True )
def OnPopupLapDetail( self, event ): with Model.LockRace() as race: if not race: return tLapStart = self.entryStart.t tLapEnd = self.entryEnd.t iLap = self.entryStart.lap try: leaderNum = GanttChartPanel.numFromLabel( self.ganttChart.labels[0] ) leaderEntries = race.getRider(leaderNum).interpolate() leaderEntryStart = leaderEntries[self.entryStart.lap] leaderEntryEnd = leaderEntries[self.entryEnd.lap] except: leaderEntryStart = None leaderEntryEnd = None try: riderInfo = race.excelLink.read()[self.entryEnd.num] except: riderInfo = {} try: riderName = u'{}, {} {}'.format(riderInfo['LastName'], riderInfo['FirstName'], self.entryEnd.num) except KeyError: try: riderName = u'{} {}'.format(riderInfo['LastName'], self.entryEnd.num) except KeyError: try: riderName = u'{} {}'.format(riderInfo['FirstName'], self.entryEnd.num) except KeyError: riderName = u'{}'.format(self.entryEnd.num) if leaderEntryStart: tDown = tLapStart - leaderEntryStart.t infoDownStart = _('\nLap Start {} down from leader {}').format(Utils.formatTime(tDown, True), leaderEntryStart.num) else: infoDownStart = '' if leaderEntryEnd: tDown = tLapEnd - leaderEntryEnd.t infoDownEnd = _('\nLap End {} down from leader {}').format(Utils.formatTime(tDown, True), leaderEntryStart.num) else: infoDownEnd = '' infoStart = race.numTimeInfo.getInfoStr( self.entryStart.num, tLapStart ) if infoStart: infoStart = _('\nLap Start ') + infoStart infoEnd = race.numTimeInfo.getInfoStr( self.entryEnd.num, tLapEnd ) if infoEnd: infoEnd = _('\nLap End ') + infoEnd info = (_('Rider: {} Lap: {}\nLap Start: {} Lap End: {}\nLap Time: {}\n{}{}{}{}').format( riderName, self.entryEnd.lap, Utils.formatTime(tLapStart), Utils.formatTime(tLapEnd), Utils.formatTime(tLapEnd - tLapStart), infoDownStart, infoDownEnd, infoStart, infoEnd )).strip() Utils.MessageOK( self, info, _('Lap Details') )
def onRightClick( self, xPos, yPos, num, iRider, iLap ): with Model.LockRace() as race: if not race or num not in race: return category = FixCategories( self.categoryChoice, getattr(race, 'ganttCategory', 0) ) entries = race.getRider(num).interpolate() try: self.entry = entries[iLap] self.entryStart = entries[iLap-1] self.entryEnd = self.entry except (IndexError, KeyError): return self.setNumSelect( num ) self.numSelect = num if Utils.isMainWin(): wx.CallAfter( Utils.getMainWin().setNumSelect, self.ganttChart.numSelect ) self.iLap = iLap self.iRow = iRider allCases = 0 interpCase = 1 nonInterpCase = 2 if not hasattr(self, 'popupInfo'): self.popupInfo = [ (wx.NewId(), _('Add Missing Last Lap'), _('Add Missing Last Lap'), self.OnPopupAddMissingLastLap, allCases), (None, None, None, None, None), (wx.NewId(), _('Pull after Lap End') + u'...', _('Pull after Lap End'), self.OnPopupPull, allCases), (wx.NewId(), _('DNF after Lap End') + u'...', _('DNF after Lap End'), self.OnPopupDNF, allCases), (None, None, None, None, None), (wx.NewId(), _('Correct Lap End Time') + u'...',_('Change number or lap end time'), self.OnPopupCorrect, interpCase), (wx.NewId(), _('Shift Lap End Time') + u'...', _('Move lap end time earlier/later'), self.OnPopupShift, interpCase), (wx.NewId(), _('Delete Lap End Time') + u'...', _('Delete Lap End Time'), self.OnPopupDelete, nonInterpCase), (None, None, None, None, None), (wx.NewId(), _('Note') + u'...', _('Add/Edit lap Note'), self.OnPopupLapNote, allCases), (None, None, None, None, None), (wx.NewId(), _('Turn off Autocorrect') + u'...',_('Turn off Autocorrect'), self.OnPopupAutocorrect, allCases), (None, None, None, None, None), (wx.NewId(), _('Swap with Rider before'), _('Swap with Rider before'), self.OnPopupSwapBefore, nonInterpCase), (wx.NewId(), _('Swap with Rider after'), _('Swap with Rider after'), self.OnPopupSwapAfter, nonInterpCase), (None, None, None, None, None), (wx.NewId(), _('Show Lap Details') + u'...', _('Show Lap Details'), self.OnPopupLapDetail, allCases), (None, None, None, None, None), ] if Model.race and Model.race.enableUSBCamera: self.popupInfo.append( (wx.NewId(), _('Photos')+ u'...', _('Show Photos'), self.OnPopupPhotos, allCases), ) self.popupInfo.extend( [ (wx.NewId(), _('RiderDetail'), _('Show RiderDetail Dialog'), self.OnPopupRiderDetail, allCases), (wx.NewId(), _('Results'), _('Switch to Results tab'), self.OnPopupResults, allCases), ] ) self.splitMenuInfo = [ (wx.NewId(), u'{} {}'.format(split-1, _('Split') if split-1 == 1 else _('Splits')), lambda evt, s = self, splits = split: s.doSplitLap(splits)) for split in xrange(2,8) ] + [ (wx.NewId(), _('Custom') + u'...', lambda evt, s = self: s.doCustomSplitLap())] for id, name, text, callback, cCase in self.popupInfo: if id: self.Bind( wx.EVT_MENU, callback, id=id ) for id, name, callback in self.splitMenuInfo: self.Bind( wx.EVT_MENU, callback, id=id ) caseCode = 1 if entries[iLap].interp else 2 riderResults = dict( (r.num, r) for r in GetResults(category) ) self.numBefore, self.numAfter = None, None for iRow, attr in [(self.iRow - 1, 'numBefore'), (self.iRow + 1, 'numAfter')]: if not(0 <= iRow < len(self.ganttChart.labels)): continue numAdjacent = GanttChartPanel.numFromLabel(self.ganttChart.labels[iRow]) if RidersCanSwap( riderResults, num, numAdjacent ): setattr( self, attr, numAdjacent ) menu = wx.Menu() for id, name, text, callback, cCase in self.popupInfo: if not id: Utils.addMissingSeparator( menu ) continue if caseCode < cCase: continue if (name.endswith(_('before')) and not self.numBefore) or (name.endswith(_('after')) and not self.numAfter): continue menu.Append( id, name, text ) if caseCode == 2: submenu = wx.Menu() for id, name, callback in self.splitMenuInfo: submenu.Append( id, name ) Utils.addMissingSeparator( menu ) menu.PrependSeparator() menu.PrependMenu( wx.NewId(), _('Add Missing Split'), submenu ) Utils.deleteTrailingSeparators( menu ) self.PopupMenu( menu ) menu.Destroy()
def OnPopupLapDetail(self, event): with Model.LockRace() as race: if not race: return tLapStart = self.entryStart.t tLapEnd = self.entryEnd.t iLap = self.entryStart.lap try: leaderNum = GanttChartPanel.numFromLabel( self.ganttChart.labels[0]) leaderEntries = race.getRider(leaderNum).interpolate() leaderEntryStart = leaderEntries[self.entryStart.lap] leaderEntryEnd = leaderEntries[self.entryEnd.lap] except: leaderEntryStart = None leaderEntryEnd = None try: riderInfo = race.excelLink.read()[self.entryEnd.num] except: riderInfo = {} try: riderName = u'{}, {} {}'.format(riderInfo['LastName'], riderInfo['FirstName'], self.entryEnd.num) except KeyError: try: riderName = u'{} {}'.format(riderInfo['LastName'], self.entryEnd.num) except KeyError: try: riderName = u'{} {}'.format(riderInfo['FirstName'], self.entryEnd.num) except KeyError: riderName = u'{}'.format(self.entryEnd.num) if leaderEntryStart: tDown = tLapStart - leaderEntryStart.t infoDownStart = u'\n' + u'{}: {} ({})'.format( _('Lap Start down from leader'), Utils.formatTime(tDown, True), leaderEntryStart.num) else: infoDownStart = '' if leaderEntryEnd: tDown = tLapEnd - leaderEntryEnd.t infoDownEnd = u'\n' + u'{}: {} {}'.format( _('Lap End down from leader'), Utils.formatTime( tDown, True), leaderEntryStart.num) else: infoDownEnd = '' infoStart = race.numTimeInfo.getInfoStr(self.entryStart.num, tLapStart) if infoStart: infoStart = u'\n{} {}'.format(_('Lap Start'), infoStart) infoEnd = race.numTimeInfo.getInfoStr(self.entryEnd.num, tLapEnd) if infoEnd: infoEnd = u'\n{} {}'.format(_('Lap End'), infoEnd) info = ( u'{}: {} {}: {}\n{}: {} {}: {}\n{}: {}\n{}{}{}{}'.format( _('Rider'), riderName, _('Lap'), self.entryEnd.lap, _('Lap Start'), Utils.formatTime(tLapStart), _('Lap End'), Utils.formatTime(tLapEnd), _('Lap Time'), Utils.formatTime(tLapEnd - tLapStart), infoDownStart, infoDownEnd, infoStart, infoEnd)).strip() Utils.MessageOK(self, info, _('Lap Details'))
def onRightClick(self, xPos, yPos, num, iRider, iLap): with Model.LockRace() as race: if not race or num not in race.riders: return category = FixCategories(self.categoryChoice, getattr(race, 'ganttCategory', 0)) entries = race.getRider(num).interpolate() try: self.entry = entries[iLap] self.entryStart = entries[iLap - 1] self.entryEnd = self.entry except (IndexError, KeyError): return self.setNumSelect(num) self.numSelect = num if Utils.isMainWin(): wx.CallAfter(Utils.getMainWin().setNumSelect, self.ganttChart.numSelect) self.iLap = iLap self.iRow = iRider allCases = 0 interpCase = 1 nonInterpCase = 2 if not hasattr(self, 'popupInfo'): self.popupInfo = [ (_('Add Missing Last Lap'), _('Add Missing Last Lap'), self.OnPopupAddMissingLastLap, allCases), (None, None, None, None), (_('Pull after Lap End') + u'...', _('Pull after Lap End'), self.OnPopupPull, allCases), (_('DNF after Lap End') + u'...', _('DNF after Lap End'), self.OnPopupDNF, allCases), (None, None, None, None), (_('Correct Lap End Time') + u'...', _('Change number or lap end time'), self.OnPopupCorrect, interpCase), (_('Shift Lap End Time') + u'...', _('Move lap end time earlier/later'), self.OnPopupShift, interpCase), (_('Delete Lap End Time') + u'...', _('Delete Lap End Time'), self.OnPopupDelete, nonInterpCase), (None, None, None, None), (_('Mass Pull after Lap End Time') + u'...', _('Pull Rider and all Riders after at Lap End'), self.OnPopupMassPull, allCases), (None, None, None, None), (_('Note') + u'...', _('Add/Edit lap Note'), self.OnPopupLapNote, allCases), (None, None, None, None), (_('Turn off Autocorrect') + u'...', _('Turn off Autocorrect'), self.OnPopupAutocorrect, allCases), (None, None, None, None), (_('Swap with Rider before'), _('Swap with Rider before'), self.OnPopupSwapBefore, nonInterpCase), (_('Swap with Rider after'), _('Swap with Rider after'), self.OnPopupSwapAfter, nonInterpCase), (None, None, None, None), (_('Show Lap Details') + u'...', _('Show Lap Details'), self.OnPopupLapDetail, allCases), (None, None, None, None), (_('RiderDetail'), _('Show RiderDetail Dialog'), self.OnPopupRiderDetail, allCases), (_('Results'), _('Switch to Results tab'), self.OnPopupResults, allCases), ] self.splitMenuInfo = [ (u'{} {}'.format( split - 1, _('Split') if split - 1 == 1 else _('Splits')), lambda evt, s=self, splits=split: s.doSplitLap(splits)) for split in range(2, 8) ] + [(_('Custom') + u'...', lambda evt, s=self: s.doCustomSplitLap())] self.menuOptions = {} for numBefore in [False, True]: for numAfter in [False, True]: for caseCode in range(3): menu = wx.Menu() for name, text, callback, cCase in self.popupInfo: if not name: Utils.addMissingSeparator(menu) continue if caseCode < cCase: continue if (name.endswith(_('before')) and not numBefore) or (name.endswith( _('after')) and not numAfter): continue item = menu.Append(wx.ID_ANY, name, text) self.Bind(wx.EVT_MENU, callback, item) if caseCode == 2: submenu = wx.Menu() for name, callback in self.splitMenuInfo: item = submenu.Append(wx.ID_ANY, name) self.Bind(wx.EVT_MENU, callback, item) Utils.addMissingSeparator(menu) menu.PrependSeparator() menu.Prepend(wx.ID_ANY, _('Add Missing Split'), submenu) Utils.deleteTrailingSeparators(menu) self.menuOptions[(numBefore, numAfter, caseCode)] = menu caseCode = 1 if entries[iLap].interp else 2 riderResults = dict((r.num, r) for r in GetResults(category)) self.numBefore, self.numAfter = None, None for iRow, attr in [(self.iRow - 1, 'numBefore'), (self.iRow + 1, 'numAfter')]: if not (0 <= iRow < len(self.ganttChart.labels)): continue numAdjacent = GanttChartPanel.numFromLabel( self.ganttChart.labels[iRow]) if RidersCanSwap(riderResults, num, numAdjacent): setattr(self, attr, numAdjacent) menu = self.menuOptions[(bool(self.numBefore), bool(self.numAfter), caseCode)] try: self.PopupMenu(menu) except Exception as e: Utils.writeLog('Gantt:onRightClick: {}'.format(e))