class ItemViewDragStartEventListener(QObject): dragStarted = Signal(QModelIndex) def __init__(self, parent=None): QObject.__init__(self, parent) self._pos = None self._index = None def eventFilter(self, viewport, event): view = viewport.parent() if event.type() == QEvent.MouseButtonPress and \ event.button() == Qt.LeftButton: index = view.indexAt(event.pos()) if index is not None: self._pos = event.pos() self._index = QPersistentModelIndex(index) elif event.type() == QEvent.MouseMove and self._pos is not None and \ ((self._pos - event.pos()).manhattanLength() >= QApplication.startDragDistance()): if self._index.isValid(): # Map to a QModelIndex in the model. index = self._index index = index.model().index(index.row(), index.column(), index.parent()) self._pos = None self._index = None self.dragStarted.emit(index) return QObject.eventFilter(self, view, event)
def LayerSelectionChanged(self, new_layer): persistent_new_layer = QPersistentModelIndex(new_layer) if self.previousActiveLayer is None: previous_layer = QPersistentModelIndex(self.layersModel.index( 0, 0)) else: previous_layer = self.previousActiveLayer self.previousActiveLayer = persistent_new_layer # remember parameter settings from previous layer when switching to new layer # store layer dependent parameters if previous_layer.isValid(): # could have been deleted... for t in TABS_WITH_PER_LAYER_PARAMS: tabidx = t.get_id() self.layersModel.itemFromIndex(QModelIndex(previous_layer)).parameters_per_tab[tabidx] = \ self.tabhandlers[tabidx].ui_to_model() # store overall parameters for t in TABS_OVER_ALL_LAYERS: tabidx = t.get_id() self.properties_over_all_layers_per_tab[tabidx] = self.tabhandlers[ tabidx].ui_to_model() # show parameter settings on newly selected layer if they were stored in a previous visit already for t in TABS_WITH_PER_LAYER_PARAMS: tabidx = t.get_id() self.tabhandlers[tabidx].model_to_ui( self.layersModel.itemFromIndex( new_layer).get_parameters_for_tab(tabidx)) # restore overall parameters for t in TABS_OVER_ALL_LAYERS: tabidx = t.get_id() if tabidx in self.properties_over_all_layers_per_tab: self.tabhandlers[tabidx].model_to_ui( self.properties_over_all_layers_per_tab[tabidx]) # also make last used method the active tab last_used_method = self.layersModel.itemFromIndex( new_layer).get_last_used_method() self.squigglifySetup.setCurrentIndex(TAB_ORDER[last_used_method])
def set_current_idx(self, set_current: QPersistentModelIndex): if set_current: assert isinstance(set_current, QPersistentModelIndex) assert set_current.isValid() self.selectionModel().select(QModelIndex(set_current), QItemSelectionModel.SelectCurrent)
def set_current_idx(self, set_current: QPersistentModelIndex): if set_current: assert isinstance(set_current, QPersistentModelIndex) assert set_current.isValid() self.selectionModel().select(QModelIndex(set_current), QItemSelectionModel.SelectCurrent)
class Tab(QWidget): currItemChanged = pyqtSignal(['QModelIndex']) def __init__(self, packItem=QModelIndex(), parent: TabWidget = None): super(Tab, self).__init__(parent) self.tabWidget = parent self.icon = QIcon() self.initActions() self.pathToolBar = ToolBar(self) self.pathToolBar.addAction(self.backAct) self.pathToolBar.addAction(self.forwardAct) self.pathLine: AddressLine = AddressLine(self) self.objTypeLine = LineEdit(self, placeholderText="Object Type") self.objTypeLine.setFixedWidth(168) self.objTypeLine.setReadOnly(True) self.descrLabel = QLabel(self) self.descrLabel.setWordWrap(True) self.descrLabel.setTextInteractionFlags(Qt.TextSelectableByMouse) QWebEngineSettings.defaultSettings().setAttribute( QWebEngineSettings.PluginsEnabled, True) self.mediaWidget = QWebEngineView() self.saveMediaAsBtn = QPushButton( f"Save media as..", self, toolTip="Save media file as..", clicked=lambda: self.saveMediaAsWithDialog( QStandardPaths.writableLocation(QStandardPaths. DocumentsLocation))) self.saveMediaBtn = QPushButton( f"Save media on desktop", self, toolTip="Save media file on desktop", clicked=lambda: self.saveMediaAsWithDialog( QStandardPaths.writableLocation(QStandardPaths.DesktopLocation) )) self.mediaViewWidget = QWidget() mediaViewWidgetLayout = QVBoxLayout(self.mediaViewWidget) mediaViewWidgetLayout.setContentsMargins(0, 0, 0, 0) mediaViewWidgetLayout.addWidget(self.mediaWidget) mediaViewWidgetLayout.addWidget(self.saveMediaBtn) mediaViewWidgetLayout.addWidget(self.saveMediaAsBtn) self.mediaViewWidget.hide() self.attrsTreeView = AttrsTreeView(self) self.attrsTreeView.setFrameShape(QFrame.NoFrame) self.toolBar = ToolBar(self) self.toolBar.addAction(self.attrsTreeView.zoomInAct) self.toolBar.addAction(self.attrsTreeView.zoomOutAct) self.toolBar.addAction(self.attrsTreeView.collapseAllAct) self.toolBar.addAction(self.attrsTreeView.expandAllAct) self.toolBar.addSeparator() self.toolBar.addAction(self.attrsTreeView.undoAct) self.toolBar.addAction(self.attrsTreeView.redoAct) self.toolBar.addAction(self.attrsTreeView.copyAct) self.toolBar.addAction(self.attrsTreeView.cutAct) self.toolBar.addAction(self.attrsTreeView.pasteAct) self.toolBar.addAction(self.attrsTreeView.delClearAct) self.toolBar.addAction(self.attrsTreeView.editCreateInDialogAct) self.toolBar.addAction(self.attrsTreeView.addAct) self.searchBar = SearchBar( self.attrsTreeView, parent=self, filterColumns=[ATTRIBUTE_COLUMN, VALUE_COLUMN], closable=True) self.searchBar.hide() self.openSearchBarSC = QShortcut(SC_SEARCH, self, activated=self.openSearchBar) self.packItem = QPersistentModelIndex(QModelIndex()) self.prevItems = [] self.nextItems = [] if packItem.isValid(): self.openItem(packItem) else: self.openEmptyItem() self._initLayout() # noinspection PyArgumentList def initActions(self): self.backAct = QAction(BACK_ICON, "Back", self, statusTip=f"Go back one item", toolTip=f"Go back one item", shortcut=SC_BACK, triggered=self.openPrevItem, enabled=False) self.forwardAct = QAction(FORWARD_ICON, "Forward", self, statusTip=f"Go forward one item", toolTip=f"Go forward one item", shortcut=SC_FORWARD, triggered=self.openNextItem, enabled=False) def windowTitle(self) -> str: return self.packItem.data(NAME_ROLE) def windowIcon(self) -> QIcon: return self.packItem.data(Qt.DecorationRole) def openSearchBar(self): self.searchBar.show() self.searchBar.searchLine.setFocus() def openItem(self, packItem: QModelIndex): if not packItem == QModelIndex(self.packItem): self.nextItems.clear() if self.packItem.isValid(): self.prevItems.append(self.packItem) self._openItem(packItem) def openPrevItem(self): if self.prevItems: prevItem = self.prevItems.pop() self.nextItems.append(self.packItem) self._openItem(QModelIndex(prevItem)) def openNextItem(self): if self.nextItems: nextItem = self.nextItems.pop() self.prevItems.append(self.packItem) self._openItem(QModelIndex(nextItem)) def openEmptyItem(self): self._openItem(QModelIndex()) def _openItem(self, packItem: QModelIndex): try: currTab: Tab = self.tabWidget.currentWidget() state = currTab.attrsTreeView.header().saveState() except AttributeError: # if there is no curr widget, there is no current header state, it state = None self.packItem = QPersistentModelIndex(packItem.siblingAtColumn(0)) self.descrLabel.setText("") self.packItemObj = self.packItem.data(OBJECT_ROLE) self.updateMediaWidget() self.pathLine.setText(getTreeItemPath(self.packItem)) self.objTypeLine.setText(getTypeName(type(self.packItemObj))) icon = self.packItem.data(Qt.DecorationRole) if icon: self.setWindowIcon(icon) self.setWindowTitle(self.packItem.data(Qt.DisplayRole)) self.attrsTreeView.newPackItem(self.packItem) self.attrsTreeView.selectionModel().currentChanged.connect( self.showDetailInfoItemDoc) self.currItemChanged.emit(QModelIndex(self.packItem)) self.forwardAct.setEnabled( True) if self.nextItems else self.forwardAct.setDisabled(True) self.backAct.setEnabled( True) if self.prevItems else self.backAct.setDisabled(True) if state: self.attrsTreeView.header().restoreState(state) def updateMediaWidget(self): if self.packItem.data(IS_MEDIA_ROLE): self.mediaWidget.setContent(b"loading...") self.mediaViewWidget.show() if not self.mediaWidget.width(): # set equal sizes oldSizes = self.splitter.sizes() newSizes = [ sum(oldSizes) / (len(oldSizes)) for size in oldSizes ] self.splitter.setSizes(newSizes) try: mediaContent = self.packItem.data(MEDIA_CONTENT_ROLE) if self.packItem.data(IS_URL_MEDIA_ROLE): self.mediaWidget.load(QUrl(mediaContent.value)) else: self.mediaWidget.setContent(mediaContent.value, mediaContent.mime_type) except Exception as e: print(e) self.mediaWidget.setContent( b"Error occurred while loading media") self.mediaWidget.setZoomFactor(1.0) else: self.mediaViewWidget.hide() def saveMediaAsWithDialog(self, directory="") -> bool: mediaContent = self.packItem.data(MEDIA_CONTENT_ROLE) file = self.packItem.data(NAME_ROLE) saved = False while not saved: try: file = QFileDialog.getSaveFileName( self, 'Save media File', directory + "/" + file.strip("/"), options=FILE_DIALOG_OPTIONS)[0] except AttributeError as e: QMessageBox.critical(self, "Error", f"{e}") else: if file: saved = self.saveMedia(mediaContent, file) else: # cancel pressed return def saveMedia(self, media=None, file: str = None) -> bool: try: with open(file, "wb") as f: f.write(media.value) return True except (TypeError, ValueError) as e: QMessageBox.critical(self, "Error", f"Media couldn't be saved: {file}: {e}") except AttributeError as e: QMessageBox.critical(self, "Error", f"No chosen media to save: {e}") return False def showDetailInfoItemDoc(self, detailInfoItem: QModelIndex): self.descrLabel.setText(detailInfoItem.data(Qt.WhatsThisRole)) def _initLayout(self): pathWidget = QWidget() pathLayout = QHBoxLayout(pathWidget) pathLayout.setContentsMargins(0, 0, 0, 0) pathLayout.addWidget(self.pathToolBar) pathLayout.addWidget(self.pathLine) pathLayout.addWidget(self.objTypeLine) pathWidget.setFixedHeight(TOOLBARS_HEIGHT) toolBarWidget = QWidget() toolBarLayout = QHBoxLayout(toolBarWidget) toolBarLayout.setContentsMargins(0, 0, 0, 0) toolBarLayout.addWidget(self.toolBar) toolBarLayout.addWidget(self.searchBar) toolBarWidget.setFixedHeight(TOOLBARS_HEIGHT) treeViewWidget = QWidget() treeViewLayout = QVBoxLayout(treeViewWidget) treeViewLayout.setContentsMargins(0, 0, 0, 0) treeViewLayout.addWidget(pathWidget) treeViewLayout.addWidget(self.attrsTreeView) treeViewLayout.addWidget(self.descrLabel) self.splitter = QSplitter() self.splitter.setOrientation(Qt.Horizontal) self.splitter.setContentsMargins(0, 0, 0, 0) self.splitter.addWidget(treeViewWidget) self.splitter.addWidget(self.mediaViewWidget) layout = QVBoxLayout(self) layout.setObjectName("tabLayout") layout.addWidget(pathWidget) layout.addWidget(toolBarWidget) layout.addWidget(self.splitter) layout.setSpacing(2) layout.setContentsMargins(0, 2, 0, 2)