class MarkWriteMainWindow(QtGui.QMainWindow): sigProjectChanged = QtCore.Signal(object) # new_project sigResetProjectData = QtCore.Signal(object) # project sigSelectedPenDataUpdate = QtCore.Signal(object, object) # (smin,smax), segmentdata sigSegmentCreated = QtCore.Signal(object) # new segment sigSegmentRemoved = QtCore.Signal(object, object) # segment being removed, # segment index in list sigAppSettingsUpdated = QtCore.Signal(object, #dict of app settings that changed object,) #ful settings dict sigActiveObjectChanged = QtCore.Signal(object, object) #new, old active objects _mainwin_instance=None _appdirs = None def __init__(self, qtapp): global SETTINGS QtGui.QMainWindow.__init__(self) MarkWriteMainWindow._mainwin_instance = self self._current_project = None self._activeobject = None self._predefinedtags = loadPredefinedSegmentTagList(u'default.tag') # create qt actions used by menu, toolbar, or both self.createGuiActions() # init GUI related stuff self.setupGUI(qtapp) self.sigProjectChanged.connect(self.handleProjectChange) self.sigSelectedPenDataUpdate.connect(self.handleSelectedPenDataUpdate) self.sigAppSettingsUpdated.connect(self._penDataTimeLineWidget.handleUpdatedSettingsEvent) self.sigAppSettingsUpdated.connect(self._penDataSpatialViewWidget.handleUpdatedSettingsEvent) self.sigAppSettingsUpdated.connect(self._selectedPenDataViewWidget.handleUpdatedSettingsEvent) @staticmethod def instance(): return MarkWriteMainWindow._mainwin_instance @property def project(self): return self._current_project @property def activeobject(self): return self._activeobject def setActiveObject(self, timeperioddatatype=None): prevactiveobj = self._activeobject self._activeobject = timeperioddatatype if timeperioddatatype is None: self._activeobject = self.project.selectedtimeregion #print "Settings active object:",self._activeobject if isinstance(self._activeobject,PenDataSegment): #print "**Setting region:",self._activeobject self._segmenttree.doNotSetActiveObject=True self.project.selectedtimeregion.setRegion(self._activeobject.timerange) self._segmenttree.doNotSetActiveObject=False self.removeSegmentAction.setEnabled(True) else: self.removeSegmentAction.setEnabled(False) self.sigActiveObjectChanged.emit(self._activeobject,prevactiveobj) return self._activeobject @property def predefinedtags(self): if self.project: return self.project.autodetected_segment_tags + self._predefinedtags return self._predefinedtags def createGuiActions(self): # # File Menu / Toolbar Related Actions # atext = 'Open a supported digitized pen position ' \ 'file format.' aicon = 'folder&32.png' self.openFileAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), '&Open', self) self.openFileAction.setShortcut('Ctrl+O') self.openFileAction.setEnabled(True) self.openFileAction.setStatusTip(atext) self.openFileAction.triggered.connect(self.openFile) #atext = 'Save Current Project.' #aicon = 'save&32.png' #self.saveProjectAction = ContextualStateAction( # QtGui.QIcon(getIconFilePath(aicon)), # 'Save', # self) #self.saveProjectAction.setShortcut('Ctrl+S') #self.saveProjectAction.setEnabled(False) #self.saveProjectAction.setStatusTip(atext) #self.saveProjectAction.triggered.connect(self.saveProject) atext = 'Export Pen Sample Level Report to a File.' aicon = 'sample_report&32.png' self.exportSampleReportAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Sample Report', self) #self.exportSampleReportAction.setShortcut('Ctrl+S') self.exportSampleReportAction.setEnabled(False) self.exportSampleReportAction.setStatusTip(atext) self.exportSampleReportAction.triggered.connect( self.createPenSampleLevelReportFile) atext = 'Export Segment Level Report to a File.' aicon = 'segment_report&32.png' self.exportSegmentReportAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Segment Report', self) #self.exportSampleReportAction.setShortcut('Ctrl+S') self.exportSegmentReportAction.setEnabled(False) self.exportSegmentReportAction.setStatusTip(atext) self.exportSegmentReportAction.triggered.connect( self.createSegmentLevelReportFile) self.exportSampleReportAction.enableActionsList.append(self.exportSegmentReportAction) atext = 'Open the Application Settings Dialog.' aicon = 'settings&32.png' self.showProjectSettingsDialogAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), '&Settings', self) self.showProjectSettingsDialogAction.setShortcut('Alt+S') self.showProjectSettingsDialogAction.setEnabled(True) self.showProjectSettingsDialogAction.setStatusTip(atext) self.showProjectSettingsDialogAction.triggered.connect( self.handleDisplayAppSettingsDialogEvent) atext = 'Close the MarkWrite Application. Any data segmention will be lost!' aicon = 'shut_down&32.png' self.exitAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Exit', self) self.exitAction.setShortcut('Ctrl+Alt+Q') self.exitAction.setEnabled(True) self.exitAction.setStatusTip(atext) self.exitAction.triggered.connect(self.closeEvent) # # Selection Menu / Toolbar Related Actions # atext = 'Create a Segment Using Currently Selected Pen Data.' aicon = 'accept&32.png' self.createSegmentAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Create &New', self) self.createSegmentAction.setShortcut(QtCore.Qt.Key_Return) self.createSegmentAction.setEnabled(False) self.createSegmentAction.setStatusTip(atext) self.createSegmentAction.triggered.connect(self.createSegment) atext = 'Delete the Selected Segment and any of the segments children.' aicon = 'delete&32.png' self.removeSegmentAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), '&Delete', self) self.removeSegmentAction.setShortcut('Ctrl+D') self.removeSegmentAction.setEnabled(False) self.removeSegmentAction.setStatusTip(atext) self.removeSegmentAction.triggered.connect(self.removeSegment) # # Timeline Plot Zoom Related Actions # atext = 'Increase Timeplot Horizontal Magnification 2x' aicon = 'zoom_in&32.png' self.zoomInTimelineAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Zoom In 2x', self) self.zoomInTimelineAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Plus) self.zoomInTimelineAction.setEnabled(False) self.zoomInTimelineAction.setStatusTip(atext) self.zoomInTimelineAction.triggered.connect(self.zoomInTimeline) atext = 'Decrease Timeplot Horizontal Magnification 2x' aicon = 'zoom_out&32.png' self.zoomOutTimelineAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Zoom Out 2x', self) self.zoomOutTimelineAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Minus) self.zoomOutTimelineAction.setEnabled(False) self.zoomOutTimelineAction.setStatusTip(atext) self.zoomOutTimelineAction.triggered.connect(self.zoomOutTimeline) self.exportSampleReportAction.enableActionsList.append(self.zoomInTimelineAction) self.exportSampleReportAction.enableActionsList.append(self.zoomOutTimelineAction) atext = 'Reposition Views around Selected Time Period' aicon = 'target&32.png' self.gotoSelectedTimePeriodAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Go To Selected Time Period', self) self.gotoSelectedTimePeriodAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Home) self.gotoSelectedTimePeriodAction.setEnabled(False) self.gotoSelectedTimePeriodAction.setStatusTip(atext) self.gotoSelectedTimePeriodAction.triggered.connect(self.gotoSelectTimelinePeriod) atext = "Move selected time period forward, so that it's start time is one sample after the current selection's end time" aicon = 'move_selection_forward&32.png' self.forwardSelectionAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Jump Forward', self) self.forwardSelectionAction.setShortcut(QtCore.Qt.Key_Right) self.forwardSelectionAction.setEnabled(False) self.forwardSelectionAction.setStatusTip(atext) self.forwardSelectionAction.triggered.connect(self.jumpTimeSelectionForward) atext = "Move selected time period backward, so that it's end time is one sample prior to the current selection's start time." aicon = 'move_selection_backward&32.png' self.backwardSelectionAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Jump Backward', self) self.backwardSelectionAction.setShortcut(QtCore.Qt.Key_Left) self.backwardSelectionAction.setEnabled(False) self.backwardSelectionAction.setStatusTip(atext) self.backwardSelectionAction.triggered.connect(self.jumpTimeSelectionBackward) atext = 'Increase Timeline Selection End Time' aicon = 'increase_select_endtime&32.png' self.increaseSelectionEndPointAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Increase Selection End', self) self.increaseSelectionEndPointAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Right) self.increaseSelectionEndPointAction.setEnabled(False) self.increaseSelectionEndPointAction.setStatusTip(atext) self.increaseSelectionEndPointAction.triggered.connect(self.increaseSelectionEndPointTime) atext = 'Decrease Timeline Selection End Time' aicon = 'descrease_select_endtime&32.png' self.decreaseSelectionEndPointAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Decrease Selection End', self) self.decreaseSelectionEndPointAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Left) self.decreaseSelectionEndPointAction.setEnabled(False) self.decreaseSelectionEndPointAction.setStatusTip(atext) self.decreaseSelectionEndPointAction.triggered.connect(self.decreaseSelectionEndPointTime) #====================================== atext = 'Increase Timeline Selection Start Time' aicon = 'increase_select_starttime&32.png' self.increaseSelectionStartPointAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Increase Selection Start', self) self.increaseSelectionStartPointAction.setShortcut(QtCore.Qt.ALT + QtCore.Qt.Key_Right) self.increaseSelectionStartPointAction.setEnabled(False) self.increaseSelectionStartPointAction.setStatusTip(atext) self.increaseSelectionStartPointAction.triggered.connect(self.increaseSelectionStartPointTime) atext = 'Decrease Timeline Selection Start Time' aicon = 'decrease_select_starttime&32.png' self.decreaseSelectionStartPointAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Decrease Selection Start', self) self.decreaseSelectionStartPointAction.setShortcut(QtCore.Qt.ALT + QtCore.Qt.Key_Left) self.decreaseSelectionStartPointAction.setEnabled(False) self.decreaseSelectionStartPointAction.setStatusTip(atext) self.decreaseSelectionStartPointAction.triggered.connect(self.decreaseSelectionStartPointTime) self.exportSampleReportAction.enableActionsList.append(self.zoomInTimelineAction) self.exportSampleReportAction.enableActionsList.append(self.zoomOutTimelineAction) self.exportSampleReportAction.enableActionsList.append(self.gotoSelectedTimePeriodAction) self.exportSampleReportAction.enableActionsList.append(self.decreaseSelectionEndPointAction) self.exportSampleReportAction.enableActionsList.append(self.increaseSelectionEndPointAction) self.exportSampleReportAction.enableActionsList.append(self.decreaseSelectionStartPointAction) self.exportSampleReportAction.enableActionsList.append(self.increaseSelectionStartPointAction) self.exportSampleReportAction.enableActionsList.append(self.forwardSelectionAction) self.exportSampleReportAction.enableActionsList.append(self.backwardSelectionAction) # # Help Menu / Toolbar Related Actions # atext = 'Displays the MarkWrite About Dialog.' aicon = 'info&32.png' self.aboutAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'About', self) self.aboutAction.setEnabled(True) self.aboutAction.setStatusTip(atext) self.aboutAction.triggered.connect(self.showAboutDialog) def setupGUI(self, app): ''' :return: ''' # ## Create Main GUI Menu Bar # menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(self.openFileAction) #fileMenu.addAction(self.saveProjectAction) fileMenu.addAction(self.showProjectSettingsDialogAction) fileMenu.addSeparator() exportMenu = fileMenu.addMenu("&Export") exportMenu.addAction(self.exportSampleReportAction) exportMenu.addAction(self.exportSegmentReportAction) exportMenu.addSeparator() self.customReportActions=[] for custom_report in custom_report_classes: a = exportMenu.addAction(custom_report.reportlabel(), lambda: self.exportCustomReport(custom_report)) a.setEnabled(False) self.customReportActions.append(a) self.exportSampleReportAction.enableActionsList.append(a) fileMenu.addSeparator() fileMenu.addAction(self.exitAction) segmentMenu = menubar.addMenu('&Segment') segmentMenu.addAction(self.createSegmentAction) segmentMenu.addAction(self.removeSegmentAction) helpMenu = menubar.addMenu('&Help') helpMenu.addAction(self.aboutAction) self.toolbarFile = self.addToolBar('File') self.toolbarFile.addAction(self.openFileAction) #self.toolbarFile.addAction(self.saveProjectAction) self.toolbarFile.addAction(self.showProjectSettingsDialogAction) self.toolbarFile.addAction(self.exportSampleReportAction) self.toolbarFile.addAction(self.exportSegmentReportAction) self.toolbarsegment = self.addToolBar('Segment') self.toolbarsegment.addAction(self.createSegmentAction) self.toolbarsegment.addAction(self.removeSegmentAction) self.toolbartimelineview = self.addToolBar('Timeline View') self.toolbartimelineview.addAction(self.zoomInTimelineAction) self.toolbartimelineview.addAction(self.zoomOutTimelineAction) self.toolbarsegment = self.addToolBar('Timeline Selection') self.toolbarsegment.addAction(self.gotoSelectedTimePeriodAction) self.toolbarsegment.addAction(self.decreaseSelectionStartPointAction) self.toolbarsegment.addAction(self.increaseSelectionStartPointAction) self.toolbarsegment.addAction(self.backwardSelectionAction) self.toolbarsegment.addAction(self.forwardSelectionAction) self.toolbarsegment.addAction(self.decreaseSelectionEndPointAction) self.toolbarsegment.addAction(self.increaseSelectionEndPointAction) self.toolbarHelp = self.addToolBar('Help') self.toolbarHelp.addAction(self.aboutAction) # ## Create App Dock Area # self._dockarea = DockArea() self.setCentralWidget(self._dockarea) # Enable antialiasing for prettier plots pg.setConfigOptions(antialias=True) # Create Docking Layout def addDock(name, inner_widget=None): ww, wh = DEFAULT_WIN_SIZE dpos, (dw, dh) = DEFAULT_DOCK_PLACEMENT[name] if isinstance(dpos, basestring): self._dockarea.addDock(Dock(name, size=[ww * dw, wh * dh]), dpos) else: self._dockarea.addDock(Dock(name, size=[ww * dw, wh * dh]), dpos[0], self._dockarea.docks[dpos[1]]) if inner_widget: self._dockarea.docks[name].addWidget(inner_widget) from markwrite.gui.selecteddataview import SelectedPointsPlotWidget from markwrite.gui.spatialview import PenDataSpatialPlotWidget from markwrite.gui.timelineplot import PenDataTemporalPlotWidget from markwrite.gui.segmenttree import SegmentInfoDockArea self._segmenttree = SegmentInfoDockArea() addDock(u"Segment Tree", self._segmenttree) self._penDataTimeLineWidget = PenDataTemporalPlotWidget() self._penDataSpatialViewWidget = PenDataSpatialPlotWidget() addDock(u"Timeline", self._penDataTimeLineWidget) addDock(u"Spatial View", self._penDataSpatialViewWidget) self._selectedPenDataViewWidget = SelectedPointsPlotWidget() addDock(u"Selected Data", self._selectedPenDataViewWidget) # ## Do Misc. GUI setup. # self.setWindowIcon(QtGui.QIcon(getIconFilePath('edit&32.png'))) self.statusBar().showMessage('Ready') self.updateAppTitle() self.resize(*DEFAULT_WIN_SIZE) @property def penDataTemporalPlotWidget(self): return self._penDataTimeLineWidget def updateAppTitle(self): if self._current_project is None: fileName = u'' else: fileName = self._current_project.name fileName = u'{0} : '.format(fileName) app_title = u'MarkWrite' full_title = u'{0}{1}'.format(fileName, app_title) self.setWindowTitle(full_title) def showAboutDialog(self): QtGui.QMessageBox.about(self, ABOUT_DIALOG_TITLE, ABOUT_DIALOG_TEXT) self.sender().enableAndDisableActions() def openFile(self): file_path = fileOpenDlg() if file_path: file_path = file_path[0] if len(file_path) > 0: try: wmproj = MarkWriteProject(file_path=file_path,mwapp=self) self.createSegmentAction.setEnabled(True) self.sigProjectChanged.emit(wmproj) self.sigResetProjectData.emit(wmproj) except: import traceback traceback.print_exc() ErrorDialog.info_text = u"An error occurred while " \ u"opening:\n%s\nMarkWrite will " \ u"now close." % ( file_path) ErrorDialog().display() self.closeEvent(u'FORCE_EXIT') def createPenSampleLevelReportFile(self): default_file_name = u"pen_samples_{0}.txt".format(self.project.name) file_path = fileSaveDlg(initFileName=default_file_name, prompt="Export Pen Sample Report") if file_path: PenSampleReportExporter().export(file_path, self.project) def createSegmentLevelReportFile(self): default_file_name = u"segments_{0}.txt".format(self.project.name) file_path = fileSaveDlg(initFileName=default_file_name, prompt="Export Segment Level Report") if file_path: SegmentLevelReportExporter().export(file_path, self.project) def exportCustomReport(self,reportcls): default_file_name = u"{}_{}.txt".format(reportcls.outputfileprefix(),self.project.name) file_path = fileSaveDlg(initFileName=default_file_name, prompt="Export %s"%(reportcls.reportlabel())) if file_path: reportcls().export(file_path, self.project) def createSegment(self): """ Displays the Create Segment dialog. If dialog is not cancelled and segment name length >0, then create a new segment and add to the projects segment list. :return: """ if self.createSegmentAction.isEnabled(): # Shrink timeline selection region to fit start and end time # of possible segment being created. selectedtimeperiod = self.project.selectedtimeperiod[:] pendata_ix_range = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(*selectedtimeperiod) if len(pendata_ix_range)>0: segmenttimeperiod = self.project.pendata['time'][pendata_ix_range] self.project.selectedtimeregion.setRegion(segmenttimeperiod) tag, ok = showSegmentNameDialog(self.predefinedtags) tag = unicode(tag).strip().replace('\t', "#") if len(tag) > 0 and ok: psid = self.project.getSelectedDataSegmentIDs()[0] new_segment = self.project.createSegmentFromSelectedPenData(tag, psid) self.handleSelectedPenDataUpdate(None,None) self.sigSegmentCreated.emit(new_segment) self.setActiveObject(new_segment) else: # If segment creation was cancelled or failed, then reset # timeline selection region to original time period. self.project.selectedtimeregion.setRegion(selectedtimeperiod) else: ErrorDialog.info_text = u"Segment Creation Failed.\nNo selected " \ u"pen data." ErrorDialog().display() def removeSegment(self): ConfirmAction.text = 'Delete Segment Confirmation' ConfirmAction.info_text = "Are you sure you want to <b>permanently deleted</b> the currently selected segment?" \ "<br><br>" \ "Any children of this segment will also be deleted." yes = ConfirmAction.display() if not yes: return segment = self.activeobject if segment and segment.parent is not None: seg_ix = segment.parent.getChildIndex(segment) # Decrement the pendata array 'segment_id' field for elements within # the segment being removed so that # of segments that contain each # pen point can be tracked allpendata = self.project.pendata segment_filter = (allpendata['time'] >= segment.starttime) & ( allpendata['time'] <= segment.endtime) allpendata['segment_id'][segment_filter] = segment.parent.id self.setActiveObject(self.project.selectedtimeregion) self.handleSelectedPenDataUpdate(None,None) self.sigSegmentRemoved.emit(segment, seg_ix) segment.parent.removeChild(segment) else: print " - Remove action IGNORED" print "<< removeSegment" def handleProjectChange(self, project): if self._current_project: pass self._current_project = project self.setActiveObject(self.project.selectedtimeregion) self.updateAppTitle() #self.saveProjectAction.setEnabled(project.modified) self.exportSampleReportAction.setEnabled(True) def zoomInTimeline(self): # TODO: Move method to _penDataTimeLineWidget self._penDataTimeLineWidget.getPlotItem().getViewBox().scaleBy(x=0.5) def zoomOutTimeline(self): # TODO: Move method to _penDataTimeLineWidget self._penDataTimeLineWidget.getPlotItem().getViewBox().scaleBy(x=2.0)#,center=(xmin+xmax)/2) def gotoSelectTimelinePeriod(self): # TODO: Move method to _penDataTimeLineWidget xmin, xmax , selpendat= self._penDataTimeLineWidget.currentSelection.selectedtimerangeanddata xpad = (xmax-xmin)/2 pdat=self.project.pendata rx=(max(0,xmin-xpad),min(xmax+xpad,self._penDataTimeLineWidget.maxTime)) if SETTINGS['timeplot_enable_ymouse']: ry = ( min(selpendat['x'].min(), selpendat['y'].min()), max(selpendat['x'].max(), selpendat['y'].max())) else: ry = (0, max(pdat['x'].max(),pdat['y'].max())) self._penDataTimeLineWidget.getPlotItem().setRange(xRange=rx, yRange=ry) def jumpTimeSelectionForward(self): # TODO: Move method to _penDataTimeLineWidget xmin, xmax = self.project.selectedtimeregion.getRegion() pendata_ix_range = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax) if len(pendata_ix_range): nix_min = pendata_ix_range[1]+1 if self.project.pendata['pressure'][nix_min]==0.0: start_ixs,stop_ixs,lengths=self.project.nonzero_region_ix next_starts = start_ixs[start_ixs>nix_min] if len(next_starts)>0: nix_min=next_starts[0] else: infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved forward.<br>Reason: NTs index not available.") return nxmin = self.project.pendata['time'][nix_min] nxmax = min(nxmin +(xmax-xmin), self.project.pendata['time'][-1]) if nxmin >= nxmax: infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved forward.<br>Reason: End of data reached.") return self.project.selectedtimeregion.setRegion([nxmin,nxmax]) (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange() if nxmax >= vmax: self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmax-vmax)*1.25) def jumpTimeSelectionBackward(self): # TODO: Move method to _penDataTimeLineWidget if 0: xmin, xmax = self.project.selectedtimeregion.getRegion() nxmax =xmin-0.001 nxmin = max(nxmax-(xmax-xmin),0.0) pendata_ix_range = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(nxmin,nxmax) if len(pendata_ix_range): segmenttimeperiod = self.project.pendata['time'][pendata_ix_range] self.project.selectedtimeregion.setRegion(segmenttimeperiod) (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange() if nxmin < vmin: self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmin-vmin)*1.25) else: xmin, xmax = self.project.selectedtimeregion.getRegion() pendata_ix_range = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax) if len(pendata_ix_range): nix_max = pendata_ix_range[0]-1 if nix_max<=0: infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved backward.<br>Reason: NTe index out of bounds.") return if self.project.pendata['pressure'][nix_max]==0.0: start_ixs,stop_ixs,lengths=self.project.nonzero_region_ix prev_stops = stop_ixs[stop_ixs<=nix_max] if len(prev_stops)>0: nix_max=prev_stops[-1] else: infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved backward.<br>Reason: NTe index not available.") return nxmax = self.project.pendata['time'][nix_max] nxmin = max(nxmax -(xmax-xmin), 0.0) if nxmin >= nxmax: infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved backward.<br>Reason: End of data reached.") return self.project.selectedtimeregion.setRegion([nxmin,nxmax]) (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange() if nxmin <= vmin: self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmin-vmin)*1.25) def increaseSelectionEndPointTime(self): # TODO: Move method to _penDataTimeLineWidget xmin, xmax = self.project.selectedtimeregion.getRegion() ix_bounds = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax) if len(ix_bounds)>0: min_ix, max_ix = ix_bounds start_ixs,stop_ixs,lengths=self.project.nonzero_region_ix next_max_ix = stop_ixs[stop_ixs>(max_ix+1)][0] #print "org_max_ix, new_max_ix",max_ix,next_max_ix #print 'new start , end samples: ',self.project.pendata[[min_ix, next_max_ix]] if next_max_ix < self.project.pendata.shape[0]: segmenttimeperiod = self.project.pendata['time'][[min_ix, next_max_ix]] min_ix, next_max_ix = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(*segmenttimeperiod) self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, next_max_ix]]) _,nxmax=segmenttimeperiod (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange() if nxmax >= vmax: self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmax-vmax)*1.25) else: infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be extended<br>as it is at the end of the data samples.") def decreaseSelectionEndPointTime(self): # TODO: Move method to _penDataTimeLineWidget xmin, xmax = self.project.selectedtimeregion.getRegion() ix_bounds = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax) if len(ix_bounds)>0: min_ix, max_ix = ix_bounds if np.all(self.project.nonzero_pressure_mask[min_ix:max_ix]): self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, max_ix]]) return start_ixs, stop_ixs, lengths=self.project.nonzero_region_ix prev_maxs = stop_ixs[stop_ixs<max_ix] if prev_maxs.shape[0]>0: if prev_maxs[-1] > min_ix: prev_max_ix = prev_maxs[-1] segmenttimeperiod = self.project.pendata['time'][[min_ix, prev_max_ix]] min_ix, max_ix = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(*segmenttimeperiod) self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, max_ix]]) else: infoDlg(title=u"Action Aborted", prompt=u"The end time of the selected time period can not be decreased further<br>without it being equal to the selected periods start time.") def increaseSelectionStartPointTime(self): # TODO: Move method to _penDataTimeLineWidget xmin, xmax = self.project.selectedtimeregion.getRegion() ix_bounds = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax) if len(ix_bounds)>0: min_ix, max_ix = ix_bounds if np.all(self.project.nonzero_pressure_mask[min_ix:max_ix]): self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, max_ix]]) return start_ixs,stop_ixs,lengths=self.project.nonzero_region_ix higher_starts=start_ixs[start_ixs>(min_ix)] if len(higher_starts)==0: infoDlg(title=u"Action Aborted", prompt=u"The start time of the selected time period can not be increased<br> any further; it is the last IPS run of the file.") elif higher_starts[0]>=max_ix-1: infoDlg(title=u"Action Aborted", prompt=u"The start time of the selected time period can not be further increased<br> without it exceeding the selected periods end time.") else: segmenttimeperiod = self.project.pendata['time'][[higher_starts[0], max_ix]] self.project.selectedtimeregion.setRegion(segmenttimeperiod) def decreaseSelectionStartPointTime(self): # TODO: Move method to _penDataTimeLineWidget xmin, xmax = self.project.selectedtimeregion.getRegion() ix_bounds = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax) if len(ix_bounds)>0: min_ix, max_ix = ix_bounds start_ixs, stop_ixs, lengths=self.project.nonzero_region_ix prev_starts = start_ixs[start_ixs<min_ix] if len(prev_starts)>0 and prev_starts[-1] >= 0: prev_start_ix = prev_starts[-1] segmenttimeperiod = self.project.pendata['time'][[prev_start_ix, max_ix]] min_ix, max_ix = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(*segmenttimeperiod) self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, max_ix]]) nxmin,_=segmenttimeperiod (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange() if nxmin < vmin: self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmin-vmin)*1.25) def handleSelectedPenDataUpdate(self, timeperiod, pendata): #print '>> App.handleSelectedPenDataUpdate:',timeperiod self.createSegmentAction.setEnabled( self.project and self.project.isSelectedDataValidForNewSegment()) #print '<< App.handleSelectedPenDataUpdate' def handleDisplayAppSettingsDialogEvent(self): usersettings = readPickle(self._appdirs.user_config_dir,u'usersettings.pkl') updatedsettings, allsettings, savestate, ok = ProjectSettingsDialog.getProjectSettings(self, usersettings) if ok is True: writePickle(self._appdirs.user_config_dir,u'usersettings.pkl', savestate) if self.project and len(updatedsettings)>0: self.sigAppSettingsUpdated.emit(updatedsettings, allsettings) def closeEvent(self, event): if event == u'FORCE_EXIT': QtCore.QCoreApplication.instance().quit() return exitapp = ExitApplication.display() if exitapp: pass if event: event.accept() else: QtCore.QCoreApplication.instance().quit() else: if event: event.ignore() def __del__(self): pass
def setupGUI(self, app): ''' :return: ''' # ## Create Main GUI Menu Bar # menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(self.openFileAction) #fileMenu.addAction(self.saveProjectAction) fileMenu.addAction(self.showProjectSettingsDialogAction) fileMenu.addSeparator() exportMenu = fileMenu.addMenu("&Export") exportMenu.addAction(self.exportSampleReportAction) exportMenu.addAction(self.exportSegmentReportAction) exportMenu.addSeparator() self.customReportActions=[] for custom_report in custom_report_classes: a = exportMenu.addAction(custom_report.reportlabel(), lambda: self.exportCustomReport(custom_report)) a.setEnabled(False) self.customReportActions.append(a) self.exportSampleReportAction.enableActionsList.append(a) fileMenu.addSeparator() fileMenu.addAction(self.exitAction) segmentMenu = menubar.addMenu('&Segment') segmentMenu.addAction(self.createSegmentAction) segmentMenu.addAction(self.removeSegmentAction) helpMenu = menubar.addMenu('&Help') helpMenu.addAction(self.aboutAction) self.toolbarFile = self.addToolBar('File') self.toolbarFile.addAction(self.openFileAction) #self.toolbarFile.addAction(self.saveProjectAction) self.toolbarFile.addAction(self.showProjectSettingsDialogAction) self.toolbarFile.addAction(self.exportSampleReportAction) self.toolbarFile.addAction(self.exportSegmentReportAction) self.toolbarsegment = self.addToolBar('Segment') self.toolbarsegment.addAction(self.createSegmentAction) self.toolbarsegment.addAction(self.removeSegmentAction) self.toolbartimelineview = self.addToolBar('Timeline View') self.toolbartimelineview.addAction(self.zoomInTimelineAction) self.toolbartimelineview.addAction(self.zoomOutTimelineAction) self.toolbarsegment = self.addToolBar('Timeline Selection') self.toolbarsegment.addAction(self.gotoSelectedTimePeriodAction) self.toolbarsegment.addAction(self.decreaseSelectionStartPointAction) self.toolbarsegment.addAction(self.increaseSelectionStartPointAction) self.toolbarsegment.addAction(self.backwardSelectionAction) self.toolbarsegment.addAction(self.forwardSelectionAction) self.toolbarsegment.addAction(self.decreaseSelectionEndPointAction) self.toolbarsegment.addAction(self.increaseSelectionEndPointAction) self.toolbarHelp = self.addToolBar('Help') self.toolbarHelp.addAction(self.aboutAction) # ## Create App Dock Area # self._dockarea = DockArea() self.setCentralWidget(self._dockarea) # Enable antialiasing for prettier plots pg.setConfigOptions(antialias=True) # Create Docking Layout def addDock(name, inner_widget=None): ww, wh = DEFAULT_WIN_SIZE dpos, (dw, dh) = DEFAULT_DOCK_PLACEMENT[name] if isinstance(dpos, basestring): self._dockarea.addDock(Dock(name, size=[ww * dw, wh * dh]), dpos) else: self._dockarea.addDock(Dock(name, size=[ww * dw, wh * dh]), dpos[0], self._dockarea.docks[dpos[1]]) if inner_widget: self._dockarea.docks[name].addWidget(inner_widget) from markwrite.gui.selecteddataview import SelectedPointsPlotWidget from markwrite.gui.spatialview import PenDataSpatialPlotWidget from markwrite.gui.timelineplot import PenDataTemporalPlotWidget from markwrite.gui.segmenttree import SegmentInfoDockArea self._segmenttree = SegmentInfoDockArea() addDock(u"Segment Tree", self._segmenttree) self._penDataTimeLineWidget = PenDataTemporalPlotWidget() self._penDataSpatialViewWidget = PenDataSpatialPlotWidget() addDock(u"Timeline", self._penDataTimeLineWidget) addDock(u"Spatial View", self._penDataSpatialViewWidget) self._selectedPenDataViewWidget = SelectedPointsPlotWidget() addDock(u"Selected Data", self._selectedPenDataViewWidget) # ## Do Misc. GUI setup. # self.setWindowIcon(QtGui.QIcon(getIconFilePath('edit&32.png'))) self.statusBar().showMessage('Ready') self.updateAppTitle() self.resize(*DEFAULT_WIN_SIZE)