class PlotPygal(QDialog): def __init__(self, live=False): super().__init__() self.live = live self.setWindowTitle('Saved session plotted with Pygal') self.setWindowIcon(QtGui.QIcon('icons/pulse.svg')) self.webW = QWebEngineView() self.saveButton = QtGui.QPushButton(self) self.saveButton.setText('Save as SVG') self.saveButton.clicked.connect(self.saveSVG) self.verticalLayout = QtGui.QVBoxLayout(self) self.verticalLayout.addWidget(self.webW) self.verticalLayout.addWidget(self.saveButton) self.plotPygal() def plotPygal(self): w.oxi.plot_pygal(live=self.live) self.webW.setContent(w.oxi.chart, mimeType='image/svg+xml') self.show() def saveSVG(self): filename = QFileDialog.getSaveFileName(self)[0] if filename: print(filename) w.oxi.write_svg(filename) else: print('No file selected')
class PlotPygal(QDialog): def __init__(self, live=False): super().__init__() self.live = live self.setWindowTitle('Saved session plotted with Pygal') self.setWindowIcon(QtGui.QIcon('icons/pulse.svg')) self.webW = QWebEngineView() self.saveButton = QtGui.QPushButton(self) self.saveButton.setText('Save as SVG') self.saveButton.clicked.connect(self.saveSVG) self.verticalLayout = QtGui.QVBoxLayout(self) self.verticalLayout.addWidget(self.webW) self.verticalLayout.addWidget(self.saveButton) self.plotPygal() def plotPygal(self): w.oxi.plot_pygal(live=self.live) size = sys.getsizeof(w.oxi.chart) if size > 2097152: # QWebEngineView can only directly display sizes up to 2 MiB # https://bugreports.qt.io/browse/QTBUG-53414 # (I'm just assuming MiB, not MB.) self.webW.setHtml('<p><center><big><b>The plot is too large to be displayed within this window. Save the file first and view it in a viewer of your choice.</b></big></center></p>') else: self.webW.setContent(w.oxi.chart, mimeType='image/svg+xml') self.show() def saveSVG(self): filename = QFileDialog.getSaveFileName(self)[0] if filename: print(filename) w.oxi.write_svg(filename) else: print('No file selected')
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)