def dataChanged(self, topLeft: QModelIndex, bottomRight: QModelIndex, roles=None): """ Listens for dataChanged on an Intent (TreeItem)'s check state. Renders/unrenders according to the check state. Then, defers showing canvases to any derived views (e.g. StackedCanvasView). """ # We only care about the check state changing here (whether to render or unrender) if Qt.CheckStateRole in roles or EnsembleModel.canvas_role in roles: intent_row_start = topLeft.row() intent_row_stop = bottomRight.row() new_intents = set() if topLeft.isValid() and bottomRight.isValid(): for row in range(intent_row_start, intent_row_stop + 1): intent_index = self.model().index(row, 0) intent = intent_index.internalPointer().data( EnsembleModel.object_role) try: canvas = self._canvas_manager.canvas_from_index( intent_index.internalPointer()) try: canvas.sigInteractiveAction.connect( self.sigInteractiveAction, type=Qt.UniqueConnection) except TypeError: # ignore errors from connection already being established pass except Exception as ex: msg.logMessage( f'A error occurred displaying the intent named {intent.name}:', level=msg.ERROR) msg.logError(ex) else: new_intents.add((canvas, intent)) removed_intents = self._last_seen_intents - new_intents added_intents = new_intents - self._last_seen_intents for canvas, intent in removed_intents: if canvas is not None: self.unrender(intent, canvas) for canvas, intent in added_intents: if canvas is not None: self.render(intent, canvas) self._last_seen_intents = new_intents self.show_canvases()
def data(self, index: QModelIndex, role: int = ...) -> typing.Any: if not index.isValid(): return QVariant() elif role != Qt.DisplayRole: return QVariant() else: return QVariant(self._measurementModel[index.row()]._name)
def data(self, index: QModelIndex, role: int) -> Union[str, None]: if not index.isValid(): return None node = index.internalPointer() if role == Qt.DisplayRole: return node.name
def hasChildren(self, parent: QModelIndex) -> bool: # Reimplemented, since in the source model, the realizations have # children (i.e. valid indices.). Realizations do not have children in # this model. if parent.isValid(): return False return self.sourceModel().hasChildren(self.mapToSource(parent))
def doubleClicked_callback(self, index: QModelIndex): import pandas as pd import numpy as np import numpy.ma if index.isValid() and index.column() == NodeCols.Value: item = index.internalPointer() obj = item.node['obj']['fullname'] args = str(item.node['args']) data, _ = self.shell.get_obj_value( 'analyze_getval', obj, args) if isinstance(data, (pd.DataFrame, pd.Index, pd.Series)): dialog = DataFrameEditor(self) dialog.setup_and_check(data) elif isinstance(data, (np.ndarray, np.ma.MaskedArray)): dialog = ArrayEditor(self) dialog.setup_and_check(data, title='', readonly=True) elif isinstance(data, (list, set, tuple, dict)): dialog = CollectionsEditor(self) dialog.setup(data, title='', readonly=True) else: return dialog.show()
def setData(self, index: QModelIndex, value, role=Qt.EditRole): if not index.isValid(): return False node = index.internalPointer() if role == Qt.EditRole: if isinstance(node, JsonItem): if node.type in ('float', 'int', None): node.value = value try: # PyQt5 self.dataChanged.emit(index, index, [Qt.EditRole]) except TypeError: # PyQt4, PySide self.dataChanged.emit(index, index) elif role == Qt.CheckStateRole: if isinstance(node, JsonItem): if node.type == 'bool': node.value = value == Qt.Checked try: # PyQt5 self.dataChanged.emit( index, index, [Qt.CheckStateRole]) except TypeError: # PyQt4, PySide self.dataChanged.emit(index, index) return True return False
def flags(self, index: QModelIndex) -> Qt.ItemFlags: """Returns the item flags for the given `index`. This describes the properties of a given item in the model. We set them to be editable, checkable, dragable, droppable, etc... If index is not a list, we additionally set `Qt.ItemNeverHasChildren` (for optimization). Editable models must return a value containing `Qt.ItemIsEditable`. See Qt.ItemFlags https://doc.qt.io/qt-5/qt.html#ItemFlag-enum """ if ( not index.isValid() or index.row() >= len(self._root) or index.model() is not self ): # we allow drops outside the items return Qt.ItemIsDropEnabled base_flags = ( Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled | Qt.ItemIsEnabled ) if isinstance(self.getItem(index), MutableSequence): return base_flags | Qt.ItemIsDropEnabled return base_flags | Qt.ItemNeverHasChildren
def mapFromSource(self, sourceIndex: QModelIndex) -> QModelIndex: if not sourceIndex.isValid(): return QModelIndex() if not self._index_is_on_our_branch(sourceIndex): return QModelIndex() source_node = sourceIndex.internalPointer() return self.index(source_node.row(), sourceIndex.column(), QModelIndex())
def data(self, index: QModelIndex, role=Qt.DisplayRole) -> QVariant: if not index.isValid(): return QVariant() if role == Qt.TextAlignmentRole: return Qt.AlignCenter if role == ProgressRole: return self._progress if role in (Qt.StatusTipRole, Qt.WhatsThisRole, Qt.ToolTipRole): return "" if role == Qt.SizeHintRole: return QSize(30, 30) if role == Qt.FontRole: return QFont() if role in (Qt.BackgroundRole, Qt.ForegroundRole, Qt.DecorationRole): return QColor() if role == Qt.DisplayRole: return "" return QVariant()
def data(self, index: QModelIndex, role: int = ...) -> typing.Any: if not index.isValid(): return QVariant() elif role != Qt.DisplayRole: return QVariant() else: filter_at_row = self.__filter_model[index.row()] if index.column() == 0: return QVariant(filter_at_row.filter_type) elif index.column() == 1: if hasattr(filter_at_row, 'freq'): return QVariant(filter_at_row.freq) else: return QVariant('N/A') elif index.column() == 2: if hasattr(filter_at_row, 'q'): return QVariant(filter_at_row.q) else: return QVariant('N/A') elif index.column() == 3: if hasattr(filter_at_row, 'q_to_s'): return QVariant(round(filter_at_row.q_to_s(), 3)) else: return QVariant('N/A') elif index.column() == 4: if hasattr(filter_at_row, 'gain'): return QVariant(filter_at_row.gain) else: return QVariant('N/A') elif index.column() == 5: return QVariant(len(filter_at_row)) else: return QVariant()
def data(self, index: QModelIndex, role: Qt.ItemDataRole): """Return data stored under ``role`` for the item at ``index``.""" if not index.isValid(): return None layer = self.getItem(index) if role == Qt.DisplayRole: # used for item text return layer.name if role == Qt.TextAlignmentRole: # alignment of the text return Qt.AlignCenter if role == Qt.EditRole: # used to populate line edit when editing return layer.name if role == Qt.ToolTipRole: # for tooltip return layer.name if role == Qt.CheckStateRole: # the "checked" state of this item return Qt.Checked if layer.visible else Qt.Unchecked if role == Qt.SizeHintRole: # determines size of item return QSize(200, 34) if role == ThumbnailRole: # return the thumbnail thumbnail = layer.thumbnail return QImage( thumbnail, thumbnail.shape[1], thumbnail.shape[0], QImage.Format_RGBA8888, ) # normally you'd put the icon in DecorationRole, but we do that in the # # LayerDelegate which is aware of the theme. # if role == Qt.DecorationRole: # icon to show # pass return super().data(index, role)
def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex): """Renders the delegate using the given painter and style option for the item specified by index. :param painter: A QPainter object to draw :param option: Options to describe what should be drawn :param index: _description_ """ if not index.isValid(): return # Initialize the style options. This is not very Pythonic as it uses C++ # references under the hood so opt is affected by the second call opt = QStyleOptionViewItem(option) self.initStyleOption(opt, index) # Standard setup, paint, restore operation painter.save() try: painter.setClipRect(opt.rect) foreground_colour, background_colour = index.data(Qt.ForegroundRole), index.data(Qt.BackgroundRole) if foreground_colour is not None: painter.setPen(foreground_colour) if background_colour is not None: painter.fillRect(option.rect, background_colour) padding = self._padding opt.rect = option.rect.adjusted(padding, padding, -padding, -padding) painter.drawText(opt.rect, int(Qt.AlignLeft | Qt.AlignVCenter), opt.fontMetrics.elidedText(opt.text, Qt.ElideRight, opt.rect.width())) finally: painter.restore()
def canvas_from_index(self, index: QModelIndex): if not index.isValid(): return None if index.data( EnsembleModel.data_type_role) != WorkspaceDataType.Intent: print(f'WARNING: canvas_from_index index {index} is not an intent') return None # Canvas exists for index, return # TODO: in tab view, with multiple intents selected (e.g. 2 rows checked), # non-0 row intents (every intent except first) does not have a valid object in canvas_role canvas = index.model().data(index, EnsembleModel.canvas_role) if canvas: return canvas # There is another canvas we know about we should use for match_index in self.all_intent_indexes(index.model()): if self.is_matching_canvas_type(index, match_index): canvas = match_index.model().data(match_index, EnsembleModel.canvas_role) if canvas is not None: index.model().setData(index, canvas, EnsembleModel.canvas_role) return canvas # Does not exist, create new canvas and return intent = index.model().data(index, EnsembleModel.object_role) canvas_class_name = intent.canvas registry = pluginmanager canvas = self.canvas_from_registry(canvas_class_name, registry, intent.canvas_name) index.model().setData(index, canvas, EnsembleModel.canvas_role) return canvas
def currentChanged(self, current: QModelIndex, previous: QModelIndex) -> None: if current.isValid(): item = current.internalPointer() if isinstance(item, ValueItem) and item.attrs["spec"]: self.parent().update_dataattrs(item) else: self.parent().update_dataattrs(None)
def setData(self, index: QModelIndex, value: str, role=Qt.EditRole) -> bool: col = index.column() row = index.row() if index.isValid() and role == Qt.EditRole: # type(value) == str data = self.col_data[col] key = data.key if value and not value.isspace(): try: value = data.cls(value) except ValueError: return False else: value = data.default if key.startswith(self.TRIGGER): key = behead(key, self.TRIGGER) trigger = self.triggers(row) if value == data.default: # Delete key if (key: value) present trigger.pop(key, None) else: trigger[key] = value else: setattr(self.channels[row], key, value) self.dataChanged.emit(index, index, [role]) return True return False
def columnCount(self, index: QModelIndex) -> int: """Returns the number of columns in the given index.""" if index.isValid(): return index.internalPointer().columnCount() # For an invalid index, return the number of columns defined at the root item of the tree else: return self.rootItem.columnCount()
def flags(self, index: QModelIndex) -> int: if not index.isValid(): return Qt.NoItemFlags flags = super(ChannelTableModel, self).flags(index) if index.column() == self.CHECK_COLUMN: flags |= Qt.ItemIsUserCheckable return flags
def flags(self, index: QModelIndex): if not index.isValid(): return None if index.column() == 0: flags = Qt.ItemIsEnabled else: flags = super(DerivedDataModel, self).flags(index) return flags
def _source_rows_about_to_be_inserted( self, parent: QModelIndex, start: int, end: int ): if not parent.isValid(): return if not self._index_is_on_our_branch(parent): return self.beginInsertRows(self.mapFromSource(parent), start, end)
def flags(self, index: QModelIndex) -> Qt.ItemFlag: """Re-implement to additionally ensure that this model is checkable.""" if not index.isValid(): return Qt.NoItemFlags return super( TreeModel, self).flags(index) | Qt.ItemIsUserCheckable #|Qt.ItemIsEditable
def flags(self, index: QModelIndex) -> int: if not index.isValid(): return Qt.NoItemFlags flags = super(IMCFileTreeModel, self).flags(index) item: IMCFileTreeItem = index.internalPointer() if index.column( ) == self.CHECK_COLUMN and item.imc_file_tree_is_checkable: flags |= Qt.ItemIsUserCheckable return flags
def parent(self, index: QModelIndex = None, **kwargs) -> QModelIndex: if index is not None and index.isValid(): parent_item: IMCFileTreeItem = index.internalPointer( ).imc_file_tree_parent if parent_item is not None and parent_item.imc_file_tree_parent is not None: parent_row = parent_item.imc_file_tree_parent.imc_file_tree_children.index( parent_item) return self.createIndex(parent_row, 0, parent_item) return QModelIndex()
def mapToSource(self, proxyIndex: QModelIndex) -> QModelIndex: if not proxyIndex.isValid(): return QModelIndex() sm = self.sourceModel() iter_index = sm.index(self._iter, 0, QModelIndex()) if not iter_index.isValid() or not sm.hasChildren(iter_index): return QModelIndex() real_index = sm.index(proxyIndex.row(), proxyIndex.column(), iter_index) return real_index
def _redecorate_root(self, parent: QModelIndex = None, *_): """Add a branch/arrow column only if there are Groups in the root. This makes the tree fall back to looking like a simple list if there are no lists in the root level. """ if not parent or not parent.isValid(): hasgroup = any(isinstance(i, MutableSequence) for i in self._root) self.setRootIsDecorated(hasgroup)
def data(self, index: QModelIndex, role: Optional[int] = None) -> Any: if index.isValid(): channel = self._controller.channels[index.row()] if index.column( ) == self.CHECK_COLUMN and role == Qt.CheckStateRole: return Qt.Checked if channel.is_shown else Qt.Unchecked if index.column() == self.LABEL_COLUMN and role == Qt.DisplayRole: return channel.label return None
def getItem(self, index: QModelIndex) -> Node: """Return ``Node`` object for a given `QModelIndex`. A null or invalid ``QModelIndex`` will return the root Node. """ if index.isValid(): item = index.internalPointer() if item is not None: return item return self._root
def _index_is_on_our_branch(self, index: QModelIndex) -> bool: # the tree is only traversed towards the root if index.internalPointer().type not in (NodeType.ITER, NodeType.REAL): return False while index.isValid() and index.internalPointer() is not None: node = index.internalPointer() if node.type == NodeType.ITER and node.row() != self._iter: return False index = index.parent() return True
def data(self, index: QModelIndex, role=Qt.DisplayRole) -> QVariant: if not index.isValid(): return QVariant() if role == Qt.TextAlignmentRole: return Qt.AlignCenter if role == ProgressRole: return self._progress return QVariant()
def getItem(self, index: QModelIndex) -> TreeItem: """Convenience method to get a TreeItem from a given index. Returns the root item if the index passed is not valid.""" if index.isValid(): item = index.internalPointer() if item: return item return self.rootItem
def on_new_iteration(self, parent: QModelIndex, start: int, end: int) -> None: if not parent.isValid(): iter = start self._iteration_progress_label.setText(f"Progress for iteration {iter}") widget = RealizationWidget(iter) widget.setSnapshotModel(self._snapshot_model) widget.currentChanged.connect(self._select_real) self._tab_widget.addTab(widget, f"Realizations for iteration {iter}")
def getItem(self, index: QModelIndex) -> NodeType: """Return python object for a given `QModelIndex`. An invalid `QModelIndex` will return the root object. """ if index.isValid(): item = index.internalPointer() if item is not None: return item return self._root
def flags(self, index: QModelIndex): flags = (Qt.NoItemFlags | Qt.ItemIsDragEnabled | Qt.ItemIsSelectable | Qt.ItemIsEnabled) if index.isValid(): node = self.node_from_index(index) column = self.columns[index.column()].name if isinstance(node, JsonItem): if column == 'value' and not node.readonly: if not node.type == 'bool': flags |= Qt.ItemIsEditable else: flags |= Qt.ItemIsUserCheckable return flags