def columnCount(self, parent: QModelIndex = QModelIndex()) -> int: if not parent.isValid(): return 1 if not parent.parent().isValid(): return 1 return len(ItemModel.item_column_names)
def move_drop(self, destination_index: QModelIndex): if not self.view.supports_drag_move: return LOGGER.debug('Drop with MoveAction at Proxy @%sP%s', destination_index.row(), destination_index.parent().row()) self.view.editor.move_rows(destination_index)
def _set_data(index: QModelIndex, data, parent_user_data): model = index.model() model.setData(index, data) # Flag the parent with UserData that some child has been edited(or not on Undo) if index.parent().isValid(): result = model.setData(index.parent().siblingAtColumn(0), parent_user_data, Qt.UserRole) if result and parent_user_data: # Style italic, children contain item edits model.setData(index.parent().siblingAtColumn(0), FontRsc.italic, Qt.FontRole) else: # Style regular, children have not been edited model.setData(index.parent().siblingAtColumn(0), FontRsc.regular, Qt.FontRole)
def _has_checked_ancestor(self, index: QtCore.QModelIndex) -> bool: parent = index.parent() while parent.isValid() and self.filePath(parent) != self.rootPath(): if QtCore.QPersistentModelIndex(parent) in self.selected: return True parent = parent.parent() return False
def get_index_group_parent(prx_index: QModelIndex) -> QModelIndex: """ Get the highest valid parent index """ parent_idx = prx_index.parent() while parent_idx.parent().isValid(): parent_idx = parent_idx.parent() return parent_idx
def parent(self, child: QModelIndex = None): if not child.isValid(): return QModelIndex() child = child.internalPointer() parent = child.parent() if parent == self.root: return QModelIndex() return self.createIndex(parent.row(), 0, parent)
def removeRows(self, position: int, rows: int, index: QtCore.QModelIndex = QtCore.QModelIndex()) -> bool: self.beginRemoveRows(index.parent(), position, position + rows - 1) for row in range(rows): self._deleled_files.append(self._data['filename'][position]) self._data.remove_row(position) self._mask.remove_row(position) self.endRemoveRows() return True
def _uncheck_exclusive_ancestors(self, index: QtCore.QModelIndex) -> None: "Uncheck ancestors of index that have no other checked descendants" parent = index.parent() while self.filePath(parent) != self.rootPath(): child_data = (self._data(parent.child(i, index.column())) for i in range(self.rowCount(parent))) if all(state == QtCore.Qt.Unchecked for state in child_data): self._set_check_state(parent, QtCore.Qt.Unchecked) else: break parent = parent.parent()
def removeEntry(self): selectedIndexes = self.ui.ganttView.selectionModel().selectedIndexes() if len(selectedIndexes) > 0: index = selectedIndexes[0] else: index = QModelIndex() if not index.isValid(): return self.model.removeRow(index.row(), index.parent())
def setData(self, index: QModelIndex, value: str, role: int = Qt.EditRole) -> bool: if index.isValid() and role == Qt.EditRole: # If the new value is invalid, then remove the row and quit value = value.strip() if not value or value in self.stringList(): self.removeRow(index.row(), index.parent()) return False # In every other case call superclass return super().setData(index, value, role)
def __init__(self, parent_cmd: TreeOrderCommandChain, editor, index: QModelIndex, new_order: int): """ Re-order items by re-writing the order column. :param parent_cmd: :param modules.itemview.editor.KnechtEditor editor: :param index: :param new_order: """ super(TreeOrderCommand, self).__init__(parent_cmd) self.debug = TreeUndoCommandChainWorker.debug self.editor = editor self.new_order = new_order self.model: KnechtModel = index.model() self.position = index.row() self.parent_idx = index.parent() self.parent_position = index.parent().row() # Make sure index is in Order column self.index = self.model.sibling(index.row(), Kg.ORDER, index) self.current_order = int(self.index.data())
def mapFromSource(self, source_index: QModelIndex) -> QModelIndex: # noqa: N802 """ Maps from source model to this model's index. Args: source_index (:obj:`QModelIndex`): The source model index. Returns: (:obj:`QModelIndex`): This model's index. """ column_map = { MaterialsCoverageData.column_name: self.column_name, MaterialsCoverageData.column_user_text: self.column_user_text, MaterialsCoverageData.column_user_option: self.column_user_option } if source_index.column() in column_map.keys(): return self.index(source_index.row(), column_map[source_index.column()], source_index.parent()) return super().mapFromSource(source_index)
def mapToSource(self, proxy_index: QModelIndex) -> QModelIndex: # noqa: N802 """ Maps from this model's index to the source model's index. Args: proxy_index (:obj:`QModelIndex`): The proxy model index. Returns: (:obj:`QModelIndex`): The source model's index. """ column_map = { self.column_name: MaterialsCoverageData.column_name, self.column_user_text: MaterialsCoverageData.column_user_text, self.column_user_option: MaterialsCoverageData.column_user_option } if proxy_index.column() in column_map.keys(): return self.sourceModel().index(proxy_index.row(), column_map[proxy_index.column()], proxy_index.parent()) return super().mapToSource(proxy_index)
def duplicateRow(self, row: QtCore.QModelIndex): """ copies tree, increments its name, adds it as sibling :param row : QModelIndex for row """ print("model duplicate row") parent = row.parent() print("parent", parent, "row", row) parentItem = self.itemFromIndex(parent) rowItem = self.itemFromIndex(row) print(parentItem, rowItem) #address = self.data(row, objRole) address = self.data(row, relAddressRole) print("address", address) tree = self.tree(address) treeParent = tree.parent #newTree = tree.fromDict(tree.serialise()) newTree = tree.copy(deep=True) print(newTree, type(newTree), treeParent.branches) print(newTree is tree, newTree.uid == tree.uid) print(tree in treeParent.branches, newTree in treeParent.branches) newTree = treeParent.addChild(newTree)
def _select_next_item(self, idx: QModelIndex, reverse): if not idx.isValid(): return # If there is a sibling, attempt to select the first leaf in the subtree, or, if there is no leaf, continue on # to the next item. for next_idx in _iter_siblings(idx, reverse): self._select_first_leaf(next_idx, reverse) return # Find the first ancestor with a sibling node parent_node = idx.parent() while parent_node is not None and parent_node.isValid( ) and not _next_sibling(parent_node, reverse).isValid(): parent_node = parent_node.parent() # If no such ancestor exists, we're out of trees to explore, which means that there's no next leaf. if parent_node is None or not parent_node.isValid(): return # Once we find the first sibling among ancestors, the next leaf will be the first leaf in the sibling's subtree. self._select_first_leaf(_next_sibling(parent_node, reverse), reverse) return
def _partially_check_ancestors(self, index: QtCore.QModelIndex) -> None: "Mark all ancestors of index as checked" parent = index.parent() while self.filePath(parent) != self.rootPath(): self._set_check_state(parent, QtCore.Qt.PartiallyChecked) parent = parent.parent()
def expand_parent_index(self, proxy_index: QModelIndex): if not self.view.isExpanded(proxy_index.parent()): self.view.expand(proxy_index.parent())
class HierarchyTreeView(QTreeView): """ Graficki prikaz hijerarhijskog stabla uz implementiran kontekstni meni, i displayer za sadrzaj stranice """ def __init__(self, model): """ Konstruktor Uključuje opciju prikazivanja kontekstnog menija. """ super(HierarchyTreeView, self).__init__() self.tree = model self.setModel(self.tree) self.setSelectionMode(QAbstractItemView.SingleSelection) self.tree.removedPage.connect(self.Clear) self.tree.clearedSignal.connect(self.Clear) # ukljucuje kontekstni meni self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.openMenu) selModel = self.selectionModel() selModel.selectionChanged.connect(self.updateTxt) selModel.selectionChanged.connect(self.updateSelection) self.lastSelectedPage = Page("tmp") self.lastSelectedIndex = QModelIndex() def getModel(self): """ Vraca tree Return: Tree """ return self.tree def openMenu(self, position): """ Metoda povezana na customContextMenuRequested. Kreira kontekstni meni sa akcijama dodavanja, brisanja i promene naziva elemenata. Kontekstni meni se prikazuje na poziciji na kojoj se nalazio kursor misa. Args: position(QPoint): pozicija kursora misa """ self.contextMenu = QMenu() actionManager = QApplication.instance().actionManager tmp = QApplication.instance().selectionModel if not isinstance(tmp, Text) and not isinstance(tmp, Picture): self.contextMenu.addAction(actionManager.addChildAction) self.contextMenu.addAction(actionManager.addAtAction) self.contextMenu.addAction(actionManager.addBefore) self.contextMenu.addSeparator() if not isinstance(tmp, Page): self.contextMenu.addAction(actionManager.renameNodeAction) #if isinstance(tmp, Picture): #self.contextMenu.addAction(actionManager.renameNodeAction) self.contextMenu.addAction(actionManager.removeChildAction) # prikaz kontekstnog menija self.contextMenu.exec_(self.viewport().mapToGlobal(position)) def mousePressEvent(self, event): """ Redefinisanje mouse pressed event-a. Uradjeno jer default-na implementacija rukovanja ovim dogadjajem ne podrazumeva deselekciju elementa stabla prilikom klika na praznu povrsinu. """ if (self.selectionMode() == QAbstractItemView.SingleSelection): self.selectionModel().clear() self.clearSelection() self.setCurrentIndex(QModelIndex()) super(HierarchyTreeView, self).mousePressEvent(event) def updateSelection(self, new): """ Promena selekcije """ if new.empty(): self.SelectRoot() else: QApplication.instance().selectionModel = self.selectionModel( ).currentIndex().internalPointer() def Clear(self): """ Refresh stranice """ try: self.clearSelection() self.setCurrentIndex(self.lastSelectedIndex) except: pass def SelectRoot(self): """ Selektovanje koren node """ QApplication.instance().selectionModel = self.model().root def updateTxt(self): """ Updateovanje status bara, labela za prikaz stranice, sadrzaja text i slika komponenti pri promeni selektovane strane """ try: tmp = self.selectionModel().currentIndex().internalPointer() if isinstance(tmp, Page): self.lastSelectedIndex = self.selectionModel().currentIndex() widgetList = [] j = 0 for i in reversed(range(QApplication.instance().page.count())): QApplication.instance().page.takeAt(i).widget().setParent( None) for child in tmp.getChildren(): try: if isinstance(child, Text): widget = MyTextEdit(child) QApplication.instance().page.addWidget( widget, Qt.FramelessWindowHint) widget.show() if isinstance(child, Picture): widget = MyPictureEdit(child) QApplication.instance().page.addWidget(widget) widget.show() widgetList.append(widget) for widget in widgetList: widget.setPosition(widget.object.getPosition()) except Exception as e: print(e) pageLabel = QApplication.instance().pageLabel pageLabel.setText( str(tmp.getName()[:-1]) + ": " + tmp.getName()[-1]) self.lastSelectedPage = tmp if isinstance(tmp, Page): QApplication.instance().statusBar.setText( str(tmp.getParent().getParent().getName()) + "->" + str(tmp.getParent().getName()) + "->" + str(tmp.getName())) if isinstance(tmp, Chapter): QApplication.instance().statusBar.setText( str(tmp.getParent().getName()) + "->" + str(tmp.getName())) except: pass def leftButtonPressed(self): """ Prelazak na prethodnu stranu """ try: tmp = self.lastSelectedIndex.sibling( self.lastSelectedPage.getIndex() - 1, 0) if tmp.isValid(): self.setCurrentIndex(tmp) self.lastSelectedIndex = tmp self.lastSelectedPage = self.selectionModel().currentIndex( ).internalPointer() else: parent = self.lastSelectedIndex.parent() pageUncle = self.lastSelectedPage.getParent() book = pageUncle.getParent() index = pageUncle.getIndex() i = -1 while len(book.childAt(index + i).getChildren()) == 0: i -= 1 parent = parent.sibling( self.lastSelectedPage.getParent().getIndex() + i, 0) i = 0 isValid = True while isValid: if parent.child(i, 0).isValid(): i += 1 else: isValid = False parent = parent.child(i - 1, 0) if parent.isValid(): self.setCurrentIndex(parent) self.lastSelectedIndex = parent self.lastSelectedPage = self.selectionModel().currentIndex( ).internalPointer() except: pass def rightButtonPressed(self): """ Prelazak na narednu stranu """ try: tmp = self.lastSelectedIndex.sibling( self.lastSelectedPage.getIndex() + 1, 0) if tmp.isValid(): self.setCurrentIndex(tmp) self.lastSelectedIndex = tmp self.lastSelectedPage = self.selectionModel().currentIndex( ).internalPointer() else: parent = self.lastSelectedIndex.parent() pageUncle = self.lastSelectedPage.getParent() book = pageUncle.getParent() index = pageUncle.getIndex() i = 1 while len(book.childAt(index + i).getChildren()) == 0: i += 1 parent = parent.sibling( self.lastSelectedPage.getParent().getIndex() + i, 0) parent = parent.child(0, 0) if parent.isValid(): self.setCurrentIndex(parent) self.lastSelectedIndex = parent self.lastSelectedPage = self.selectionModel().currentIndex( ).internalPointer() except: pass
def setData( self, # pylint: disable=too-many-return-statements index: QModelIndex, value: Any, role: Qt.ItemDataRole = Qt.EditRole) -> bool: """Set the LeafNode value and corresponding data entry to value. Returns true if successful; otherwise returns false. The dataChanged() signal should be emitted if the data was successfully set. Args: index (QModelIndex): The index value (Any): The value role (Qt.ItemDataRole): The role of the data (Default: Qt.EditRole) Returns: bool: True if successful, False otherwise """ try: if not index.isValid(): return False if role == QtCore.Qt.EditRole: if index.column( ) == self.VALUE: # only want to edit col1 if it's a leafnode node = self.nodeFromIndex(index) if isinstance(node, LeafNode): value = str(value) # new value old_value = node.value # option value if old_value == value: return False # Set the value of an option when the new value is different node.value = value # # pylint: disable=attribute-defined-outside-init return True # why doesn't this require a self.init_load()? elif index.column( ) == self.NAME: # either editing BranchNode name or LeafNode name node = self.nodeFromIndex(index) if node.parent is None: raise Exception( "Trying to edit node without a parent. " "The root node should be uneditable.") old_value = node.name if old_value == value: return False node.update_name(value) cop = self.get_path_of_expanded_items() self.reload() self.expand_items_in_paths(cop) # update node # at each parent: # data.emit changed from 0,0 to len(children), lenCol return True elif index.column() == self.TYPE: # this is a type node = self.nodeFromIndex( self.index(index.row(), 0, index.parent())) node.type = value cop = self.get_path_of_expanded_items() self.reload() self.expand_items_in_paths(cop) return True return False except Exception as e: # pylint: disable=broad-except self._design.logger.error(f"Unable to parse tree information: {e}") return False