def handle_parts_tree_activated(self, qindex: QModelIndex): if isinstance(qindex.internalPointer(), ArmorSetNode): return self.armor_item_mapper.setRootIndex(qindex.parent()) self.armor_item_mapper.setCurrentModelIndex(qindex) entry = qindex.internalPointer().ref self.crafting_requirements_editor.set_current(entry.id)
def createEditor(self, parent: QWidget, option: QStyleOptionViewItem, index: QtCore.QModelIndex) -> QWidget: if isinstance(index.internalPointer(), IterableSequencerStep): widg = IterationRangeEditor(parent) widg.setFromStep(index.internalPointer()) widg.resize(option.rect.size()) self.editor: IterationRangeEditor = widg return widg else: return None # Don't allow handling other types of values. # super().createEditor(parent, option, index)
def setData(self, index: QModelIndex, value: typing.Any, role: int = ...) -> bool: if role == Qt.CheckStateRole: if value == Qt.Checked: index.internalPointer().enabled = True else: index.internalPointer().enabled = False self.dataChanged.emit(index, index) return True
def data(self, index: QModelIndex, role): if not index.isValid(): return None self._load() item: TreeItem = index.internalPointer() if role == Qt.DisplayRole: return item.data(index.column()) if item.parentItem( ) is not None else '<<ROOT>>' elif role == Qt.UserRole: item = index.internalPointer() return item.get_key() if item else None else: return None
def lessThan(self, left_index: QModelIndex, right_index: QModelIndex): try: left_item = left_index.internalPointer() right_item = right_index.internalPointer() if left_item.childCount() == 0: if left_item.name() < right_item.name(): return True else: return False else: return False except AttributeError: return False
def flags(self, index: QModelIndex): flags = Qt.ItemIsEnabled if self.headers[index.column( )] in self.buttonHeaders and index.internalPointer( ).parent != self.root: flags |= Qt.ItemIsUserCheckable return flags
def getItem(self, index: QModelIndex) -> ProtocolTreeItem: if index.isValid(): item = index.internalPointer() if item: return item return self.rootItem
def setData(self, index: QModelIndex, value: QVariant, role: int = None): if not index.isValid(): return False item = index.internalPointer() if role == Qt.CheckStateRole: childrenCount = item.childrenCount() if childrenCount: for i in range(childrenCount): self.setData(index.child(i, 0), value, role = role) else: item.selected = bool(value) self.dataChanged.emit(index, index, [Qt.CheckStateRole]) # recalculate parents p = index while True: p = p.parent() if p.isValid(): self.dataChanged.emit(p, p, [Qt.CheckStateRole]) else: break # success return True if role == Qt.EditRole: assert index.column() == TaskTreeColumn.FileName item.setNameByUser(value) self.dataChanged.emit(index, index, [Qt.DisplayRole]) return True return False
def rowCount(self, parent: QModelIndex): if parent.column() > 0: return 0 if not parent.isValid(): return self._rootItem.childCount() else: return parent.internalPointer().childCount()
def data(self, index: QtCore.QModelIndex, role: Qt = Qt.DisplayRole) -> typing.Any: result = None invalid_index = QtCore.QModelIndex() if index.isValid(): node = index.internalPointer() if index.parent() == invalid_index: check_head: ChecklistItemHead = node.ref if role == Qt.DisplayRole: if index.column() == 0: result = check_head.name elif index.column() == 1: pass else: raise RuntimeError(f'Invalid column: {index.column()}') elif role == Qt.CheckStateRole and index.column() == 1: result = check_head.validated elif role == Qt.BackgroundRole and index.column() == 1 and check_head.validated == Qt.Checked: result = QtGui.QColor(Qt.green) else: # it is a checklist property check_head: ChecklistItemHead = index.parent().internalPointer().ref check_property: ChecklistItemProperty = node.ref if role == Qt.DisplayRole: if index.column() == 0: result = check_property.name elif index.column() == 1: if index.row() == ChecklistItemPropertyColumn.AUTOMATION.value: if check_head.automation is None: result = 'Not enabled' else: pass else: result = check_property.value else: raise RuntimeError(f'Invalid column: {index.column()}') return result
def item(self, index: QtCore.QModelIndex) -> Item: if not index.isValid(): raise ValueError("Invalid index") item = index.internalPointer() assert item is not None return item
def __findDuplicates(self, cond, special, showMessage=False, index=None): """ Private method to check, if an entry already exists. @param cond condition to check (string) @param special special condition to check (string) @param showMessage flag indicating a message should be shown, if a duplicate entry is found (boolean) @param index index that should not be considered duplicate (QModelIndex) @return flag indicating a duplicate entry (boolean) """ if index is None: index = QModelIndex() idx = self.__model.getWatchPointIndex(cond, special) duplicate = (idx.isValid() and idx.internalPointer() != index.internalPointer()) if showMessage and duplicate: if not special: msg = self.tr("""<p>A watch expression '<b>{0}</b>'""" """ already exists.</p>""").format( Utilities.html_encode(cond)) else: msg = self.tr( """<p>A watch expression '<b>{0}</b>'""" """ for the variable <b>{1}</b> already exists.</p>""" ).format(special, Utilities.html_encode(cond)) E5MessageBox.warning(self, self.tr("Watch expression already exists"), msg) return duplicate
def setData(self, index: QModelIndex, value: QVariant, role: int = None): if not index.isValid(): return False item = index.internalPointer() if role == Qt.CheckStateRole: childrenCount = item.childrenCount() if childrenCount: for i in range(childrenCount): self.setData(index.child(i, 0), value, role=role) else: item.selected = bool(value) self.dataChanged.emit(index, index, [Qt.CheckStateRole]) # recalculate parents p = index while True: p = p.parent() if p.isValid(): self.dataChanged.emit(p, p, [Qt.CheckStateRole]) else: break # success return True if role == Qt.EditRole: assert index.column() == TaskTreeColumn.FileName item.setNameByUser(value) self.dataChanged.emit(index, index, [Qt.DisplayRole]) return True return False
def getItem(self, index: QModelIndex): if index.isValid(): item = index.internalPointer() if item: return item return self.workspace_data
def filterAcceptsRow(self, source_row: int, source_parent: QModelIndex): p = source_parent.internalPointer() if p == self.sourceModel().root or p is None: return True node: LogBrowserNode = p.children[source_row] if self.filterSuccess: if node.result != LogBrowserModel.TXT_SUCCESS: return False if self.filterAccount is not "": if self.filterAccount not in node.accounts: return False if self.filterChar is not "": if self.filterChar not in node.characters: return False if self.filterNew: if not node.isNew: return False if self.filterStartTime > node.timeStamp: if node.timeStamp == 0: None else: return False if self.filterEndTime < node.timeStamp: return False return True
def data(self, index: QModelIndex, role: int): if not index.isValid(): return None if role != QtCore.Qt.DisplayRole: # We only support this role type. Return the SequencerStep itself as the data. return None item: SequencerStep = index.internalPointer() return item
def select_by_names(self, names): self.unselect_all() for name in names: try: codes = self.name2num[name].split(" ") for code in codes: if code[0] != TreeWidget.codes[self.name]: continue keys = code[1:].split(".") node = self.model.root_node index = QModelIndex() for key in keys: row = node.children_numbers().index(key) index = self.model.index(row, 0, index) node = index.internalPointer() self.selectionModel().select( index, QItemSelectionModel.Select) self.expand(index) self.selectionModel().select(index, QItemSelectionModel.Select) except: print("Could not select using this name: %s" % name)
def data(self, index: QModelIndex, role=None): if not index.isValid(): return QVariant() row = index.row() col = index.column() node = index.internalPointer() if role == Qt.DisplayRole or role == Qt.ToolTipRole: if col == 0: return QVariant(row + 1) return QVariant(node[col]) elif role == self.RoleId: return node['id'] elif role == self.RoleTier: return node['tier'] elif role == self.RoleProgress: if col == self.ColumnProgress: if node['tier'] == self.TIER_1: return node['progress'] elif role == Qt.BackgroundRole: retcol = QColor(Qt.white) if col == self.ColumnProgress: if node['tier'] == self.TIER_2: if node['received']: retcol = QColor(Qt.green).lighter(150) else: retcol = QColor(Qt.red).lighter(150) return QBrush(retcol) return QVariant()
def sizeHint(self, option: QtWidgets.QStyleOptionViewItem, index: QtCore.QModelIndex) -> QtCore.QSize: is_first_level = index.parent() == QtCore.QModelIndex() multiline_columns = ( ChecklistItemPropertyColumn.DESCRIPTION.value, ChecklistItemPropertyColumn.GUIDE.value, ChecklistItemPropertyColumn.VALIDATION_NOTES.value, ) is_multiline = index.row() in multiline_columns if not is_first_level and is_multiline and index.column() == 1: check_property: ChecklistItemProperty = index.internalPointer().ref text_to_draw = check_property.value base_width = self.gui_view.columnWidth(1) base_height = 10000 # some ridiculous high value just for initialization base_size = QtCore.QSize(base_width, base_height) metrics = QtGui.QFontMetrics(option.font) out_rect: QtCore.QRect = metrics.boundingRect( QtCore.QRect(QtCore.QPoint(0, 0), base_size), Qt.AlignLeft | Qt.AlignTop | Qt.TextWordWrap, text_to_draw, ) base_size.setHeight(out_rect.height()) result = base_size else: result = super().sizeHint(option, index) return result
def data(self, index: QtCore.QModelIndex, role: int = QtCore.Qt.DisplayRole): if not index.isValid(): return None if role != QtCore.Qt.DisplayRole: return None Item: TeamStatItem = index.internalPointer() return Item.GetData(index.column())
def highlightCurrentNode(self, current: QModelIndex, old: QModelIndex): node: SketchObjectNode = current.internalPointer() if isinstance(node, SketchNode): self.selectSketchNode(node) elif isinstance(node, SketchObjectNode): self._display.Context.SetSelected( node.sketchObject.myAIS_InteractiveObject, True)
def setData(self, index: QModelIndex, value: typing.Any, role: int = Qt.EditRole) -> bool: if not index.isValid(): return False item: TreeItem = index.internalPointer()
def parent(self, in_index: QModelIndex = None): if in_index.isValid(): parent = in_index.internalPointer().parent if parent: return QtCore.QAbstractItemModel.createIndex( self, parent.row, 0, parent) return QtCore.QModelIndex()
def data(self, index: QtCore.QModelIndex, role: int) -> Any: if not index.isValid(): return False if role == QtCore.Qt.CheckStateRole: if index.column() == 0: if index in self._checkedIndexes: return QtCore.Qt.Checked else: return QtCore.Qt.Unchecked node = index.internalPointer() if role == QtCore.Qt.DecorationRole: icon = None if index.column() == 0: if node.__icon__ is None: identity = node.__mapper_args__.get('polymorphic_identity') if identity.endswith('Folder'): icon = QtGui.QIcon(':Folder') else: icon = QtGui.QIcon(node.__icon__) return icon if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole: colnr = index.column() return node._qt_data_colnr(colnr)
def rowCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int: if not parent.isValid(): result = len(self.root_nodes) else: node: TreeNode = parent.internalPointer() result = len(node.sub_nodes) return result
def rowCount(self, parent: QtCore.QModelIndex) -> int: if not parent.isValid(): parentNode = self._rootNode else: parentNode = parent.internalPointer() return parentNode.childCount()
def data(self, index: QModelIndex, role: int) -> typing.Any: if not index.isValid(): return QVariant() if index.column() == 1 and role == Qt.CheckStateRole and isinstance( index.internalPointer(), PartitionItem): if index.internalPointer().enabled: return Qt.CheckState(Qt.Checked) else: return Qt.CheckState(Qt.Unchecked) if role != Qt.DisplayRole or index.column() == 1: return QVariant() item = index.internalPointer() return item.data(index.column())
def columnCount(self, parent: QtCore.QModelIndex = None, *args, **kwargs): if not parent: parent = QtCore.QModelIndex() if parent.isValid(): return parent.internalPointer().GetColumnCount() else: return self.RootItem.GetColumnCount()
def index(self, row: int, column: int, parent: QModelIndex): # is this the hidden root index if not parent.isValid(): if len(self.root_nodes): return self.createIndex(row, column, self.root_nodes[row]) return QModelIndex() parent_node = parent.internalPointer() return self.createIndex(row, column, parent_node.subnodes[row])
def parent(self, index: QModelIndex): if not index.isValid(): return QModelIndex() child = index.internalPointer() parent = child.parent if parent is self.root: return QModelIndex() return self.createIndex(parent.row, 0, parent)
def getNode(self, index: QtCore.QModelIndex) -> Any: """ Returns the actual node object behind a index""" if index.isValid(): node = index.internalPointer() if node: return node return self._rootNode
def rowCount(self, parent: QModelIndex = None, *args, **kwargs): if not self._root: return 0 if parent.isValid(): parentItem = parent.internalPointer() return parentItem.childrenCount() else: return self._root.childrenCount()
def parent(self, index: QtCore.QModelIndex): if not index.isValid(): return QtCore.QModelIndex() item = index.internalPointer().parent if item == self.root or item is None: return QtCore.QModelIndex() else: return self.createIndex(item.row, 0, item)
def data(self, index: QtCore.QModelIndex, role=QtCore.Qt.DisplayRole): if index.isValid(): ip = index.internalPointer() if index.column() == 0: if role == QtCore.Qt.DisplayRole: return ("*" if ip.unfinished() else "") + ip.title() elif role == QtCore.Qt.ToolTipRole: return ip.tooltip() elif role == QtCore.Qt.DecorationRole: return ip.image()
def parent(self, index: QModelIndex = None): if not index.isValid(): return QModelIndex() childItem = index.internalPointer() parentItem = childItem.parent if parentItem == self._root: return QModelIndex() else: return self.createIndex(parentItem.siblingNumber(), 0, parentItem)
def data(self, index: QModelIndex, role = None): if not index.isValid(): return None item = index.internalPointer() if role == Qt.DisplayRole: return item.data(index.column()) elif role == Qt.CheckStateRole and index.column() == TaskTreeColumn.FileName: return item.selected elif role == Qt.DecorationRole and index.column() == TaskTreeColumn.FileName: # TODO: use with real icons from PyQt5.QtGui import QIcon return QIcon.fromTheme("xware-desktop") return None
def item(self, index: QtCore.QModelIndex) -> FileItem: return index.internalPointer() if index.isValid() else self.root_item
class editorWidget(QWidget, Ui_editorWidget_ui): """ `editorWidget` is a class responsible for displaying and editing one `outlineItem`. This item can be a folder or a text. It has four views (see `self.setView`) - For folders: "text", "outline" or "cork" (set in `self.folderView`) Text: displays a list of `textEditView` in a scroll area Outline: displays an outline, using an `outlineView` Cork: displays flash cards, using a `corkView` - For text: item is simply displayed in a `textEditView` All those views are contained in `editorWidget` single widget: `self.stack`. `editorWidget` are managed in `tabSplitted` (that allow to open several `outlineItem`s, either in Tabs or in split views. `tabSplitted` are in turn managed by the `mainEditor`, which is unique and gives UI buttons to manage all those views. """ toggledSpellcheck = pyqtSignal(bool) dictChanged = pyqtSignal(str) _maxTabTitleLength = 24 def __init__(self, parent): QWidget.__init__(self, parent) self.setupUi(self) self.currentIndex = QModelIndex() self.currentID = None self.txtEdits = [] self.scroll.setBackgroundRole(QPalette.Base) self.toggledSpellcheck.connect(self.txtRedacText.toggleSpellcheck, AUC) self.dictChanged.connect(self.txtRedacText.setDict, AUC) self.txtRedacText.setHighlighting(True) self.currentDict = "" self.spellcheck = settings.spellcheck self.folderView = "cork" self.mw = mainWindow() self._tabWidget = None # set by mainEditor on creation self._model = None # Capture textEdit scrollbar, so that we can put it outside the margins. self.txtEditScrollBar = self.txtRedacText.verticalScrollBar() self.txtEditScrollBar.setParent(self) self.stack.currentChanged.connect(self.setScrollBarVisibility) # def setModel(self, model): # self._model = model # self.setView() def resizeEvent(self, event): """ textEdit's scrollBar has been reparented to self. So we need to update it's geomtry when self is resized, and put it where we want it to be. """ # Update scrollbar geometry r = self.geometry() w = 10 # Cf. style.mainEditorTabSS r.setWidth(w) r.moveRight(self.geometry().width()) self.txtEditScrollBar.setGeometry(r) QWidget.resizeEvent(self, event) def setScrollBarVisibility(self): """ Since the texteEdit scrollBar has been reparented to self, it is not hidden when stack changes. We have to do it manually. """ self.txtEditScrollBar.setVisible(self.stack.currentIndex() == 0) def setFolderView(self, v): oldV = self.folderView if v == "cork": self.folderView = "cork" elif v == "outline": self.folderView = "outline" else: self.folderView = "text" # Saving value settings.folderView = self.folderView if oldV != self.folderView and self.currentIndex: self.setCurrentModelIndex(self.currentIndex) def setCorkSizeFactor(self, v): self.corkView.itemDelegate().setCorkSizeFactor(v) self.redrawCorkItems() def redrawCorkItems(self): r = self.corkView.rootIndex() if r.isValid(): count = r.internalPointer().childCount() elif self._model: count = self._model.rootItem.childCount() else: count = 0 for c in range(count): self.corkView.itemDelegate().sizeHintChanged.emit(r.child(c, 0)) def updateTabTitle(self): """ `editorWidget` belongs to a `QTabWidget` in a `tabSplitter`. We update the tab title to reflect that of current item. """ # `self._tabWidget` is set by mainEditor when creating tab and `editorWidget`. # if `editorWidget` is ever used out of `mainEditor`, this could throw # an error. if not self._tabWidget: return if self.currentIndex.isValid(): item = self.currentIndex.internalPointer() elif self._model: item = self._model.rootItem else: return i = self._tabWidget.indexOf(self) self._tabWidget.setTabText(i, self.ellidedTitle(item.title())) self._tabWidget.setTabToolTip(i, item.title()) def ellidedTitle(self, title): if len(title) > self._maxTabTitleLength: return "{}…".format(title[:self._maxTabTitleLength]) else: return title def setView(self): # index = mainWindow().treeRedacOutline.currentIndex() # Counting the number of other selected items # sel = [] # for i in mainWindow().treeRedacOutline.selectionModel().selection().indexes(): # if i.column() != 0: continue # if i not in sel: sel.append(i) # if len(sel) != 0: # item = index.internalPointer() # else: # index = QModelIndex() # item = self.mw.mdlOutline.rootItem # self.currentIndex = index if self.currentIndex.isValid(): item = self.currentIndex.internalPointer() else: item = self.mw.mdlOutline.rootItem self.updateTabTitle() def addTitle(itm): edt = MDEditView(self, html="<h{l}>{t}</h{l}>".format(l=min(itm.level() + 1, 5), t=itm.title()), autoResize=True) edt.setFrameShape(QFrame.NoFrame) self.txtEdits.append(edt) l.addWidget(edt) def addLine(): line = QFrame(self.text) line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) l.addWidget(line) def addText(itm): edt = MDEditView(self, index=itm.index(), spellcheck=self.spellcheck, dict=settings.dict, highlighting=True, autoResize=True) edt.setFrameShape(QFrame.NoFrame) edt.setStatusTip("{}".format(itm.path())) self.toggledSpellcheck.connect(edt.toggleSpellcheck, AUC) self.dictChanged.connect(edt.setDict, AUC) # edt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self.txtEdits.append(edt) l.addWidget(edt) def addChildren(itm): for c in range(itm.childCount()): child = itm.child(c) if child.isFolder(): addTitle(child) addChildren(child) else: addText(child) addLine() def addSpacer(): l.addItem(QSpacerItem(10, 1000, QSizePolicy.Minimum, QSizePolicy.Expanding)) # Display multiple selected items # if len(sel) > 1 and False: # Buggy and not very useful, skip # self.stack.setCurrentIndex(1) # w = QWidget() # l = QVBoxLayout(w) # self.txtEdits = [] # for idx in sel: # sItem = idx.internalPointer() # addTitle(sItem) # if sItem.isFolder(): # addChildren(sItem) # else: # addText(sItem) # addLine() # addSpacer() # self.scroll.setWidget(w) if item and item.isFolder() and self.folderView == "text": self.stack.setCurrentIndex(1) w = QWidget() w.setObjectName("editorWidgetFolderText") l = QVBoxLayout(w) opt = settings.textEditor background = (opt["background"] if not opt["backgroundTransparent"] else "transparent") w.setStyleSheet("background: {};".format(background)) self.stack.widget(1).setStyleSheet("background: {}" .format(background)) # self.scroll.setWidgetResizable(False) self.txtEdits = [] if item != self._model.rootItem: addTitle(item) addChildren(item) addSpacer() self.scroll.setWidget(w) elif item and item.isFolder() and self.folderView == "cork": self.stack.setCurrentIndex(2) self.corkView.setModel(self._model) self.corkView.setRootIndex(self.currentIndex) try: self.corkView.selectionModel().selectionChanged.connect(mainWindow().redacMetadata.selectionChanged, AUC) self.corkView.clicked.connect(mainWindow().redacMetadata.selectionChanged, AUC) self.corkView.clicked.connect(mainWindow().mainEditor.updateTargets, AUC) except TypeError: pass elif item and item.isFolder() and self.folderView == "outline": self.stack.setCurrentIndex(3) self.outlineView.setModelCharacters(mainWindow().mdlCharacter) self.outlineView.setModelLabels(mainWindow().mdlLabels) self.outlineView.setModelStatus(mainWindow().mdlStatus) self.outlineView.setModel(self._model) self.outlineView.setRootIndex(self.currentIndex) try: self.outlineView.selectionModel().selectionChanged.connect(mainWindow().redacMetadata.selectionChanged, AUC) self.outlineView.clicked.connect(mainWindow().redacMetadata.selectionChanged, AUC) self.outlineView.clicked.connect(mainWindow().mainEditor.updateTargets, AUC) except TypeError: pass if item and item.isText(): self.txtRedacText.setCurrentModelIndex(self.currentIndex) self.stack.setCurrentIndex(0) # Single text item else: self.txtRedacText.setCurrentModelIndex(QModelIndex()) try: self._model.dataChanged.connect(self.modelDataChanged, AUC) self._model.rowsInserted.connect(self.updateIndexFromID, AUC) self._model.rowsRemoved.connect(self.updateIndexFromID, AUC) #self.mw.mdlOutline.rowsAboutToBeRemoved.connect(self.rowsAboutToBeRemoved, AUC) except TypeError: pass self.updateStatusBar() def setCurrentModelIndex(self, index=None): if index.isValid(): self.currentIndex = index self._model = index.model() self.currentID = self._model.ID(index) else: self.currentIndex = QModelIndex() self.currentID = None if self._model: self.setView() def updateIndexFromID(self): """ Index might have changed (through drag an drop), so we keep current item's ID and update index. Item might have been deleted too. """ idx = self._model.getIndexByID(self.currentID) # If we have an ID but the ID does not exist, it has been deleted if self.currentID and idx == QModelIndex(): # Item has been deleted, we open the parent instead self.setCurrentModelIndex(self.currentIndex.parent()) # FIXME: selection in self.mw.treeRedacOutline is not updated # but we cannot simply setCurrentIndex through treeRedacOutline # because this might be a tab in the background / out of focus # Also the UI of mainEditor is not updated (so the folder icons # are not display, button "up" doesn't work, etc.). # Item has been moved elif idx != self.currentIndex: # We update the index self.currentIndex = idx self.setView() def modelDataChanged(self, topLeft, bottomRight): # if self.currentID: # self.updateIndexFromID() if not self.currentIndex: return if topLeft.row() <= self.currentIndex.row() <= bottomRight.row(): self.updateStatusBar() #def rowsAboutToBeRemoved(self, parent, first, last): #if self.currentIndex: #if self.currentIndex.parent() == parent and \ #first <= self.currentIndex.row() <= last: ## Item deleted, close tab #self.mw.mainEditor.tab.removeTab(self.mw.mainEditor.tab.indexOf(self)) def updateStatusBar(self): # Update progress # if self.currentIndex and self.currentIndex.isValid(): # if self._model: mw = mainWindow() if not mw: return mw.mainEditor.updateStats() def toggleSpellcheck(self, v): self.spellcheck = v self.toggledSpellcheck.emit(v) def setDict(self, dct): self.currentDict = dct self.dictChanged.emit(dct) ############################################################################### # FUNCTIONS FOR MENU ACCESS ############################################################################### def getCurrentItemView(self): """ Returns the current item view, between txtRedacText, outlineView and corkView. If folder/text view, returns None. (Because handled differently) """ if self.stack.currentIndex() == 0: return self.txtRedacText elif self.folderView == "outline": return self.outlineView elif self.folderView == "cork": return self.corkView else: return None def copy(self): if self.getCurrentItemView(): self.getCurrentItemView().copy() def cut(self): if self.getCurrentItemView(): self.getCurrentItemView().cut() def paste(self): if self.getCurrentItemView(): self.getCurrentItemView().paste() def rename(self): if self.getCurrentItemView(): self.getCurrentItemView().rename() def duplicate(self): if self.getCurrentItemView(): self.getCurrentItemView().duplicate() def delete(self): if self.getCurrentItemView(): self.getCurrentItemView().delete() def moveUp(self): if self.getCurrentItemView(): self.getCurrentItemView().moveUp() def moveDown(self): if self.getCurrentItemView(): self.getCurrentItemView().moveDown() def splitDialog(self): """ Opens a dialog to split selected items. """ if self.getCurrentItemView() == self.txtRedacText: # Text editor if not self.currentIndex.isValid(): return sel = self.txtRedacText.textCursor().selectedText() # selectedText uses \u2029 instead of \n, no idea why. sel = sel.replace("\u2029", "\n") splitDialog(self, [self.currentIndex], mark=sel) elif self.getCurrentItemView(): # One of the views self.getCurrentItemView().splitDialog() def splitCursor(self): """ Splits items at cursor position. If there is a selection, that selection becomes the new item's title. Call context: Only works when editing a file. """ if not self.currentIndex.isValid(): return if self.getCurrentItemView() == self.txtRedacText: c = self.txtRedacText.textCursor() title = c.selectedText() # selection can be backward pos = min(c.selectionStart(), c.selectionEnd()) item = self.currentIndex.internalPointer() item.splitAt(pos, len(title)) def merge(self): """ Merges selected items together. Call context: Multiple selection, same parent. """ if self.getCurrentItemView() == self.txtRedacText: # Text editor, nothing to merge pass elif self.getCurrentItemView(): # One of the views self.getCurrentItemView().merge()
def itemFromIndex(self, index): index = QModelIndex(index) # explicitly convert from QPersistentModelIndex if index.isValid(): return index.internalPointer().childAt(index.row()) return self._root
def parentFromIndex(self, index): index = QModelIndex(index) # explicitly convert from QPersistentModelIndex if index.isValid(): return index.internalPointer() return self._root
def _indexToItem(self, index: QModelIndex): if not index.isValid(): return self._root else: return index.internalPointer()
class editorWidget(QWidget, Ui_editorWidget_ui): toggledSpellcheck = pyqtSignal(bool) dictChanged = pyqtSignal(str) def __init__(self, parent): QWidget.__init__(self, parent) self.setupUi(self) self.currentIndex = QModelIndex() self.currentID = None self.txtEdits = [] self.scroll.setBackgroundRole(QPalette.Base) self.toggledSpellcheck.connect(self.txtRedacText.toggleSpellcheck, AUC) self.dictChanged.connect(self.txtRedacText.setDict, AUC) self.txtRedacText.setHighlighting(True) self.currentDict = "" self.spellcheck = True self.folderView = "cork" self.mw = mainWindow() # def setModel(self, model): # self._model = model # self.setView() def setFolderView(self, v): oldV = self.folderView if v == "cork": self.folderView = "cork" elif v == "outline": self.folderView = "outline" else: self.folderView = "text" # Saving value settings.folderView = self.folderView if oldV != self.folderView and self.currentIndex: self.setCurrentModelIndex(self.currentIndex) def setCorkSizeFactor(self, v): self.corkView.itemDelegate().setCorkSizeFactor(v) self.redrawCorkItems() def redrawCorkItems(self): r = self.corkView.rootIndex() if r.isValid(): count = r.internalPointer().childCount() else: count = self.mw.mdlOutline.rootItem.childCount() for c in range(count): self.corkView.itemDelegate().sizeHintChanged.emit(r.child(c, 0)) def setView(self): # index = mainWindow().treeRedacOutline.currentIndex() # Couting the number of other selected items # sel = [] # for i in mainWindow().treeRedacOutline.selectionModel().selection().indexes(): # if i.column() != 0: continue # if i not in sel: sel.append(i) # if len(sel) != 0: # item = index.internalPointer() # else: # index = QModelIndex() # item = self.mw.mdlOutline.rootItem # self.currentIndex = index if self.currentIndex.isValid(): item = self.currentIndex.internalPointer() else: item = self.mw.mdlOutline.rootItem def addTitle(itm): edt = textEditView(self, html="<h{l}>{t}</h{l}>".format(l=min(itm.level() + 1, 5), t=itm.title()), autoResize=True) edt.setFrameShape(QFrame.NoFrame) self.txtEdits.append(edt) l.addWidget(edt) def addLine(): line = QFrame(self.text) line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) l.addWidget(line) def addText(itm): edt = textEditView(self, index=itm.index(), spellcheck=self.spellcheck, dict=settings.dict, highlighting=True, autoResize=True) edt.setFrameShape(QFrame.NoFrame) edt.setStyleSheet("background: {};".format(settings.textEditor["background"])) edt.setStatusTip("{} ({})".format(itm.path(), itm.type())) self.toggledSpellcheck.connect(edt.toggleSpellcheck, AUC) self.dictChanged.connect(edt.setDict, AUC) # edt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self.txtEdits.append(edt) l.addWidget(edt) def addChildren(itm): for c in range(itm.childCount()): child = itm.child(c) if child.isFolder(): addTitle(child) addChildren(child) else: addText(child) addLine() def addSpacer(): l.addItem(QSpacerItem(10, 1000, QSizePolicy.Minimum, QSizePolicy.Expanding)) # Display multiple selected items # if len(sel) > 1 and False: # Buggy and not very useful, skip # self.stack.setCurrentIndex(1) # w = QWidget() # l = QVBoxLayout(w) # self.txtEdits = [] # for idx in sel: # sItem = idx.internalPointer() # addTitle(sItem) # if sItem.isFolder(): # addChildren(sItem) # else: # addText(sItem) # addLine() # addSpacer() # self.scroll.setWidget(w) if item and item.isFolder() and self.folderView == "text": self.stack.setCurrentIndex(1) w = QWidget() l = QVBoxLayout(w) w.setStyleSheet("background: {};".format(settings.textEditor["background"])) # self.scroll.setWidgetResizable(False) self.txtEdits = [] if item != self.mw.mdlOutline.rootItem: addTitle(item) addChildren(item) addSpacer() self.scroll.setWidget(w) elif item and item.isFolder() and self.folderView == "cork": self.stack.setCurrentIndex(2) self.corkView.setModel(self.mw.mdlOutline) self.corkView.setRootIndex(self.currentIndex) self.corkView.selectionModel().selectionChanged.connect( lambda: mainWindow().redacMetadata.selectionChanged(self.corkView), AUC) self.corkView.clicked.connect( lambda: mainWindow().redacMetadata.selectionChanged(self.corkView), AUC) elif item and item.isFolder() and self.folderView == "outline": self.stack.setCurrentIndex(3) self.outlineView.setModelPersos(mainWindow().mdlPersos) self.outlineView.setModelLabels(mainWindow().mdlLabels) self.outlineView.setModelStatus(mainWindow().mdlStatus) self.outlineView.setModel(self.mw.mdlOutline) self.outlineView.setRootIndex(self.currentIndex) self.outlineView.selectionModel().selectionChanged.connect( lambda: mainWindow().redacMetadata.selectionChanged(self.outlineView), AUC) self.outlineView.clicked.connect( lambda: mainWindow().redacMetadata.selectionChanged(self.outlineView), AUC) else: self.txtRedacText.setCurrentModelIndex(self.currentIndex) self.stack.setCurrentIndex(0) # Single text item try: self.mw.mdlOutline.dataChanged.connect(self.modelDataChanged, AUC) self.mw.mdlOutline.rowsInserted.connect(self.updateIndexFromID, AUC) self.mw.mdlOutline.rowsRemoved.connect(self.updateIndexFromID, AUC) self.mw.mdlOutline.rowsAboutToBeRemoved.connect(self.rowsAboutToBeRemoved, AUC) except TypeError: pass self.updateStatusBar() def setCurrentModelIndex(self, index=None): if index.isValid(): self.currentIndex = index self.currentID = self.mw.mdlOutline.ID(index) # self._model = index.model() else: self.currentIndex = QModelIndex() self.setView() def updateIndexFromID(self): idx = self.mw.mdlOutline.getIndexByID(self.currentID) if idx != self.currentIndex: self.currentIndex = idx self.setView() def modelDataChanged(self, topLeft, bottomRight): # if self.currentID: # self.updateIndexFromID() if not self.currentIndex: return if topLeft.row() <= self.currentIndex.row() <= bottomRight.row(): self.updateStatusBar() def rowsAboutToBeRemoved(self, parent, first, last): if self.currentIndex: if self.currentIndex.parent() == parent and \ first <= self.currentIndex.row() <= last: # Item deleted, close tab self.mw.mainEditor.tab.removeTab(self.mw.mainEditor.tab.indexOf(self)) def updateStatusBar(self): # Update progress # if self.currentIndex and self.currentIndex.isValid(): # if self._model: mw = mainWindow() if not mw: return mw.mainEditor.updateStats() def toggleSpellcheck(self, v): self.spellcheck = v self.toggledSpellcheck.emit(v) def setDict(self, dct): self.currentDict = dct self.dictChanged.emit(dct)