Exemplo n.º 1
0
class Actions(wx.Panel):
    iResetStartClockOnFirstTag = 1
    iSkipFirstTagRead = 2

    def __init__(self, parent, id=wx.ID_ANY):
        wx.Panel.__init__(self, parent, id)

        self.SetBackgroundColour(wx.Colour(255, 255, 255))

        ps = wx.BoxSizer(wx.VERTICAL)
        self.splitter = wx.SplitterWindow(self, wx.VERTICAL)
        ps.Add(self.splitter, 1, flag=wx.EXPAND)
        self.SetSizer(ps)

        #---------------------------------------------------------------------------------------------

        self.leftPanel = wx.Panel(self.splitter)
        bs = wx.BoxSizer(wx.VERTICAL)
        self.leftPanel.SetSizer(bs)
        self.leftPanel.SetBackgroundColour(wx.Colour(255, 255, 255))
        self.leftPanel.Bind(wx.EVT_SIZE, self.setWrappedRaceInfo)

        buttonSize = 220
        self.button = RoundButton(self.leftPanel,
                                  size=(buttonSize, buttonSize))
        self.button.SetLabel(FinishText)
        self.button.SetFontToFitLabel()
        self.button.SetForegroundColour(wx.Colour(128, 128, 128))
        self.Bind(wx.EVT_BUTTON, self.onPress, self.button)

        self.clock = Clock(self, size=(190, 190), checkFunc=self.updateClock)
        self.clock.SetBackgroundColour(wx.WHITE)

        self.raceIntro = wx.StaticText(self.leftPanel, label=u'')
        self.raceIntro.SetFont(wx.Font(20, wx.DEFAULT, wx.NORMAL, wx.NORMAL))

        self.chipTimingOptions = wx.RadioBox(
            self.leftPanel,
            label=_("Chip Timing Options"),
            majorDimension=1,
            choices=Properties.RfidProperties.choices,
            style=wx.RA_SPECIFY_COLS)

        self.Bind(wx.EVT_RADIOBOX, self.onChipTimingOptions,
                  self.chipTimingOptions)

        self.settingsButton = wx.BitmapButton(
            self.leftPanel, bitmap=Utils.GetPngBitmap('settings-icon.png'))
        self.settingsButton.SetToolTip(wx.ToolTip(_('Properties Shortcut')))
        self.settingsButton.Bind(wx.EVT_BUTTON, self.onShowProperties)

        self.startRaceTimeCheckBox = wx.CheckBox(
            self.leftPanel, label=_('Start Race Automatically at Future Time'))

        hsSettings = wx.BoxSizer(wx.HORIZONTAL)
        hsSettings.Add(self.settingsButton, flag=wx.ALIGN_CENTER_VERTICAL)
        hsSettings.Add(self.startRaceTimeCheckBox,
                       flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL,
                       border=12)

        border = 8
        hs = wx.BoxSizer(wx.HORIZONTAL)
        hs.Add(self.button, border=border, flag=wx.LEFT | wx.TOP)
        hs.Add(self.raceIntro,
               1,
               border=border,
               flag=wx.LEFT | wx.TOP | wx.RIGHT | wx.EXPAND)
        bs.Add(hs, border=border, flag=wx.ALL)

        hsClock = wx.BoxSizer(wx.HORIZONTAL)
        hsClock.AddSpacer(26)
        hsClock.Add(self.clock)
        hsClock.Add(hsSettings, border=4, flag=wx.LEFT)
        bs.Add(hsClock, border=4, flag=wx.ALL)

        bs.Add(self.chipTimingOptions, border=border, flag=wx.ALL)

        #---------------------------------------------------------------------------------------------

        self.rightPanel = wx.Panel(self.splitter)
        self.rightPanel.SetBackgroundColour(wx.Colour(255, 255, 255))
        checklistTitle = wx.StaticText(self.rightPanel, label=_('Checklist:'))
        checklistTitle.SetFont(
            wx.Font(14, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
                    wx.FONTWEIGHT_NORMAL))
        self.checklist = Checklist.Checklist(self.rightPanel)

        hsSub = wx.BoxSizer(wx.VERTICAL)
        hsSub.Add(checklistTitle, 0, flag=wx.ALL, border=4)
        hsSub.Add(self.checklist,
                  1,
                  flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
                  border=4)
        self.rightPanel.SetSizer(hsSub)

        #---------------------------------------------------------------------------------------------

        self.splitter.SplitVertically(self.leftPanel, self.rightPanel)
        self.splitter.SetMinimumPaneSize(100)
        wx.CallAfter(self.refresh)
        wx.CallAfter(self.splitter.SetSashPosition, 650)
        wx.CallAfter(self.GetSizer().Layout)

    def setWrappedRaceInfo(self, event=None):
        wrapWidth = self.leftPanel.GetClientSize(
        )[0] - self.button.GetClientSize()[0] - 20
        dc = wx.WindowDC(self.raceIntro)
        dc.SetFont(self.raceIntro.GetFont())
        label = wordwrap(Model.race.getRaceIntro() if Model.race else u'',
                         wrapWidth, dc)
        self.raceIntro.SetLabel(label)
        self.leftPanel.GetSizer().Layout()
        if event:
            event.Skip()

    def updateChipTimingOptions(self):
        if not Model.race:
            return

        iSelection = self.chipTimingOptions.GetSelection()
        race = Model.race
        race.resetStartClockOnFirstTag = bool(
            iSelection == self.iResetStartClockOnFirstTag)
        race.skipFirstTagRead = bool(iSelection == self.iSkipFirstTagRead)

    def updateClock(self):
        mainWin = Utils.getMainWin()
        return not mainWin or mainWin.isShowingPage(self)

    def onShowProperties(self, event):
        if not Model.race:
            Utils.MessageOK(
                self,
                _("You must have a valid race.  Open or New a race first."),
                _("No Valid Race"),
                iconMask=wx.ICON_ERROR)
            return
        if not hasattr(self, 'propertiesDialog'):
            self.propertiesDialog = PropertiesDialog(self,
                                                     showFileFields=False,
                                                     updateProperties=True,
                                                     size=(600, 400))
        else:
            self.propertiesDialog.properties.refresh(forceUpdate=True)
        self.propertiesDialog.properties.setPage('raceOptionsProperties')
        if self.propertiesDialog.ShowModal() == wx.ID_OK:
            self.propertiesDialog.properties.doCommit()
            Utils.refresh()

    def onChipTimingOptions(self, event):
        if not Model.race:
            return
        self.updateChipTimingOptions()

    def onPress(self, event):
        if not Model.race:
            return
        with Model.LockRace() as race:
            running = race.isRunning()
        if running:
            self.onFinishRace(event)
            return

        self.updateChipTimingOptions()
        if getattr(Model.race, 'enableJChipIntegration', False):
            try:
                externalFields = race.excelLink.getFields()
                externalInfo = race.excelLink.read()
            except:
                externalFields = []
                externalInfo = {}
            if not externalInfo:
                Utils.MessageOK(
                    self, u'\n\n'.join([
                        _('Cannot Start. Excel Sheet read failure.'),
                        _('The Excel file is either unconfigured or unreadable.'
                          )
                    ]), _('Excel Sheet Read '), wx.ICON_ERROR)
                return
            try:
                i = next((i for i, field in enumerate(externalFields)
                          if field.startswith('Tag')))
            except StopIteration:
                Utils.MessageOK(
                    self, u'\n\n'.join([
                        _('Cannot Start.  Excel Sheet missing Tag column.'),
                        _('The Excel file must contain a Tag column to use RFID.'
                          )
                    ]), _('Excel Sheet missing Tag column'), wx.ICON_ERROR)
                return

        if self.startRaceTimeCheckBox.IsChecked():
            self.onStartRaceTime(event)
        else:
            self.onStartRace(event)

    def onStartRace(self, event):
        if Model.race and Utils.MessageOKCancel(self, _('Start Race Now?\n\n'),
                                                _('Start Race')):
            StartRaceNow()

    def onStartRaceTime(self, event):
        if Model.race is None:
            return
        dlg = StartRaceAtTime(self)
        dlg.ShowModal()
        dlg.Destroy()

    def onFinishRace(self, event):
        if Model.race is None or not Utils.MessageOKCancel(
                self, _('Finish Race Now?'), _('Finish Race')):
            return

        with Model.LockRace() as race:
            race.finishRaceNow()
            if race.numLaps is None:
                race.numLaps = race.getMaxLap()
            SetNoDataDNS()
            Model.resetCache()

        Utils.writeRace()
        self.refresh()
        mainWin = Utils.getMainWin()
        if mainWin:
            mainWin.refresh()

        OutputStreamer.writeRaceFinish()
        OutputStreamer.StopStreamer()
        try:
            ChipReader.chipReaderCur.StopListener()
        except:
            pass

        if getattr(Model.race, 'ftpUploadDuringRace', False):
            realTimeFtpPublish.publishEntry(True)

    def commit(self):
        self.checklist.commit()

    def refresh(self):
        self.clock.Start()
        self.button.Enable(False)
        self.startRaceTimeCheckBox.Enable(False)
        self.settingsButton.Enable(False)
        self.button.SetLabel(StartText)
        self.button.SetForegroundColour(wx.Colour(100, 100, 100))
        self.chipTimingOptions.SetSelection(0)
        self.chipTimingOptions.Enable(False)

        with Model.LockRace() as race:
            if race:
                self.settingsButton.Enable(True)

                # Adjust the chip recording options for TT.
                if getattr(race, 'isTimeTrial', False):
                    race.resetStartClockOnFirstTag = False
                    race.skipFirstTagRead = False

                if getattr(race, 'resetStartClockOnFirstTag', True):
                    self.chipTimingOptions.SetSelection(
                        self.iResetStartClockOnFirstTag)
                elif getattr(race, 'skipFirstTagRead', False):
                    self.chipTimingOptions.SetSelection(self.iSkipFirstTagRead)

                if race.startTime is None:
                    self.button.Enable(True)
                    self.button.SetLabel(StartText)
                    self.button.SetForegroundColour(wx.Colour(0, 128, 0))

                    self.startRaceTimeCheckBox.Enable(True)
                    self.startRaceTimeCheckBox.Show(True)

                    self.chipTimingOptions.Enable(
                        getattr(race, 'enableJChipIntegration', False))
                    self.chipTimingOptions.Show(
                        getattr(race, 'enableJChipIntegration', False))
                elif race.isRunning():
                    self.button.Enable(True)
                    self.button.SetLabel(FinishText)
                    self.button.SetForegroundColour(wx.Colour(128, 0, 0))

                    self.startRaceTimeCheckBox.Enable(False)
                    self.startRaceTimeCheckBox.Show(False)

                    self.chipTimingOptions.Enable(False)
                    self.chipTimingOptions.Show(False)

                # Adjust the time trial display options.
                if getattr(race, 'isTimeTrial', False):
                    self.chipTimingOptions.Enable(False)
                    self.chipTimingOptions.Show(False)

            self.GetSizer().Layout()

        self.setWrappedRaceInfo()
        self.checklist.refresh()

        mainWin = Utils.getMainWin()
        if mainWin is not None:
            mainWin.updateRaceClock()
Exemplo n.º 2
0
	def __init__( self, parent, id = wx.ID_ANY, title='', size=(1000,800) ):
		wx.Frame.__init__(self, parent, id, title, size=size)
		
		self.db = Database()
		
		self.bufferSecs = 10
		self.setFPS( 30 )
		self.xFinish = None
		
		self.tFrameCount = self.tLaunch = self.tLast = now()
		self.frameCount = 0
		self.fpt = timedelta(seconds=0)
		self.iTriggerSelect = None
		self.triggerInfo = None
		self.tsMax = None
		
		self.captureTimer = wx.CallLater( 10, self.stopCapture )
		
		self.tdCaptureBefore = tdCaptureBeforeDefault
		self.tdCaptureAfter = tdCaptureAfterDefault

		self.config = wx.Config()
		
		self.requestQ = Queue()		# Select photos from photobuf.
		self.dbWriterQ = Queue()	# Photos waiting to be written
		self.messageQ = Queue()		# Collection point for all status/failure messages.
		
		self.SetBackgroundColour( wx.Colour(232,232,232) )
		
		self.focusDialog = FocusDialog( self )
		self.photoDialog = PhotoDialog( self )
		self.autoCaptureDialog = AutoCaptureDialog( self )
		self.triggerDialog = TriggerDialog( self )
				
		mainSizer = wx.BoxSizer( wx.VERTICAL )
		
		#------------------------------------------------------------------------------------------------
		headerSizer = wx.BoxSizer( wx.HORIZONTAL )
		
		self.logo = Utils.GetPngBitmap('CrossMgrHeader.png')
		headerSizer.Add( wx.StaticBitmap(self, wx.ID_ANY, self.logo) )
		
		self.title = wx.StaticText(self, label='CrossMgr Video\nVersion {}'.format(AppVerName.split()[1]), style=wx.ALIGN_RIGHT )
		self.title.SetFont( wx.Font( (0,28), wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL ) )
		headerSizer.Add( self.title, flag=wx.ALL, border=10 )
		
		clock = Clock( self, size=(90,90) )
		clock.SetBackgroundColour( self.GetBackgroundColour() )
		clock.Start()

		headerSizer.Add( clock, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border=4 )
		
		#------------------------------------------------------------------------------
		self.cameraDevice = wx.StaticText( self )
		self.cameraResolution = wx.StaticText( self )
		self.targetFPS = wx.StaticText( self, label='30 fps' )
		self.actualFPS = wx.StaticText( self, label='30.0 fps' )
		
		boldFont = self.cameraDevice.GetFont()
		boldFont.SetWeight( wx.BOLD )
		for w in (self.cameraDevice, self.cameraResolution, self.targetFPS, self.actualFPS):
			w.SetFont( boldFont )
		
		fgs = wx.FlexGridSizer( 2, 2, 2 )	# 2 Cols
		fgs.Add( wx.StaticText(self, label='Camera Device:'), flag=wx.ALIGN_RIGHT )
		fgs.Add( self.cameraDevice )
		
		fgs.Add( wx.StaticText(self, label='Resolution:'), flag=wx.ALIGN_RIGHT )
		fgs.Add( self.cameraResolution )
		
		fgs.Add( wx.StaticText(self, label='Target:'), flag=wx.ALIGN_RIGHT )
		fgs.Add( self.targetFPS, flag=wx.ALIGN_RIGHT )
		
		fgs.Add( wx.StaticText(self, label='Actual:'), flag=wx.ALIGN_RIGHT )
		fgs.Add( self.actualFPS, flag=wx.ALIGN_RIGHT )
		
		self.focus = wx.Button( self, label="Focus..." )
		self.focus.Bind( wx.EVT_BUTTON, self.onFocus )
		
		self.reset = wx.Button( self, label="Reset Camera" )
		self.reset.Bind( wx.EVT_BUTTON, self.resetCamera )
		
		self.manage = wx.Button( self, label="Manage Database" )
		self.manage.Bind( wx.EVT_BUTTON, self.manageDatabase )
		
		self.autoCaptureBtn = wx.Button( self, label="Config Auto Capture" )
		self.autoCaptureBtn.Bind( wx.EVT_BUTTON, self.autoCaptureConfig )
		
		self.help = wx.Button( self, wx.ID_HELP )
		self.help.Bind( wx.EVT_BUTTON, self.onHelp )
		
		self.snapshot, self.autoCapture, self.capture = CreateCaptureButtons( self )
		
		self.snapshot.Bind( wx.EVT_LEFT_DOWN, self.onStartSnapshot )
		self.focusDialog.snapshot.Bind( wx.EVT_LEFT_DOWN, self.onStartSnapshot )
		self.autoCapture.Bind( wx.EVT_LEFT_DOWN, self.onStartAutoCapture )
		self.focusDialog.autoCapture.Bind( wx.EVT_LEFT_DOWN, self.onStartAutoCapture )
		self.capture.Bind( wx.EVT_LEFT_DOWN, self.onStartCapture )
		self.capture.Bind( wx.EVT_LEFT_UP, self.onStopCapture )
		self.focusDialog.capture.Bind( wx.EVT_LEFT_DOWN, self.onStartCapture )
		self.focusDialog.capture.Bind( wx.EVT_LEFT_UP, self.onStopCapture )
		
		headerSizer.Add( fgs, flag=wx.ALIGN_CENTER_VERTICAL )
		
		fgs = wx.FlexGridSizer( rows=2, cols=0, hgap=8, vgap=4 )
		
		fgs.Add( self.focus, flag=wx.EXPAND )
		fgs.Add( self.reset, flag=wx.EXPAND )
		fgs.Add( self.manage, flag=wx.EXPAND )
		fgs.Add( self.autoCaptureBtn, flag=wx.EXPAND )
		fgs.Add( self.help, flag=wx.EXPAND )
		
		headerSizer.Add( fgs, flag=wx.ALIGN_CENTRE|wx.LEFT, border=4 )
		headerSizer.AddStretchSpacer()
		
		headerSizer.Add( self.snapshot, flag=wx.ALIGN_CENTRE_VERTICAL|wx.LEFT, border=8 )
		headerSizer.Add( self.autoCapture, flag=wx.ALIGN_CENTRE_VERTICAL|wx.LEFT, border=8 )
		headerSizer.Add( self.capture, flag=wx.ALIGN_CENTRE_VERTICAL|wx.LEFT|wx.RIGHT, border=8 )

		#------------------------------------------------------------------------------
		mainSizer.Add( headerSizer, flag=wx.EXPAND )
		
		#------------------------------------------------------------------------------------------------
		self.finishStrip = FinishStripPanel( self, size=(-1,wx.GetDisplaySize()[1]//2) )
		self.finishStrip.finish.Bind( wx.EVT_RIGHT_DOWN, self.onRightClick )
		
		self.primaryBitmap = ScaledBitmap( self, style=wx.BORDER_SUNKEN, size=(int(imageWidth*0.75), int(imageHeight*0.75)) )
		self.primaryBitmap.SetTestBitmap()
		self.primaryBitmap.Bind( wx.EVT_LEFT_UP, self.onFocus )
		self.primaryBitmap.Bind( wx.EVT_RIGHT_UP, self.onFocus )
		
		hsDate = wx.BoxSizer( wx.HORIZONTAL )
		hsDate.Add( wx.StaticText(self, label='Show Triggers for'), flag=wx.ALIGN_CENTER_VERTICAL )
		tQuery = now()
		self.date = wx.adv.DatePickerCtrl(
			self,
			dt=wx.DateTime.FromDMY( tQuery.day, tQuery.month-1, tQuery.year ),
			style=wx.adv.DP_DROPDOWN|wx.adv.DP_SHOWCENTURY
		)
		self.date.Bind( wx.adv.EVT_DATE_CHANGED, self.onQueryDateChanged )
		hsDate.Add( self.date, flag=wx.LEFT, border=2 )
		
		self.dateSelect = wx.Button( self, label='Select Date' )
		hsDate.Add( self.dateSelect, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT, border=2 )
		self.dateSelect.Bind( wx.EVT_BUTTON, self.onDateSelect )
		
		hsDate.Add( wx.StaticText(self, label='Filter by Bib'), flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT, border=12 )
		self.bib = wx.lib.intctrl.IntCtrl( self, style=wx.TE_PROCESS_ENTER, size=(64,-1), min=1, allow_none=True, value=None )
		self.bib.Bind( wx.EVT_TEXT_ENTER, self.onQueryBibChanged )
		hsDate.Add( self.bib, flag=wx.LEFT, border=2 )
		
		self.tsQueryLower = datetime(tQuery.year, tQuery.month, tQuery.day)
		self.tsQueryUpper = self.tsQueryLower + timedelta(days=1)
		self.bibQuery = None
		
		self.triggerList = AutoWidthListCtrl( self, style=wx.LC_REPORT|wx.BORDER_SUNKEN|wx.LC_SORT_ASCENDING|wx.LC_HRULES )
		
		self.il = wx.ImageList(16, 16)
		self.sm_close = []
		for bm in getCloseFinishBitmaps():
			self.sm_close.append( self.il.Add(bm) )
		self.sm_up = self.il.Add( Utils.GetPngBitmap('SmallUpArrow.png'))
		self.sm_up = self.il.Add( Utils.GetPngBitmap('SmallUpArrow.png'))
		self.sm_dn = self.il.Add( Utils.GetPngBitmap('SmallDownArrow.png'))
		self.triggerList.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
		
		self.fieldCol = {f:c for c, f in enumerate('ts bib name team wave race_name note kmh mph frames'.split())}
		headers = ['Time', 'Bib', 'Name', 'Team', 'Wave', 'Race', 'Note', 'km/h', 'mph', 'Frames']
		for i, h in enumerate(headers):
			self.triggerList.InsertColumn(
				i, h,
				wx.LIST_FORMAT_RIGHT if h in ('Bib','km/h','mph','Frames') else wx.LIST_FORMAT_LEFT
			)
		self.itemDataMap = {}
		
		self.triggerList.Bind( wx.EVT_LIST_ITEM_SELECTED, self.onTriggerSelected )
		self.triggerList.Bind( wx.EVT_LIST_ITEM_ACTIVATED, self.onTriggerEdit )
		self.triggerList.Bind( wx.EVT_LIST_ITEM_RIGHT_CLICK, self.onTriggerRightClick )
		#self.triggerList.Bind( wx.EVT_LIST_DELETE_ITEM, self.onTriggerDelete )
		
		vsTriggers = wx.BoxSizer( wx.VERTICAL )
		vsTriggers.Add( hsDate )
		vsTriggers.Add( self.triggerList, 1, flag=wx.EXPAND|wx.TOP, border=2)
		
		#------------------------------------------------------------------------------------------------
		mainSizer.Add( self.finishStrip, 1, flag=wx.EXPAND )
		
		border=2
		row1Sizer = wx.BoxSizer( wx.HORIZONTAL )
		row1Sizer.Add( self.primaryBitmap, flag=wx.ALL, border=border )
		row1Sizer.Add( vsTriggers, 1, flag=wx.TOP|wx.BOTTOM|wx.RIGHT|wx.EXPAND, border=border )
		mainSizer.Add( row1Sizer, flag=wx.EXPAND )
				
		self.Bind(wx.EVT_CLOSE, self.onCloseWindow)

		self.readOptions()
		self.updateFPS( int(float(self.targetFPS.GetLabel().split()[0])) )
		self.updateAutoCaptureLabel()
		self.SetSizerAndFit( mainSizer )
		
		# Start the message reporting thread so we can see what is going on.
		self.messageThread = threading.Thread( target=self.showMessages )
		self.messageThread.daemon = True
		self.messageThread.start()
		
		wx.CallLater( 300, self.refreshTriggers )