def __init__(self, parent=None, msg="", title="Error"): super(MessageDisplay, self).__init__(parent=parent) self.layout = QtWidgets.QVBoxLayout() self.setLayout(self.layout) self.titleLabel = QtWidgets.QLabel(title) self.titleLabel.setTextFormat(Qt.PlainText) self.titleLabel.setTextInteractionFlags(Qt.TextSelectableByMouse) self.titleLabel.setAlignment(Qt.AlignHCenter) self.layout.addWidget(self.titleLabel, stretch=0) font = QtGui.QFont() font.setFamily(MONO_FONT) font.setFixedPitch(True) font.setPointSize(FONT_SIZE) self.messageLabel = QtWidgets.QLabel(msg) self.messageLabel.setFont(font) self.messageLabel.setTextFormat(Qt.PlainText) self.messageLabel.setTextInteractionFlags(Qt.TextSelectableByMouse) self.messageLabel.setWordWrap(True) self.messageLabel.setAlignment(Qt.AlignTop) self.messageLabel.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Plain) self.layout.addWidget(self.messageLabel, stretch=1)
def __init__(self, registry, onlyShowImported=False, parent=None): """ Constructor """ super(OpenInspectorDialog, self).__init__(parent=parent) self._registry = registry self.setWindowTitle('Open Inspector') self.setModal(True) layout = QtWidgets.QVBoxLayout(self) attrNames = ['name', 'library', 'nDims'] headerSizes = [250, 250, None] self.inspectorTab = RegistryTab(registry, attrNames=attrNames, headerSizes=headerSizes, onlyShowImported=onlyShowImported) self.inspectorTab.tableView.sortByColumn( 1, Qt.AscendingOrder) # sort by library layout.addWidget(self.inspectorTab) # Buttons buttonBox = QtWidgets.QDialogButtonBox( QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) layout.addWidget(buttonBox) # Double clicking is equivalent to selecting it and clicking Ok. self.inspectorTab.tableView.doubleClicked.connect(self.accept) self.resize(QtCore.QSize(800, 600))
def _drawContents(self, currentRti=None): """ Draws the attributes of the currentRTI """ table = self.table table.setUpdatesEnabled(False) try: table.clearContents() verticalHeader = table.verticalHeader() verticalHeader.setSectionResizeMode(QtWidgets.QHeaderView.Fixed) if currentRti is None: return # Each column in the repo tree corresponds to a row in this detail pane. repoModel = self._repoTreeView.model() propNames = RepoTreeModel.HEADERS table.setRowCount(len(propNames)) for row, propName in enumerate(propNames): nameItem = QtWidgets.QTableWidgetItem(propName) nameItem.setToolTip(propName) table.setItem(row, self.COL_PROP_NAME, nameItem) propValue = repoModel.itemData(currentRti, row) propItem = QtWidgets.QTableWidgetItem(propValue) propItem.setToolTip(propValue) table.setItem(row, self.COL_VALUE, propItem) table.resizeRowToContents(row) verticalHeader.setSectionResizeMode( QtWidgets.QHeaderView.ResizeToContents) finally: table.setUpdatesEnabled(True)
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
def __init__(self, collector, parent=None): """ Constructor. When subclassing the AbstractInspector try to minimize the work done in the constructor. Place all functionality that may raise an exception in updateContents or clearContents, these functions will show an error page and prevent the application from aborting. If an exception occurs in the constructor it is not caught! :param collector: the data collector from where this inspector gets its data :param parent: parent widget. """ super(AbstractInspector, self).__init__(parent) self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) self._config = MainGroupCti(nodeName='inspector') # Is typically redefined. self._collector = collector self.errorWidget = MessageDisplay() self.addWidget(self.errorWidget) self.contentsWidget = QtWidgets.QWidget() self.addWidget(self.contentsWidget) self.contentsLayout = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.TopToBottom) self.contentsLayout.setSpacing(DOCK_SPACING) self.contentsLayout.setContentsMargins(DOCK_MARGIN, DOCK_MARGIN, DOCK_MARGIN, DOCK_MARGIN) self.contentsWidget.setLayout(self.contentsLayout) self.setCurrentIndex(self.CONTENTS_PAGE_IDX)
def __init__(self, inspectorActionGroup, parent=None): super(InspectorSelectionPane, self).__init__(parent=parent) # self.setFrameShape(QtWidgets.QFrame.Box) self.menuButton = QtWidgets.QPushButton(NO_INSPECTOR_LABEL) self.menuButton.setMinimumWidth(10) inspectorMenu = QtWidgets.QMenu("Change Inspector", parent=self.menuButton) for action in inspectorActionGroup.actions(): inspectorMenu.addAction(action) self.menuButton.setMenu(inspectorMenu) self.messageLabel = QtWidgets.QLabel("") self.messageLabel.setObjectName("message_label") self.messageLabel.setFrameStyle(QtWidgets.QFrame.Panel) self.messageLabel.setFrameShadow(QtWidgets.QFrame.Sunken) self.messageLabel.setTextInteractionFlags(Qt.TextSelectableByMouse) self.mainLayout = QtWidgets.QHBoxLayout() self.mainLayout.setContentsMargins(DOCK_MARGIN, DOCK_MARGIN, DOCK_MARGIN, DOCK_MARGIN) self.setLayout(self.mainLayout) self.mainLayout.addWidget(self.menuButton, stretch=0) self.mainLayout.addWidget(self.messageLabel, stretch=1) setWidgetSizePolicy(self.menuButton, hor=QtWidgets.QSizePolicy.Minimum) setWidgetSizePolicy(self.messageLabel, hor=QtWidgets.QSizePolicy.Ignored) setWidgetSizePolicy(self, hor=QtWidgets.QSizePolicy.MinimumExpanding, ver=QtWidgets.QSizePolicy.Fixed)
def __init__(self, repoTreeModel, collector, parent=None): """ Constructor. :param parent: """ super(RepoWidget, self).__init__(parent=parent) self.detailDockPanes = [] self.mainLayout = QtWidgets.QVBoxLayout() self.mainLayout.setSpacing(DOCK_SPACING) self.mainLayout.setContentsMargins(DOCK_MARGIN, DOCK_MARGIN, DOCK_MARGIN, DOCK_MARGIN) self.setLayout(self.mainLayout) self.mainSplitter = QtWidgets.QSplitter(orientation=Qt.Vertical) self.mainLayout.addWidget(self.mainSplitter) self.repoTreeView = RepoTreeView(repoTreeModel, collector) self.mainSplitter.addWidget(self.repoTreeView) self.mainSplitter.setCollapsible(0, False) self.tabWidget = QtWidgets.QTabWidget() self.mainSplitter.addWidget(self.tabWidget) self.mainSplitter.setCollapsible(1, True) self.propertiesPane = self.addDetailsPane( PropertiesPane(self.repoTreeView)) self.attributesPane = self.addDetailsPane( AttributesPane(self.repoTreeView)) self.repoTreeView.sigRepoItemChanged.connect(self.repoItemChanged) self.tabWidget.currentChanged.connect(self.tabChanged) self.tabWidget.setCurrentIndex( 1) # Show attributes the first time the program runs
def __init__(self, borderPen=DEFAULT_BORDER_PEN, *args, **kwargs): """ Constructor. :param borderPen: pen for drawing the viewBox border. Default black and width of 1. """ super(ArgosPgPlotItem, self).__init__(*args, **kwargs) self.setMenuEnabled(False) #pg.setConfigOption('leftButtonPan', False) viewBox = self.getViewBox() viewBox.border = borderPen viewBox.setCursor(Qt.CrossCursor) viewBox.disableAutoRange(BOTH_AXES) viewBox.mouseClickEvent = lambda ev: self._axesMouseClickEvent(ev, BOTH_AXES) # Color of zoom-rectangle. alpha = 100 greyVal = 160 viewBox.rbScaleBox.setPen(pg.mkPen((0, 0, 0, alpha), width=2)) viewBox.rbScaleBox.setBrush(pg.mkBrush(greyVal, greyVal, greyVal, alpha)) # Add mouseClickEvent event handlers to the X and Y axis. This allows for resetting # the scale of each axes separately by middle mouse clicking the axis. for xAxisItem in (self.getAxis('bottom'), self.getAxis('top')): xAxisItem.mouseClickEvent = lambda ev: self._axesMouseClickEvent(ev, X_AXIS) xAxisItem.setCursor(Qt.SizeHorCursor) for yAxisItem in (self.getAxis('left'), self.getAxis('right')): yAxisItem.mouseClickEvent = lambda ev: self._axesMouseClickEvent(ev, Y_AXIS) yAxisItem.setCursor(Qt.SizeVerCursor) self.resetAxesAction = QtWidgets.QAction("Reset Axes", self, triggered = lambda: self.emitResetAxisSignal(BOTH_AXES), toolTip = "Resets the zoom factor of the X-axis and Y-axis") self.addAction(self.resetAxesAction) self.resetXAxisAction = QtWidgets.QAction("Reset X-axis", self, triggered = lambda: self.emitResetAxisSignal(X_AXIS), toolTip = "Resets the zoom factor of the X-axis") self.addAction(self.resetXAxisAction) self.resetYAxisAction = QtWidgets.QAction("Reset Y-axis", self, triggered = lambda: self.emitResetAxisSignal(Y_AXIS), toolTip = "Resets the zoom factor of the Y-axis") self.addAction(self.resetYAxisAction)
def showContextMenu(self, pos): """ Shows the context menu at position pos. """ contextMenu = QtWidgets.QMenu() addInspectorActionsToMenu(contextMenu, self.execInspectorDialogAction, self.inspectorActionGroup) contextMenu.exec_(self.mapToGlobal(pos))
def mouseClickEvent(self, mouseClickEvent): """ Handles (PyQtGraph) mouse click events. Overrides the middle mouse click to reset using the settings in the config tree. Opens the context menu if a right mouse button was clicked. (We can't simply use setContextMenuPolicy(Qt.ActionsContextMenu because the PlotItem class does not derive from QWidget). :param mouseClickEvent: pyqtgraph.GraphicsScene.mouseEvents.MouseClickEvent """ if mouseClickEvent.button() in self.resetRangeMouseButtons: self.emitResetColorScaleSignal() mouseClickEvent.accept() elif mouseClickEvent.button() == QtCore.Qt.RightButton: contextMenu = QtWidgets.QMenu() for action in self.actions(): contextMenu.addAction(action) screenPos = mouseClickEvent.screenPos( ) # Screenpos is a QPointF, convert to QPoint. screenX = round(screenPos.x()) screenY = round(screenPos.y()) contextMenu.exec_(QtCore.QPoint(screenX, screenY)) else: super(ArgosColorLegendItem, self).mouseClickEvent(mouseClickEvent)
def main(): """ Test classes """ import sys from pprint import pprint from PyQt5 import QtWidgets from argos import info from argos.utils.logs import make_log_format from argos.qt.misc import handleException from argos.reg.tabmodel import BaseTableModel, BaseItemStore, BaseItem info.DEBUGGING = True sys.excepthook = handleException logging.basicConfig(level="DEBUG", format=make_log_format()) app = QtWidgets.QApplication([]) store = BaseItemStore() model = BaseTableModel(store) window = TableEditWidget(tableModel=model) window.show() exitCode = app.exec_() print("edited store") pprint(store.marshall())
def __init__(self, cti, delegate, parent=None): """ See the AbstractCtiEditor for more info on the parameters """ super(ChoiceCtiEditor, self).__init__(cti, delegate, parent=parent) comboBox = QtWidgets.QComboBox() comboBox.setEditable(cti.editable) comboBox.setInsertPolicy(cti.insertPolicy) setWidgetSizePolicy(comboBox, QtWidgets.QSizePolicy.Expanding, None) if cti.completer is not NOT_SPECIFIED: comboBox.setCompleter(cti.completer if cti.completer else None) comboBox.addItems(cti._displayValues) # Store the configValue in the combo box, although it's not currently used. for idx, configValue in enumerate(cti._configValues): comboBox.setItemData(idx, configValue, role=Qt.UserRole) comboBox.activated.connect(self.comboBoxActivated) comboBox.model().rowsInserted.connect(self.comboBoxRowsInserted) self.comboBox = self.addSubEditor(comboBox, isFocusProxy=True) # Install an eventFilter on the QListView that pops-up and contains all the items. # This allows the user to remove items by pressing the delete key in the list. self._comboboxListView = comboBox.view() self._comboboxListView.installEventFilter(self)
def _repopulateOpenAsMenu(self, *args, **kwargs): """ Clear the window menu and fills it with the actions of the actionGroup """ logger.debug("Called repopulateOpenAsMenu") for action in self.openAsMenu.actions(): self.openAsMenu.removeAction(action) rtiRegistry = self.argosApplication.rtiRegistry for rtiRegItem in (rtiRegistry.items + rtiRegistry.extraItemsForOpenAsMenu()): if not rtiRegItem.triedImport: rtiRegItem.tryImportClass() def createTrigger(): "Function to create a closure with the regItem" _rtiRegItem = rtiRegItem # keep reference in closure return lambda: self.openFiles(rtiRegItem=_rtiRegItem, fileMode = QtWidgets.QFileDialog.ExistingFiles, caption="Open {}".format(_rtiRegItem.name)) action = QtWidgets.QAction("{}...".format(rtiRegItem.name), self, enabled=bool(rtiRegItem.successfullyImported), triggered=createTrigger(), icon=rtiRegItem.decoration) self.openAsMenu.addAction(action)
def __init__(self, cti, delegate, parent=None): """ See the AbstractCtiEditor for more info on the parameters """ super(IntCtiEditor, self).__init__(cti, delegate, parent=parent) spinBox = QtWidgets.QSpinBox(parent) spinBox.setKeyboardTracking(False) if cti.minValue is None: spinBox.setMinimum(np.iinfo('i').min) else: spinBox.setMinimum(cti.minValue) if cti.maxValue is None: spinBox.setMaximum(np.iinfo('i').max) else: spinBox.setMaximum(cti.maxValue) spinBox.setSingleStep(cti.stepSize) spinBox.setPrefix(cti.prefix) spinBox.setSuffix(cti.suffix) if cti.specialValueText is not None: spinBox.setSpecialValueText(cti.specialValueText) self.spinBox = self.addSubEditor(spinBox, isFocusProxy=True) self.spinBox.valueChanged.connect(self.commitChangedValue)
def contextMenuEvent(self, event): """ Creates and executes the context menu for the tree view """ menu = QtWidgets.QMenu(self) for action in self.actions(): menu.addAction(action) openAsMenu = QtWidgets.QMenu(parent=menu) openAsMenu.setTitle("Open Item As") openAsMenu.aboutToShow.connect( lambda: self._populateOpenAsMenu(openAsMenu)) menu.insertMenu(self.closeItemAction, openAsMenu) # Insert before "Close Item" entry. menu.exec_(event.globalPos())
def __init__(self, label, widget, layoutSpacing=None, layoutContentsMargins=(0, 0, 0, 0), labelStretch=0, spacerStretch=0, widgetStretch=1, parent=None): """ Constructor. :param widget: the 'wrapped' widget, which will be displayed on the right :param labelText: text given to the label :param parent: parent wigdet """ super(LabeledWidget, self).__init__(parent=parent) self.layout = QtWidgets.QHBoxLayout(self) self.layout.setContentsMargins(*layoutContentsMargins) if layoutSpacing is not None: self.layout.setSpacing(layoutSpacing) self.label = label self.widget = widget self.layout.addWidget(self.label, stretch=labelStretch) if spacerStretch: self.layout.addStretch(stretch=spacerStretch) self.layout.addWidget(self.widget, stretch=widgetStretch)
def __init__(self, cti, delegate, parent=None): """ See the AbstractCtiEditor for more info on the parameters """ super(FloatCtiEditor, self).__init__(cti, delegate, parent=parent) spinBox = QtWidgets.QDoubleSpinBox(parent) spinBox.setKeyboardTracking(False) setWidgetSizePolicy(spinBox, QtWidgets.QSizePolicy.Expanding, None) if cti.minValue is None: spinBox.setMinimum(-sys.float_info.max) else: spinBox.setMinimum(cti.minValue) if cti.maxValue is None: spinBox.setMaximum(sys.float_info.max) else: spinBox.setMaximum(cti.maxValue) spinBox.setSingleStep(cti.stepSize) spinBox.setDecimals(cti.decimals) spinBox.setPrefix(cti.prefix) spinBox.setSuffix(cti.suffix) if cti.specialValueText is not None: spinBox.setSpecialValueText(cti.specialValueText) self.spinBox = self.addSubEditor(spinBox, isFocusProxy=True) self.spinBox.valueChanged.connect(self.commitChangedValue)
def __init__(self, nodeName, defaultFamily='Helvetica'): """ Constructor. :param defaultFamily: A string representing the defaultValue. :editable: True if the underlying QFontComboBox is editable. The default is False as it does not work well with the FontCti. For the (other) parameters see the AbstractCti constructor documentation. """ check_is_a_string(defaultFamily) # Get a list of of configValues by reading them from a temporary QFontComboBox. tempFontComboBox = QtWidgets.QFontComboBox() configValues = [] defaultData = 0 for idx in range(tempFontComboBox.count()): fontFamily = tempFontComboBox.itemText(idx) configValues.append(fontFamily) if fontFamily.lower() == defaultFamily.lower(): defaultData = idx # Set after self._displayValues are defined. The parent constructor calls _enforceDataType super(FontChoiceCti, self).__init__(nodeName, defaultData, configValues=configValues)
def __init__(self, cti, delegate, parent=None): """ See the AbstractCtiEditor for more info on the parameters """ super(GroupCtiEditor, self).__init__(cti, delegate, parent=parent) # Add hidden widget to store editor value self.widget = self.addSubEditor(QtWidgets.QWidget()) self.widget.hide()
def __init__(self, collector, parent=None): super(BuggyInspector, self).__init__(collector, parent=parent) self.label = QtWidgets.QLabel() self.contentsLayout.addWidget(self.label) self._config = self._createConfig()
def __init__(self, cti, delegate, parent=None): """ See the AbstractCtiEditor for more info on the parameters """ super(FontCtiEditor, self).__init__(cti, delegate, parent=parent) pickButton = QtWidgets.QToolButton() pickButton.setText("...") pickButton.setToolTip("Open font dialog.") pickButton.setFocusPolicy(Qt.NoFocus) pickButton.clicked.connect(self.execFontDialog) self.pickButton = self.addSubEditor(pickButton) if DEBUGGING: self.label = self.addSubEditor(QtWidgets.QLabel(self.cti.displayValue)) labelSizePolicy = self.label.sizePolicy() self.label.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, labelSizePolicy.verticalPolicy())
def __init__(self, cti, delegate, parent=None): """ See the AbstractCtiEditor for more info on the parameters """ super(StringCtiEditor, self).__init__(cti, delegate, parent=parent) self.lineEditor = self.addSubEditor(QtWidgets.QLineEdit(), isFocusProxy=True) if cti.maxLength is not None: self.lineEditor.setMaxLength(cti.maxLength)
def __init__(self, collector, parent=None): super(DebugInspector, self).__init__(collector, parent=parent) self.label = QtWidgets.QLabel() self.label.setWordWrap(True) self.contentsLayout.addWidget(self.label) self._config = self._createConfig()
def __setupViews(self): """ Creates the UI widgets. """ self._collector = Collector(self.windowNumber) self._collector.sigShowMessage.connect(self.sigShowMessage) self.configWidget = ConfigWidget(self._configTreeModel) self.repoWidget = RepoWidget(self.argosApplication.repo, self.collector) # self._configTreeModel.insertItem(self.repoWidget.repoTreeView.config) # No configurable items yet # Define a central widget that will be the parent of the inspector widget. # We don't set the inspector directly as the central widget to retain the size when the # inspector is changed. self.mainWidget = QtWidgets.QWidget() self.mainLayout = QtWidgets.QVBoxLayout(self.mainWidget) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.setCentralWidget(self.mainWidget) self.topPane = QtWidgets.QFrame() # self.topPane.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Raised) # self.topPane.setLineWidth(1) self.mainLayout.addWidget(self.topPane) self.topLayout = QtWidgets.QHBoxLayout(self.topPane) self.topLayout.setContentsMargins(0, 0, 0, 0) self.topLayout.setSpacing(0) self.inspectorSelectionPane = InspectorSelectionPane(self.inspectorActionGroup) self.topLayout.addWidget(self.inspectorSelectionPane) self.sigInspectorChanged.connect(self.inspectorSelectionPane.updateFromInspectorRegItem) self.sigShowMessage.connect(self.inspectorSelectionPane.showMessage) showInspectorMenuAction = QtWidgets.QAction("ShowInspectorMenu", self, triggered=self.inspectorSelectionPane.menuButton.showMenu, checkable=False) showInspectorMenuAction.setShortcut("Ctrl+I") self.addAction(showInspectorMenuAction) self.wrapperWidget = QtWidgets.QWidget() self.mainLayout.addWidget(self.wrapperWidget) self.wrapperLayout = QtWidgets.QVBoxLayout(self.wrapperWidget) self.wrapperLayout.setContentsMargins(0, 0, 0, 0) self.wrapperLayout.setSpacing(0) self.wrapperLayout.addWidget(self.inspector) # Must be after setInspector since that already draws the inspector self.collector.sigContentsChanged.connect(self.collectorContentsChanged) self._configTreeModel.sigItemChanged.connect(self.configContentsChanged) # Populate table headers menu self.__addTableHeadersSubMenu("Data", self.repoWidget.repoTreeView) self.__addTableHeadersSubMenu("Settings", self.configWidget.configTreeView) self.__addTableHeadersSubMenu( "Properties", self.repoWidget.propertiesPane.table) self.__addTableHeadersSubMenu( "Attributes", self.repoWidget.attributesPane.table)
def __init__(self, collector, parent=None): super(TextInspector, self).__init__(collector, parent=parent) self.editor = QtWidgets.QPlainTextEdit() self.editor.setReadOnly(True) self.contentsLayout.addWidget(self.editor) self._config = self._createConfig()
def main(): """ Small stand-alone test """ app = QtWidgets.QApplication(sys.argv[1:]) spinBox = ScientificDoubleSpinBox(precision = 9, largeStepFactor=2, smallStepsPerLargeStep=3) spinBox.selectAll() spinBox.setSingleStep(2) spinBox.raise_() spinBox.show() sys.exit(app.exec_())
def __init__(self, cti, delegate, parent=None): """ See the AbstractCtiEditor for more info on the parameters """ super(ColorCtiEditor, self).__init__(cti, delegate, parent=parent) lineEditor = QtWidgets.QLineEdit(parent) regExp = QtCore.QRegExp(r'#?[0-9A-F]{6}', Qt.CaseInsensitive) validator = QtGui.QRegExpValidator(regExp, parent=lineEditor) lineEditor.setValidator(validator) self.lineEditor = self.addSubEditor(lineEditor, isFocusProxy=True) pickButton = QtWidgets.QToolButton() pickButton.setText("...") pickButton.setToolTip("Open color dialog.") pickButton.setFocusPolicy(Qt.NoFocus) pickButton.clicked.connect(self.openColorDialog) self.pickButton = self.addSubEditor(pickButton)
def paintEvent(self, event): """ Reimplementation of paintEvent to allow for style sheets See: http://qt-project.org/wiki/How_to_Change_the_Background_Color_of_QWidget """ opt = QtWidgets.QStyleOption() opt.initFrom(self) painter = QtGui.QPainter(self) self.style().drawPrimitive(QtWidgets.QStyle.PE_Widget, opt, painter, self) painter.end()
def __init__(self, cti, delegate, subEditors=None, parent=None): """ Wraps the child widgets in a horizontal layout and appends a reset button. Maintains a reference to the ConfigTreeItem (cti) and to delegate, this last reference is so that we can command the delegate to commit and close the editor. The subEditors must be a list of QWidgets. Note that the sub editors do not yet have to be initialized with editor data since setData will be called by the delegate after construction. There it can be taken care of. """ super(AbstractCtiEditor, self).__init__(parent=parent) # Prevent underlying table cell from being visible if the editor doesn't fill the cell self.setAutoFillBackground(True) self._subEditors = [] self.delegate = delegate self.cti = cti # From the QAbstractItemDelegate.createEditor docs: The returned editor widget should have # Qt.StrongFocus; otherwise, QMouseEvents received by the widget will propagate to the view. # The view's background will shine through unless the editor paints its own background # (e.g., with setAutoFillBackground()). self.setFocusPolicy(Qt.StrongFocus) self.hBoxLayout = QtWidgets.QHBoxLayout() self.hBoxLayout.setContentsMargins(0, 0, 0, 0) self.hBoxLayout.setSpacing(0) self.setLayout(self.hBoxLayout) self.resetButton = QtWidgets.QToolButton() self.resetButton.setText("Reset") self.resetButton.setToolTip("Reset to default value.") self.resetButton.setIcon( QtGui.QIcon(os.path.join(icons_directory(), 'reset-l.svg'))) self.resetButton.setFocusPolicy(Qt.NoFocus) self.resetButton.clicked.connect(self.resetEditorValue) self.hBoxLayout.addWidget(self.resetButton, alignment=Qt.AlignRight) self.cti.model.sigItemChanged.connect(self.modelItemChanged) for subEditor in (subEditors if subEditors is not None else []): self.addSubEditor(subEditor)
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)