def _construct_UI(self): """ Construct the main GUI, consisting of: - Tabbed input widgets (left side) - Tabbed plot widgets (right side) - Logger window (right side, below plot tab) """ # ============== UI Layout with H and V-Splitter ===================== inputTabWidgets = input_tab_widgets.InputTabWidgets( self) # input widgets pltTabWidgets = plot_tab_widgets.PlotTabWidgets(self) # plot widgets self.loggerWin = QPlainTextEdit(self) # logger window self.loggerWin.setReadOnly(True) # set custom right-button context menu policy self.loggerWin.setContextMenuPolicy(Qt.CustomContextMenu) self.loggerWin.customContextMenuRequested.connect( self.logger_win_context_menu) # create context menu and define actions and shortcuts self.popMenu = QMenu(self) self.popMenu.addAction('Select &All', self.loggerWin.selectAll, "Ctrl+A") self.popMenu.addAction('&Copy Selected', self.loggerWin.copy) self.popMenu.addSeparator() self.popMenu.addAction('Clear &Window', self.loggerWin.clear) # ============================================================================= # add logger window underneath plot Tab Widgets spltVPltLogger = QSplitter(QtCore.Qt.Vertical) spltVPltLogger.addWidget(pltTabWidgets) spltVPltLogger.addWidget(self.loggerWin) # create horizontal splitter that contains all subwidget groups spltHMain = QSplitter(QtCore.Qt.Horizontal) spltHMain.addWidget(inputTabWidgets) spltHMain.addWidget(spltVPltLogger) spltHMain.setStretchFactor(1, 4) # relative initial sizes of subwidgets spltHMain.setContentsMargins(*rc.params['wdg_margins']) spltHMain.setFocus() # make spltHMain occupy the main area of QMainWindow and make QMainWindow its parent !!! self.setCentralWidget(spltHMain) spltVPltLoggerH = spltVPltLogger.size().height() spltVPltLogger.setSizes( [int(spltVPltLoggerH * 0.95), int(spltVPltLoggerH * 0.05 - 8)]) self.setWindowTitle('pyFDA - Python Filter Design and Analysis') #=============== Menubar ======================================= # aboutAction = QAction('&About', self) # aboutAction.setShortcut('Ctrl+A') # aboutAction.setStatusTip('Info about pyFDA') # # menubar = self.menuBar() # fileMenu = menubar.addMenu('&About') # fileMenu.addAction(aboutAction) # self.statusMessage("Application is initialized.") #---------------------------------------------------------------------- # GLOBAL SIGNALS & SLOTs #---------------------------------------------------------------------- self.sig_rx.connect(self.process_sig_rx) #---------------------------------------------------------------------- # SIGNALS & SLOTs #---------------------------------------------------------------------- # Here, signals about spec and design changes from lower hierarchies # are distributed. At the moment, only changes in the input widgets are # routed to the plot widgets: inputTabWidgets.sig_tx.connect(pltTabWidgets.sig_rx) inputTabWidgets.sig_tx.connect(self.process_sig_rx) pltTabWidgets.sig_tx.connect(inputTabWidgets.sig_rx) # open pop-up "about" window #aboutAction.triggered.connect(self.aboutWindow) # trigger the close event in response to sigQuit generated in another subwidget: # inputTabWidgets.input_filter_specs.sigQuit.connect(self.close) # when a message has been written, pass it via signal-slot mechanism and # print it to logger window XStream.stdout().messageWritten.connect(self.loggerWin.appendHtml)
class pyFDA(QMainWindow): """ Create the main window consisting of a tabbed widget for entering filter specifications, poles / zeros etc. and another tabbed widget for plotting various filter characteristics QMainWindow is used here as it is a class that understands GUI elements like toolbar, statusbar, central widget, docking areas etc. """ sig_rx = pyqtSignal(object) # incoming # sig_tx = pyqtSignal(object) # outgoing def __init__(self, parent=None): super(QMainWindow, self).__init__() self.setAttribute(QtCore.Qt.WA_DeleteOnClose) # create clipboard instance that can be accessed from other modules fb.clipboard = QApplication.clipboard() # initialize the FilterTreeBuilder class: # read config file and construct filter tree from it _ = Tree_Builder() # TODO_ couldn't this be a function? self._construct_UI() def _construct_UI(self): """ Construct the main GUI, consisting of: - Tabbed input widgets (left side) - Tabbed plot widgets (right side) - Logger window (right side, below plot tab) """ # ============== UI Layout with H and V-Splitter ===================== inputTabWidgets = input_tab_widgets.InputTabWidgets( self) # input widgets pltTabWidgets = plot_tab_widgets.PlotTabWidgets(self) # plot widgets self.loggerWin = QPlainTextEdit(self) # logger window self.loggerWin.setReadOnly(True) # set custom right-button context menu policy self.loggerWin.setContextMenuPolicy(Qt.CustomContextMenu) self.loggerWin.customContextMenuRequested.connect( self.logger_win_context_menu) # create context menu and define actions and shortcuts self.popMenu = QMenu(self) self.popMenu.addAction('Select &All', self.loggerWin.selectAll, "Ctrl+A") self.popMenu.addAction('&Copy Selected', self.loggerWin.copy) self.popMenu.addSeparator() self.popMenu.addAction('Clear &Window', self.loggerWin.clear) # ============================================================================= # add logger window underneath plot Tab Widgets spltVPltLogger = QSplitter(QtCore.Qt.Vertical) spltVPltLogger.addWidget(pltTabWidgets) spltVPltLogger.addWidget(self.loggerWin) # create horizontal splitter that contains all subwidget groups spltHMain = QSplitter(QtCore.Qt.Horizontal) spltHMain.addWidget(inputTabWidgets) spltHMain.addWidget(spltVPltLogger) spltHMain.setStretchFactor(1, 4) # relative initial sizes of subwidgets spltHMain.setContentsMargins(*rc.params['wdg_margins']) spltHMain.setFocus() # make spltHMain occupy the main area of QMainWindow and make QMainWindow its parent !!! self.setCentralWidget(spltHMain) spltVPltLoggerH = spltVPltLogger.size().height() spltVPltLogger.setSizes( [int(spltVPltLoggerH * 0.95), int(spltVPltLoggerH * 0.05 - 8)]) self.setWindowTitle('pyFDA - Python Filter Design and Analysis') #=============== Menubar ======================================= # aboutAction = QAction('&About', self) # aboutAction.setShortcut('Ctrl+A') # aboutAction.setStatusTip('Info about pyFDA') # # menubar = self.menuBar() # fileMenu = menubar.addMenu('&About') # fileMenu.addAction(aboutAction) # self.statusMessage("Application is initialized.") #---------------------------------------------------------------------- # GLOBAL SIGNALS & SLOTs #---------------------------------------------------------------------- self.sig_rx.connect(self.process_sig_rx) #---------------------------------------------------------------------- # SIGNALS & SLOTs #---------------------------------------------------------------------- # Here, signals about spec and design changes from lower hierarchies # are distributed. At the moment, only changes in the input widgets are # routed to the plot widgets: inputTabWidgets.sig_tx.connect(pltTabWidgets.sig_rx) inputTabWidgets.sig_tx.connect(self.process_sig_rx) pltTabWidgets.sig_tx.connect(inputTabWidgets.sig_rx) # open pop-up "about" window #aboutAction.triggered.connect(self.aboutWindow) # trigger the close event in response to sigQuit generated in another subwidget: # inputTabWidgets.input_filter_specs.sigQuit.connect(self.close) # when a message has been written, pass it via signal-slot mechanism and # print it to logger window XStream.stdout().messageWritten.connect(self.loggerWin.appendHtml) #------------------------------------------------------------------------------ def process_sig_rx(self, dict_sig=None): """ Process signals coming from sig_rx: - trigger close event in response to 'quit_program' emitted in another subwidget: """ logger.debug("Processing {0}: {1}".format( type(dict_sig).__name__, dict_sig)) if 'quit_program' in dict_sig: self.close() #============================================================================== # def statusMessage(self, message): # """ # Display a message in the statusbar. # """ # self.statusBar().showMessage(message) # # #============================================================================== def logger_win_context_menu(self, point): """ Show right mouse button context menu """ self.popMenu.exec_(self.loggerWin.mapToGlobal(point)) # ============================================================================= def closeEvent(self, event): """ reimplement QMainWindow.closeEvent() to prompt the user """ reply = QMessageBox.question(self, 'Message', "Quit pyFDA?", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: # Clear clipboard before exit to avoid error message on older Qt versions # "QClipboard: Unable to receive an event from the clipboard manager # in a reasonable time fb.clipboard.clear() event.accept() else: event.ignore()