def __init__(self): QWidget.__init__(self) self.title = u"执行" # View RunDef self.__wid_run_def = ViewRunDef() # View ReportDet self.__wid_report_det = ViewReportDet() # Search condition widget self.__wid_search_cond = ViewSearch(def_view_run_def) self.__wid_search_cond.create() # 底部 layout _layout_bottom = QSplitter() _layout_bottom.addWidget(self.__wid_run_def) _layout_bottom.addWidget(self.__wid_report_det) # main layout _layout = QVBoxLayout() _layout.addWidget(self.__wid_search_cond) _layout.addWidget(_layout_bottom) _layout.setContentsMargins(0, 0, 0, 0) self.setLayout(_layout) self.__wid_run_def.sig_search.connect(self.search) self.__wid_run_def.sig_selected.connect( self.__wid_report_det.usr_refresh)
def __init__(self, parent=None): """Create Qt widgets, connect event handlers.""" super(App, self).__init__(parent) self.windowTitle = 'DMD | ' self.fileName = '' self.setWindowTitle(self.windowTitle + 'Unsaved File') exitAction = QAction('Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.close) openAction = QAction('Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open Markdown File') openAction.triggered.connect(self.openFile) newAction = QAction('New', self) newAction.setShortcut('Ctrl+N') newAction.setStatusTip('New Markdown File') newAction.triggered.connect(self.newFile) saveAction = QAction('Save', self) saveAction.setShortcut('Ctrl+S') saveAction.setStatusTip('Save File') saveAction.triggered.connect(self.saveFile) self.statusBar() menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(newAction) fileMenu.addAction(openAction) fileMenu.addAction(saveAction) fileMenu.addAction(exitAction) self.setGeometry(300, 300, 1024, 768) self.show() self.txtInput = QTextEdit() self.txtInput.setTabStopWidth(20) self.webPreview = QWebView() self.webPreview.setHtml('Start typing...', baseUrl=QUrl('preview')) self.txtInput.textChanged.connect(self.loadPreview) splitter = QSplitter() splitter.addWidget(self.txtInput) splitter.addWidget(self.webPreview) self.setCentralWidget(splitter)
def setCanvas(self): ''' set widgets for a tab page - left side show image of current frame - right side show two plots: raw and rms - bot: button to edit triggers and slider to adjust video-emg offset ''' ######################## # set matplotlib plots # ######################## self.fig = Figure(dpi=70) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.ui.mainFrame) self.axes = self.fig.add_subplot(211) self.axesRMS = self.fig.add_subplot(212) self.mpl_toolbar = NavigationToolbar2(self.canvas, self.ui.mainFrame) self.canvas.mpl_connect('draw_event', self.onDraw) #################################### # add button to matplotlib toolbar # #################################### redb = QPushButton('Edit Triggers') redb.setCheckable(True) self.mpl_toolbar.addWidget(redb) redb.clicked[bool].connect(self.toggleEditMode) # container for current frame of video layout = pq.GraphicsLayoutWidget() vb = layout.addViewBox() vb.setAspectLocked(True) self.ri = pq.ImageItem() vb.addItem(self.ri) # layout to organize elements grid = QGridLayout() wrapper = QWidget() vbox = QVBoxLayout(wrapper) splitter = QSplitter() vbox.addWidget(self.canvas) vbox.addWidget(self.mpl_toolbar) wrapper.setLayout(vbox) splitter.addWidget(layout) splitter.addWidget(wrapper) grid.addWidget(splitter) self.ri.show() layout.show() self.ui.mainFrame.setLayout(grid)
def __init__(self, options, parent=None): QWidget.__init__(self, parent) # Variables self._options = options # Widgets self._lbl_title = QLabel("Untitled") font = self._lbl_title.font() font.setBold(True) font.setPointSize(14) self._lbl_title.setFont(font) self._lbl_subtitle = QLabel("") font = self._lbl_subtitle.font() font.setItalic(True) font.setPointSize(14) self._lbl_subtitle.setFont(font) # Layouts layout = QVBoxLayout() sublayout = QHBoxLayout() sublayout.addWidget(self._lbl_title) sublayout.addStretch() sublayout.addWidget(self._lbl_subtitle) layout.addLayout(sublayout) wdglayout = QVBoxLayout() wdglayout.addLayout(self._initUI(), 1) wdglayout.addWidget(self._initToolbar()) toolbox = self._initToolbox() if toolbox.count() == 0: layout.addLayout(wdglayout) else: wdg_dummy = QWidget() wdg_dummy.setLayout(wdglayout) splitter = QSplitter() splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) splitter.addWidget(wdg_dummy) splitter.addWidget(toolbox) splitter.setCollapsible(0, False) splitter.setCollapsible(1, True) layout.addWidget(splitter) self.setLayout(layout)
def setup_ui(self): splitter = QSplitter(self) left = QWidget(splitter) left.setLayout(QVBoxLayout(left)) left.layout().addWidget(QLabel('QTableView', left)) tableview = QTableView(left) tableview.setModel(TableModel(tableview)) left.layout().addWidget(tableview) splitter.addWidget(left) right = QWidget(splitter) right.setLayout(QVBoxLayout(right)) right.layout().addWidget(QLabel('QTableWidget', right)) # create a table widget for DATA tablewidget = QTableWidget(len(DATA), len(DATA[1]), right) right.layout().addWidget(tablewidget) splitter.addWidget(right) self.setCentralWidget(splitter) # add tablewidget data self.add_data(tablewidget)
def __init__(self, *args, **kwargs): super(Widget_textEdit_splitter, self).__init__(*args, **kwargs) self.installEventFilter(self) mainLayout = QVBoxLayout(self) w_convertButton = QWidget() lay_convertButton = QHBoxLayout(w_convertButton) label_orig = QLabel("Original") label_orig.setAlignment(QtCore.Qt.AlignCenter) label_convert = QLabel("Converted") label_convert.setAlignment(QtCore.Qt.AlignCenter) button = QPushButton(" >> ") lay_convertButton.addWidget(label_orig) lay_convertButton.addWidget(button) lay_convertButton.addWidget(label_convert) w_convertButton.setStyleSheet("font-size:13px") sizePolicy = QSizePolicy() sizePolicy.setVerticalPolicy(QSizePolicy.Fixed) sizePolicy.setHorizontalPolicy(QSizePolicy.Expanding) w_convertButton.setSizePolicy(sizePolicy) splitter = QSplitter() splitter.setStretchFactor(1, 1) textEdit_left = QTextEdit() textEdit_right = QTextEdit() splitter.addWidget(textEdit_left) splitter.addWidget(textEdit_right) textEdit_left.setLineWrapMode(QTextEdit.NoWrap) textEdit_right.setLineWrapMode(QTextEdit.NoWrap) mainLayout.addWidget(w_convertButton) mainLayout.addWidget(splitter) self.textEdit_left = textEdit_left self.textEdit_right = textEdit_right button.clicked.connect(self.load_convertedText)
def __init__(self): super(Window, self).__init__() self.glWidget = GLWidget() renderarea = QSplitter(Qt.Vertical) renderarea.addWidget(self.glWidget) self.dummy_object = QLabel("wat") mainlayout = QVBoxLayout() splitter = QSplitter() splitter.addWidget(renderarea) splitter.addWidget(self.dummy_object) mainlayout.addWidget(splitter) self.setLayout(mainlayout) self.setWindowTitle("Hello GL")
def __init__(self): QMainWindow.__init__(self) self.resize(800, 600) self.setWindowTitle('PDF Merger') about = QAction('About', self) self.connect(about, SIGNAL('triggered()'), self.show_about) exit = QAction('Exit', self) exit.setShortcut('Ctrl+Q') self.connect(exit, SIGNAL('triggered()'), SLOT('close()')) self.statusBar() menubar = self.menuBar() file = menubar.addMenu('File') file.addAction(about) file.addAction(exit) self.main_widget = QWidget(self) self.setCentralWidget(self.main_widget) self.up_down_widget = QWidget(self) self.options_widget = QWidget(self) input_files_label = QLabel( "Input PDFs\nThis is the order in which the files will be merged too" ) self.files_list = QListWidget() self.files_list.setSelectionMode(QAbstractItemView.ExtendedSelection) add_button = QPushButton("Add PDF(s) to merge...") add_button.clicked.connect(self.clicked_add) up_button = QPushButton("Up") up_button.clicked.connect(self.move_file_up) down_button = QPushButton("Down") down_button.clicked.connect(self.move_file_down) remove_button = QPushButton("Remove PDF") remove_button.clicked.connect(self.remove_file) select_path_label = QLabel("Output PDF") self.dest_path_edit = QLineEdit() self.dest_path_edit.setReadOnly(True) select_path = QPushButton("Select...") select_path.clicked.connect(self.select_save_path) start = QPushButton("Start") start.clicked.connect(self.merge_pdf) up_down_vbox = QVBoxLayout(self.up_down_widget) up_down_vbox.addWidget(up_button) up_down_vbox.addWidget(down_button) up_down_vbox.addWidget(remove_button) self.up_down_widget.setLayout(up_down_vbox) group_input = QGroupBox() grid_input = QGridLayout() grid_input.addWidget(add_button, 0, 0) grid_input.addWidget(input_files_label, 1, 0) grid_input.addWidget(self.files_list, 2, 0) grid_input.addWidget(self.up_down_widget, 2, 1) group_input.setLayout(grid_input) group_output = QGroupBox() grid_output = QGridLayout() grid_output.addWidget(select_path_label, 0, 0) grid_output.addWidget(self.dest_path_edit, 1, 0) grid_output.addWidget(select_path, 1, 1) group_output.setLayout(grid_output) vbox_options = QVBoxLayout(self.options_widget) vbox_options.addWidget(group_input) vbox_options.addWidget(group_output) vbox_options.addWidget(start) self.options_widget.setLayout(vbox_options) splitter_filelist = QSplitter() splitter_filelist.setOrientation(Qt.Vertical) splitter_filelist.addWidget(self.options_widget) vbox_main = QVBoxLayout(self.main_widget) vbox_main.addWidget(splitter_filelist) vbox_main.setContentsMargins(0, 0, 0, 0)
def createElements(self): """ Creates the widgets and docks of which the main window is composed. """ self.mainWindow = QMainWindow() projectController = ProjectController.Instance() self.transformTool = None # Render widgets self.fixedDataWidget = RenderWidget() self.movingDataWidget = RenderWidget() self.multiDataWidget = MultiRenderWidget() self.fixedRenderController = RenderController(self.fixedDataWidget, "fixed") self.movingRenderController = RenderController(self.movingDataWidget, "moving") self.multiRenderController = MultiRenderController( self.multiDataWidget) # Give references of the render controllers to the project controller projectController.fixedRenderController = self.fixedRenderController projectController.movingRenderController = self.movingRenderController projectController.multiRenderController = self.multiRenderController # Render properties widgets sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(1) self.fixedPropWidget = RenderPropWidget(self.fixedRenderController, parent=self) self.fixedPropWidget.setSizePolicy(sizePolicy) self.fixedPropWidget.setFileChangedSignal( projectController.fixedFileChanged) self.fixedPropWidget.setLoadDataSlot(self.loadFixedDataSetFile) self.movingPropWidget = RenderPropWidget(self.movingRenderController, parent=self) self.movingPropWidget.setSizePolicy(sizePolicy) self.movingPropWidget.setFileChangedSignal( projectController.movingFileChanged) self.movingPropWidget.setLoadDataSlot(self.loadMovingDataSetFile) self.multiPropWidget = MultiRenderPropWidget( self.multiRenderController, parent=self) self.multiPropWidget.setSizePolicy(sizePolicy) self.verticalSplitter = QSplitter() self.verticalSplitter.setOrientation(Qt.Vertical) # Create the layouts fixedDataTitleWidget = TitleWidget("Fixed volume") multiDataTitleWidget = TitleWidget("Fixed + Moving") movingDataTitleWidget = TitleWidget("Moving volume") fixedLayout = QGridLayout() fixedLayout.setSpacing(0) fixedLayout.setContentsMargins(0, 0, 0, 0) fixedLayout.addWidget(fixedDataTitleWidget) fixedLayout.addWidget(self.fixedDataWidget) fixedWidget = QWidget() fixedWidget.setLayout(fixedLayout) multiLayout = QGridLayout() multiLayout.setSpacing(0) multiLayout.setContentsMargins(0, 0, 0, 0) multiLayout.addWidget(multiDataTitleWidget) multiLayout.addWidget(self.multiDataWidget) multiWidget = QWidget() multiWidget.setLayout(multiLayout) movingLayout = QGridLayout() movingLayout.setSpacing(0) movingLayout.setContentsMargins(0, 0, 0, 0) movingLayout.addWidget(movingDataTitleWidget) movingLayout.addWidget(self.movingDataWidget) movingWidget = QWidget() movingWidget.setLayout(movingLayout) horizontalSplitter = QSplitter() horizontalSplitter.setOrientation(Qt.Horizontal) horizontalSplitter.addWidget(fixedWidget) horizontalSplitter.addWidget(multiWidget) horizontalSplitter.addWidget(movingWidget) propsLayout = QHBoxLayout() propsLayout.setSpacing(1) propsLayout.setContentsMargins(0, 0, 0, 0) propsLayout.addWidget(self.fixedPropWidget) propsLayout.addWidget(self.multiPropWidget) propsLayout.addWidget(self.movingPropWidget) propsWidget = QWidget() propsWidget.setMinimumHeight(245) propsWidget.setMaximumHeight(350) propsWidget.setLayout(propsLayout) self.verticalSplitter.addWidget(horizontalSplitter) self.verticalSplitter.addWidget(propsWidget) self.verticalSplitter.setStretchFactor(0, 2) self.verticalSplitter.setStretchFactor(1, 1) self.setCentralWidget(self.verticalSplitter)
def __init__(self): QMainWindow.__init__(self) self.resize(800,600) self.setWindowTitle('PDF Merger') about = QAction('About', self) self.connect(about, SIGNAL('triggered()'), self.show_about) exit = QAction('Exit', self) exit.setShortcut('Ctrl+Q') self.connect(exit, SIGNAL('triggered()'), SLOT('close()')) self.statusBar() menubar = self.menuBar() file = menubar.addMenu('File') file.addAction(about) file.addAction(exit) self.main_widget = QWidget(self) self.setCentralWidget(self.main_widget) self.up_down_widget = QWidget(self) self.options_widget = QWidget(self) input_files_label = QLabel("Input PDFs\nThis is the order in which the files will be merged too") self.files_list = QListWidget() self.files_list.setSelectionMode(QAbstractItemView.ExtendedSelection) add_button = QPushButton("Add PDF(s) to merge...") add_button.clicked.connect(self.clicked_add) up_button = QPushButton("Up") up_button.clicked.connect(self.move_file_up) down_button = QPushButton("Down") down_button.clicked.connect(self.move_file_down) remove_button = QPushButton("Remove PDF") remove_button.clicked.connect(self.remove_file) select_path_label = QLabel("Output PDF") self.dest_path_edit = QLineEdit() self.dest_path_edit.setReadOnly(True) select_path = QPushButton("Select...") select_path.clicked.connect(self.select_save_path) start = QPushButton("Start") start.clicked.connect(self.merge_pdf) up_down_vbox = QVBoxLayout(self.up_down_widget) up_down_vbox.addWidget(up_button) up_down_vbox.addWidget(down_button) up_down_vbox.addWidget(remove_button) self.up_down_widget.setLayout(up_down_vbox) group_input = QGroupBox() grid_input = QGridLayout() grid_input.addWidget(add_button, 0, 0) grid_input.addWidget(input_files_label, 1, 0) grid_input.addWidget(self.files_list, 2, 0) grid_input.addWidget(self.up_down_widget, 2, 1) group_input.setLayout(grid_input) group_output = QGroupBox() grid_output = QGridLayout() grid_output.addWidget(select_path_label, 0, 0) grid_output.addWidget(self.dest_path_edit, 1, 0) grid_output.addWidget(select_path, 1, 1) group_output.setLayout(grid_output) vbox_options = QVBoxLayout(self.options_widget) vbox_options.addWidget(group_input) vbox_options.addWidget(group_output) vbox_options.addWidget(start) self.options_widget.setLayout(vbox_options) splitter_filelist = QSplitter() splitter_filelist.setOrientation(Qt.Vertical) splitter_filelist.addWidget(self.options_widget) vbox_main = QVBoxLayout(self.main_widget) vbox_main.addWidget(splitter_filelist) vbox_main.setContentsMargins(0,0,0,0)
class RegistrationShop(MainWindow, WindowDialog): """ Main class that starts up the application. Creates UI and starts project/plugin managers. """ def __init__(self, args): """ Sets app specific properties. Initializes the UI. """ super(RegistrationShop, self).__init__(args) self.setApplicationPath() # Instantiate the project controller ProjectController.Instance() # Initialize the user interface self.initUI() lastProject = RegistrationShop.settings.value("project/lastProject", None) if lastProject: self.openProject(lastProject) def initialize(self): # Initialize the render window interactors only after calling show() # otherwise OpenGL errors will occur on OS X self.fixedDataWidget.rwi.Initialize() self.movingDataWidget.rwi.Initialize() self.multiDataWidget.rwi.Initialize() # UI setup methods def initUI(self): """ Initializes the UI. Makes sure previous state of application is restored. """ # Create actions and elements self.createElements() self.connectElements() self.createActions() self.createMenus() self.createToolbar() self.restoreState() # Set some window/application properties self.setUnifiedTitleAndToolBarOnMac(True) self.setWindowTitle(APPNAME) self.setWindowState(Qt.WindowActive) def createElements(self): """ Creates the widgets and docks of which the main window is composed. """ self.mainWindow = QMainWindow() projectController = ProjectController.Instance() self.transformTool = None # Render widgets self.fixedDataWidget = RenderWidget() self.movingDataWidget = RenderWidget() self.multiDataWidget = MultiRenderWidget() self.fixedRenderController = RenderController(self.fixedDataWidget, "fixed") self.movingRenderController = RenderController(self.movingDataWidget, "moving") self.multiRenderController = MultiRenderController( self.multiDataWidget) # Give references of the render controllers to the project controller projectController.fixedRenderController = self.fixedRenderController projectController.movingRenderController = self.movingRenderController projectController.multiRenderController = self.multiRenderController # Render properties widgets sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(1) self.fixedPropWidget = RenderPropWidget(self.fixedRenderController, parent=self) self.fixedPropWidget.setSizePolicy(sizePolicy) self.fixedPropWidget.setFileChangedSignal( projectController.fixedFileChanged) self.fixedPropWidget.setLoadDataSlot(self.loadFixedDataSetFile) self.movingPropWidget = RenderPropWidget(self.movingRenderController, parent=self) self.movingPropWidget.setSizePolicy(sizePolicy) self.movingPropWidget.setFileChangedSignal( projectController.movingFileChanged) self.movingPropWidget.setLoadDataSlot(self.loadMovingDataSetFile) self.multiPropWidget = MultiRenderPropWidget( self.multiRenderController, parent=self) self.multiPropWidget.setSizePolicy(sizePolicy) self.verticalSplitter = QSplitter() self.verticalSplitter.setOrientation(Qt.Vertical) # Create the layouts fixedDataTitleWidget = TitleWidget("Fixed volume") multiDataTitleWidget = TitleWidget("Fixed + Moving") movingDataTitleWidget = TitleWidget("Moving volume") fixedLayout = QGridLayout() fixedLayout.setSpacing(0) fixedLayout.setContentsMargins(0, 0, 0, 0) fixedLayout.addWidget(fixedDataTitleWidget) fixedLayout.addWidget(self.fixedDataWidget) fixedWidget = QWidget() fixedWidget.setLayout(fixedLayout) multiLayout = QGridLayout() multiLayout.setSpacing(0) multiLayout.setContentsMargins(0, 0, 0, 0) multiLayout.addWidget(multiDataTitleWidget) multiLayout.addWidget(self.multiDataWidget) multiWidget = QWidget() multiWidget.setLayout(multiLayout) movingLayout = QGridLayout() movingLayout.setSpacing(0) movingLayout.setContentsMargins(0, 0, 0, 0) movingLayout.addWidget(movingDataTitleWidget) movingLayout.addWidget(self.movingDataWidget) movingWidget = QWidget() movingWidget.setLayout(movingLayout) horizontalSplitter = QSplitter() horizontalSplitter.setOrientation(Qt.Horizontal) horizontalSplitter.addWidget(fixedWidget) horizontalSplitter.addWidget(multiWidget) horizontalSplitter.addWidget(movingWidget) propsLayout = QHBoxLayout() propsLayout.setSpacing(1) propsLayout.setContentsMargins(0, 0, 0, 0) propsLayout.addWidget(self.fixedPropWidget) propsLayout.addWidget(self.multiPropWidget) propsLayout.addWidget(self.movingPropWidget) propsWidget = QWidget() propsWidget.setMinimumHeight(245) propsWidget.setMaximumHeight(350) propsWidget.setLayout(propsLayout) self.verticalSplitter.addWidget(horizontalSplitter) self.verticalSplitter.addWidget(propsWidget) self.verticalSplitter.setStretchFactor(0, 2) self.verticalSplitter.setStretchFactor(1, 1) self.setCentralWidget(self.verticalSplitter) def connectElements(self): """ All the elements have to be connected because they are dependent on each other. There is the project controller, two render controllers and a multi render controller. Also there are two render widgets and a multi render widget. Together with some parameter widgets that show settings and with which the user can interact. """ projectController = ProjectController.Instance() projectController.fixedFileChanged.connect( self.fixedRenderController.setFile) projectController.fixedFileChanged.connect( self.multiRenderController.setFixedFile) projectController.movingFileChanged.connect( self.movingRenderController.setFile) projectController.movingFileChanged.connect( self.multiRenderController.setMovingFile) projectController.fixedSettingsChanged.connect( self.fixedRenderController.setRenderSettings) projectController.movingSettingsChanged.connect( self.movingRenderController.setRenderSettings) projectController.multiSettingsChanged.connect( self.multiRenderController.setRenderSettings) self.fixedRenderController.visualizationChanged.connect( self.multiRenderController.setFixedVisualization) self.fixedRenderController.visualizationUpdated.connect( self.multiRenderController.setFixedVisualization) self.movingRenderController.visualizationChanged.connect( self.multiRenderController.setMovingVisualization) self.movingRenderController.visualizationUpdated.connect( self.multiRenderController.setMovingVisualization) self.multiDataWidget.transformations.transformationChanged.connect( self.movingDataWidget.transformationsUpdated) def createActions(self): """ Create actions that can be attached to buttons and menus. """ userTransformIconName = AppResources.imageNamed( 'UserTransformButton.png') landmarkTransformIconName = AppResources.imageNamed( 'LandmarkTransformButton.png') deformableTransformIconName = AppResources.imageNamed( 'DeformableTransformButton.png') compareIconName = AppResources.imageNamed('CompareButton.png') helpIconName = AppResources.imageNamed('HelpButton.png') self.actionFreeTransformTool = QAction('Manual transform', self, shortcut='Ctrl+1') self.actionFreeTransformTool.setIcon(QIcon(userTransformIconName)) self.actionFreeTransformTool.triggered.connect(self.addManualTransform) self.actionLandmarkTransformTool = QAction('Landmark transform', self, shortcut='Ctrl+2') self.actionLandmarkTransformTool.setIcon( QIcon(landmarkTransformIconName)) self.actionLandmarkTransformTool.triggered.connect( self.addLandmarkTransform) self.actionDeformableTransformTool = QAction('Automatic transform', self, shortcut='Ctrl+3') self.actionDeformableTransformTool.setIcon( QIcon(deformableTransformIconName)) self.actionDeformableTransformTool.triggered.connect( self.addDeformableTransform) self.actionLoadFixedData = QAction('Load fixed data', self, shortcut='Ctrl+Shift+F') self.actionLoadFixedData.triggered.connect(self.loadFixedDataSetFile) self.actionLoadMovingData = QAction('Load moving data', self, shortcut='Ctrl+Shift+M') self.actionLoadMovingData.triggered.connect(self.loadMovingDataSetFile) self.actionSaveProject = QAction('Save project', self, shortcut='Ctrl+S') self.actionSaveProject.triggered.connect(self.saveProject) self.actionSaveProjectAs = QAction('Save project as...', self, shortcut='Ctrl+Shift+S') self.actionSaveProjectAs.triggered.connect(self.saveProjectAs) self.actionExportDataAs = QAction('Export data...', self, shortcut='Ctrl+E') self.actionExportDataAs.triggered.connect(self.exportDataAs) self.actionOpenProject = QAction('Open project...', self, shortcut='Ctrl+O') self.actionOpenProject.triggered.connect(self.openProject) self.actionNewProject = QAction('New project', self, shortcut='Ctrl+N') self.actionNewProject.triggered.connect(self.newProject) self.actionCompare = QAction('Compare', self, shortcut='Ctrl+U') self.actionCompare.setIcon(QIcon(compareIconName)) self.actionCompare.triggered.connect(self.startComparison) self.actionHelp = QAction('Help', self, shortcut='Ctrl+H') self.actionHelp.setIcon(QIcon(helpIconName)) self.actionHelp.triggered.connect(self.showHelp) def createMenus(self): """ Creates menus from actions. """ self.menuBar = self.menuBar() self.menuItemFile = self.menuBar.addMenu('&File') self.menuItemFile.addAction(self.actionNewProject) self.menuItemFile.addAction(self.actionOpenProject) # TODO: Open recent > self.menuItemFile.addAction(self.actionSaveProject) self.menuItemFile.addAction(self.actionSaveProjectAs) self.menuItemFile.addAction(self.actionExportDataAs) self.menuItemProject = self.menuBar.addMenu('&Project') self.menuItemProject.addAction(self.actionLoadFixedData) self.menuItemProject.addAction(self.actionLoadMovingData) self.menuItemProject.addSeparator() def createToolbar(self): """ Creates the main toolbar and sets the toolbar buttons. """ # Add toolbar self.toolbar = self.addToolBar('Main tools') self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.toolbar.setAllowedAreas(Qt.TopToolBarArea) self.toolbar.setFloatable(False) self.toolbar.setMovable(False) # Create custom toolbar widget that can align items left, center and right self.toolbarWidget = ToolbarWidget() self.toolbarWidget.addActionLeft(self.actionFreeTransformTool) self.toolbarWidget.addActionLeft(self.actionLandmarkTransformTool) self.toolbarWidget.addActionLeft(self.actionDeformableTransformTool) statusWidget = StatusWidget.Instance() statusWidget.setText( "Welcome to RegistrationShop!\nStart your registration by loading two datasets. " + "After that you can use the transform tools to align your volume data." ) self.toolbarWidget.addCenterItem(statusWidget) # Add help button self.toolbarWidget.addActionRight(self.actionCompare) self.toolbarWidget.addActionRight(self.actionHelp) self.toolbar.addWidget(self.toolbarWidget) # Private Functions def setApplicationPath(self): """ Finds the path to the application. This is done so that it can figure out where certain resources are located. QCoreApplication::applicationDirPath() on OS X does not return the desired path to the actual application but to the python executable in /Library/FrameWorks. This is inconvenient because images can't be located that way. So instead os.path is used to find the location of this __file__. """ AppVars.setPath(os.path.dirname(os.path.abspath(__file__))) # Action callbacks @Slot() def addManualTransform(self): """ What happens when manual transform is added: * Entry is added to the tab history * Translation fields * Rotation fields * Scale field(s) * Transform box is added to the render widget * Button with apply (will apply the transform to the data) Applying the transform to the data means: * Create new dataset from transformed data * Save this data to the project folder * Read in the new data and update this in the multi render widget * this would mean a new data model for the multi render widget """ if not self.movingDataWidget.imageData: statusWidget = StatusWidget.Instance() statusWidget.setText( "Please load a moving dataset before starting a manual transform." ) return if self.transformTool is not None: self.transformTool.cleanUp() self.transformTool = UserTransformationTool() self.transformTool.setRenderWidgets(moving=self.movingDataWidget, multi=self.multiDataWidget) self.multiPropWidget.setTransformTool(self.transformTool) self.transformTool.toolFinished.connect(self.transformToolFinished) @Slot() def addLandmarkTransform(self): if not self.fixedDataWidget.imageData or not self.movingDataWidget.imageData: statusWidget = StatusWidget.Instance() statusWidget.setText( "Please load a fixed and a moving dataset before starting a landmark transform." ) return # Clean up the last transform tool if self.transformTool is not None: self.transformTool.cleanUp() self.transformTool = LandmarkTransformationTool() self.transformTool.setRenderWidgets(fixed=self.fixedDataWidget, moving=self.movingDataWidget, multi=self.multiDataWidget) # Create a tab page under the fixed render widget fixedLandmarkWidget = LandmarkWidget() self.fixedPropWidget.addTabWidget(fixedLandmarkWidget, "Landmark") # Create a tab page under the moving render widget movingLandmarkWidget = LandmarkWidget() self.movingPropWidget.addTabWidget(movingLandmarkWidget, "Landmark") # Make sure the landmark transform tool knows of these tab widgets self.transformTool.setLandmarkWidgets(fixedLandmarkWidget, movingLandmarkWidget) # Start the transformation self.multiPropWidget.setTransformTool(self.transformTool) self.transformTool.toolFinished.connect(self.transformToolFinished) @Slot() def addDeformableTransform(self): if not self.fixedDataWidget.imageData or not self.movingDataWidget.imageData: statusWidget = StatusWidget.Instance() statusWidget.setText( "Please load a fixed and a moving dataset before starting a deformable transform." ) return self.multiPropWidget.tabWidget.setCurrentWidget( self.multiPropWidget.transformParamWidget) if self.transformTool is not None: self.transformTool.cleanUp() statusWidget = StatusWidget.Instance() statusWidget.setText( "Choose a template for a deformable transform. After choosing " "a template you will be able to review and adjust the parameters.") dialog = ElastixMainDialog(self) dialog.setModal(True) result = dialog.exec_() if not result: return if not dialog.transformation: # load custom file filename, other = QFileDialog.getOpenFileName( self, "Open custom parameter file", "", "(*.c *.txt)") if len(filename) == 0: return transformation = ParameterList() if not transformation.loadFromFile(filename): transformation = None statusWidget = StatusWidget.Instance() statusWidget.setText( "Warning: could not load transformation file") else: transformation = dialog.transformation self.transformTool = DeformableTransformationTool() self.transformTool.setTransformation(transformation) self.transformTool.startedElastix.connect(self.showProgressBar) self.transformTool.endedElastix.connect(self.hideProgressBar) self.transformTool.setRenderWidgets(fixed=self.fixedDataWidget, moving=self.movingDataWidget, multi=self.multiDataWidget) self.multiPropWidget.setTransformTool(self.transformTool) self.transformTool.toolFinished.connect(self.transformToolFinished) @Slot() def transformToolFinished(self): self.multiPropWidget.transformToolFinished() self.fixedPropWidget.removeTabWidget() self.movingPropWidget.removeTabWidget() @Slot() def loadFixedDataSetFile(self): """ Open file dialog to search for data files. If valid data is given, it will pass the data file location on to the slicer and the project controller. """ dataReader = DataReader() extensions = dataReader.GetSupportedExtensionsAsString() fileName, other = QFileDialog.getOpenFileName( self, "Open fixed data set", "", "Images (" + extensions + ")", options=QFileDialog.Directory) if len(fileName) > 0: # If there was another dataset first, ask if the user if the # visualizations should be reset projectController = ProjectController.Instance() if projectController.currentProject.fixedData: dialog = ResetVisualizationDialog(self) dialog.setWindowModality(Qt.WindowModal) dialog.exec_() if dialog.result is not None: projectController.loadFixedDataSet(fileName) if dialog.result: self.fixedRenderController.resetVisualizations() else: projectController.loadFixedDataSet(fileName) @Slot() def loadMovingDataSetFile(self): """ Open file dialog to search for data files. If valid data is given, it will pass the data file location on to the slicer and the project controller. """ dataReader = DataReader() extensions = dataReader.GetSupportedExtensionsAsString() fileName, other = QFileDialog.getOpenFileName( self, "Open moving data set", "", "Images (" + extensions + ")", options=QFileDialog.Directory) if len(fileName) > 0: # If there was another dataset first, ask if the user if the # visualizations should be reset projectController = ProjectController.Instance() if projectController.currentProject.movingData: dialog = ResetVisualizationDialog(self) dialog.setWindowModality(Qt.WindowModal) dialog.exec_() if dialog.result is not None: projectController.loadMovingDataSet(fileName) if dialog.result: self.movingRenderController.resetVisualizations() else: # Inserting an identity transform self.multiDataWidget.transformations.append( Transformation(vtkTransform(), "No transform", fileName)) projectController.loadMovingDataSet(fileName) @Slot() def saveProject(self): """ Save the project to the specified name in the current project. If no name is specified, then 'save project as' is called. """ projCont = ProjectController.Instance() if projCont.currentProject.folder is not None: # Save that project saved = projCont.saveProject() statusWidget = StatusWidget.Instance() if saved: # Save it in the settings that this was the last opened project RegistrationShop.settings.setValue( "project/lastProject", projCont.currentProject.folder) statusWidget.setText( "The project was succesfully saved to disk.") else: statusWidget.setText( "Something went wrong while saving the project to disk. " "Please try to save the project again.") else: self.saveProjectAs() @Slot() def saveProjectAs(self): """ Opens a file dialog so that the user can select a folder in which to save the project. """ # Open file dialog fileName = QFileDialog.getExistingDirectory(self, "Select project folder", "", QFileDialog.ShowDirsOnly) if len(fileName) > 0: # TODO: check for existing project! # Set filename of project ProjectController.Instance().currentProject.folder = fileName # Call save project self.saveProject() @Slot() def openProject(self, folderName=None): """ If no project name is supplied, it will open a file dialog so that the user can select a project file or project folder. :param folderName: Name of a folder with a project :type folderName: basestring """ fileName = "" if folderName: fileName = folderName else: fileName = QFileDialog.getExistingDirectory( self, "Open project", "", QFileDialog.ShowDirsOnly) if len(fileName) > 0: fullName = fileName + ProjectController.Instance().ProjectFile if os.path.isfile(fullName): self.multiDataWidget.transformations.clear() loaded = ProjectController.Instance().loadProject(fileName) if loaded: RegistrationShop.settings.setValue("project/lastProject", fileName) else: print "Couldn't load project:", folderName else: print "Warning: Project file does not exist" RegistrationShop.settings.remove("project/lastProject") @Slot() def newProject(self): """ Create new project by calling the project controller """ self.multiDataWidget.transformations.clear() ProjectController.Instance().newProject() # Reset the last loaded project in the settings RegistrationShop.settings.setValue("project/lastProject", "") @Slot() def exportDataAs(self): """ Opens a file dialog so that the user can provide a filename for saving the transformed dataset to. """ fileType = FileTypeDialog.getFileType(self, "Choose file type for export") if len(fileType) == 0: return extension = "(*." + fileType + ")" fileName, other = QFileDialog.getSaveFileName( self, "Save registration result to...", "", extension) if len(fileName) == 0: return self.showProgressBar("Exporting data...") transform = self.multiDataWidget.transformations.completeTransform() dataReader = DataReader() imageData = dataReader.GetImageData( ProjectController.Instance().currentProject.movingData) transformer = DataTransformer() outputData = transformer.TransformImageData(imageData, transform) writer = DataWriter() writer.WriteToFile(outputData, fileName, fileType) self.hideProgressBar() @Slot() def startComparison(self): projectController = ProjectController.Instance() project = projectController.currentProject if not project or not project.fixedData or not project.movingData: statusWidget = StatusWidget.Instance() statusWidget.setText( "Could not start comparison. Please make a project first" " and make sure to load two datasets.") return if hasattr(self, "compareWidget"): del self.compareWidget transform = self.multiDataWidget.transformations.completeTransform() self.controller = ComparisonController() self.controller.setInputData(project.fixedData, project.movingData, transform) self.compareWidget = CompareWidget(self.controller.widgets) self.compareWidget.show() self.controller.initialize() self.controller.slicerChanged(self.controller.fixedImageWidget) @Slot() def showHelp(self): statusWidget = StatusWidget.Instance() statusWidget.setText("Don't panic!")
class Window(QWidget): def init(self, self_mysql): self.ref = False self.ndb = False self.Data_Name = None self.table_Name = None self.mysql = self_mysql self.table = Table() self.tree = treeWidget(self.mysql) text = ( "<center><h1 style=';color:Lightblue;'>MySQL<small style='color:#0099CC;'> Control Panel</small></h1></center>" ) self.vbox = QVBoxLayout(self) self.split = QSplitter() self.tree.setHidden(True) self.tree.itemClicked.connect(self.setInTable) self.tree.itemExpanded.connect(self.expand) self.tree.itemCollapsed.connect(self.collaps) self.split.addWidget(self.tree) self.split.addWidget(self.table) self.split.setSizes([60, 400]) self.vbox.addWidget(label(text)) self.vbox.addWidget(self.split) self.vbox.setContentsMargins(-18, -18, -18, -18) def expand(self, it): if it.isExpanded(): if not it.text(0) in self.tree.li: self.tree.li.append(it.text(0)) def collaps(self, it): if it.text(0) in self.tree.li: self.tree.li.remove(it.text(0)) # set Name 'database & table' in TreeList # def con(self): self.tree.clear() if self.tree.isHidden: self.tree.setHidden(False) self.tree.headerItem().setText(0, self.Data_Name) self.tree.add_to_tree() self.ref = True def setInTable(self, nt): if not str(nt).startswith('<'): table = nt self.table_Name = nt else: if nt.statusTip(0) != 'main': self.tree.headerItem().setText(0, nt.statusTip(0)) self.ndb = nt.statusTip(0) self.Data_Name = nt.statusTip(0) self.table_Name = nt.text(0) else: self.tree.headerItem().setText(0, nt.text(0)) self.Data_Name = nt.text(0) self.table_Name = None if self.ndb: if self.table_Name in self.mysql.getTables(self.Data_Name): self.setDataInTable(self.table_Name) self.ref = True else: pass # Set Data Table In TableWidget # def setDataInTable(self, tab): Icol = 0 if self.ndb: data_dic = self.mysql.dataCol(self.ndb, tab) cols = self.mysql.getColumns(self.ndb, tab) self.table.setColumnCount(len(cols)) if data_dic != None: self.table.setRowCount(int(data_dic[1])) for col in cols: item = QTableWidgetItem self.table.setHorizontalHeaderItem(Icol, item(col)) Irow = 0 for row in data_dic[0][col]: self.item = QTableWidgetItem(str(row)) self.item.setFont(QFont("andalus", 12)) self.table.setItem(Irow, Icol, self.item) Irow += 1 Icol += 1
class ConsoleWidget(QMainWindow): def __init__(self): super(ConsoleWidget, self).__init__() self.setWindowTitle('1c query') self._connection = None self._home = os.path.expanduser('~/%s' % QApplication.applicationName()) if not os.path.isdir(self._home): os.mkdir(self._home) self.queryToolBar = self.addToolBar('Query') self.queryAction = self.queryToolBar.addAction('Run', self.executeQuery) self.queryAction.setDisabled(True) uri_history = list() path = os.path.join(self._home, 'uri_history.txt') if os.path.isfile(path): uri_history = open(path, 'r').read().split('\n') self.connectionToolBar = self.addToolBar('Connection') self.connectionUriCombo = QComboBox(self) self.connectionUriCombo.setEditable(True) if not uri_history: self.connectionUriCombo.addItem('File="";usr="";pwd="";') self.connectionUriCombo.addItem('Srvr="{host}";Ref="{ref}";Usr="******";Pwd="{password}";') else: self.connectionUriCombo.addItems(uri_history) self.connectionUriCombo.setCurrentIndex(len(uri_history) - 1) self.connectionUriCombo.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Maximum) self.connectionToolBar.addWidget(self.connectionUriCombo) self.onesVersionCombo = QComboBox(self) self.onesVersionCombo.addItems(['8.3', '8.2', '8.1', '8.0']) self.onesVersionCombo.setCurrentIndex(0) self.connectionToolBar.addWidget(self.onesVersionCombo) self.connectAction = self.connectionToolBar.addAction('Connect', self.connectOneS) self.disconnectAction = self.connectionToolBar.addAction('Disconnect', self.disconnectOneS) self.disconnectAction.setDisabled(True) self.logEdit = QPlainTextEdit(self) self.logDock = QDockWidget('Log', self) self.logDock.setWidget(self.logEdit) self.addDockWidget(Qt.BottomDockWidgetArea, self.logDock, Qt.Horizontal) self.splitter = QSplitter(Qt.Vertical, self) self.setCentralWidget(self.splitter) self.sqlEdit = QTextEdit(self) self.sqlEdit.setLineWrapMode(QTextEdit.NoWrap) path = os.path.join(self._home, 'last-sql.txt') if os.path.isfile(path): sql = open(path, 'r').read() self.sqlEdit.setText(sql) self.model = QStandardItemModel(self) self.tableView = QTableView(self) self.tableView.setModel(self.model) self.splitter.addWidget(self.sqlEdit) self.splitter.addWidget(self.tableView) self.splitter.setStretchFactor(0, 3) self.splitter.setStretchFactor(1, 2) def query(self, sql): if not self._connection: self.logEdit.appendPlainText('No connection') return None try: query = self._connection.NewObject('Query', sql) result = query.Execute() except Exception as e: self.logEdit.appendPlainText(str(e)) return None return result def refresh(self, result): self.model.clear() columns = list() result_columns = result.Columns for index in range(result_columns.Count()): name = result_columns.Get(index).Name columns.append(name) self.model.setColumnCount(len(columns)) for section, name in enumerate(columns): self.model.setHeaderData(section, Qt.Horizontal, name) select = result.Choose() self.logEdit.appendPlainText('Selected %d records' % select.Count()) while select.Next(): items = list() for index in range(len(columns)): value = select.Get(index) item = QStandardItem('') if isinstance(value, bool): item.setText(value and 'Yes' or 'No') elif isinstance(value, (int, str)): item.setText(str(value)) elif isinstance(value, datetime.datetime): item.setText(value.strftime('%Y.%m.%d %H:%M:%S')) else: item.setText(str(value)) items.append(item) self.model.appendRow(items) @Slot() def executeQuery(self): sql = self.sqlEdit.toPlainText() result = self.query(sql) if result: path = os.path.join(self._home, 'last-sql.txt') open(path, 'w').write(sql) self.refresh(result) @Slot() def connectOneS(self): uri = self.connectionUriCombo.currentText().strip() if not uri: self.logEdit.appendPlainText('Need a connection string') return version = self.onesVersionCombo.currentText() comName = "V%s.COMConnector" % str(version).replace('.', '') pythoncom.CoInitialize() try: obj = win32com.client.Dispatch(comName) self._connection = obj.Connect(uri) except Exception as e: self.logEdit.appendPlainText(str(e)) return self.connectAction.setDisabled(True) self.disconnectAction.setEnabled(True) self.queryAction.setEnabled(True) uri_history = list() for i in range(self.connectionUriCombo.count()): uri_history.append(self.connectionUriCombo.itemText(i)) if uri not in uri_history: self.connectionUriCombo.clearEditText() self.connectionUriCombo.addItem(uri) self.connectionUriCombo.setCurrentIndex(len(uri_history)) uri_history.append(uri) path = os.path.join(self._home, 'uri_history.txt') open(path, 'w').write('\n'.join(uri_history)) @Slot() def disconnectOneS(self): pythoncom.CoUninitialize() self._connection = None self.connectAction.setEnabled(True) self.disconnectAction.setDisabled(True) self.queryAction.setDisabled(True)
class MainWindow(QMainWindow): """The application's main window """ # Emitted when there are pending files to be processed new_pending_files = QtCore.Signal() def __init__(self, app): super(MainWindow, self).__init__() # Window layout - a splitter with the image on the left and controls # on the right self._image_widget = ImageLabel(self) self._controls = Controls(self) self._splitter = QSplitter() self._splitter.addWidget(self._image_widget) self._splitter.addWidget(self._controls) self._splitter.setSizes([1200, 600]) # Main window layout self.setCentralWidget(self._splitter) # Connect controls to handlers self._controls.ok.clicked.connect(self.ok) self._controls.cancel.clicked.connect(self.cancel) self._controls.inbox.choose_directory.clicked.connect( self.choose_inbox) self._controls.processed.choose_directory.clicked.connect( self.choose_processed) # Directories mydocuments = QDesktopServices.storageLocation( QDesktopServices.DocumentsLocation) self._inbox = Path(QSettings().value('inbox', str(Path(mydocuments) / 'inbox'))) self._processed = Path(QSettings().value( 'processed', str(Path(mydocuments) / 'processed'))) self._controls.inbox.set_link(str(self._inbox.as_uri()), self._inbox.name) self._controls.processed.set_link(str(self._processed.as_uri()), self._processed.name) # A stack of Path objects to be processed self._pending_files = [] # The Path currently shown in the UI self._under_review = None # Watch the inbox directory, if it exists self.new_pending_files.connect(self.process_next_pending, QtCore.Qt.QueuedConnection) if self._inbox.is_dir(): self._watcher = NewFileWatcher(self._inbox, IMAGE_SUFFIXES_RE) self._watcher.new_file.connect(self.new_image_file) else: self._watcher = None self.empty_controls() # Setup drag-drop handling self.setAcceptDrops(True) self._controls.installEventFilter(self) self._splitter.installEventFilter(self) def new_inbox_directory(self): """Watch the inbox directory """ print('MainWindow.new_inbox_directory [{0}]'.format(self._inbox)) if self._watcher: self._watcher.new_file.disconnect() self._watcher = NewFileWatcher(self._inbox, IMAGE_SUFFIXES_RE) self._watcher.new_file.connect(self.new_image_file) def new_image_file(self, path): """Slot for self._watcher.new_file """ print('MainWindow.new_image_file [{0}]'.format(path)) self._pending_files.append(path) self.new_pending_files.emit() @report_to_user def process_next_pending(self): """Loads the next pending image for review """ print('MainWindow.process_next_pending: [{0}] files'.format( len(self._pending_files))) if not self._under_review: if self._pending_files: self.review_image(self._pending_files.pop()) else: self.empty_controls() def review_image(self, path): """Loads path for review """ print('MainWindow.review_image [{0}]'.format(path)) # Arbitrary delay to give the capture software time to finish writing # the image. time.sleep(1) image = cv2.imread(str(path)) if image is None: raise ValueError('Unable to read [{0}]'.format(path)) else: self._under_review = path self.setWindowTitle('') self.setWindowFilePath(str(path)) self._controls.specimen.setText(QSettings().value('specimen')) self._controls.location.setText(QSettings().value('location')) self._image_widget.set_pixmap( QPixmap.fromImage(qimage_of_bgr(image))) self._controls.image_handling.setEnabled(True) def empty_controls(self): """Clears controls """ print('MainWindow.empty_controls') self._under_review = None self.setWindowTitle('Syrup') self.setWindowFilePath(None) self._image_widget.set_pixmap(None) self._controls.clear() self._controls.image_handling.setEnabled(False) @report_to_user def ok(self): print('MainWindow.ok') specimen = self._controls.specimen.text() location = self._controls.location.text() if not SPECIMEN_RE.match(specimen): raise ValueError( 'Please enter nine digits for the specimen barcode') elif not LOCATION_RE.match(location): raise ValueError( 'Please enter a letter "L" and nine digits for the ' 'location barcode') else: if not self._processed.is_dir(): self._processed.mkdir(parents=True) destination = self._processed / '{0}_{1}'.format( specimen, location) destination = destination.with_suffix(self._under_review.suffix) move_and_rename(self._under_review, destination) QSettings().setValue('specimen', specimen) QSettings().setValue('location', location) self._under_review = None self.process_next_pending() @report_to_user def cancel(self): """Closes the image under review without moving the image file """ print('MainWindow.cancel') self._under_review = None self.process_next_pending() @report_to_user def choose_inbox(self): """Prompts the user to choose the inbox directory """ directory = QFileDialog.getExistingDirectory( self, "Choose the inbox directory", str(self._inbox)) if directory: directory = Path(directory) if directory == self._processed: raise ValueError('The inbox directory cannot be the same as ' 'the processed directory') else: self._inbox = directory print('New inbox directory [{0}]'.format(self._inbox)) self._controls.inbox.set_link(str(self._inbox.as_uri()), self._inbox.name) QSettings().setValue('inbox', str(self._inbox)) self.new_inbox_directory() @report_to_user def choose_processed(self): """Prompts the user to choose the processed directory """ directory = QFileDialog.getExistingDirectory( self, "Choose the processed directory", str(self._processed)) if directory: directory = Path(directory) if directory == self._inbox: raise ValueError('The inbox directory cannot be the same as ' 'the processed directory') else: self._processed = directory print('New processed directory [{0}]'.format(self._processed)) self._controls.processed.set_link( str(self._processed.as_uri()), self._processed.name) QSettings().setValue('processed', str(self._processed)) def write_geometry_settings(self): "Writes geometry to settings" print('MainWindow.write_geometry_settings') # Taken from http://stackoverflow.com/a/8736705 # TODO LH Test on multiple display system s = QSettings() s.setValue("mainwindow/geometry", self.saveGeometry()) s.setValue("mainwindow/pos", self.pos()) s.setValue("mainwindow/size", self.size()) def show_from_geometry_settings(self): print('MainWindow.show_from_geometry_settings') # TODO LH What if screen resolution, desktop config change or roaming # profile means that restored state is outside desktop? s = QSettings() self.restoreGeometry( s.value("mainwindow/geometry", self.saveGeometry())) if not (self.isMaximized() or self.isFullScreen()): self.move(s.value("mainwindow/pos", self.pos())) self.resize(s.value("mainwindow/size", self.size())) self.show() def closeEvent(self, event): """QWidget virtual """ print('MainWindow.closeEvent') self.write_geometry_settings() event.accept() def eventFilter(self, obj, event): "Event filter that accepts drag-drop events" if event.type() in (QEvent.DragEnter, QEvent.Drop): return True else: return super(MainWindow, self).eventFilter(obj, event) def _accept_drag_drop(self, event): """If no image is under review and event refers to a single image file, returns the path. Returns None otherwise. """ if self._under_review: return None else: urls = event.mimeData().urls() if event.mimeData() else None path = Path( urls[0].toLocalFile()) if urls and 1 == len(urls) else None print(path, IMAGE_SUFFIXES_RE.match(path.suffix)) if path and IMAGE_SUFFIXES_RE.match(path.suffix): return urls[0].toLocalFile() else: return None def dragEnterEvent(self, event): """QWidget virtual """ print('MainWindow.dragEnterEvent') if self._accept_drag_drop(event): event.acceptProposedAction() else: super(MainWindow, self).dragEnterEvent(event) @report_to_user def dropEvent(self, event): """QWidget virtual """ print('MainWindow.dropEvent') res = self._accept_drag_drop(event) if res: event.acceptProposedAction() self.review_image(Path(res)) else: super(MainWindow, self).dropEvent(event)
class MainWindow(QMainWindow): def __init__(self, datta): QMainWindow.__init__(self) self.setWindowTitle('Project Parser') appIcon = QIcon('search.png') self.setWindowIcon(appIcon) self.viewPortBL = QDesktopWidget().availableGeometry().topLeft() self.viewPortTR = QDesktopWidget().availableGeometry().bottomRight() self.margin = int(QDesktopWidget().availableGeometry().width()*0.1/2) self.shirina = QDesktopWidget().availableGeometry().width() - self.margin*2 self.visota = QDesktopWidget().availableGeometry().height() - self.margin*2 self.setGeometry(self.viewPortBL.x() + self.margin, self.viewPortBL.y() + self.margin, self.shirina, self.visota) # statusbar self.myStatusBar = QStatusBar() self.setStatusBar(self.myStatusBar) #lower long layout self.lowerLong = QFrame() self.detailsLabel = QLabel() self.skillsLabel = QLabel() self.urlLabel = QLabel() self.locationLabel = QLabel() self.skillsLabel.setText('skills') self.detailsLabel.setWordWrap(True) self.la = QVBoxLayout() self.la.addWidget(self.detailsLabel) self.la.addWidget(self.skillsLabel) self.la.addWidget(self.urlLabel) self.la.addWidget(self.locationLabel) self.lowerLong.setLayout(self.la) # table self.source_model = MyTableModel(self, datta, ['Id', 'Date', 'Title']) self.proxy_model = myTableProxy(self) self.proxy_model.setSourceModel(self.source_model) self.proxy_model.setDynamicSortFilter(True) self.table_view = QTableView() self.table_view.setModel(self.proxy_model) self.table_view.setAlternatingRowColors(True) self.table_view.resizeColumnsToContents() self.table_view.resizeRowsToContents() self.table_view.horizontalHeader().setStretchLastSection(True) self.table_view.setSortingEnabled(True) self.table_view.sortByColumn(2, Qt.AscendingOrder) # events self.selection = self.table_view.selectionModel() self.selection.selectionChanged.connect(self.handleSelectionChanged) #DO NOT use CreateIndex() method, use index() index = self.proxy_model.index(0,0) self.selection.select(index, QItemSelectionModel.Select) self.upperLong = self.table_view # right side widgets self.right = QFrame() self.la1 = QVBoxLayout() self.btnDownload = QPushButton('Download data') self.btnDownload.clicked.connect(self.download) self.myButton = QPushButton('Show Skillls') self.myButton.clicked.connect(self.showAllSkills) self.btnSearchByWord = QPushButton('Search by word(s)') self.btnSearchByWord.clicked.connect(self.onSearchByWord) self.btnResetFilter= QPushButton('Discard Filter') self.btnResetFilter.clicked.connect(self.discardFilter) self.btnCopyURL = QPushButton('URL to Clipboard') self.btnCopyURL.clicked.connect(self.copyToClipboard) self.btnExit = QPushButton('Exit') self.btnExit.clicked.connect(lambda: sys.exit()) self.dateTimeStamp = QLabel() self.la1.addWidget(self.btnDownload) self.la1.addSpacing(10) self.la1.addWidget(self.myButton) self.la1.addSpacing(10) self.la1.addWidget(self.btnSearchByWord) self.la1.addSpacing(10) self.la1.addWidget(self.btnResetFilter) self.la1.addSpacing(10) self.la1.addWidget(self.btnCopyURL) self.la1.addSpacing(70) self.la1.addWidget(self.btnExit) self.la1.addStretch(stretch=0) self.la1.addWidget(self.dateTimeStamp) self.right.setLayout(self.la1) self.right.setFrameShape(QFrame.StyledPanel) # splitters self.horiSplit = QSplitter(Qt.Vertical) self.horiSplit.addWidget(self.upperLong) self.horiSplit.addWidget(self.lowerLong) self.horiSplit.setSizes([self.visota/2, self.visota/2]) self.vertiSplit = QSplitter(Qt.Horizontal) self.vertiSplit.addWidget(self.horiSplit) self.vertiSplit.addWidget(self.right) self.vertiSplit.setSizes([self.shirina*3/4, self.shirina*1/4]) self.setCentralWidget(self.vertiSplit) self.settings = QSettings('elance.ini', QSettings.IniFormat) self.settings.beginGroup('DATE_STAMP') self.dateTimeStamp.setText('Data actuality: %s' % self.settings.value('date/time')) self.settings.endGroup() self.statusText = '' def handleSelectionChanged(self, selected, deselected): for index in selected.first().indexes(): #print('Row %d is selected' % index.row()) ind = index.model().mapToSource(index) desc = ind.model().mylist[ind.row()]['Description'] self.detailsLabel.setText(desc) skills = ', '.join(ind.model().mylist[ind.row()]['Skills']).strip() self.skillsLabel.setText(skills) url = ind.model().mylist[ind.row()]['URL'] self.urlLabel.setText(url) location = ind.model().mylist[ind.row()]['Location'] self.locationLabel.setText(location) def showAllSkills(self): listSkills = [] for elem in self.source_model.mylist: listSkills += elem['Skills'] allSkills = Counter(listSkills) tbl = MyTableModel(self, allSkills.items(), ['Skill', 'Freq']) win = skillsWindow(tbl, self.table_view) win.exec_() def discardFilter(self): self.table_view.model().emit(SIGNAL("modelAboutToBeReset()")) self.table_view.model().criteria = {} self.table_view.model().emit(SIGNAL("modelReset()")) self.table_view.resizeRowsToContents() def download(self): self.btnDownload.setDisabled(True) self.statusLabel = QLabel('Connecting') self.progressBar = QProgressBar() self.progressBar.setMinimum(0) self.progressBar.setMaximum(100) self.myStatusBar.addWidget(self.statusLabel, 2) self.myStatusBar.addWidget(self.progressBar, 1) self.progressBar.setValue(1) self.settings.beginGroup('URLS') initialLink = self.settings.value('CategoriesDetailed/VahaSelected/InitialLink') pagingLink = self.settings.value('CategoriesDetailed/VahaSelected/PagingLink') self.settings.endGroup() downloader = Downloader(initialLink, pagingLink, 25, 5) downloader.messenger.downloadProgressChanged.connect(self.onDownloadProgressChanged) downloader.messenger.downloadComplete.connect(self.onDownloadComplete) downloader.download() def onDownloadComplete(self): #QMessageBox.information(self, 'Download complete', 'Download complete!', QMessageBox.Ok) self.table_view.model().emit(SIGNAL("modelAboutToBeReset()")) self.settings.beginGroup('DATE_STAMP') self.settings.setValue('date/time', time.strftime('%d-%b-%Y, %H:%M:%S')) self.dateTimeStamp.setText('Data actuality: %s' % self.settings.value('date/time')) self.settings.endGroup() with open("elance.json") as json_file: jobDB = json.load(json_file) for elem in jobDB: words = nltk.tokenize.regexp_tokenize(elem['Title'].lower(), r'\w+') elem['Tokens'] = words elem['Skills'] = [t.strip() for t in elem['Skills'].split(',')] self.source_model.mylist = jobDB self.table_view.model().emit(SIGNAL("modelReset()")) self.btnDownload.setEnabled(True) self.myStatusBar.removeWidget(self.statusLabel) self.myStatusBar.removeWidget(self.progressBar) self.myStatusBar.showMessage(self.statusText, timeout = 5000) def onDownloadProgressChanged(self, stata): self.progressBar.setValue(stata[2]) #text = 'Processed records{:5d} of{:5d}'.format(percentage[0], percentage[1]) bajtikov = '{:,}'.format(stata[5]) self.statusText = 'Processed page{:4d} of{:4d}. \ Job entries{:5d} of{:5d}. \ Downloaded{:>12s} Bytes'.format(stata[3], stata[4], stata[0], stata[1], bajtikov) self.statusLabel.setText(self.statusText) def copyToClipboard(self): clipboard = QApplication.clipboard() clipboard.setText(self.urlLabel.text()) self.myStatusBar.showMessage(self.urlLabel.text(), timeout = 3000) def onSearchByWord(self): text, ok = QInputDialog.getText(self, 'Search the base by word(s)', 'Enter your keyword/phrase to search for:') if ok: words = [t.strip() for t in nltk.tokenize.regexp_tokenize(text.lower(), r'\w+')] self.table_view.model().emit(SIGNAL("modelAboutToBeReset()")) self.table_view.model().criteria = {'Description' : words} self.table_view.model().emit(SIGNAL("modelReset()"))
class StepperWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) # filename = QFileDialog.getOpenFileName(self, "Open File")[0] # self.setWindowTitle(os.path.basename(filename)) # self.transcript = StepperTranscript(filename) self.save_file_name = None self.explorer_table = None self.transcript = None self.setupUi(self) self.setAcceptDrops(True) def dragEnterEvent(self, event): event.accept() def dropEvent(self, event): for url in event.mimeData().urls(): path = url.toLocalFile() self.open_transcript(fullname=path) def open_transcript(self, fullname=None): if self.transcript is not None: newStepperWindow = StepperWindow() stepper_windows.append(newStepperWindow) newStepperWindow.show() newStepperWindow.resize(1250, 1000) newStepperWindow.open_transcript(fullname) else: if fullname is None: fullname = QFileDialog.getOpenFileName(self, "Open File")[0] self.save_file_name = fullname self.setWindowTitle(os.path.basename(fullname)) self.transcript = StepperTranscript(fullname) self.display_current_turn() self.show_transcript_in_explorer() if self.transcript.video_file_name != None: self.open_video(self.transcript.video_file_name) def position_transcript(self, position): self.transcript.move_to_position(1.0 * position / 100) self.display_current_turn() def show_transcript_in_explorer(self): transcript_array = self.transcript.get_transcript_as_array() self.click_handler = ExploreClickHandler(self) self.explorer_table = ExplorerTable(transcript_array, click_handler=self.click_handler) self.big_splitter.addWidget(self.explorer_table) # self.outer_layout.setStretch(2, 1) self.explorer_table.highlight_row(self.transcript.current_index()) def go_to_next_turn(self): self.transcript.go_to_next() self.display_current_turn() def update_time(self): self.turn["time"] = self.time_field.value if self.explorer_table is not None: table_item = self.explorer_table.item(self.transcript.current_index(), 1) table_item.setText(self.time_field.value) def update_speaker(self): self.turn["speaker"] = self.speaker_field.value if self.explorer_table is not None: table_item = self.explorer_table.item(self.transcript.current_index(), 2) table_item.setText(self.speaker_field.value) def update_utterance(self): self.turn["utterance"] = self.utt_field.value if self.explorer_table is not None: table_item = self.explorer_table.item(self.transcript.current_index(), 3) table_item.setText(self.utt_field.value) def go_to_previous_turn(self): self.transcript.go_to_previous() self.display_current_turn() def go_to_row(self, the_row): self.transcript.go_to_index(the_row) self.display_current_turn() def display_current_turn(self): self.turn = self.transcript.current_turn() self.time_field.value = self.turn["time"] self.speaker_field.value = self.turn["speaker"] self.utt_field.value = self.turn["utterance"] if self.explorer_table is not None: self.explorer_table.highlight_row(self.transcript.current_index()) self.utt_field.efield.setFocus() self.utt_field.efield.moveCursor(QTextCursor.Start, mode=QTextCursor.MoveAnchor) def delete_current_turn(self): self.transcript.delete_current() self.display_current_turn() def save_file_as(self): filename = QFileDialog.getSaveFileName(self, "File name for save")[0] self.save_file_name = filename self.transcript.commit_all() self.transcript.save_as_csv(filename) def save_file(self): if self.save_file_name is None: self.save_file_as() else: self.transcript.commit_all() self.transcript.save_as_csv(self.save_file_name) def revert_current_and_redisplay(self): self.transcript.revert_current() self.display_current_turn() def open_video(self, filename=None): # self.player = Player() # self.player.show() # self.player.resize(640, 480) self.player.OpenFile(filename) def play_or_pause(self): self.player.PlayPause() def slower(self): self.player.decrease_rate() def faster(self): self.player.increase_rate() def normal_speed(self): self.player.reset_rate() def fill_time_code(self): self.time_field.value = self.player.getCurrentTimeCode() def sync_video_and_play(self): self.sync_video() if not self.player.mediaplayer.is_playing(): self.play_or_pause() def jump_back(self): self.player.jump_video_backward() def jump_forward(self): self.player.jump_video_forward() def sync_video(self): self.player.setTimeCode(self.time_field.value) def insert_before(self): new_uid = self.transcript.insert_new(self.transcript.current_uid) if self.explorer_table is not None: self.explorer_table.insert_row(self.transcript.current_index(), [new_uid, "", "", ""]) self.display_current_turn() def insert_after(self): new_uid = self.transcript.insert_new(self.transcript.current_uid, "after") if self.explorer_table is not None: self.explorer_table.insert_row(self.transcript.current_index(), [new_uid, "", "", ""]) self.display_current_turn() def closeEvent(self, event): msgBox = QMessageBox() msgBox.setText("Do you want to save before quitting?") msgBox.setInformativeText("Do you want to save your changes?") msgBox.setStandardButtons(QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) msgBox.setDefaultButton(QMessageBox.Save) ret = msgBox.exec_() if ret == QMessageBox.Save: self.save_file() event.accept() elif ret == QMessageBox.Discard: event.accept() else: event.ignore() def commit(self): self.transcript.commit_current() def commit_all(self): self.transcript.commit_all() def go_to_next_word(self): c = self.utt_field.efield.textCursor() if c.selectedText() != "": # If nothing is selected, select the current word self.utt_field.efield.moveCursor(QTextCursor.NextWord, QTextCursor.MoveAnchor) self.utt_field.efield.moveCursor(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) c = self.utt_field.efield.textCursor() if c.selectedText() == "": # this addresses the case where I'm in front of a blank space self.utt_field.efield.moveCursor(QTextCursor.NextWord, QTextCursor.MoveAnchor) self.utt_field.efield.moveCursor(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) def go_to_previous_word(self): c = self.utt_field.efield.textCursor() pos = c.position() self.utt_field.efield.moveCursor(QTextCursor.StartOfWord, QTextCursor.MoveAnchor) self.utt_field.efield.moveCursor(QTextCursor.PreviousWord, QTextCursor.MoveAnchor) self.utt_field.efield.moveCursor(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) c = self.utt_field.efield.textCursor() if c.position() == pos: self.utt_field.efield.moveCursor(QTextCursor.StartOfWord, QTextCursor.MoveAnchor) self.utt_field.efield.moveCursor(QTextCursor.PreviousWord, QTextCursor.MoveAnchor) self.utt_field.efield.moveCursor(QTextCursor.PreviousWord, QTextCursor.MoveAnchor) self.utt_field.efield.moveCursor(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) def setupUi(self, stepperWindow): stepperWindow.setObjectName("stepperWindow") self.outer_widget = QtGui.QWidget(stepperWindow) # sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) # sizePolicy.setHorizontalStretch(0) # sizePolicy.setVerticalStretch(0) # sizePolicy.setHeightForWidth(self.outer_widget.sizePolicy().hasHeightForWidth()) # self.outer_widget.setSizePolicy(sizePolicy) self.outer_widget.setObjectName("outer_widget") self.outer_layout = QtGui.QHBoxLayout(self.outer_widget) self.outer_layout.setContentsMargins(0, 0, 0, 0) self.outer_layout.setObjectName("outer_layout") self.big_splitter = QSplitter() self.outer_layout.addWidget(self.big_splitter) self.left_layout = QtGui.QVBoxLayout() self.left_layout.setObjectName("left_layout") self.left_widget = QWidget() self.left_widget.setLayout(self.left_layout) self.big_splitter.addWidget(self.left_widget) self.player = Player() self.left_layout.addWidget(self.player) self.left_layout.setStretch(0, 1) self.createDisplayFields() # Add all of the buttons self.allbuttonslayout = QtGui.QHBoxLayout() self.allbuttonslayout.setSizeConstraint(QtGui.QLayout.SetNoConstraint) self.allbuttonslayout.setObjectName("allbuttonslayout") self.gridbuttonlayout = QtGui.QGridLayout() self.gridbuttonlayout.setSizeConstraint(QtGui.QLayout.SetFixedSize) self.gridbuttonlayout.setVerticalSpacing(1) self.gridbuttonlayout.setObjectName("gridbuttonlayout") self.DeleteButton = QtGui.QPushButton(self.outer_widget) self.DeleteButton.setObjectName("DeleteButton") self.gridbuttonlayout.addWidget(self.DeleteButton, 0, 2, 1, 1) self.InsertAfterButton = QtGui.QPushButton(self.outer_widget) self.InsertAfterButton.setObjectName("InsertAfterButton") self.gridbuttonlayout.addWidget(self.InsertAfterButton, 0, 1, 1, 1) self.SaveAsButton = QtGui.QPushButton(self.outer_widget) self.SaveAsButton.setObjectName("SaveAsButton") self.gridbuttonlayout.addWidget(self.SaveAsButton, 1, 1, 1, 1) self.CommitAllButton = QtGui.QPushButton(self.outer_widget) self.CommitAllButton.setObjectName("CommitAllButton") self.gridbuttonlayout.addWidget(self.CommitAllButton, 2, 1, 1, 1) self.CommitButton = QtGui.QPushButton(self.outer_widget) self.CommitButton.setObjectName("CommitButton") self.gridbuttonlayout.addWidget(self.CommitButton, 2, 0, 1, 1) self.InsertBeforeButton = QtGui.QPushButton(self.outer_widget) self.InsertBeforeButton.setObjectName("InsertBeforeButton") self.gridbuttonlayout.addWidget(self.InsertBeforeButton, 0, 0, 1, 1) self.SaveButton = QtGui.QPushButton(self.outer_widget) self.SaveButton.setObjectName("SaveButton") self.gridbuttonlayout.addWidget(self.SaveButton, 1, 0, 1, 1) self.RevertButton = QtGui.QPushButton(self.outer_widget) self.RevertButton.setObjectName("RevertButton") self.gridbuttonlayout.addWidget(self.RevertButton, 2, 2, 1, 1) self.allbuttonslayout.addLayout(self.gridbuttonlayout) self.keypadGridLayout = QtGui.QGridLayout() self.keypadGridLayout.setSizeConstraint(QtGui.QLayout.SetFixedSize) self.keypadGridLayout.setObjectName("keypadGridLayout") self.SlowerButton = QtGui.QPushButton(self.outer_widget) self.SlowerButton.setObjectName("SlowerButton") self.keypadGridLayout.addWidget(self.SlowerButton, 2, 0, 1, 1) self.FasterButton = QtGui.QPushButton(self.outer_widget) self.FasterButton.setObjectName("FasterButton") self.keypadGridLayout.addWidget(self.FasterButton, 2, 2, 1, 1) self.NormalButton = QtGui.QPushButton(self.outer_widget) self.NormalButton.setObjectName("NormalButton") self.keypadGridLayout.addWidget(self.NormalButton, 2, 1, 1, 1) self.JumpBackButton = QtGui.QPushButton(self.outer_widget) self.JumpBackButton.setObjectName("JumpBackButton") self.keypadGridLayout.addWidget(self.JumpBackButton, 1, 0, 1, 1) self.NextButton = QtGui.QPushButton(self.outer_widget) self.NextButton.setObjectName("NextButton") self.keypadGridLayout.addWidget(self.NextButton, 0, 2, 1, 1) self.JumpForward = QtGui.QPushButton(self.outer_widget) self.JumpForward.setObjectName("JumpForward") self.keypadGridLayout.addWidget(self.JumpForward, 1, 2, 1, 1) self.PlayButton = QtGui.QPushButton(self.outer_widget) self.PlayButton.setObjectName("PlayButton") self.keypadGridLayout.addWidget(self.PlayButton, 1, 1, 1, 1) self.PreviousButton = QtGui.QPushButton(self.outer_widget) self.PreviousButton.setObjectName("PreviousButton") self.keypadGridLayout.addWidget(self.PreviousButton, 0, 0, 1, 1) self.GotoButton = QtGui.QPushButton(self.outer_widget) self.GotoButton.setObjectName("GotoButton") self.keypadGridLayout.addWidget(self.GotoButton, 0, 1, 1, 1) self.SyncButton = QtGui.QPushButton(self.outer_widget) self.SyncButton.setObjectName("SyncButton") self.keypadGridLayout.addWidget(self.SyncButton, 3, 2, 1, 1) self.FillButton = QtGui.QPushButton(self.outer_widget) self.FillButton.setObjectName("FillButton") self.keypadGridLayout.addWidget(self.FillButton, 3, 0, 1, 1) self.allbuttonslayout.addLayout(self.keypadGridLayout) self.ExplorerButton = QtGui.QPushButton(self.outer_widget) self.ExplorerButton.setObjectName("ExplorerButton") self.gridbuttonlayout.addWidget(self.ExplorerButton, 1, 2, 1, 1) # Change made by hand here self.left_layout.addLayout(self.allbuttonslayout) self.left_layout.setStretch(1, 0) self.left_layout.setStretch(2, 0) # self.splitter = QSplitter() # self.splitter.addWidget(self.player) # self.outer_layout.addWidget(self.splitter) # self.outer_layout.setStretch(1, 1) # stepperWindow.show_transcript_in_explorer() # if stepperWindow.transcript.video_file_name != None: # self.open_video(stepperWindow.transcript.video_file_name) stepperWindow.setCentralWidget(self.outer_widget) self.menubar = QtGui.QMenuBar() self.menubar.setGeometry(QtCore.QRect(0, 0, 1500, 22)) self.menubar.setObjectName("menubar") stepperWindow.setMenuBar(self.menubar) self.statusbar = QtGui.QStatusBar(stepperWindow) self.statusbar.setObjectName("statusbar") stepperWindow.setStatusBar(self.statusbar) self.retranslateUi(stepperWindow) QtCore.QObject.connect(self.GotoButton, QtCore.SIGNAL("clicked()"), stepperWindow.sync_video_and_play) QtCore.QObject.connect(self.JumpForward, QtCore.SIGNAL("clicked()"), stepperWindow.jump_forward) QtCore.QObject.connect(self.PlayButton, QtCore.SIGNAL("clicked()"), stepperWindow.play_or_pause) QtCore.QObject.connect(self.SyncButton, QtCore.SIGNAL("clicked()"), stepperWindow.sync_video) QtCore.QObject.connect(self.FillButton, QtCore.SIGNAL("clicked()"), stepperWindow.fill_time_code) QtCore.QObject.connect(self.NextButton, QtCore.SIGNAL("clicked()"), stepperWindow.go_to_next_turn) QtCore.QObject.connect(self.CommitButton, QtCore.SIGNAL("clicked()"), stepperWindow.commit) QtCore.QObject.connect(self.InsertBeforeButton, QtCore.SIGNAL("clicked()"), stepperWindow.insert_before) QtCore.QObject.connect(self.JumpBackButton, QtCore.SIGNAL("clicked()"), stepperWindow.jump_back) QtCore.QObject.connect(self.SlowerButton, QtCore.SIGNAL("clicked()"), stepperWindow.slower) QtCore.QObject.connect(self.FasterButton, QtCore.SIGNAL("clicked()"), stepperWindow.faster) QtCore.QObject.connect(self.NormalButton, QtCore.SIGNAL("clicked()"), stepperWindow.normal_speed) QtCore.QObject.connect(self.PreviousButton, QtCore.SIGNAL("clicked()"), stepperWindow.go_to_previous_turn) QtCore.QObject.connect(self.SaveButton, QtCore.SIGNAL("clicked()"), stepperWindow.save_file) QtCore.QObject.connect(self.SaveAsButton, QtCore.SIGNAL("clicked()"), stepperWindow.save_file_as) QtCore.QObject.connect(self.RevertButton, QtCore.SIGNAL("clicked()"), stepperWindow.revert_current_and_redisplay) QtCore.QObject.connect(self.DeleteButton, QtCore.SIGNAL("clicked()"), stepperWindow.delete_current_turn) QtCore.QObject.connect(self.InsertAfterButton, QtCore.SIGNAL("clicked()"), stepperWindow.insert_after) QtCore.QObject.connect(self.CommitAllButton, QtCore.SIGNAL("clicked()"), stepperWindow.commit_all) # Added this line by hand QtCore.QObject.connect(self.ExplorerButton, QtCore.SIGNAL("clicked()"), stepperWindow.show_transcript_in_explorer) QtCore.QMetaObject.connectSlotsByName(stepperWindow) # The following menu and shortcut stuff added by hand command_list = [ [self.open_transcript, "Open Transcript", {}, "Ctrl+t"], [self.open_video, "Open Video", {}, "Ctrl+v"], [self.play_or_pause, "Play/Pause", {}, Qt.CTRL + Qt.Key_K], [self.save_file, "Save", {}, "Ctrl+s"], [self.player.jump_video_backward, "Jump Back", {}, Qt.CTRL + Qt.Key_J], [self.player.jump_video_forward, "Jump Forward", {}, Qt.CTRL + Qt.Key_L], [self.go_to_previous_turn, "Previous Turn", {}, "Ctrl+u"], [self.go_to_next_turn, "Next Turn", {}, "Ctrl+o"], [self.go_to_previous_word, "Previous Word", {}, "Ctrl+n"], [self.go_to_next_word, "Next Word", {}, "Ctrl+m"] ] menubar = self.menuBar() create_menu(self, menubar, "Stepper", command_list) QShortcut(QKeySequence(Qt.CTRL + Qt.Key_0), self, self.play_or_pause) QShortcut(QKeySequence(Qt.CTRL + Qt.Key_5), self, self.play_or_pause) QShortcut(QKeySequence(Qt.CTRL + Qt.Key_7), self, self.go_to_previous_turn) QShortcut(QKeySequence(Qt.CTRL + Qt.Key_9), self, self.go_to_next_turn) QShortcut(QKeySequence(Qt.CTRL + Qt.Key_4), self, self.player.jump_video_backward) QShortcut(QKeySequence(Qt.CTRL + Qt.Key_6), self, self.player.jump_video_forward) QShortcut(QKeySequence(Qt.CTRL + Qt.Key_2), self, self.player.reset_rate) QShortcut(QKeySequence(Qt.CTRL + Qt.Key_1), self, self.player.decrease_rate) QShortcut(QKeySequence(Qt.CTRL + Qt.Key_3), self, self.player.increase_rate) QShortcut(QKeySequence(Qt.CTRL + Qt.Key_I), self, self.sync_video_and_play) QShortcut(QKeySequence(Qt.CTRL + Qt.Key_8), self, self.sync_video_and_play) def retranslateUi(self, stepperWindow): stepperWindow.setWindowTitle(QtGui.QApplication.translate("stepperWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)) self.DeleteButton.setText(QtGui.QApplication.translate("stepperWindow", "Delete", None, QtGui.QApplication.UnicodeUTF8)) self.InsertAfterButton.setText(QtGui.QApplication.translate("stepperWindow", "Ins After", None, QtGui.QApplication.UnicodeUTF8)) self.SaveAsButton.setText(QtGui.QApplication.translate("stepperWindow", "Save As ...", None, QtGui.QApplication.UnicodeUTF8)) self.CommitAllButton.setText(QtGui.QApplication.translate("stepperWindow", "Commit all", None, QtGui.QApplication.UnicodeUTF8)) self.CommitButton.setText(QtGui.QApplication.translate("stepperWindow", "Commit", None, QtGui.QApplication.UnicodeUTF8)) self.InsertBeforeButton.setText(QtGui.QApplication.translate("stepperWindow", "Ins Before", None, QtGui.QApplication.UnicodeUTF8)) self.SaveButton.setText(QtGui.QApplication.translate("stepperWindow", "Save", None, QtGui.QApplication.UnicodeUTF8)) self.RevertButton.setText(QtGui.QApplication.translate("stepperWindow", "Revert", None, QtGui.QApplication.UnicodeUTF8)) self.SlowerButton.setText(QtGui.QApplication.translate("stepperWindow", "Slower", None, QtGui.QApplication.UnicodeUTF8)) self.FasterButton.setText(QtGui.QApplication.translate("stepperWindow", "Faster", None, QtGui.QApplication.UnicodeUTF8)) self.NormalButton.setText(QtGui.QApplication.translate("stepperWindow", "Normal", None, QtGui.QApplication.UnicodeUTF8)) self.JumpBackButton.setText(QtGui.QApplication.translate("stepperWindow", "Jump-", None, QtGui.QApplication.UnicodeUTF8)) self.NextButton.setText(QtGui.QApplication.translate("stepperWindow", "Next", None, QtGui.QApplication.UnicodeUTF8)) self.JumpForward.setText(QtGui.QApplication.translate("stepperWindow", "Jump+", None, QtGui.QApplication.UnicodeUTF8)) self.PlayButton.setText(QtGui.QApplication.translate("stepperWindow", "Play", None, QtGui.QApplication.UnicodeUTF8)) self.PreviousButton.setText(QtGui.QApplication.translate("stepperWindow", "Prev", None, QtGui.QApplication.UnicodeUTF8)) self.GotoButton.setText(QtGui.QApplication.translate("stepperWindow", "GoTo", None, QtGui.QApplication.UnicodeUTF8)) self.SyncButton.setText(QtGui.QApplication.translate("stepperWindow", "Sync Vid", None, QtGui.QApplication.UnicodeUTF8)) self.FillButton.setText(QtGui.QApplication.translate("stepperWindow", "Fill Time", None, QtGui.QApplication.UnicodeUTF8)) self.ExplorerButton.setText(QtGui.QApplication.translate("stepperWindow", "Explorer", None, QtGui.QApplication.UnicodeUTF8)) def createDisplayFields(self): display_widget = QFrame() display_widget.setFrameStyle(QtGui.QFrame.Panel | QtGui.QFrame.Sunken) self.left_layout.addWidget(display_widget) self.display_layout = QHBoxLayout() # self.turn = self.transcript.current_turn() self.time_field = qHotField("time", str, "00:00:00", min_size=75, max_size=75, pos="top", handler=self.update_time) self.display_layout.addWidget(self.time_field) self.speaker_field = qHotField("speaker", str, " ", min_size=75, max_size=75, pos="top", handler=self.update_speaker) self.display_layout.addWidget(self.speaker_field) self.utt_field = qHotField("utterance", str, " ", min_size=350, max_size=500, pos="top", handler=self.update_utterance, multiline=True) self.utt_field.setStyleSheet("font: 14pt \"Courier\";") # self.utt_field.efield.setFont(QFont('SansSerif', 12)) self.display_layout.addWidget(self.utt_field) display_widget.setLayout(self.display_layout) self.display_layout.setStretchFactor(self.speaker_field, 0) self.display_layout.setStretchFactor(self.utt_field, 1) self.transcript_slider = QSlider(QtCore.Qt.Horizontal, self) self.display_layout.addWidget(self.transcript_slider) self.transcript_slider.setMaximum(100) self.connect(self.transcript_slider, QtCore.SIGNAL("sliderMoved(int)"), self.position_transcript) self.left_layout.addWidget(self.transcript_slider)
class PostViewWidget(HorsePanel): def __init__(self, parent, order_overview_widget, find_order_slot): global configuration super(PostViewWidget, self).__init__(parent) self.set_panel_title(_("Post overview")) self.bold_font = QFont(self.font()) self.bold_font.setBold(True) self.nb_cols = 8 # Number of columns in the operation definition table self.order_overview_widget = order_overview_widget self.button = QPushButton(_("Refresh"), self) self.button.clicked.connect(self.refresh_action) self.sort_by_deadline_button = QRadioButton(_("By deadline"), self) self.sort_by_deadline_button.toggled.connect(self.sort_by_deadline) self.sort_by_size_button = QRadioButton(_("By hours left to do"), self) self.sort_by_size_button.toggled.connect(self.sort_by_size) # hlayout = QHBoxLayout() # hlayout.setObjectName("halyout") # hlayout.setContentsMargins(0,0,0,0) # hlayout.addWidget(self.sort_by_deadline_button) # hlayout.addWidget(self.sort_by_size_button) # hlayout.addWidget(self.button) # hlayout.addStretch() self.navbar = NavBar(self, [(self.sort_by_deadline_button, None), (self.sort_by_size_button, None), (self.button, None), (_("Find"), find_order_slot)]) self.navbar.buttons[3].setObjectName("specialMenuButton") self.vlayout = QVBoxLayout(self) self.vlayout.setObjectName("Vlayout") self.vlayout.addWidget( TitleWidget(_("Posts Overview"), self, self.navbar)) self._table_model = QStandardItemModel(1, self.nb_cols, self) self.table_view = QTableView(None) self.table_view.setModel(self._table_model) self.table_view.selectionModel().currentChanged.connect( self.operation_selected) self.table_view.verticalHeader().hide() self.table_view.horizontalHeader().hide() self.table_view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows) # This forces Qt to expand layout once I fill data in # FIXME dirty but I really don't get why setting # the mini width to something smaller (that happens at # startup, on first refresh) doesn't work self.table_view.setMinimumWidth(1) self.table_view.setMaximumWidth(1) self.post_view_scene = PostViewScene(self, order_overview_widget) self.post_view_scene_view = QGraphicsView(self) self.post_view_scene_view.setScene(self.post_view_scene) self.post_view_scene_view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.splitter = QSplitter(Qt.Horizontal) self.splitter.addWidget( SubFrame(_("Posts"), self.table_view, self.splitter)) self.splitter.addWidget( SubFrame(_("Workload"), self.post_view_scene_view, self.splitter)) # self.splitter.setStretchFactor(0,1) self.splitter.setStretchFactor(1, 1) self.vlayout.addWidget(self.splitter) # hlayout = QHBoxLayout() # hlayout.addWidget(SubFrame(_("Posts"),self.table_view,self)) # hlayout.addWidget(SubFrame(_("Workload"),self.post_view_scene_view,self)) # hlayout.setStretch(1,1) # self.vlayout.addLayout(hlayout) self.vlayout.setStretch(0, 0) self.vlayout.setStretch(1, 1) self.setLayout(self.vlayout) self.timer = QTimer(self) self.timer.timeout.connect(self.slidePostsScene) self.current_view_y = 0 def _data_load(self): global dao all_operations = dao.operation_dao.load_all_operations_ready_for_production( ) operation_definitions = dao.operation_definition_dao.all_direct_frozen( ) return operation_definitions, all_operations def _reset_operation_definitions(self, operations): self._table_model.setColumnCount(1) self._table_model.setRowCount(len(operations)) # BUG This should be refreshed on reload() too row = col = 0 first_active = None for opdef in operations: if opdef.operation_definition_id in self.post_view_scene.drawn_operations_data: # currently total planned time t = self.post_view_scene.drawn_operations_data[ opdef.operation_definition_id] ndx = self._table_model.index(row, col) if not first_active: first_active = ndx self._table_model.setData( ndx, u"{} {}".format(opdef.description, t), Qt.DisplayRole) # self._table_model.setData(ndx,self.bold_font,Qt.FontRole) self._table_model.setData(self._table_model.index(row, col), opdef.operation_definition_id, Qt.UserRole) row += 1 else: pass # self._table_model.setData(self._table_model.index(row,col),opdef.description,Qt.DisplayRole) # = col + 1 # if col == self.nb_cols: # col = 0 # row += 1 self._table_model.setRowCount(row) # self.table_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) # self.vlayout.setStretch(0,0) # self.vlayout.setStretch(1,10) # self.vlayout.setStretch(2,10000) # height = 0 # for c in range(self.table_view.model().rowCount()): # height += self.table_view.rowHeight(c) + 1 # +1 for cell border # self.table_view.setMinimumHeight(height) # self.table_view.setMaximumHeight(height) for i in range(self.nb_cols): self.table_view.resizeColumnToContents(i) self.table_view.setMaximumWidth(self.table_view.columnWidth(0)) self.table_view.setMinimumWidth(self.table_view.columnWidth(0)) self.table_view.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred) self.table_view.update() self.splitter.update() return first_active def slide_to_operation(self, opdef_id): if opdef_id in self.post_view_scene.posts_offsets: self.slide_target_opdef_id = opdef_id # mainlog.debug("Target y = {}".format(self.post_view_scene.posts_offsets[self.slide_target_opdef])) self.timer.start(20) @Slot() def slidePostsScene(self): if self.slide_target_opdef_id is None: return # self.post_view_scene_view self.post_view_scene.set_cursor_on( self.slide_target_opdef_id ) # This done here also aviod some screen trashing v = self.post_view_scene_view.verticalScrollBar().value() # mainlog.debug( "slidePostsScene : {}".format(v)) r = self.post_view_scene.posts_offsets[self.slide_target_opdef_id] target_y = r.y() + r.height() / 2 delta = (target_y - self.current_view_y) * 0.4 self.current_view_y = self.current_view_y + delta self.post_view_scene_view.centerOn(0, self.current_view_y) # mainlog.debug( "slidePostsScene : {} / {}".format(target_y, self.current_view_y)) if self.post_view_scene_view.verticalScrollBar().value() == v: # Close enough => stop moving # FIXME not correct because we must stop when the view stops moving, not when the goal we set for centerOn is reached self.timer.stop() @Slot(QModelIndex, QModelIndex) def operation_selected(self, ndx_cur, ndx_old): if ndx_cur.isValid(): opdef = self._table_model.data(ndx_cur, Qt.UserRole) if opdef: self.slide_to_operation( self._table_model.data(ndx_cur, Qt.UserRole)) @Slot() def refresh_action(self): # FIXME reload operations as well operation_definitions, all_operations = self._data_load() # mainlog.debug("reload") if self.sort_by_deadline_button.isChecked(): self.post_view_scene.reload(self, operation_definitions, all_operations, 1) elif self.sort_by_size_button.isChecked(): self.post_view_scene.reload(self, operation_definitions, all_operations, 2) else: self.post_view_scene.reload(self, operation_definitions, all_operations, 0) # mainlog.debug("reset") first_active = self._reset_operation_definitions(operation_definitions) # self.table_view.selectionModel().currentChanged.connect(self.operation_selected) if first_active: self.table_view.setCurrentIndex(first_active) # mainlog.debug("done reset") @Slot(bool) def sort_by_deadline(self, checked): if checked: self.refresh_action() @Slot(bool) def sort_by_size(self, checked): if checked: self.refresh_action() order_part_double_clicked = Signal(int) # Callback that will be called by HooverBar def set_on_order_part(self, order_part_id): self.order_part_double_clicked.emit(order_part_id)
class MainWindow(QDialog): """monkey_linux UI""" def __init__(self,parent=None): super(MainWindow, self).__init__() self.init_conf() self.setParent(parent) common.Log.info("set up ui") self.setup_ui() self.findDeviceAction.triggered.connect(self.get_device_status) self.deleteDeviceAction.triggered.connect(self.del_device) # self.storeButton.clicked.connect(self.set_conf) self.startButton.clicked.connect(self.start) self.stopButton.clicked.connect(self.stop) self.checkLogButton.clicked.connect(self.check) self.monkeyButton.clicked.connect(self.checkMonkeyLog) self.exportButton.clicked.connect(self.exportConf) self.importButton.clicked.connect(self.importConf) self.setAbout.triggered.connect(self.about) self.startTime = datetime.datetime.now() self.secsTime = float(1) * 60 * 60 def setup_ui(self): # main window width hand height # self.setMinimumWidth(600) self.setMaximumWidth(800) self.setMinimumHeight(600) # main window title self.setWindowTitle(static.title) # file menu bar self.menuBar = QMenuBar() self.menuBar.setMaximumHeight(23) # self.menuFile = self.menuBar.addMenu(static.menuFile) # self.importAction = QAction(QIcon(static.importPNG), static.importFile, self) # self.exportAction = QAction(QIcon(static.exportPNG), static.exportFile, self) # self.menuFile.addAction(self.importAction) # self.menuFile.addAction(self.exportAction) self.setEnvActioin = QAction(QIcon(static.setPNG), static.pcSet, self) self.menuSet = self.menuBar.addMenu(static.menuSet) self.menuSet.addAction(self.setEnvActioin) self.setAbout = QAction(QIcon(static.setPNG), static.menuAbout, self) self.setAbout.setStatusTip('About') # 状态栏提示 self.menuHelp = self.menuBar.addMenu(static.menuHelp) self.menuHelp.addAction(self.setAbout) # set all layout self.hbox = QHBoxLayout(self) # device ======== self.topLeft = QFrame(self) self.topLeft.setMaximumSize(218, 300) self.topLeft.setMinimumSize(218, 200) self.topLeft.setFrameShape(QFrame.StyledPanel) self.topLeftLayout = QVBoxLayout(self.topLeft) self.toolBar = QToolBar() # self.androidDeviceAction = QRadioButton('Android', self) # self.androidDeviceAction.setFocusPolicy(Qt.NoFocus) # self.ipDeviceAction = QRadioButton('IP', self) # self.ipDeviceAction.setFocusPolicy(Qt.NoFocus) # self.ipDeviceAction.move(10, 10) # self.ipDeviceAction.toggle() self.findDeviceAction = QAction(QIcon(static.findDevice), static.findDeviceButton, self) self.deleteDeviceAction = QAction(QIcon(static.deleteDevice), static.deleteDeviceButton, self) # self.toolBar.addWidget(self.androidDeviceAction) # self.toolBar.addWidget(self.ipDeviceAction) self.toolBar.addAction(self.findDeviceAction) self.toolBar.addAction(self.deleteDeviceAction) self.deviceLab = QLabel(static.deviceName, self) self.device = QTableWidget(1, 2) self.device.setHorizontalHeaderLabels(['name', 'status']) self.device.setColumnWidth(0, 100) self.device.setColumnWidth(1, 80) self.topLeftLayout.addWidget(self.deviceLab) self.topLeftLayout.addWidget(self.toolBar) self.topLeftLayout.addWidget(self.device) # set button or other for running monkey or not and status of device and log ======== self.topRight = QFrame(self) self.topRight.setFrameShape(QFrame.StyledPanel) self.topRight.setMaximumHeight(40) self.startButton = QPushButton(QIcon(static.startPNG), "") self.stopButton = QPushButton(QIcon(static.stopPNG), "") self.status = QLabel(static.status) self.statusEdit = QLineEdit(self) self.statusEdit.setReadOnly(True) self.statusEdit.setMaximumWidth(80) self.statusEdit.setMinimumWidth(80) self.statusEdit.setText("") # check log self.checkLogButton = QPushButton(static.checkLog) self.checkLogButton.setMaximumHeight(20) self.checkLogButton.setMinimumHeight(20) self.checkLogButton.setMaximumWidth(60) self.selectLog = QLabel(static.selectlog) self.logfile = QComboBox() self.dirlist = os.listdir(os.path.join(DIR, "Result")) for d in self.dirlist: if d != "AutoMonkey.log": self.logfile.insertItem(0, d) self.logfile.setMaximumWidth(150) self.logfile.setMaximumHeight(20) self.logfile.setMinimumHeight(20) self.topLayout = QHBoxLayout(self.topRight) self.topLayout.addWidget(self.startButton) self.topLayout.addWidget(self.stopButton) self.topLayout.addWidget(self.status) self.topLayout.addWidget(self.statusEdit) self.topLayout.addWidget(self.selectLog) self.topLayout.addWidget(self.logfile) self.topLayout.addWidget(self.checkLogButton) # set parameter for monkey ======= self.midRight = QFrame(self) self.midRight.setMaximumSize(555, 200) self.midRight.setMinimumSize(555, 200) self.midRight.setFrameShape(QFrame.StyledPanel) self.midRightLayout = QVBoxLayout(self.midRight) self.subLayout0 = QVBoxLayout() self.subLayout1 = QVBoxLayout() self.subLayout2 = QHBoxLayout() self.subLayout3 = QVBoxLayout() self.subLayout4 = QVBoxLayout() self.subLayout5 = QHBoxLayout() self.subLayout6 = QHBoxLayout() self.toolBar = QToolBar() # self.storeAction = QAction(QIcon(static.storePNG), static.storeButton, self) self.startAction = QAction(QIcon(static.startPNG), static.startButton, self) self.stopAction = QAction(QIcon(static.stopPNG), static.stopButton, self) # self.toolBar.addAction(self.storeAction) self.toolBar.addAction(self.startAction) self.toolBar.addAction(self.stopAction) self.timeLongLbl = QLabel(static.timeString, self) self.timeLong = QLineEdit(self) self.timeLong.setMaximumWidth(100) self.timeLong.setMinimumWidth(100) self.timeLong.setPlaceholderText(static.timeLong) self.timeLongUnit = QLabel("H") self.etSetLbl = QLabel(static.eventTypeSet) self.etSet = QTableWidget(2, 2) self.etSet.setMaximumHeight(150) self.etSet.setHorizontalHeaderLabels(['option', 'value']) self.etSet.horizontalHeader().setStretchLastSection(True) self.etSet.setItem(0, 0, QTableWidgetItem("--throttle")) self.etSet.setItem(0, 1, QTableWidgetItem(str(static.eventType["--throttle"]))) # set event type percent self.etPercentLbl = QLabel(static.eventTpyePercent, self) self.etPercent = QTableWidget(2, 2) self.etPercent.setMaximumHeight(150) self.etPercent.setHorizontalHeaderLabels(['option', 'value']) self.etPercent.horizontalHeader().setStretchLastSection(True) self.etPercent.setItem(0, 0, QTableWidgetItem("--pct-touch")) self.etPercent.setItem(0, 1, QTableWidgetItem(str(static.eventPercent["--pct-touch"]))) self.etPercent.setItem(1, 0, QTableWidgetItem("--pct-motion")) self.etPercent.setItem(1, 1, QTableWidgetItem(str(static.eventPercent["--pct-motion"]))) # self.storeButton = QPushButton(QIcon(static.storePNG), static.storeButton) # self.storeButton.setToolTip(static.storeButton) self.exportButton = QPushButton(QIcon(static.exportPNG), static.exportFile) self.exportButton.setToolTip(static.exportFile) self.importButton = QPushButton(QIcon(static.importPNG), static.importFile) self.importButton.setToolTip(static.importFile) self.subLayout2.addWidget(self.timeLongLbl) self.subLayout2.addWidget(self.timeLong) self.subLayout2.addWidget(self.timeLongUnit) self.subLayout2.addWidget(QLabel(" " * 300)) # self.subLayout2.addWidget(self.storeButton) self.subLayout2.addWidget(self.exportButton) self.subLayout2.addWidget(self.importButton) self.subLayout0.addLayout(self.subLayout2) self.subLayout3.addWidget(self.etSetLbl) self.subLayout3.addWidget(self.etSet) self.subLayout4.addWidget(self.etPercentLbl) self.subLayout4.addWidget(self.etPercent) self.subLayout5.addLayout(self.subLayout0) self.subLayout6.addLayout(self.subLayout3) self.subLayout6.addLayout(self.subLayout4) self.midRightLayout.addLayout(self.subLayout5) self.midRightLayout.addLayout(self.subLayout6) # log ======== self.bottom = QFrame(self) self.bottom.setFrameShape(QFrame.StyledPanel) # log information self.logInfo = QLabel(static.logInfo) # information filter self.logFilter = QLabel(static.logFilter) self.monkeyButton = QPushButton(static.openMonkeyLog) self.combo = QComboBox() for i in range(len(static.logLevel)): self.combo.addItem(static.logLevel[i]) self.combo.setMaximumWidth(55) self.combo.setMaximumHeight(20) self.combo.setMinimumHeight(20) # information details self.bottomLayout = QVBoxLayout(self.bottom) self.subLayout = QHBoxLayout() self.subLayout.addWidget(self.logInfo) for i in range(10): self.subLayout.addWidget(QLabel("")) self.subLayout.addWidget(self.monkeyButton) self.subLayout.addWidget(self.logFilter) self.subLayout.addWidget(self.combo) self.bottomLayout.addLayout(self.subLayout) self.tabwidget = TabWidget() self.tabwidget.setMinimumHeight(100) self.bottomLayout.addWidget(self.tabwidget) # splitter mainWindow ++++++++++++++++++++++++++++++++++++ self.splitter2 = QSplitter(Qt.Vertical) self.splitter2.addWidget(self.topRight) self.splitter2.addWidget(self.midRight) self.splitter0 = QSplitter(Qt.Horizontal) self.splitter0.addWidget(self.topLeft) self.splitter0.addWidget(self.splitter2) self.splitter1 = QSplitter(Qt.Vertical) self.splitter1.addWidget(self.menuBar) self.splitter1.addWidget(self.splitter0) self.splitter1.addWidget(self.bottom) self.hbox.addWidget(self.splitter1) self.setLayout(self.hbox) self.show() def about(self): common.showDialog(static.menuAbout, static.dialogAbout) def init_conf(self): common.Log.info("init monkey conf") with open(monkeyConfFile, "w") as f: f.write("deviceList = []" + "\n") f.write("times = " + static.times + "\n") f.write("--throttle = " + static.eventType["--throttle"] + "\n") f.write("--pct-touch = " + static.eventPercent["--pct-touch"] + "\n") f.write("--pct-motion = " + static.eventPercent["--pct-motion"] + "\n") def setup_env(self): pass def _set_eventType(self, confFile): try: option = self.etSet.item(0, 0).text() value = self.etSet.item(0, 1).text() if value > "0": with open(confFile, 'a+') as f: f.write(option + " = " + value + "\n") except AttributeError, e: pass
class FilterTab(QWidget): """This class is the GUI for creating filters for the FilterBox module. This GUI will be added as a tab to the ModuleFrame tab dialog. """ applySignal = Signal(Clause) def __init__(self, parent, mframe, existing_filters): """Create a FilterTab with the given parent TabDialog, logical parent ModuleFrame mframe, and existing_filters list of Clause objects. """ super(FilterTab, self).__init__(parent) self.mframe = mframe self.parent = parent self.attributes = self.mframe.agent.datatree.generateAttributeList() self.clause_list = list() self.clause_dict = dict() # Right now we only look at the first passed in filter. # TODO: At GUI to switch between existing filters if existing_filters is not None and len(existing_filters) > 0: for clause in existing_filters[0].conditions.clauses: self.clause_list.append(str(clause)) self.clause_dict[str(clause)] = clause self.clause_model = QStringListModel(self.clause_list) layout = QVBoxLayout(self) self.sidesplitter = QSplitter(Qt.Horizontal) # You can only select one attribute at a time to build the # filter clauses self.data_view = QTreeView(self) self.data_view.setModel(self.mframe.agent.datatree) self.data_view.setDragEnabled(True) self.data_view.setDropIndicatorShown(True) self.data_view.expandAll() self.sidesplitter.addWidget(self.data_view) self.sidesplitter.setStretchFactor(1,1) self.filter_widget = self.buildFilterWidget() self.sidesplitter.addWidget(self.filter_widget) self.sidesplitter.setStretchFactor(1,0) layout.addWidget(self.sidesplitter) # Apply buttons buttonWidget = QWidget() buttonLayout = QHBoxLayout(buttonWidget) self.applyButton = QPushButton("Apply") self.applyButton.clicked.connect(self.applyFilter) self.closeButton = QPushButton("Apply & Close") self.closeButton.clicked.connect(self.applyCloseFilter) buttonLayout.addWidget(self.applyButton) buttonLayout.addWidget(self.closeButton) buttonWidget.setLayout(buttonLayout) layout.addWidget(buttonWidget) self.setLayout(layout) def applyFilter(self): """Emits the applySignal with the Clause object currently represented by this FilterTab. """ num_clauses = len(self.clause_list) if num_clauses == 0: self.applySignal.emit(None) else: self.applySignal.emit(Clause("and", *self.clause_dict.values())) def applyCloseFilter(self): """Calls applyFilter and then closes the containing TabDialog.""" self.applyFilter() self.parent.close() def buildFilterWidget(self): """Creates the filter portion of the widget by laying out the subwidgets for relations, workspace and existing clauses. """ filter_widget = QWidget() filter_layout = QVBoxLayout(filter_widget) filter_layout.addWidget(self.buildRelationsWidget()) filter_layout.addItem(QSpacerItem(5,5)) filter_layout.addWidget(self.buildWorkFrame()) filter_layout.addItem(QSpacerItem(5,5)) filter_layout.addWidget(self.buildFilterListView()) filter_widget.setLayout(filter_layout) return filter_widget def buildFilterListView(self): """Creates the QListView that contains all of the basic Clause objects. """ groupBox = QGroupBox("Clauses") layout = QVBoxLayout(groupBox) self.list_view = QListView(groupBox) self.list_view.setModel(self.clause_model) layout.addWidget(self.list_view) layout.addItem(QSpacerItem(5,5)) self.delButton = QPushButton("Remove Selected Clause") self.delButton.clicked.connect(self.deleteClause) layout.addWidget(self.delButton) groupBox.setLayout(layout) return groupBox def buildWorkFrame(self): """Creates the grouped set of widgets that allow users to build basic Clause objects. """ groupBox = QGroupBox("Clause Workspace") layout = QHBoxLayout(groupBox) attributeCompleter = QCompleter(self.attributes) attributeCompleter.setCompletionMode(QCompleter.InlineCompletion) self.dropAttribute = DropLineEdit(self, self.mframe.agent.datatree, "", attributeCompleter) self.dropRelation = DropTextLabel("__") self.dropValue = FilterValueLineEdit(groupBox, self.mframe.agent.datatree, self.dropAttribute) # Clear dropValue when dropAttribute changes self.dropAttribute.textChanged.connect(self.dropValue.clear) # Enter in dropValue works like addButton self.dropValue.returnPressed.connect(self.addClause) self.addButton = QPushButton("Add", groupBox) self.addButton.clicked.connect(self.addClause) layout.addWidget(self.dropAttribute) layout.addItem(QSpacerItem(5,5)) layout.addWidget(self.dropRelation) layout.addItem(QSpacerItem(5,5)) layout.addWidget(self.dropValue) layout.addItem(QSpacerItem(5,5)) layout.addWidget(self.addButton) groupBox.setLayout(layout) return groupBox def buildRelationsWidget(self): """Creates the set of draggable relations. These relations are whatever is available in the relations dict of Table. """ relations_widget = QWidget() layout = QHBoxLayout(relations_widget) for relation in Table.relations: layout.addWidget(DragTextLabel(relation)) relations_widget.setLayout(layout) return relations_widget def addClause(self): """Adds a basic Clause to the current filter.""" if self.dropRelation.text() in Table.relations \ and len(self.dropValue.text()) > 0 \ and len(self.dropAttribute.text()) > 0: clause = Clause(self.dropRelation.text(), TableAttribute(self.dropAttribute.text()), self.dropValue.text()) # Guard double add if str(clause) not in self.clause_dict: self.clause_list.append(str(clause)) self.clause_dict[str(clause)] = clause self.clause_model.setStringList(self.clause_list) def deleteClause(self): """Removes the selected basic Clause objects from the current filter. """ clause = self.clause_model.data( self.list_view.selectedIndexes()[0], Qt.DisplayRole) if clause is not None and clause in self.clause_list: self.clause_list.remove(clause) del self.clause_dict[clause] self.clause_model.setStringList(self.clause_list)
class RobocompDslGui(QMainWindow): def __init__(self, parent=None): super(RobocompDslGui, self).__init__(parent) self.setWindowTitle("Create new component") # self._idsl_paths = [] self._communications = { "implements": [], "requires": [], "subscribesTo": [], "publishes": [] } self._interfaces = {} self._cdsl_doc = CDSLDocument() self._command_process = QProcess() self._main_widget = QWidget() self._main_layout = QVBoxLayout() self.setCentralWidget(self._main_widget) self._name_layout = QHBoxLayout() self._name_line_edit = QLineEdit() self._name_line_edit.textEdited.connect(self.update_component_name) self._name_line_edit.setPlaceholderText("New component name") self._name_layout.addWidget(self._name_line_edit) self._name_layout.addStretch() # DIRECTORY SELECTION self._dir_line_edit = QLineEdit() # self._dir_line_edit.textEdited.connect(self.update_completer) self._dir_completer = QCompleter() self._dir_completer_model = QFileSystemModel() if os.path.isdir(ROBOCOMP_COMP_DIR): self._dir_line_edit.setText(ROBOCOMP_COMP_DIR) self._dir_completer_model.setRootPath(ROBOCOMP_COMP_DIR) self._dir_completer.setModel(self._dir_completer_model) self._dir_line_edit.setCompleter(self._dir_completer) self._dir_button = QPushButton("Select directory") self._dir_button.clicked.connect(self.set_output_directory) self._dir_layout = QHBoxLayout() self._dir_layout.addWidget(self._dir_line_edit) self._dir_layout.addWidget(self._dir_button) # LIST OF ROBOCOMP INTERFACES self._interface_list = QListWidget() self._interface_list.setSelectionMode( QAbstractItemView.ExtendedSelection) self._interface_list.itemSelectionChanged.connect( self.set_comunication) # LIST OF CONNECTION TyPES self._type_combo_box = QComboBox() self._type_combo_box.addItems( ["publishes", "implements", "subscribesTo", "requires"]) self._type_combo_box.currentIndexChanged.connect( self.reselect_existing) # BUTTON TO ADD A NEW CONNECTION # self._add_connection_button = QPushButton("Add") # self._add_connection_button.clicked.connect(self.add_new_comunication) self._add_connection_layout = QHBoxLayout() # self._add_connection_layout.addWidget(self._add_connection_button) self._language_combo_box = QComboBox() self._language_combo_box.addItems(["Python", "Cpp", "Cpp11"]) self._language_combo_box.currentIndexChanged.connect( self.update_language) self._add_connection_layout.addWidget(self._language_combo_box) self._add_connection_layout.addStretch() self._gui_check_box = QCheckBox() self._gui_check_box.stateChanged.connect(self.update_gui_selection) self._gui_label = QLabel("Use Qt GUI") self._add_connection_layout.addWidget(self._gui_label) self._add_connection_layout.addWidget(self._gui_check_box) # WIDGET CONTAINING INTERFACES AND TYPES self._selection_layout = QVBoxLayout() self._selection_layout.addWidget(self._type_combo_box) self._selection_layout.addWidget(self._interface_list) self._selection_layout.addLayout(self._add_connection_layout) self._selection_widget = QWidget() self._selection_widget.setLayout(self._selection_layout) # TEXT EDITOR WITH THE RESULTING CDSL CODE self._editor = QTextEdit(self) self._editor.setHtml("") self._document = self._editor.document() self._component_directory = None # SPLITTER WITH THE SELECTION AND THE CODE self._body_splitter = QSplitter(Qt.Horizontal) self._body_splitter.addWidget(self._selection_widget) self._body_splitter.addWidget(self._editor) self._body_splitter.setStretchFactor(0, 2) self._body_splitter.setStretchFactor(1, 9) # CREATION BUTTONS self._create_button = QPushButton("Create .cdsl") self._create_button.clicked.connect(self.write_cdsl_file) self._creation_layout = QHBoxLayout() self._creation_layout.addStretch() self._creation_layout.addWidget(self._create_button) self._console = QConsole() self._command_process.readyReadStandardOutput.connect( self._console.standard_output) self._command_process.readyReadStandardError.connect( self._console.error_output) # ADDING WIDGETS TO MAIN LAYOUT self._main_widget.setLayout(self._main_layout) self._main_layout.addLayout(self._name_layout) self._main_layout.addLayout(self._dir_layout) self._main_layout.addWidget(self._body_splitter) self._main_layout.addLayout(self._creation_layout) self._main_layout.addWidget(self._console) self.setMinimumSize(800, 500) self._editor.setText(self._cdsl_doc.generate_doc()) # self.editor->show(); # def update_completer(self, path): # print "update_completer %s"%path # info = QFileInfo(path) # if info.exists() and info.isDir(): # if not path.endswith(os.path.pathsep): # new_path = os.path.join(path, os.sep) # # self._dir_line_edit.setText(new_path) # all_dirs_output = [dI for dI in os.listdir(path) if os.path.isdir(os.path.join(path, dI))] # print all_dirs_output # self._dir_completer.complete() def load_idsl_files(self, fullpath=None): if fullpath is None: fullpath = ROBOCOMP_INTERFACES idsls_dir = os.path.join(ROBOCOMP_INTERFACES, "IDSLs") if os.path.isdir(idsls_dir): for full_filename in os.listdir(idsls_dir): file_name, file_extension = os.path.splitext(full_filename) if "idsl" in file_extension.lower(): full_idsl_path = os.path.join(idsls_dir, full_filename) # self._idsl_paths.append(os.path.join(idsls_dir,full_filename)) self.parse_idsl_file(full_idsl_path) self._interface_list.addItems(self._interfaces.keys()) def parse_idsl_file(self, fullpath): with open(fullpath, 'r') as fin: interface_name = None for line in fin: result = re.findall(r'^\s*interface\s+(\w+)\s*\{?\s*$', line, flags=re.MULTILINE) if len(result) > 0: interface_name = result[0] print("%s for idsl %s" % (interface_name, fullpath)) if interface_name is not None: self._interfaces[interface_name] = fullpath def add_new_comunication(self): interface_names = self._interface_list.selectedItems() com_type = str(self._type_combo_box.currentText()) for iface_name_item in interface_names: iface_name = str(iface_name_item.text()) self._communications[com_type].append(iface_name) idsl_full_path = self._interfaces[iface_name] idsl_full_filename = os.path.basename(idsl_full_path) self._cdsl_doc.add_comunication(com_type, iface_name) self._cdsl_doc.add_import(idsl_full_filename) self.update_editor() def set_comunication(self): interface_names = self._interface_list.selectedItems() com_type = str(self._type_combo_box.currentText()) self._communications[com_type] = [] self._cdsl_doc.clear_comunication(com_type) for iface_name_item in interface_names: iface_name = str(iface_name_item.text()) self._communications[com_type].append(iface_name) self._cdsl_doc.add_comunication(com_type, iface_name) self.update_imports() self.update_editor() def update_imports(self): self._cdsl_doc.clear_imports() for com_type in self._communications: for iface_name in self._communications[com_type]: idsl_full_path = self._interfaces[iface_name] idsl_full_filename = os.path.basename(idsl_full_path) self._cdsl_doc.add_import(idsl_full_filename) def update_language(self): language = self._language_combo_box.currentText() self._cdsl_doc.set_language(str(language)) self.update_editor() def update_gui_selection(self): checked = self._gui_check_box.isChecked() if checked: self._cdsl_doc.set_qui(True) else: self._cdsl_doc.set_qui(False) self.update_editor() def update_component_name(self, name): self._cdsl_doc.set_name(name) self.update_editor() def update_editor(self): self._editor.setText(self._cdsl_doc.generate_doc()) def set_output_directory(self): dir_set = False while not dir_set: dir = QFileDialog.getExistingDirectory( self, "Select Directory", ROBOCOMP_COMP_DIR, QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) if self.check_dir_is_empty(str(dir)): self._dir_line_edit.setText(dir) dir_set = True def write_cdsl_file(self): component_dir = str(self._dir_line_edit.text()) text = self._cdsl_doc.generate_doc() if not self._name_line_edit.text(): component_name, ok = QInputDialog.getText(self, 'No component name set', 'Enter component name:') if ok: self.update_component_name(component_name) self._name_line_edit.setText(component_name) else: return False if not os.path.exists(component_dir): if QMessageBox.Yes == QMessageBox.question( self, "Directory doesn't exist.", "Do you want create the directory %s?" % component_dir, QMessageBox.Yes | QMessageBox.No): os.makedirs(component_dir) else: QMessageBox.question( self, "Directory not exist", "Can't create a component witout a valid directory") return False file_path = os.path.join(component_dir, str(self._name_line_edit.text()) + ".cdsl") if os.path.exists(file_path): if QMessageBox.No == QMessageBox.question( self, "File already exists", "Do you want to overwrite?", QMessageBox.Yes | QMessageBox.No): return False with open(file_path, 'w') as the_file: the_file.write(text) self.execute_robocomp_cdsl() return True def execute_robocomp_cdsl(self): cdsl_file_path = os.path.join( str(self._dir_line_edit.text()), str(self._name_line_edit.text()) + ".cdsl") command = "python -u %s/robocompdsl.py %s %s" % ( ROBOCOMPDSL_DIR, cdsl_file_path, os.path.join(str(self._dir_line_edit.text()))) self._console.append_custom_text("%s\n" % command) self._command_process.start(command, QProcess.Unbuffered | QProcess.ReadWrite) def reselect_existing(self): com_type = self._type_combo_box.currentText() selected = self._communications[com_type] self._interface_list.clearSelection() for iface in selected: items = self._interface_list.findItems(iface, Qt.MatchFlag.MatchExactly) if len(items) > 0: item = items[0] item.setSelected(True) def check_dir_is_empty(self, dir_path): if len(os.listdir(dir_path)) > 0: msgBox = QMessageBox() msgBox.setWindowTitle("Directory not empty") msgBox.setText( "The selected directory is not empty.\n" "For a new Component you usually want a new directory.\n" "Do you want to use this directory anyway?") msgBox.setStandardButtons(QMessageBox.Yes) msgBox.addButton(QMessageBox.No) msgBox.setDefaultButton(QMessageBox.No) if msgBox.exec_() == QMessageBox.Yes: return True else: return False else: return True
class BrowserWindow(QMainWindow): MO_ROLE = Qt.UserRole+1 def __init__(self, conn): super(BrowserWindow, self).__init__() self._conn = conn self._resolver = AsyncResolver() self._resolver.object_resolved.connect(self._data_resolved) self._resolver.start() self._init_models() self._init_gui() self._init_data() self._init_connections() def __del__(self): self._resolver.stop_work() self._resolver.terminate() def _init_models(self): self._hierarchy_model = QStandardItemModel() self._hierarchy_model.setColumnCount(2) self._hierarchy_model.setHorizontalHeaderLabels(['class', 'dn']) self._details_model = QStandardItemModel() self._details_model.setColumnCount(2) self._details_model.setHorizontalHeaderLabels(['Property', 'Value']) def _init_gui(self): self._widget = QSplitter(self, Qt.Horizontal) self._hierarchy_view = QTreeView(self._widget) self._details_view = QTableView(self._widget) self._widget.addWidget(self._hierarchy_view) self._widget.addWidget(self._details_view) self._widget.setStretchFactor(0, 2) self._widget.setStretchFactor(1, 1) self.setCentralWidget(self._widget) self._hierarchy_view.setModel(self._hierarchy_model) self._details_view.setModel(self._details_model) self._hierarchy_view.expanded.connect(self._mo_item_expand) def _init_data(self): item = self._row_for_mo(self._conn.resolve_dn('')) self._hierarchy_model.insertRow(0, item) def _init_connections(self): self.connect(self._resolver, SIGNAL('object_resolved(QVariant)'), self, SLOT('_data_resolved(QVariant)')) self._hierarchy_view.activated.connect(self._item_activated) #self.connect(self._hierarchy_view.selectionModel(), # SIGNAL('currentChanged(QModelIndex,QModelIndex)'), # self, # SLOT('_current_changed(QModelIndex, QModelIndex)')) self.connect(self._hierarchy_view.selectionModel(), SIGNAL('activated(QModelIndex)'), self, SLOT('_item_activated(QModelIndex)')) def _row_for_mo(self, mo): row = [QStandardItem(mo.ucs_class), QStandardItem(mo.dn)] for item in row: item.setEditable(False) row[0].appendColumn([QStandardItem('Loading...')]) row[0].setData(mo, self.MO_ROLE) return row def _add_mo_in_tree(self, mo, index=QtCore.QModelIndex()): item = None if index.isValid(): item = self._hierarchy_model.itemFromIndex(index) else: item = self._get_item_for_dn(self._parent_dn(mo.dn)) if item: item.appendColumn([self._row_for_mo(mo)[0]]) self.auto_width() def _add_mos_in_tree(self, mos, index=QtCore.QModelIndex()): item = None if index.isValid(): item = self._hierarchy_model.itemFromIndex(index) else: if not mos: return item = self._get_item_for_dn(self._parent_dn(mos[0].dn)) while item.columnCount(): item.removeColumn(0) items = map(self._row_for_mo, mos) if items: for x in xrange(len(items[0])): item.appendColumn([row[x] for row in items]) self.auto_width() @staticmethod def _parent_dn(dn): parent_dn, _, rn = dn.rpartition('/') return parent_dn def _get_item_for_dn(self, dn): parent_dn = dn items = self._hierarchy_model.findItems(parent_dn, column=1) if items: return self._hierarchy_model.item(items[0].row()) return None @QtCore.Slot('_data_resolved(QVariant)') def _data_resolved(self, datav): print 'Data resolved: ', datav index, data = datav if isinstance(data, UcsmObject): self._add_mo_in_tree(data, index=index) else: self._add_mos_in_tree(data, index=index) @QtCore.Slot('_current_changed(QModelIndex,QModelIndex)') def _current_changed(self, curr, prev): self._item_activated(curr) @QtCore.Slot('_item_activated(QModelIndex)') def _item_activated(self, index): print 'Activated: %s data %s' % (index, index.data(self.MO_ROLE)) if index.sibling(0, 0).isValid(): index = index.sibling(0, 0) data = index.data(self.MO_ROLE) self.set_detail_object(data) def _mo_item_expand(self, index): obj = index.data(self.MO_ROLE) print 'Expanded object: %s' % obj try: self._resolver.add_task(lambda: (index, self._conn.resolve_children(obj.dn))) except (KeyError, AttributeError): QtGui.QMessageBox.critical(0, 'Error', 'Object does not have dn') def auto_width(self): for view in [self._hierarchy_view, self._details_view]: for col in xrange(view.model().columnCount()): view.resizeColumnToContents(col) def set_detail_object(self, object): self._details_model.removeRows(0, self._details_model.rowCount()) for k, v in object.attributes.iteritems(): row = [QStandardItem(k), QStandardItem(v)] for item in row: item.setEditable(False) self._details_model.appendRow(row) self.auto_width()
def __init__(self, *args, **kwargs ): QMainWindow.__init__( self, *args, **kwargs ) self.installEventFilter( self ) #self.setWindowFlags( QtCore.Qt.Drawer ) self.setWindowTitle( Window_global.title ) verticalSplitter = QSplitter(QtCore.Qt.Vertical) self.setCentralWidget( verticalSplitter ) horizonSplitter1 = QSplitter(QtCore.Qt.Horizontal) horizonSplitter2 = QSplitter(QtCore.Qt.Horizontal) verticalSplitter.addWidget( horizonSplitter1 ) verticalSplitter.addWidget( horizonSplitter2 ) widgetSelArea = QWidget() layoutSelArea = QVBoxLayout(widgetSelArea) labelSelTextList = QLabel( 'Images from Selection' ) selTextureList = QListWidget() selTextureList.setSelectionMode( QAbstractItemView.ExtendedSelection ) layoutSelArea.addWidget( labelSelTextList ) layoutSelArea.addWidget( selTextureList ) imageBaseSelArea = ImageBase() horizonSplitter1.addWidget( widgetSelArea ) horizonSplitter1.addWidget( imageBaseSelArea ) widgetPathArea = QWidget() layoutPathArea = QVBoxLayout( widgetPathArea ) layoutAddTab = QHBoxLayout() removeTabButton = QPushButton( 'Remove Tab' ) addTabButton = QPushButton( 'Add Tab' ) self.tabWidget = Tab() buttonLayout = QHBoxLayout() getImageButton = QPushButton( 'Get Image' ) removeImageButton = QPushButton( 'Remove Image' ) layoutPathArea.addLayout( layoutAddTab ) layoutPathArea.addWidget( self.tabWidget ) layoutPathArea.addLayout( buttonLayout ) imageBasePathArea = ImageBase() layoutAddTab.addWidget( removeTabButton ) layoutAddTab.addWidget( addTabButton ) buttonLayout.addWidget( getImageButton ) buttonLayout.addWidget( removeImageButton ) horizonSplitter2.addWidget( widgetPathArea ) horizonSplitter2.addWidget( imageBasePathArea ) Window_global.selTextureList = selTextureList Window_global.imageBaseSelArea = imageBaseSelArea Window_global.imageBasePathArea = imageBasePathArea Window_global.verticalSplitter = verticalSplitter Window_global.horizonSplitter1 = horizonSplitter1 Window_global.horizonSplitter2 = horizonSplitter2 Window_global.getImageButton = getImageButton Window_global.removeImageButton = removeImageButton Window_global.tabWidget = self.tabWidget Window_global.tabWidget.addTab( 'newTab' ) verticalSplitter.setSizes( [100,100] ) horizonSplitter1.setSizes( [100,100] ) horizonSplitter2.setSizes( [100,100] ) Window_global.loadInfo() try:Window_global.loadInfo2() except:pass Functions.updateSelTextureList() QtCore.QObject.connect( addTabButton, QtCore.SIGNAL( 'clicked()' ), self.addTab ) QtCore.QObject.connect( removeTabButton, QtCore.SIGNAL( 'clicked()' ), self.removeTab ) QtCore.QObject.connect( Window_global.selTextureList, QtCore.SIGNAL( 'itemSelectionChanged()' ), Functions.loadImageSelArea ) QtCore.QObject.connect( Window_global.horizonSplitter1, QtCore.SIGNAL( 'splitterMoved(int,int)' ), Functions.splitterMoved1 ) QtCore.QObject.connect( Window_global.horizonSplitter2, QtCore.SIGNAL( 'splitterMoved(int,int)' ), Functions.splitterMoved2 ) QtCore.QObject.connect( getImageButton, QtCore.SIGNAL( 'clicked()' ), Functions.getImage ) QtCore.QObject.connect( removeImageButton, QtCore.SIGNAL( 'clicked()' ), Functions.removeImage ) imageBaseSelArea.clear() imageBasePathArea.clear() getImageButton.setEnabled( False ) removeImageButton.setEnabled( False )
def __init__(self, *args, **kwargs): QMainWindow.__init__(self, *args, **kwargs) self.installEventFilter(self) #self.setWindowFlags( QtCore.Qt.Drawer ) self.setWindowTitle(Window_global.title) verticalSplitter = QSplitter(QtCore.Qt.Vertical) self.setCentralWidget(verticalSplitter) horizonSplitter1 = QSplitter(QtCore.Qt.Horizontal) horizonSplitter2 = QSplitter(QtCore.Qt.Horizontal) verticalSplitter.addWidget(horizonSplitter1) verticalSplitter.addWidget(horizonSplitter2) widgetSelArea = QWidget() layoutSelArea = QVBoxLayout(widgetSelArea) labelSelTextList = QLabel('Images from Selection') selTextureList = QListWidget() selTextureList.setSelectionMode(QAbstractItemView.ExtendedSelection) layoutSelArea.addWidget(labelSelTextList) layoutSelArea.addWidget(selTextureList) imageBaseSelArea = ImageBase() horizonSplitter1.addWidget(widgetSelArea) horizonSplitter1.addWidget(imageBaseSelArea) widgetPathArea = QWidget() layoutPathArea = QVBoxLayout(widgetPathArea) layoutAddTab = QHBoxLayout() removeTabButton = QPushButton('Remove Tab') addTabButton = QPushButton('Add Tab') self.tabWidget = Tab() buttonLayout = QHBoxLayout() getImageButton = QPushButton('Get Image') removeImageButton = QPushButton('Remove Image') layoutPathArea.addLayout(layoutAddTab) layoutPathArea.addWidget(self.tabWidget) layoutPathArea.addLayout(buttonLayout) imageBasePathArea = ImageBase() layoutAddTab.addWidget(removeTabButton) layoutAddTab.addWidget(addTabButton) buttonLayout.addWidget(getImageButton) buttonLayout.addWidget(removeImageButton) horizonSplitter2.addWidget(widgetPathArea) horizonSplitter2.addWidget(imageBasePathArea) Window_global.selTextureList = selTextureList Window_global.imageBaseSelArea = imageBaseSelArea Window_global.imageBasePathArea = imageBasePathArea Window_global.verticalSplitter = verticalSplitter Window_global.horizonSplitter1 = horizonSplitter1 Window_global.horizonSplitter2 = horizonSplitter2 Window_global.getImageButton = getImageButton Window_global.removeImageButton = removeImageButton Window_global.tabWidget = self.tabWidget Window_global.tabWidget.addTab('newTab') verticalSplitter.setSizes([100, 100]) horizonSplitter1.setSizes([100, 100]) horizonSplitter2.setSizes([100, 100]) Window_global.loadInfo() try: Window_global.loadInfo2() except: pass Functions.updateSelTextureList() QtCore.QObject.connect(addTabButton, QtCore.SIGNAL('clicked()'), self.addTab) QtCore.QObject.connect(removeTabButton, QtCore.SIGNAL('clicked()'), self.removeTab) QtCore.QObject.connect(Window_global.selTextureList, QtCore.SIGNAL('itemSelectionChanged()'), Functions.loadImageSelArea) QtCore.QObject.connect(Window_global.horizonSplitter1, QtCore.SIGNAL('splitterMoved(int,int)'), Functions.splitterMoved1) QtCore.QObject.connect(Window_global.horizonSplitter2, QtCore.SIGNAL('splitterMoved(int,int)'), Functions.splitterMoved2) QtCore.QObject.connect(getImageButton, QtCore.SIGNAL('clicked()'), Functions.getImage) QtCore.QObject.connect(removeImageButton, QtCore.SIGNAL('clicked()'), Functions.removeImage) imageBaseSelArea.clear() imageBasePathArea.clear() getImageButton.setEnabled(False) removeImageButton.setEnabled(False)
class MainWindow(QMainWindow): """The application's main window """ # Emitted when there are pending files to be processed new_pending_files = QtCore.Signal() def __init__(self, app): super(MainWindow, self).__init__() # Window layout - a splitter with the image on the left and controls # on the right self._image_widget = ImageLabel(self) self._controls = Controls(self) self._splitter = QSplitter() self._splitter.addWidget(self._image_widget) self._splitter.addWidget(self._controls) self._splitter.setSizes([1200, 600]) # Main window layout self.setCentralWidget(self._splitter) # Connect controls to handlers self._controls.ok.clicked.connect(self.ok) self._controls.cancel.clicked.connect(self.cancel) self._controls.inbox.choose_directory.clicked.connect(self.choose_inbox) self._controls.processed.choose_directory.clicked.connect(self.choose_processed) # Directories mydocuments = QDesktopServices.storageLocation( QDesktopServices.DocumentsLocation) self._inbox = Path(QSettings().value('inbox', str(Path(mydocuments) / 'inbox'))) self._processed = Path(QSettings().value('processed', str(Path(mydocuments) / 'processed'))) self._controls.inbox.set_link(str(self._inbox.as_uri()), self._inbox.name) self._controls.processed.set_link(str(self._processed.as_uri()), self._processed.name) # A stack of Path objects to be processed self._pending_files = [] # The Path currently shown in the UI self._under_review = None # Watch the inbox directory, if it exists self.new_pending_files.connect(self.process_next_pending, QtCore.Qt.QueuedConnection) if self._inbox.is_dir(): self._watcher = NewFileWatcher(self._inbox, IMAGE_SUFFIXES_RE) self._watcher.new_file.connect(self.new_image_file) else: self._watcher = None self.empty_controls() # Setup drag-drop handling self.setAcceptDrops(True) self._controls.installEventFilter(self) self._splitter.installEventFilter(self) def new_inbox_directory(self): """Watch the inbox directory """ print('MainWindow.new_inbox_directory [{0}]'.format(self._inbox)) if self._watcher: self._watcher.new_file.disconnect() self._watcher = NewFileWatcher(self._inbox, IMAGE_SUFFIXES_RE) self._watcher.new_file.connect(self.new_image_file) def new_image_file(self, path): """Slot for self._watcher.new_file """ print('MainWindow.new_image_file [{0}]'.format(path)) self._pending_files.append(path) self.new_pending_files.emit() @report_to_user def process_next_pending(self): """Loads the next pending image for review """ print('MainWindow.process_next_pending: [{0}] files'.format( len(self._pending_files))) if not self._under_review: if self._pending_files: self.review_image(self._pending_files.pop()) else: self.empty_controls() def review_image(self, path): """Loads path for review """ print('MainWindow.review_image [{0}]'.format(path)) # Arbitrary delay to give the capture software time to finish writing # the image. time.sleep(1) image = cv2.imread(str(path)) if image is None: raise ValueError('Unable to read [{0}]'.format(path)) else: self._under_review = path self.setWindowTitle('') self.setWindowFilePath(str(path)) self._controls.specimen.setText(QSettings().value('specimen')) self._controls.location.setText(QSettings().value('location')) self._image_widget.set_pixmap(QPixmap.fromImage(qimage_of_bgr(image))) self._controls.image_handling.setEnabled(True) def empty_controls(self): """Clears controls """ print('MainWindow.empty_controls') self._under_review = None self.setWindowTitle('Syrup') self.setWindowFilePath(None) self._image_widget.set_pixmap(None) self._controls.clear() self._controls.image_handling.setEnabled(False) @report_to_user def ok(self): print('MainWindow.ok') specimen = self._controls.specimen.text() location = self._controls.location.text() if not SPECIMEN_RE.match(specimen): raise ValueError('Please enter nine digits for the specimen barcode') elif not LOCATION_RE.match(location): raise ValueError('Please enter a letter "L" and nine digits for the ' 'location barcode') else: if not self._processed.is_dir(): self._processed.mkdir(parents=True) destination = self._processed / '{0}_{1}'.format(specimen, location) destination = destination.with_suffix(self._under_review.suffix) move_and_rename(self._under_review, destination) QSettings().setValue('specimen', specimen) QSettings().setValue('location', location) self._under_review = None self.process_next_pending() @report_to_user def cancel(self): """Closes the image under review without moving the image file """ print('MainWindow.cancel') self._under_review = None self.process_next_pending() @report_to_user def choose_inbox(self): """Prompts the user to choose the inbox directory """ directory = QFileDialog.getExistingDirectory(self, "Choose the inbox directory", str(self._inbox)) if directory: directory = Path(directory) if directory == self._processed: raise ValueError('The inbox directory cannot be the same as ' 'the processed directory') else: self._inbox = directory print('New inbox directory [{0}]'.format(self._inbox)) self._controls.inbox.set_link(str(self._inbox.as_uri()), self._inbox.name) QSettings().setValue('inbox', str(self._inbox)) self.new_inbox_directory() @report_to_user def choose_processed(self): """Prompts the user to choose the processed directory """ directory = QFileDialog.getExistingDirectory(self, "Choose the processed directory", str(self._processed)) if directory: directory = Path(directory) if directory == self._inbox: raise ValueError('The inbox directory cannot be the same as ' 'the processed directory') else: self._processed = directory print('New processed directory [{0}]'.format(self._processed)) self._controls.processed.set_link(str(self._processed.as_uri()), self._processed.name) QSettings().setValue('processed', str(self._processed)) def write_geometry_settings(self): "Writes geometry to settings" print('MainWindow.write_geometry_settings') # Taken from http://stackoverflow.com/a/8736705 # TODO LH Test on multiple display system s = QSettings() s.setValue("mainwindow/geometry", self.saveGeometry()) s.setValue("mainwindow/pos", self.pos()) s.setValue("mainwindow/size", self.size()) def show_from_geometry_settings(self): print('MainWindow.show_from_geometry_settings') # TODO LH What if screen resolution, desktop config change or roaming # profile means that restored state is outside desktop? s = QSettings() self.restoreGeometry(s.value("mainwindow/geometry", self.saveGeometry())) if not (self.isMaximized() or self.isFullScreen()): self.move(s.value("mainwindow/pos", self.pos())) self.resize(s.value("mainwindow/size", self.size())) self.show() def closeEvent(self, event): """QWidget virtual """ print('MainWindow.closeEvent') self.write_geometry_settings() event.accept() def eventFilter(self, obj, event): "Event filter that accepts drag-drop events" if event.type() in (QEvent.DragEnter, QEvent.Drop): return True else: return super(MainWindow, self).eventFilter(obj, event) def _accept_drag_drop(self, event): """If no image is under review and event refers to a single image file, returns the path. Returns None otherwise. """ if self._under_review: return None else: urls = event.mimeData().urls() if event.mimeData() else None path = Path(urls[0].toLocalFile()) if urls and 1 == len(urls) else None print(path, IMAGE_SUFFIXES_RE.match(path.suffix)) if path and IMAGE_SUFFIXES_RE.match(path.suffix): return urls[0].toLocalFile() else: return None def dragEnterEvent(self, event): """QWidget virtual """ print('MainWindow.dragEnterEvent') if self._accept_drag_drop(event): event.acceptProposedAction() else: super(MainWindow, self).dragEnterEvent(event) @report_to_user def dropEvent(self, event): """QWidget virtual """ print('MainWindow.dropEvent') res = self._accept_drag_drop(event) if res: event.acceptProposedAction() self.review_image(Path(res)) else: super(MainWindow, self).dropEvent(event)