Example #1
0
    def __createInspectorActionGroup(self, parent):
        """ Creates an action group with 'set inspector' actions for all installed inspector.
        """
        actionGroup = QtWidgets.QActionGroup(parent)
        actionGroup.setExclusive(True)

        sortedItems = sorted(self.argosApplication.inspectorRegistry.items,
                             key=lambda item: item.identifier)
        shortCutNr = 1
        for item in sortedItems:
            logger.debug("item: {}".format(item.identifier))
            setAndDrawFn = partial(self.setAndDrawInspectorById,
                                   item.identifier)
            action = QtWidgets.QAction(item.name,
                                       self,
                                       triggered=setAndDrawFn,
                                       checkable=True)
            action.setData(item.identifier)
            if shortCutNr <= 9 and "debug" not in item.identifier:  # TODO: make configurable by the user
                action.setShortcut(
                    QtGui.QKeySequence("Ctrl+{}".format(shortCutNr)))
                shortCutNr += 1

            actionGroup.addAction(action)

        return actionGroup
Example #2
0
    def __init__(self, settingsFile=None, setExceptHook=True):
        """ Constructor
            :param settingsFile: Config file from which the persistent settings are loaded.

            :param setExceptHook: Sets the global sys.except hook so that Qt shows a dialog box
                when an exception is raised.

                In debugging mode, the program will just quit in case of an exception. This is
                standard Python behavior but PyQt and PySide swallow exceptions by default (only a
                log message is displayed). The practice of swallowing exceptions fosters bad
                programming IHMO as it is easy to miss errors. I strongly recommend that you set
                the setExceptHook to True.
        """
        super(ArgosApplication, self).__init__()

        if not settingsFile:
            settingsFile = ArgosApplication.defaultSettingsFile()
            logger.debug("No config file specified. Using default: {}".format(
                settingsFile))

        self._settingsFile = ArgosApplication.userConfirmedSettingsFile(
            settingsFile,
            createWithoutConfirm=ArgosApplication.defaultSettingsFile())

        if setExceptHook:
            logger.debug("Setting sys.excepthook to Argos exception handling")
            sys.excepthook = handleException

        QtCore.qInstallMessageHandler(self.handleQtLogMessages)

        if DEBUGGING:
            self.qApplication.focusChanged.connect(
                self.focusChanged)  # for debugging

        self._repo = RepoTreeModel()
        self._rtiRegistry = globalRtiRegistry()
        self._inspectorRegistry = InspectorRegistry()

        self._mainWindows = []
        self._settingsSaved = False  # boolean to prevent saving settings twice
        self._recentFiles = [
        ]  # list of recently opened files ([timeStampe, fileName] per file).
        self._maxRecentFiles = 10  # Maximum size of recent file

        #self.qApplication.lastWindowClosed.connect(self.quit)
        self.qApplication.aboutToQuit.connect(self.aboutToQuitHandler)

        # Activate-actions for all windows
        self.windowActionGroup = QtWidgets.QActionGroup(self)
        self.windowActionGroup.setExclusive(True)

        # Call setup when the event loop starts.
        QtCore.QTimer.singleShot(0, self.setup)
Example #3
0
    def addHeaderContextMenu(self, checked=None, checkable=None, enabled=None):
        """ Adds the context menu from using header information

            checked can be a header_name -> boolean dictionary. If given, headers
            with the key name will get the checked value from the dictionary.
            The corresponding column will be hidden if checked is False.

            checkable can be a header_name -> boolean dictionary. If given, header actions
            with the key name will get the checkable value from the dictionary. (Default True)

            enabled can be a header_name -> boolean dictionary. If given, header actions
            with the key name will get the enabled value from the dictionary. (Default True)
        """
        checked = checked if checked is not None else {}
        checkable = checkable if checkable is not None else {}
        enabled = enabled if enabled is not None else {}

        horizontal_header = self.horizontalHeader()
        horizontal_header.setContextMenuPolicy(Qt.ActionsContextMenu)

        self.toggle_column_actions_group = QtWidgets.QActionGroup(self)
        self.toggle_column_actions_group.setExclusive(False)
        self.__toggle_functions = []  # for keeping references

        for col in range(horizontal_header.count()):
            column_label = self.model().headerData(col, Qt.Horizontal,
                                                   Qt.DisplayRole)
            #logger.debug("Adding: col {}: {}".format(col, column_label))
            action = QtWidgets.QAction(
                str(column_label),
                self.toggle_column_actions_group,
                checkable=checkable.get(column_label, True),
                enabled=enabled.get(column_label, True),
                toolTip="Shows or hides the {} column".format(column_label))
            func = self.__makeShowColumnFunction(col)
            self.__toggle_functions.append(func)  # keep reference
            horizontal_header.addAction(action)
            is_checked = checked.get(
                column_label, not horizontal_header.isSectionHidden(col))
            horizontal_header.setSectionHidden(col, not is_checked)
            action.setChecked(is_checked)
            action.toggled.connect(func)
Example #4
0
    def __init__(self, setExceptHook=True):
        """ Constructor

            :param setExceptHook: Sets the global sys.except hook so that Qt shows a dialog box
                when an exception is raised.

                In debugging mode, the program will just quit in case of an exception. This is
                standard Python behavior but PyQt and PySide swallow exceptions by default (only a
                log message is displayed). The practice of swallowing exceptions fosters bad
                programming IHMO as it is easy to miss errors. I strongly recommend that you set
                the setExceptHook to True.
        """
        super(ArgosApplication, self).__init__()

        # Call initQtWidgetsApplicationInstance() so that the users can call argos.browse without
        # having to call it themselves.
        self._qApplication = initQApplication()

        if setExceptHook:
            logger.debug("Setting sys.excepthook to Argos exception handling")
            sys.excepthook = handleException

        #self.qApplication.focusChanged.connect(self.focusChanged) # for debugging

        self._repo = RepoTreeModel()
        self._rtiRegistry = globalRtiRegistry()
        self._inspectorRegistry = InspectorRegistry()

        self._profile = ''
        self._mainWindows = []
        self._settingsSaved = False  # boolean to prevent saving settings twice

        self.qApplication.lastWindowClosed.connect(self.quit)

        # Activate-actions for all windows
        self.windowActionGroup = QtWidgets.QActionGroup(self)
        self.windowActionGroup.setExclusive(True)

        # Call setup when the event loop starts.
        QtCore.QTimer.singleShot(0, self.setup)
Example #5
0
    def __createInspectorActionGroup(self, parent):
        """ Creates an action group with 'set inspector' actions for all installed inspector.
        """
        actionGroup = QtWidgets.QActionGroup(parent)
        actionGroup.setExclusive(True)

        for item in self.argosApplication.inspectorRegistry.items:
            logger.debug("__createInspectorActionGroup item: {} {}".format(item.identifier, item._data))
            setAndDrawFn = partial(self.setAndDrawInspectorById, item.identifier)
            action = QtWidgets.QAction(item.name, self, triggered=setAndDrawFn, checkable=True)
            action.setData(item.identifier)
            if item.shortCut:
                try:
                    keySeq = QtGui.QKeySequence(item.shortCut.strip())
                except Exception as ex:
                    logger.warning("Unable to create short cut from: '{}".format(item.shortCut))
                else:
                    action.setShortcut(QtGui.QKeySequence(keySeq))

            actionGroup.addAction(action)

        return actionGroup
Example #6
0
    def __init__(self, repoTreeModel, collector, parent=None):
        """ Constructor.

            Maintains a reference to a collector. The repo tree view updates the collector when
            the currentIndex changes.
        """
        super(RepoTreeView, self).__init__(treeModel=repoTreeModel,
                                           parent=parent)

        self._collector = collector
        self._config = self._createConfig()

        treeHeader = self.header()
        treeHeader.resizeSection(RepoTreeModel.COL_NODE_NAME,
                                 COL_NODE_NAME_WIDTH)
        treeHeader.resizeSection(RepoTreeModel.COL_SHAPE, COL_SHAPE_WIDTH)
        treeHeader.resizeSection(RepoTreeModel.COL_ELEM_TYPE,
                                 COL_ELEM_TYPE_WIDTH)
        treeHeader.setStretchLastSection(True)

        headerNames = self.model().horizontalHeaders
        enabled = dict((name, True) for name in headerNames)
        enabled[headerNames[
            RepoTreeModel.COL_NODE_NAME]] = False  # Cannot be unchecked
        checked = dict((name, False) for name in headerNames)
        checked[headerNames[RepoTreeModel.COL_NODE_NAME]] = True
        checked[headerNames[RepoTreeModel.COL_SHAPE]] = True
        checked[headerNames[RepoTreeModel.COL_ELEM_TYPE]] = True
        self.addHeaderContextMenu(checked=checked,
                                  enabled=enabled,
                                  checkable={})

        self.setContextMenuPolicy(
            Qt.DefaultContextMenu)  # will call contextMenuEvent
        self.setUniformRowHeights(True)
        #self.setIconSize(QtCore.QSize(16, 16))

        # Add actions
        self.currentItemActionGroup = QtWidgets.QActionGroup(self)
        self.currentItemActionGroup.setExclusive(False)

        removeFileAction = QtWidgets.QAction(
            "Remove from Tree",
            self.currentItemActionGroup,
            shortcut=QtGui.QKeySequence.Delete,
            triggered=self.removeCurrentItem)
        self.addAction(removeFileAction)

        reloadFileAction = QtWidgets.QAction(
            "Reload File",
            self.currentItemActionGroup,
            shortcut=QtGui.QKeySequence.Refresh,  #"Ctrl+R",
            triggered=self.reloadFileOfCurrentItem)
        self.addAction(reloadFileAction)

        self.openItemAction = QtWidgets.QAction("Open Item",
                                                self,
                                                triggered=self.openCurrentItem)
        self.addAction(self.openItemAction)

        self.closeItemAction = QtWidgets.QAction(
            "Close Item", self, triggered=self.closeCurrentItem)
        self.addAction(self.closeItemAction)

        self.collapseItemAction = QtWidgets.QAction(
            "Collapse Item", self, triggered=self.collapseCurrentItem)
        self.addAction(self.collapseItemAction)

        # Connect signals
        selectionModel = self.selectionModel(
        )  # need to store reference to prevent crash in PySide
        selectionModel.currentChanged.connect(self.currentItemChanged)

        # Close files on collapse. Note that, self.collapsed does NOT seem to be connected to self.collapse by default,
        # so there is not conflict here. Also there is no need to connect to expand, this is automatic with the
        # fetchMore mechanism
        self.collapsed.connect(self.closeItem)

        self.model().sigItemChanged.connect(self.repoTreeItemChanged)
        self.model().sigAllChildrenRemovedAtIndex.connect(self.collapse)
Example #7
0
    def __init__(self, repoTreeModel, collector, parent=None):
        """ Constructor.

            Maintains a reference to a collector. The repo tree view updates the collector when
            the currentIndex changes.
        """
        super(RepoTreeView, self).__init__(treeModel=repoTreeModel,
                                           parent=parent)

        self._collector = collector
        self._config = self._createConfig()

        treeHeader = self.header()
        treeHeader.resizeSection(RepoTreeModel.COL_NODE_NAME,
                                 COL_NODE_NAME_WIDTH)
        treeHeader.resizeSection(RepoTreeModel.COL_SHAPE, COL_SHAPE_WIDTH)
        treeHeader.resizeSection(RepoTreeModel.COL_ELEM_TYPE,
                                 COL_ELEM_TYPE_WIDTH)
        treeHeader.setStretchLastSection(True)

        headerNames = self.model().horizontalHeaders
        enabled = dict((name, True) for name in headerNames)
        enabled[headerNames[
            RepoTreeModel.COL_NODE_NAME]] = False  # Cannot be unchecked
        checked = dict((name, False) for name in headerNames)
        checked[headerNames[RepoTreeModel.COL_NODE_NAME]] = True
        checked[headerNames[RepoTreeModel.COL_SHAPE]] = False
        checked[headerNames[RepoTreeModel.COL_ELEM_TYPE]] = False
        self.addHeaderContextMenu(checked=checked,
                                  enabled=enabled,
                                  checkable={})

        self.setContextMenuPolicy(
            Qt.DefaultContextMenu)  # will call contextMenuEvent
        self.setUniformRowHeights(True)
        #self.setIconSize(QtCore.QSize(16, 16))

        # Add actions
        self.topLevelItemActionGroup = QtWidgets.QActionGroup(
            self)  # TODO: not used anymore?
        self.topLevelItemActionGroup.setExclusive(False)
        self.currentItemActionGroup = QtWidgets.QActionGroup(self)
        self.currentItemActionGroup.setExclusive(False)

        removeFileAction = QtWidgets.QAction(
            "Remove from Tree",
            self.currentItemActionGroup,
            shortcut=QtGui.QKeySequence.Delete,
            triggered=self.removeCurrentItem)
        self.addAction(removeFileAction)

        reloadFileAction = QtWidgets.QAction(
            "Reload File",
            self.currentItemActionGroup,
            shortcut=QtGui.QKeySequence.Refresh,  #"Ctrl+R",
            triggered=self.reloadFileOfCurrentItem)
        self.addAction(reloadFileAction)

        self.openItemAction = QtWidgets.QAction(
            "Open Item",
            self,
            #shortcut="Ctrl+Shift+C",
            triggered=self.openCurrentItem)
        self.addAction(self.openItemAction)

        self.closeItemAction = QtWidgets.QAction(
            "Close Item",
            self,
            #shortcut="Ctrl+C", # Ctrl+C already taken for Copy
            triggered=self.closeCurrentItem)
        self.addAction(self.closeItemAction)

        # Connect signals
        selectionModel = self.selectionModel(
        )  # need to store reference to prevent crash in PySide
        selectionModel.currentChanged.connect(self.currentItemChanged)

        self.model().sigItemChanged.connect(self.repoTreeItemChanged)
Example #8
0
    def __init__(self, configTreeModel, parent=None):
        """ Constructor.
            :param parent:
        """
        super(ConfigWidget, self).__init__(parent=parent)

        # Actions that change the reset mode of the reset button
        self.modeActionGroup = QtWidgets.QActionGroup(self)
        self.modeActionGroup.setExclusive(True)

        self.modeAllAction = QtWidgets.QAction("Reset All",
                                               self.modeActionGroup)
        self.modeAllAction.setToolTip(
            "Changes button reset mode to reset all settings")
        self.modeAllAction.setCheckable(True)
        self.modeAllAction.triggered.connect(
            lambda: self.setResetMode(ResetMode.All))

        self.modeRangeAction = QtWidgets.QAction("Reset Ranges",
                                                 self.modeActionGroup)
        self.modeRangeAction.setToolTip(
            "Changes button reset mode to reset axes")
        self.modeRangeAction.setCheckable(True)
        self.modeRangeAction.triggered.connect(
            lambda: self.setResetMode(ResetMode.Ranges))

        # Sanity check that actions have been added to action group
        assert self.modeActionGroup.actions(
        ), "Sanity check. resetActionGroup is empty"

        # Actions that actually reset the settings

        self.resetAllAction = QtWidgets.QAction("Reset All", self)
        self.resetAllAction.setToolTip("Resets all settings.")
        self.resetAllAction.setIcon(
            QtGui.QIcon(os.path.join(icons_directory(), 'reset-l.svg')))
        self.resetAllAction.setShortcut("Ctrl+=")

        self.resetRangesAction = QtWidgets.QAction("Reset Ranges", self)
        self.resetRangesAction.setToolTip(
            "Resets range of all plots, color scales, table column/row sizes etc."
        )
        self.resetRangesAction.setIcon(
            QtGui.QIcon(os.path.join(icons_directory(), 'reset-l.svg')))
        self.resetRangesAction.setShortcut("Ctrl+0")

        self.resetButtonMenu = QtWidgets.QMenu()
        self.resetButtonMenu.addAction(self.resetAllAction)
        self.resetButtonMenu.addAction(self.resetRangesAction)
        self.resetButtonMenu.addSection("Default")
        self.resetButtonMenu.addAction(self.modeAllAction)
        self.resetButtonMenu.addAction(self.modeRangeAction)

        # Widgets

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.setSpacing(5)
        self.mainLayout.setContentsMargins(DOCK_MARGIN, DOCK_MARGIN,
                                           DOCK_MARGIN, DOCK_MARGIN)

        self.configTreeView = ConfigTreeView(configTreeModel, parent=self)
        self.mainLayout.addWidget(self.configTreeView)

        self.buttonLayout = QtWidgets.QHBoxLayout()
        self.mainLayout.addLayout(self.buttonLayout)

        self.autoCheckBox = QtWidgets.QCheckBox("Auto")
        self.autoCheckBox.setToolTip(
            "Auto reset when a new item or axis is selected.")
        self.autoCheckBox.setChecked(True)

        self.resetButton = QtWidgets.QToolButton()
        self.resetButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.resetButton.setDefaultAction(self.resetButtonMenu.defaultAction())
        self.resetButton.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup)
        self.resetButton.setMenu(self.resetButtonMenu)

        # Set font size to the same as used for push buttons
        dummyButton = QtWidgets.QPushButton("dummy")
        fontSize = dummyButton.font().pointSize()
        del dummyButton

        logger.debug(
            "Setting QToolButtons font size to: {} point".format(fontSize))
        font = self.resetButton.font()
        font.setPointSizeF(fontSize)
        self.resetButton.setFont(font)

        self.buttonLayout.addStretch()
        self.buttonLayout.addWidget(self.autoCheckBox)
        self.buttonLayout.addWidget(self.resetButton)
        self.buttonLayout.addStretch()

        self.autoCheckBox.stateChanged.connect(self.setAutoReset)
        self.resetRangesAction.triggered.connect(
            self.configTreeView.resetAllRanges)
        self.resetAllAction.triggered.connect(
            self.configTreeView.resetAllSettings)

        self.setResetMode(self.configTreeView.resetMode)