def setModelData(self, editor: QComboBox, model: QAbstractItemModel, index: QModelIndex) -> None: selectedIndex: int = editor.currentIndex() mi = QPersistentModelIndex() if selectedIndex is not None and selectedIndex >= 0: mi = QPersistentModelIndex( self.__timeLabelModel.index(selectedIndex)) model.setData(index, mi, Qt.EditRole)
def __init__(self, toolbox, index, item=None): """ Args: toolbox (ToolboxUI): Toolbox that requests this menu, used as parent. index (QModelIndex): the index item (ProjectItem, optional): passed to show_specification_form """ super().__init__(toolbox) self._toolbox = toolbox self.index = QPersistentModelIndex(index) self.add_action("Edit specification", lambda item=item: toolbox.edit_specification(self.index, item)) self.add_action("Remove specification", lambda: toolbox.remove_specification(self.index.row())) self.add_action("Open specification file...", lambda: toolbox.open_specification_file(self.index))
def __init__(self, parent, index): """ Args: parent (QWidget): Parent for menu widget (ToolboxUI) position (QPoint): Position on screen index (QModelIndex): the index """ super().__init__(parent) self.index = QPersistentModelIndex(index) self.add_action("Edit specification", lambda: parent.edit_specification(self.index)) self.add_action("Remove specification", lambda: parent.remove_specification(self.index.row())) self.add_action("Open specification file...", lambda: parent.open_specification_file(self.index)) self.addSeparator()
def contextMenuEvent(self, event): contextMenu = QMenu(self) removeAction = contextMenu.addAction('Usuń') action = contextMenu.exec_(self.mapToGlobal(event.pos())) if action == removeAction: index_list = [] for model_index in self.table.selectionModel().selectedRows(): index = QPersistentModelIndex(model_index) index_list.append(index) for index in index_list: self.sti.removeRow(index.row())
def hide_row(self): """Hides a row (or multiple rows).""" index_list = [] for model_index in self.window.tableView.selectionModel().selectedRows( ): index = QPersistentModelIndex(model_index) index_list.append(index) # Remove from table model, query_list, and queries for index in sorted(index_list, reverse=True): self.window.tableView.setRowHidden(index.row(), True) self.hidden.append(index) # todo set enabled 'show all rows" button now that rows are hidden # Refresh self.window.tableView.reset() self.refresh()
def remove_query(self): """Deletes a query from the form completely.""" index_list = [] for model_index in self.window.tableView.selectionModel().selectedRows( ): index = QPersistentModelIndex(model_index) index_list.append(index) # Remove from table model, query_list, and queries for index in sorted(index_list, reverse=True): del self.queries[index.row()] self.query_list.drop(self.query_list.index[[index.row()]], inplace=True) # Refresh self.window.tableView.reset() self.refresh()
def toggle_full_tree(self): """Called to toggle the full class tree or a partial tree. """ self.hide_empty_classes = not self.hide_empty_classes self.prefs['hide_empty_classes'] = 1 if self.hide_empty_classes else 0 self.prefs.write_settings() tree = self.classTree current = tree.currentIndex() current_persistent = QPersistentModelIndex(current) if self.idf: if self.prefs[ 'save_hidden_classes'] == 1 and self.hide_empty_classes is True: save_hidden = 'HideEmptyClasses' else: save_hidden = '' self.idf.set_options({'save_hidden_classes': save_hidden}) tree_model = self.classTree.model() if tree_model: tree_model.hide_empty_classes = not self.classTree.model( ).hide_empty_classes self.treeFilterRegExpChanged() # TODO need to find a way to handle what happens when 'currentIndex' disappears # during the filtering. tree.scrollTo(current_persistent, QAbstractItemView.PositionAtCenter)
def deleteSelectedRows(self): """ deleteSelectedRows delete selected rows """ bAnswer = yesNoDelete(self, "Permanently delete selected rows", "Delete rows") if bAnswer: jobsDB = SqlJobsTable(config.data.get(config.ConfigKey.SystemDB)) model = self.proxyModel.sourceModel() proxyIndexList = [] for i in self.selectionModel().selectedRows(): index = QPersistentModelIndex(i) proxyIndexList.append(index) for index in proxyIndexList: modelIndex = self.proxyModel.mapToSource(index) row = modelIndex.row() rowid = model.dataset.data[row][JobHistoryKey.ID].obj rowid0 = model.dataset[row, JobHistoryKey.ID] removeFromDb(jobsDB, rowid, rowid0) model.removeRows(row, 1) jobsDB.close()
def rebuild(self): """ regenerate our collection/override/layer controls. """ if not self.needsRebuild: # early out if we no longer need to rebuild # this can happen because rebuild is asynchronous return self.scrollArea.setVisible(False) self._clearWidgets() indexes = self._getSortedSelectedIndexes() creators = { renderSetup.RENDER_LAYER_TYPE : self._addLayer, renderSetup.COLLECTION_TYPE : self._addCollection, renderSetup.RENDER_SETTINGS_TYPE : self._addCollection, renderSetup.LIGHTS_TYPE : self._addCollection, renderSetup.AOVS_TYPE : self._addCollection, renderSetup.AOVS_CHILD_COLLECTION_TYPE : self._addCollection, renderSetup.LIGHTS_CHILD_COLLECTION_TYPE : self._addCollection, renderSetup.RENDER_OVERRIDE_TYPE : self._addOverride } for i in range(0, len(indexes)): currentIndex = QPersistentModelIndex(indexes[i][0]) currentItem = self.model().itemFromIndex(currentIndex) creators[currentItem.type()](currentItem) self.scrollWidgetLayout.addStretch(1) self.rebuildInProgress = False self.needsRebuild = False self.itemsToRepopulate = [] self.scrollArea.setVisible(True)
def contextMenuEvent(self, event): # Allow user to delete selected file(s) menu = QMenu(self.ui) remove = menu.addAction('Remove Selected Files') action = menu.exec_(QCursor.pos()) # Re-selects the current row if context menu is called on disabled cell i = self.ui.file_options.indexAt(event) self.ui.file_options.selectRow(i.row()) indices = [] if action == remove: for index in self.ui.file_options.selectedIndexes(): indices.append(QPersistentModelIndex(index)) for idx in indices: self.ui.file_options.removeRow(idx.row()) if self.ui.file_options.rowCount(): for i in range(len(self.files)): self.files[i] = [] for row in range(self.ui.file_options.rowCount()): f = self.ui.file_options.item(row, 0).text() else: self.files = [] self.enable_read()
def changeImage(self, newImageIndex): # Set new image index if newImageIndex: self.imageData = QPersistentModelIndex(newImageIndex) image = QPixmap(newImageIndex.data(role=Qt.UserRole)) self.scaledImage = image.scaled(self.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) # Get matching boxes already in data frame self.boxes = self.boxManager.getBoxesForImage(newImageIndex.data(role=Qt.DisplayRole)) else: self.imageData = None self.scaledImage = None self.boxes = [] # Update to redraw self.update()
def treeFilterRegExpChanged(self): """ :return: :rtype: """ pattern = self.filterTreeBox.text() if len(pattern) < 3: pattern = None if not self.classTree.model(): return current_class = QPersistentModelIndex(self.classTree.currentIndex()) self.classTree.model().setFilterRegExp(pattern) self.classTree.model().invalidateFilter() self.classTree.expandAll() self.classTree.scrollTo(current_class, QAbstractItemView.PositionAtCenter) # If the current class was hidden by the filter, clear the tableView if not current_class.isValid(): self.classTable.model().reset_model()
def setData(self, index: QModelIndex, value: QPersistentModelIndex, role: int = Qt.EditRole) -> bool: if index.isValid() and role == Qt.EditRole and index.column() == 1: sourceIndex = self.mapToSource(index) currValue: QPersistentModelIndex = self.attributes.get( sourceIndex.row(), None) if value.isValid() and value != currValue: self.attributes[sourceIndex.row()] = value self.dataChanged.emit(index, index, [Qt.DisplayRole, Qt.EditRole]) return True return False
def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> Any: if index.isValid(): sourceIndex = self.mapToSource(index) if role == Qt.DisplayRole and index.column() == 0: dataIndex = self.sourceModel().index( sourceIndex.row(), self.sourceModel().nameColumn, sourceIndex.parent()) attributeName: str = dataIndex.data(Qt.DisplayRole) frameName: str = self.sourceModel().frameModel().name return frameName + '.' + attributeName elif index.column() == 1 and (role == Qt.EditRole or role == Qt.DisplayRole): return self.attributes.get(sourceIndex.row(), QPersistentModelIndex()) return super().data(index, role)
def __init__(self, main_window, *args, **kwargs): super(ObjectCmd, self).__init__(*args, **kwargs) # TODO many of these are not needed for all subclasses. Break them out into # separate init methods in each subclass self.indexes_in = main_window.classTable.selectedIndexes() # self.indexes = [QPersistentModelIndex(i) for i in self.indexes_in] self.indexes = self.indexes_in self.main_window = main_window obj_class_index = main_window.classTree.selectedIndexes()[0] self.obj_class_index = QPersistentModelIndex(obj_class_index) self.obj_class = main_window.current_obj_class self.obj_orientation = main_window.obj_orientation self.mime_data = None self.new_objects = None self.new_object_groups = None self.old_objects = None self.from_clipboard = kwargs.get('from_clipboard', False) self.from_selection = kwargs.get('from_selection', False) self.value = kwargs.get('value', None) self.old_value = None self.index_groups = [] self.delete_count = 1 self.model = self.main_window.classTable.model() self.selection_model = self.main_window.classTable.selectionModel() # Convert indexes to source indexes for storage, then convert back later indexes_source_partial = [ self.model.mapToSource(ind) for ind in self.indexes_in ] self.indexes_source = [ self.model.sourceModel().mapToSource(ind) for ind in indexes_source_partial ] # Convert selection to source indexes for storage, then convert back later self.selection_saved = [] for sel in self.selection_model.selection(): self.selection_saved.append((sel.topLeft(), sel.bottomRight()))
def displayText(self, value: QPersistentModelIndex, locale: QLocale) -> str: if value and value.isValid(): return value.data(Qt.DisplayRole) return ''
class Canvas(QFrame): '''Takes care of showing the currently focused image and the main app use case of creating labels''' MIN_BOX_SIZE = 0.0025 # percent of image def __init__(self, boxManager): super().__init__() # Variables self.message = '' self.imageData = None self.boxes = [] self.drawingRect = None self.drawing = False # Objects self.image = None self.messageResetTimer = QTimer() self.brush = QBrush() self.pen = QPen() self.boxManager = boxManager # Styling self.setMinimumSize(QSize(850, 725)) self.messageResetTimer.setInterval(3000) self.messageResetTimer.setSingleShot(True) # Connections self.messageResetTimer.timeout.connect(self.resetMessage) def setMessage(self, param): self.message = param self.update() self.messageResetTimer.start() def resetMessage(self): self.message = '' self.update() def changeImage(self, newImageIndex): # Set new image index if newImageIndex: self.imageData = QPersistentModelIndex(newImageIndex) image = QPixmap(newImageIndex.data(role=Qt.UserRole)) self.scaledImage = image.scaled(self.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) # Get matching boxes already in data frame self.boxes = self.boxManager.getBoxesForImage( newImageIndex.data(role=Qt.DisplayRole)) else: self.imageData = None self.scaledImage = None self.boxes = [] # Update to redraw self.update() def paintEvent(self, event): painter = QPainter(self) # Draw background painter.save() self.brush.setColor(ThemeManager.BG_L2_QC) self.brush.setStyle(Qt.SolidPattern) painter.setBrush(self.brush) painter.setPen(Qt.NoPen) painter.drawRect(0, 0, self.size().width() - 1, self.size().height() - 1) painter.restore() # If image is set if self.imageData: if self.imageData.isValid(): # Find xy offsets self.dx = self.size().width() - self.scaledImage.size().width( ) if self.size().width() - self.scaledImage.size().width( ) else self.scaledImage.size().width() - self.size().width() self.dy = self.size().height() - self.scaledImage.size( ).height() if self.size().height() - self.scaledImage.size( ).height() else self.scaledImage.size().height() - self.size( ).height() # Paint rescaled image painter.setRenderHint(QPainter.HighQualityAntialiasing, True) painter.drawPixmap(self.dx / 2, self.dy / 2, self.scaledImage) # Paint in-progress box if self.drawingRect: painter.save() x, x2, y, y2 = self.drawingRect # Convert % to xy coords, account for off by one error x = (x * self.scaledImage.size().width() + self.dx / 2) - 1 y = (y * self.scaledImage.size().height() + self.dy / 2) - 1 x2 = (x2 * self.scaledImage.size().width() + self.dx / 2) - 2 y2 = (y2 * self.scaledImage.size().height() + self.dy / 2) - 2 # Setup painter's brush and pen colors self.brush.setColor(ThemeManager.ACCENT_VLOW_OPACITY_QC) self.brush.setStyle(Qt.SolidPattern) self.pen.setColor(ThemeManager.ACCENT_QC) painter.setBrush(self.brush) painter.setPen(self.pen) painter.drawRect(QRect(QPoint(x, y), QPoint(x2, y2))) painter.restore() # Paint existing boxes for box in self.boxes: painter.save() x, x2, y, y2 = box.getRect() # Convert % to xy coords, account for off by one error, and draw box's rect x = (x * self.scaledImage.size().width() + self.dx / 2) - 1 y = (y * self.scaledImage.size().height() + self.dy / 2) - 1 x2 = (x2 * self.scaledImage.size().width() + self.dx / 2) - 1 y2 = (y2 * self.scaledImage.size().height() + self.dy / 2) - 2 painter.drawRect(QRect(QPoint(x, y), QPoint(x2, y2))) # Setup painter's brush and pen colors self.brush.setColor(ThemeManager.ACCENT_LOW_OPACITY_QC) self.brush.setStyle(Qt.SolidPattern) self.pen.setColor(ThemeManager.ACCENT_QC) painter.setBrush(self.brush) painter.setPen(self.pen) painter.drawRect(QRect(QPoint(x, y), QPoint(x2, y2))) # Draw box's label pen = QPen() font = QFont('Arial', 8) pen.setColor(ThemeManager.LABEL_QC) painter.setPen(pen) painter.drawText(x + 2, y + 11, box.getLabel()) painter.restore() # TODO: Move this logic out of Paint Event # Image this index was referencing was deleted else: self.boxes = [] self.imageData = None if self.message: painter.save() font = QFont('Arial', 20) messageWidth = QFontMetrics(font).width(self.message) painter.setFont(font) self.pen.setColor(ThemeManager.ACCENT_QC) painter.setPen(self.pen) painter.drawText((self.width() - messageWidth) / 2, self.height() * .9, self.message) painter.restore() painter.end() def translateMousePosToPercent(self, event): '''Takes a given mouse event and translates the coordinates into image-relative percentages.''' try: # Translate mouse event location to percentage x = (event.x() - self.dx / 2) / self.scaledImage.size().width() y = (event.y() - self.dy / 2) / self.scaledImage.size().height() # Cap to max and min x = max(min(1.0, x), 0.0) y = max(min(1.0, y), 0.0) return (x, y) except: return (0.0, 0.0) def checkBoxValid(self, points): '''Calculates total area % of image the box takes. Must be greater than MIN_BOX_SIZE.''' try: x, x2, y, y2 = points area = abs(x2 - x) * abs(y2 - y) return area > self.MIN_BOX_SIZE except TypeError: return False def mousePressEvent(self, event): super().mousePressEvent(event) if event.button() is Qt.LeftButton: self.xPress, self.yPress = self.translateMousePosToPercent(event) self.drawing = True def mouseMoveEvent(self, event): super().mouseMoveEvent(event) if self.drawing: self.xMove, self.yMove = self.translateMousePosToPercent(event) self.drawingRect = (self.xPress, self.xMove, self.yPress, self.yMove) self.update() def mouseReleaseEvent(self, event): super().mouseReleaseEvent(event) if event.button() == Qt.LeftButton: self.handleDrawnBox() def handleDrawnBox(self): '''Called by mouse release event. Lets the Box Manager know to add box to data frame.''' if self.drawing and self.checkBoxValid(self.drawingRect): x, x2, y, y2 = self.drawingRect newBox = self.boxManager.addBoxToDataFrame( self.imageData.data(role=Qt.DisplayRole), min([x, x2]), max([x, x2]), min([y, y2]), max([y, y2])) self.boxes.append(newBox) self.drawingRect = None self.update() self.drawing = False
from PySide2.QtCore import Qt, QPersistentModelIndex from PySide2.QtGui import QStringListModel if __name__ == '__main__': stringListModel = QStringListModel(['one', 'two']) idx = stringListModel.index(1, 0) persistentModelIndex = QPersistentModelIndex(idx) stringListModel.data(persistentModelIndex, Qt.DisplayRole)