class ModelerDialog(BASE, WIDGET): ALG_ITEM = 'ALG_ITEM' PROVIDER_ITEM = 'PROVIDER_ITEM' GROUP_ITEM = 'GROUP_ITEM' NAME_ROLE = Qt.UserRole TAG_ROLE = Qt.UserRole + 1 TYPE_ROLE = Qt.UserRole + 2 CANVAS_SIZE = 4000 update_model = pyqtSignal() def __init__(self, model=None): super().__init__(None) self.setAttribute(Qt.WA_DeleteOnClose) self.setupUi(self) self._variables_scope = None # LOTS of bug reports when we include the dock creation in the UI file # see e.g. #16428, #19068 # So just roll it all by hand......! self.propertiesDock = QgsDockWidget(self) self.propertiesDock.setFeatures( QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.propertiesDock.setObjectName("propertiesDock") propertiesDockContents = QWidget() self.verticalDockLayout_1 = QVBoxLayout(propertiesDockContents) self.verticalDockLayout_1.setContentsMargins(0, 0, 0, 0) self.verticalDockLayout_1.setSpacing(0) self.scrollArea_1 = QgsScrollArea(propertiesDockContents) sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.scrollArea_1.sizePolicy().hasHeightForWidth()) self.scrollArea_1.setSizePolicy(sizePolicy) self.scrollArea_1.setFocusPolicy(Qt.WheelFocus) self.scrollArea_1.setFrameShape(QFrame.NoFrame) self.scrollArea_1.setFrameShadow(QFrame.Plain) self.scrollArea_1.setWidgetResizable(True) self.scrollAreaWidgetContents_1 = QWidget() self.gridLayout = QGridLayout(self.scrollAreaWidgetContents_1) self.gridLayout.setContentsMargins(6, 6, 6, 6) self.gridLayout.setSpacing(4) self.label_1 = QLabel(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.label_1, 0, 0, 1, 1) self.textName = QLineEdit(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.textName, 0, 1, 1, 1) self.label_2 = QLabel(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) self.textGroup = QLineEdit(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.textGroup, 1, 1, 1, 1) self.label_1.setText(self.tr("Name")) self.textName.setToolTip(self.tr("Enter model name here")) self.label_2.setText(self.tr("Group")) self.textGroup.setToolTip(self.tr("Enter group name here")) self.scrollArea_1.setWidget(self.scrollAreaWidgetContents_1) self.verticalDockLayout_1.addWidget(self.scrollArea_1) self.propertiesDock.setWidget(propertiesDockContents) self.propertiesDock.setWindowTitle(self.tr("Model Properties")) self.inputsDock = QgsDockWidget(self) self.inputsDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.inputsDock.setObjectName("inputsDock") self.inputsDockContents = QWidget() self.verticalLayout_3 = QVBoxLayout(self.inputsDockContents) self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) self.scrollArea_2 = QgsScrollArea(self.inputsDockContents) sizePolicy.setHeightForWidth(self.scrollArea_2.sizePolicy().hasHeightForWidth()) self.scrollArea_2.setSizePolicy(sizePolicy) self.scrollArea_2.setFocusPolicy(Qt.WheelFocus) self.scrollArea_2.setFrameShape(QFrame.NoFrame) self.scrollArea_2.setFrameShadow(QFrame.Plain) self.scrollArea_2.setWidgetResizable(True) self.scrollAreaWidgetContents_2 = QWidget() self.verticalLayout = QVBoxLayout(self.scrollAreaWidgetContents_2) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(0) self.inputsTree = QTreeWidget(self.scrollAreaWidgetContents_2) self.inputsTree.setAlternatingRowColors(True) self.inputsTree.header().setVisible(False) self.verticalLayout.addWidget(self.inputsTree) self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2) self.verticalLayout_3.addWidget(self.scrollArea_2) self.inputsDock.setWidget(self.inputsDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.inputsDock) self.inputsDock.setWindowTitle(self.tr("Inputs")) self.algorithmsDock = QgsDockWidget(self) self.algorithmsDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.algorithmsDock.setObjectName("algorithmsDock") self.algorithmsDockContents = QWidget() self.verticalLayout_4 = QVBoxLayout(self.algorithmsDockContents) self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) self.scrollArea_3 = QgsScrollArea(self.algorithmsDockContents) sizePolicy.setHeightForWidth(self.scrollArea_3.sizePolicy().hasHeightForWidth()) self.scrollArea_3.setSizePolicy(sizePolicy) self.scrollArea_3.setFocusPolicy(Qt.WheelFocus) self.scrollArea_3.setFrameShape(QFrame.NoFrame) self.scrollArea_3.setFrameShadow(QFrame.Plain) self.scrollArea_3.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.verticalLayout_2 = QVBoxLayout(self.scrollAreaWidgetContents_3) self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) self.verticalLayout_2.setSpacing(4) self.searchBox = QgsFilterLineEdit(self.scrollAreaWidgetContents_3) self.verticalLayout_2.addWidget(self.searchBox) self.algorithmTree = QgsProcessingToolboxTreeView(None, QgsApplication.processingRegistry()) self.algorithmTree.setAlternatingRowColors(True) self.algorithmTree.header().setVisible(False) self.verticalLayout_2.addWidget(self.algorithmTree) self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_3) self.verticalLayout_4.addWidget(self.scrollArea_3) self.algorithmsDock.setWidget(self.algorithmsDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.algorithmsDock) self.algorithmsDock.setWindowTitle(self.tr("Algorithms")) self.searchBox.setToolTip(self.tr("Enter algorithm name to filter list")) self.searchBox.setShowSearchIcon(True) self.variables_dock = QgsDockWidget(self) self.variables_dock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.variables_dock.setObjectName("variablesDock") self.variables_dock_contents = QWidget() vl_v = QVBoxLayout() vl_v.setContentsMargins(0, 0, 0, 0) self.variables_editor = QgsVariableEditorWidget() vl_v.addWidget(self.variables_editor) self.variables_dock_contents.setLayout(vl_v) self.variables_dock.setWidget(self.variables_dock_contents) self.addDockWidget(Qt.DockWidgetArea(1), self.variables_dock) self.variables_dock.setWindowTitle(self.tr("Variables")) self.addDockWidget(Qt.DockWidgetArea(1), self.propertiesDock) self.tabifyDockWidget(self.propertiesDock, self.variables_dock) self.variables_editor.scopeChanged.connect(self.variables_changed) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.centralWidget().layout().insertWidget(0, self.bar) try: self.setDockOptions(self.dockOptions() | QMainWindow.GroupedDragging) except: pass if iface is not None: self.mToolbar.setIconSize(iface.iconSize()) self.setStyleSheet(iface.mainWindow().styleSheet()) self.toolbutton_export_to_script = QToolButton() self.toolbutton_export_to_script.setPopupMode(QToolButton.InstantPopup) self.export_to_script_algorithm_action = QAction(QCoreApplication.translate('ModelerDialog', 'Export as Script Algorithm…')) self.toolbutton_export_to_script.addActions([self.export_to_script_algorithm_action]) self.mToolbar.insertWidget(self.mActionExportImage, self.toolbutton_export_to_script) self.export_to_script_algorithm_action.triggered.connect(self.export_as_script_algorithm) self.mActionOpen.setIcon( QgsApplication.getThemeIcon('/mActionFileOpen.svg')) self.mActionSave.setIcon( QgsApplication.getThemeIcon('/mActionFileSave.svg')) self.mActionSaveAs.setIcon( QgsApplication.getThemeIcon('/mActionFileSaveAs.svg')) self.mActionSaveInProject.setIcon( QgsApplication.getThemeIcon('/mAddToProject.svg')) self.mActionZoomActual.setIcon( QgsApplication.getThemeIcon('/mActionZoomActual.svg')) self.mActionZoomIn.setIcon( QgsApplication.getThemeIcon('/mActionZoomIn.svg')) self.mActionZoomOut.setIcon( QgsApplication.getThemeIcon('/mActionZoomOut.svg')) self.mActionExportImage.setIcon( QgsApplication.getThemeIcon('/mActionSaveMapAsImage.svg')) self.mActionZoomToItems.setIcon( QgsApplication.getThemeIcon('/mActionZoomFullExtent.svg')) self.mActionExportPdf.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsPDF.svg')) self.mActionExportSvg.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsSVG.svg')) self.toolbutton_export_to_script.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsPython.svg')) self.mActionEditHelp.setIcon( QgsApplication.getThemeIcon('/mActionEditHelpContent.svg')) self.mActionRun.setIcon( QgsApplication.getThemeIcon('/mActionStart.svg')) self.addDockWidget(Qt.LeftDockWidgetArea, self.propertiesDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.inputsDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.algorithmsDock) self.tabifyDockWidget(self.inputsDock, self.algorithmsDock) self.inputsDock.raise_() self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) settings = QgsSettings() self.restoreState(settings.value("/Processing/stateModeler", QByteArray())) self.restoreGeometry(settings.value("/Processing/geometryModeler", QByteArray())) self.scene = ModelerScene(self, dialog=self) self.scene.setSceneRect(QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.view.setScene(self.scene) self.view.setAcceptDrops(True) self.view.ensureVisible(0, 0, 10, 10) self.view.scale(QgsApplication.desktop().logicalDpiX() / 96, QgsApplication.desktop().logicalDpiX() / 96) def _dragEnterEvent(event): if event.mimeData().hasText() or event.mimeData().hasFormat('application/x-vnd.qgis.qgis.algorithmid'): event.acceptProposedAction() else: event.ignore() def _dropEvent(event): def alg_dropped(algorithm_id, pos): alg = QgsApplication.processingRegistry().createAlgorithmById(algorithm_id) if alg is not None: self._addAlgorithm(alg, pos) else: assert False, algorithm_id def input_dropped(id, pos): if id in [param.id() for param in QgsApplication.instance().processingRegistry().parameterTypes()]: self.addInputOfType(itemId, pos) if event.mimeData().hasFormat('application/x-vnd.qgis.qgis.algorithmid'): data = event.mimeData().data('application/x-vnd.qgis.qgis.algorithmid') stream = QDataStream(data, QIODevice.ReadOnly) algorithm_id = stream.readQString() QTimer.singleShot(0, lambda id=algorithm_id, pos=self.view.mapToScene(event.pos()): alg_dropped(id, pos)) event.accept() elif event.mimeData().hasText(): itemId = event.mimeData().text() QTimer.singleShot(0, lambda id=itemId, pos=self.view.mapToScene(event.pos()): input_dropped(id, pos)) event.accept() else: event.ignore() def _dragMoveEvent(event): if event.mimeData().hasText() or event.mimeData().hasFormat('application/x-vnd.qgis.qgis.algorithmid'): event.accept() else: event.ignore() def _wheelEvent(event): self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) # "Normal" mouse has an angle delta of 120, precision mouses provide data # faster, in smaller steps factor = 1.0 + (factor - 1.0) / 120.0 * abs(event.angleDelta().y()) if (event.modifiers() == Qt.ControlModifier): factor = 1.0 + (factor - 1.0) / 20.0 if event.angleDelta().y() < 0: factor = 1 / factor self.view.scale(factor, factor) def _enterEvent(e): QGraphicsView.enterEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mouseReleaseEvent(e): QGraphicsView.mouseReleaseEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mousePressEvent(e): if e.button() == Qt.MidButton: self.previousMousePos = e.pos() else: QGraphicsView.mousePressEvent(self.view, e) def _mouseMoveEvent(e): if e.buttons() == Qt.MidButton: offset = self.previousMousePos - e.pos() self.previousMousePos = e.pos() self.view.verticalScrollBar().setValue(self.view.verticalScrollBar().value() + offset.y()) self.view.horizontalScrollBar().setValue(self.view.horizontalScrollBar().value() + offset.x()) else: QGraphicsView.mouseMoveEvent(self.view, e) self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.view.dragEnterEvent = _dragEnterEvent self.view.dropEvent = _dropEvent self.view.dragMoveEvent = _dragMoveEvent self.view.wheelEvent = _wheelEvent self.view.enterEvent = _enterEvent self.view.mousePressEvent = _mousePressEvent self.view.mouseMoveEvent = _mouseMoveEvent def _mimeDataInput(items): mimeData = QMimeData() text = items[0].data(0, Qt.UserRole) mimeData.setText(text) return mimeData self.inputsTree.mimeData = _mimeDataInput self.inputsTree.setDragDropMode(QTreeWidget.DragOnly) self.inputsTree.setDropIndicatorShown(True) self.algorithms_model = ModelerToolboxModel(self, QgsApplication.processingRegistry()) self.algorithmTree.setToolboxProxyModel(self.algorithms_model) self.algorithmTree.setDragDropMode(QTreeWidget.DragOnly) self.algorithmTree.setDropIndicatorShown(True) filters = QgsProcessingToolboxProxyModel.Filters(QgsProcessingToolboxProxyModel.FilterModeler) if ProcessingConfig.getSetting(ProcessingConfig.SHOW_ALGORITHMS_KNOWN_ISSUES): filters |= QgsProcessingToolboxProxyModel.FilterShowKnownIssues self.algorithmTree.setFilters(filters) if hasattr(self.searchBox, 'setPlaceholderText'): self.searchBox.setPlaceholderText(QCoreApplication.translate('ModelerDialog', 'Search…')) if hasattr(self.textName, 'setPlaceholderText'): self.textName.setPlaceholderText(self.tr('Enter model name here')) if hasattr(self.textGroup, 'setPlaceholderText'): self.textGroup.setPlaceholderText(self.tr('Enter group name here')) # Connect signals and slots self.inputsTree.doubleClicked.connect(self.addInput) self.searchBox.textChanged.connect(self.algorithmTree.setFilterString) self.algorithmTree.doubleClicked.connect(self.addAlgorithm) # Ctrl+= should also trigger a zoom in action ctrlEquals = QShortcut(QKeySequence("Ctrl+="), self) ctrlEquals.activated.connect(self.zoomIn) self.mActionOpen.triggered.connect(self.openModel) self.mActionSave.triggered.connect(self.save) self.mActionSaveAs.triggered.connect(self.saveAs) self.mActionSaveInProject.triggered.connect(self.saveInProject) self.mActionZoomIn.triggered.connect(self.zoomIn) self.mActionZoomOut.triggered.connect(self.zoomOut) self.mActionZoomActual.triggered.connect(self.zoomActual) self.mActionZoomToItems.triggered.connect(self.zoomToItems) self.mActionExportImage.triggered.connect(self.exportAsImage) self.mActionExportPdf.triggered.connect(self.exportAsPdf) self.mActionExportSvg.triggered.connect(self.exportAsSvg) #self.mActionExportPython.triggered.connect(self.exportAsPython) self.mActionEditHelp.triggered.connect(self.editHelp) self.mActionRun.triggered.connect(self.runModel) if model is not None: self.model = model.create() self.model.setSourceFilePath(model.sourceFilePath()) self.textGroup.setText(self.model.group()) self.textName.setText(self.model.displayName()) self.repaintModel() else: self.model = QgsProcessingModelAlgorithm() self.model.setProvider(QgsApplication.processingRegistry().providerById('model')) self.update_variables_gui() self.fillInputsTree() self.view.centerOn(0, 0) self.help = None self.hasChanged = False def closeEvent(self, evt): settings = QgsSettings() settings.setValue("/Processing/stateModeler", self.saveState()) settings.setValue("/Processing/geometryModeler", self.saveGeometry()) if self.hasChanged: ret = QMessageBox.question( self, self.tr('Save Model?'), self.tr('There are unsaved changes in this model. Do you want to keep those?'), QMessageBox.Save | QMessageBox.Cancel | QMessageBox.Discard, QMessageBox.Cancel) if ret == QMessageBox.Save: self.saveModel(False) evt.accept() elif ret == QMessageBox.Discard: evt.accept() else: evt.ignore() else: evt.accept() def editHelp(self): alg = self.model dlg = HelpEditionDialog(alg) dlg.exec_() if dlg.descriptions: self.model.setHelpContent(dlg.descriptions) self.hasChanged = True def update_variables_gui(self): variables_scope = QgsExpressionContextScope(self.tr('Model Variables')) for k, v in self.model.variables().items(): variables_scope.setVariable(k, v) variables_context = QgsExpressionContext() variables_context.appendScope(variables_scope) self.variables_editor.setContext(variables_context) self.variables_editor.setEditableScopeIndex(0) def variables_changed(self): self.model.setVariables(self.variables_editor.variablesInActiveScope()) def runModel(self): if len(self.model.childAlgorithms()) == 0: self.bar.pushMessage("", self.tr("Model doesn't contain any algorithm and/or parameter and can't be executed"), level=Qgis.Warning, duration=5) return dlg = AlgorithmDialog(self.model.create(), parent=iface.mainWindow()) dlg.exec_() def save(self): self.saveModel(False) def saveAs(self): self.saveModel(True) def saveInProject(self): if not self.can_save(): return self.model.setName(str(self.textName.text())) self.model.setGroup(str(self.textGroup.text())) self.model.setSourceFilePath(None) project_provider = QgsApplication.processingRegistry().providerById(PROJECT_PROVIDER_ID) project_provider.add_model(self.model) self.update_model.emit() self.bar.pushMessage("", self.tr("Model was saved inside current project"), level=Qgis.Success, duration=5) self.hasChanged = False QgsProject.instance().setDirty(True) def zoomIn(self): self.view.setTransformationAnchor(QGraphicsView.NoAnchor) point = self.view.mapToScene(QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) self.view.scale(factor, factor) self.view.centerOn(point) self.repaintModel() def zoomOut(self): self.view.setTransformationAnchor(QGraphicsView.NoAnchor) point = self.view.mapToScene(QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) factor = 1 / factor self.view.scale(factor, factor) self.view.centerOn(point) self.repaintModel() def zoomActual(self): point = self.view.mapToScene(QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) self.view.resetTransform() self.view.scale(QgsApplication.desktop().logicalDpiX() / 96, QgsApplication.desktop().logicalDpiX() / 96) self.view.centerOn(point) def zoomToItems(self): totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) self.view.fitInView(totalRect, Qt.KeepAspectRatio) def exportAsImage(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName(self, self.tr('Save Model As Image'), '', self.tr('PNG files (*.png *.PNG)')) if not filename: return if not filename.lower().endswith('.png'): filename += '.png' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) imgRect = QRectF(0, 0, totalRect.width(), totalRect.height()) img = QImage(totalRect.width(), totalRect.height(), QImage.Format_ARGB32_Premultiplied) img.fill(Qt.white) painter = QPainter() painter.setRenderHint(QPainter.Antialiasing) painter.begin(img) self.scene.render(painter, imgRect, totalRect) painter.end() img.save(filename) self.bar.pushMessage("", self.tr("Successfully exported model as image to <a href=\"{}\">{}</a>").format(QUrl.fromLocalFile(filename).toString(), QDir.toNativeSeparators(filename)), level=Qgis.Success, duration=5) self.repaintModel(controls=True) def exportAsPdf(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName(self, self.tr('Save Model As PDF'), '', self.tr('PDF files (*.pdf *.PDF)')) if not filename: return if not filename.lower().endswith('.pdf'): filename += '.pdf' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) printerRect = QRectF(0, 0, totalRect.width(), totalRect.height()) printer = QPrinter() printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(filename) printer.setPaperSize(QSizeF(printerRect.width(), printerRect.height()), QPrinter.DevicePixel) printer.setFullPage(True) painter = QPainter(printer) self.scene.render(painter, printerRect, totalRect) painter.end() self.bar.pushMessage("", self.tr("Successfully exported model as PDF to <a href=\"{}\">{}</a>").format(QUrl.fromLocalFile(filename).toString(), QDir.toNativeSeparators(filename)), level=Qgis.Success, duration=5) self.repaintModel(controls=True) def exportAsSvg(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName(self, self.tr('Save Model As SVG'), '', self.tr('SVG files (*.svg *.SVG)')) if not filename: return if not filename.lower().endswith('.svg'): filename += '.svg' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) svgRect = QRectF(0, 0, totalRect.width(), totalRect.height()) svg = QSvgGenerator() svg.setFileName(filename) svg.setSize(QSize(totalRect.width(), totalRect.height())) svg.setViewBox(svgRect) svg.setTitle(self.model.displayName()) painter = QPainter(svg) self.scene.render(painter, svgRect, totalRect) painter.end() self.bar.pushMessage("", self.tr("Successfully exported model as SVG to <a href=\"{}\">{}</a>").format(QUrl.fromLocalFile(filename).toString(), QDir.toNativeSeparators(filename)), level=Qgis.Success, duration=5) self.repaintModel(controls=True) def exportAsPython(self): filename, filter = QFileDialog.getSaveFileName(self, self.tr('Save Model As Python Script'), '', self.tr('Processing scripts (*.py *.PY)')) if not filename: return if not filename.lower().endswith('.py'): filename += '.py' text = self.model.asPythonCode() with codecs.open(filename, 'w', encoding='utf-8') as fout: fout.write(text) self.bar.pushMessage("", self.tr("Successfully exported model as python script to <a href=\"{}\">{}</a>").format(QUrl.fromLocalFile(filename).toString(), QDir.toNativeSeparators(filename)), level=Qgis.Success, duration=5) def can_save(self): """ Tests whether a model can be saved, or if it is not yet valid :return: bool """ if str(self.textName.text()).strip() == '': self.bar.pushWarning( "", self.tr('Please a enter model name before saving') ) return False return True def saveModel(self, saveAs): if not self.can_save(): return self.model.setName(str(self.textName.text())) self.model.setGroup(str(self.textGroup.text())) if self.model.sourceFilePath() and not saveAs: filename = self.model.sourceFilePath() else: filename, filter = QFileDialog.getSaveFileName(self, self.tr('Save Model'), ModelerUtils.modelsFolders()[0], self.tr('Processing models (*.model3 *.MODEL3)')) if filename: if not filename.endswith('.model3'): filename += '.model3' self.model.setSourceFilePath(filename) if filename: if not self.model.toFile(filename): if saveAs: QMessageBox.warning(self, self.tr('I/O error'), self.tr('Unable to save edits. Reason:\n {0}').format(str(sys.exc_info()[1]))) else: QMessageBox.warning(self, self.tr("Can't save model"), QCoreApplication.translate('QgsPluginInstallerInstallingDialog', ( "This model can't be saved in its original location (probably you do not " "have permission to do it). Please, use the 'Save as…' option.")) ) return self.update_model.emit() if saveAs: self.bar.pushMessage("", self.tr("Model was correctly saved to <a href=\"{}\">{}</a>").format(QUrl.fromLocalFile(filename).toString(), QDir.toNativeSeparators(filename)), level=Qgis.Success, duration=5) else: self.bar.pushMessage("", self.tr("Model was correctly saved"), level=Qgis.Success, duration=5) self.hasChanged = False def openModel(self): filename, selected_filter = QFileDialog.getOpenFileName(self, self.tr('Open Model'), ModelerUtils.modelsFolders()[0], self.tr('Processing models (*.model3 *.MODEL3)')) if filename: self.loadModel(filename) def loadModel(self, filename): alg = QgsProcessingModelAlgorithm() if alg.fromFile(filename): self.model = alg self.model.setProvider(QgsApplication.processingRegistry().providerById('model')) self.textGroup.setText(alg.group()) self.textName.setText(alg.name()) self.repaintModel() self.update_variables_gui() self.view.centerOn(0, 0) self.hasChanged = False else: QgsMessageLog.logMessage(self.tr('Could not load model {0}').format(filename), self.tr('Processing'), Qgis.Critical) QMessageBox.critical(self, self.tr('Open Model'), self.tr('The selected model could not be loaded.\n' 'See the log for more information.')) def repaintModel(self, controls=True): self.scene = ModelerScene(self, dialog=self) self.scene.setSceneRect(QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.scene.paintModel(self.model, controls) self.view.setScene(self.scene) def addInput(self): item = self.inputsTree.currentItem() param = item.data(0, Qt.UserRole) self.addInputOfType(param) def addInputOfType(self, paramType, pos=None): dlg = ModelerParameterDefinitionDialog(self.model, paramType) dlg.exec_() if dlg.param is not None: if pos is None: pos = self.getPositionForParameterItem() if isinstance(pos, QPoint): pos = QPointF(pos) component = QgsProcessingModelParameter(dlg.param.name()) component.setDescription(dlg.param.name()) component.setPosition(pos) self.model.addModelParameter(dlg.param, component) self.repaintModel() # self.view.ensureVisible(self.scene.getLastParameterItem()) self.hasChanged = True def getPositionForParameterItem(self): MARGIN = 20 BOX_WIDTH = 200 BOX_HEIGHT = 80 if len(self.model.parameterComponents()) > 0: maxX = max([i.position().x() for i in list(self.model.parameterComponents().values())]) newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH) else: newX = MARGIN + BOX_WIDTH / 2 return QPointF(newX, MARGIN + BOX_HEIGHT / 2) def fillInputsTree(self): icon = QIcon(os.path.join(pluginPath, 'images', 'input.svg')) parametersItem = QTreeWidgetItem() parametersItem.setText(0, self.tr('Parameters')) sortedParams = sorted(QgsApplication.instance().processingRegistry().parameterTypes(), key=lambda pt: pt.name()) for param in sortedParams: if param.flags() & QgsProcessingParameterType.ExposeToModeler: paramItem = QTreeWidgetItem() paramItem.setText(0, param.name()) paramItem.setData(0, Qt.UserRole, param.id()) paramItem.setIcon(0, icon) paramItem.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) paramItem.setToolTip(0, param.description()) parametersItem.addChild(paramItem) self.inputsTree.addTopLevelItem(parametersItem) parametersItem.setExpanded(True) def addAlgorithm(self): algorithm = self.algorithmTree.selectedAlgorithm() if algorithm is not None: alg = QgsApplication.processingRegistry().createAlgorithmById(algorithm.id()) self._addAlgorithm(alg) def _addAlgorithm(self, alg, pos=None): dlg = ModelerParametersDialog(alg, self.model) if dlg.exec_(): alg = dlg.createAlgorithm() if pos is None: alg.setPosition(self.getPositionForAlgorithmItem()) else: alg.setPosition(pos) from processing.modeler.ModelerGraphicItem import ModelerGraphicItem for i, out in enumerate(alg.modelOutputs()): alg.modelOutput(out).setPosition(alg.position() + QPointF(ModelerGraphicItem.BOX_WIDTH, (i + 1.5) * ModelerGraphicItem.BOX_HEIGHT)) self.model.addChildAlgorithm(alg) self.repaintModel() self.hasChanged = True def getPositionForAlgorithmItem(self): MARGIN = 20 BOX_WIDTH = 200 BOX_HEIGHT = 80 if self.model.childAlgorithms(): maxX = max([alg.position().x() for alg in list(self.model.childAlgorithms().values())]) maxY = max([alg.position().y() for alg in list(self.model.childAlgorithms().values())]) newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH) newY = min(MARGIN + BOX_HEIGHT + maxY, self.CANVAS_SIZE - BOX_HEIGHT) else: newX = MARGIN + BOX_WIDTH / 2 newY = MARGIN * 2 + BOX_HEIGHT + BOX_HEIGHT / 2 return QPointF(newX, newY) def export_as_script_algorithm(self): dlg = ScriptEditorDialog(None) dlg.editor.setText('\n'.join(self.model.asPythonCode(QgsProcessing.PythonQgsProcessingAlgorithmSubclass, 4))) dlg.show()
class ModelerDialog(BASE, WIDGET): ALG_ITEM = 'ALG_ITEM' PROVIDER_ITEM = 'PROVIDER_ITEM' GROUP_ITEM = 'GROUP_ITEM' NAME_ROLE = Qt.UserRole TAG_ROLE = Qt.UserRole + 1 TYPE_ROLE = Qt.UserRole + 2 CANVAS_SIZE = 4000 update_model = pyqtSignal() def __init__(self, model=None): super().__init__(None) self.setAttribute(Qt.WA_DeleteOnClose) self.setupUi(self) self._variables_scope = None # LOTS of bug reports when we include the dock creation in the UI file # see e.g. #16428, #19068 # So just roll it all by hand......! self.propertiesDock = QgsDockWidget(self) self.propertiesDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.propertiesDock.setObjectName("propertiesDock") propertiesDockContents = QWidget() self.verticalDockLayout_1 = QVBoxLayout(propertiesDockContents) self.verticalDockLayout_1.setContentsMargins(0, 0, 0, 0) self.verticalDockLayout_1.setSpacing(0) self.scrollArea_1 = QgsScrollArea(propertiesDockContents) sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.scrollArea_1.sizePolicy().hasHeightForWidth()) self.scrollArea_1.setSizePolicy(sizePolicy) self.scrollArea_1.setFocusPolicy(Qt.WheelFocus) self.scrollArea_1.setFrameShape(QFrame.NoFrame) self.scrollArea_1.setFrameShadow(QFrame.Plain) self.scrollArea_1.setWidgetResizable(True) self.scrollAreaWidgetContents_1 = QWidget() self.gridLayout = QGridLayout(self.scrollAreaWidgetContents_1) self.gridLayout.setContentsMargins(6, 6, 6, 6) self.gridLayout.setSpacing(4) self.label_1 = QLabel(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.label_1, 0, 0, 1, 1) self.textName = QLineEdit(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.textName, 0, 1, 1, 1) self.label_2 = QLabel(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) self.textGroup = QLineEdit(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.textGroup, 1, 1, 1, 1) self.label_1.setText(self.tr("Name")) self.textName.setToolTip(self.tr("Enter model name here")) self.label_2.setText(self.tr("Group")) self.textGroup.setToolTip(self.tr("Enter group name here")) self.scrollArea_1.setWidget(self.scrollAreaWidgetContents_1) self.verticalDockLayout_1.addWidget(self.scrollArea_1) self.propertiesDock.setWidget(propertiesDockContents) self.propertiesDock.setWindowTitle(self.tr("Model Properties")) self.inputsDock = QgsDockWidget(self) self.inputsDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.inputsDock.setObjectName("inputsDock") self.inputsDockContents = QWidget() self.verticalLayout_3 = QVBoxLayout(self.inputsDockContents) self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) self.scrollArea_2 = QgsScrollArea(self.inputsDockContents) sizePolicy.setHeightForWidth( self.scrollArea_2.sizePolicy().hasHeightForWidth()) self.scrollArea_2.setSizePolicy(sizePolicy) self.scrollArea_2.setFocusPolicy(Qt.WheelFocus) self.scrollArea_2.setFrameShape(QFrame.NoFrame) self.scrollArea_2.setFrameShadow(QFrame.Plain) self.scrollArea_2.setWidgetResizable(True) self.scrollAreaWidgetContents_2 = QWidget() self.verticalLayout = QVBoxLayout(self.scrollAreaWidgetContents_2) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(0) self.inputsTree = QTreeWidget(self.scrollAreaWidgetContents_2) self.inputsTree.setAlternatingRowColors(True) self.inputsTree.header().setVisible(False) self.verticalLayout.addWidget(self.inputsTree) self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2) self.verticalLayout_3.addWidget(self.scrollArea_2) self.inputsDock.setWidget(self.inputsDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.inputsDock) self.inputsDock.setWindowTitle(self.tr("Inputs")) self.algorithmsDock = QgsDockWidget(self) self.algorithmsDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.algorithmsDock.setObjectName("algorithmsDock") self.algorithmsDockContents = QWidget() self.verticalLayout_4 = QVBoxLayout(self.algorithmsDockContents) self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) self.scrollArea_3 = QgsScrollArea(self.algorithmsDockContents) sizePolicy.setHeightForWidth( self.scrollArea_3.sizePolicy().hasHeightForWidth()) self.scrollArea_3.setSizePolicy(sizePolicy) self.scrollArea_3.setFocusPolicy(Qt.WheelFocus) self.scrollArea_3.setFrameShape(QFrame.NoFrame) self.scrollArea_3.setFrameShadow(QFrame.Plain) self.scrollArea_3.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.verticalLayout_2 = QVBoxLayout(self.scrollAreaWidgetContents_3) self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) self.verticalLayout_2.setSpacing(4) self.searchBox = QgsFilterLineEdit(self.scrollAreaWidgetContents_3) self.verticalLayout_2.addWidget(self.searchBox) self.algorithmTree = QgsProcessingToolboxTreeView( None, QgsApplication.processingRegistry()) self.algorithmTree.setAlternatingRowColors(True) self.algorithmTree.header().setVisible(False) self.verticalLayout_2.addWidget(self.algorithmTree) self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_3) self.verticalLayout_4.addWidget(self.scrollArea_3) self.algorithmsDock.setWidget(self.algorithmsDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.algorithmsDock) self.algorithmsDock.setWindowTitle(self.tr("Algorithms")) self.searchBox.setToolTip( self.tr("Enter algorithm name to filter list")) self.searchBox.setShowSearchIcon(True) self.variables_dock = QgsDockWidget(self) self.variables_dock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.variables_dock.setObjectName("variablesDock") self.variables_dock_contents = QWidget() vl_v = QVBoxLayout() vl_v.setContentsMargins(0, 0, 0, 0) self.variables_editor = QgsVariableEditorWidget() vl_v.addWidget(self.variables_editor) self.variables_dock_contents.setLayout(vl_v) self.variables_dock.setWidget(self.variables_dock_contents) self.addDockWidget(Qt.DockWidgetArea(1), self.variables_dock) self.variables_dock.setWindowTitle(self.tr("Variables")) self.addDockWidget(Qt.DockWidgetArea(1), self.propertiesDock) self.tabifyDockWidget(self.propertiesDock, self.variables_dock) self.variables_editor.scopeChanged.connect(self.variables_changed) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.centralWidget().layout().insertWidget(0, self.bar) try: self.setDockOptions(self.dockOptions() | QMainWindow.GroupedDragging) except: pass if iface is not None: self.mToolbar.setIconSize(iface.iconSize()) self.setStyleSheet(iface.mainWindow().styleSheet()) self.toolbutton_export_to_script = QToolButton() self.toolbutton_export_to_script.setPopupMode(QToolButton.InstantPopup) self.export_to_script_algorithm_action = QAction( QCoreApplication.translate('ModelerDialog', 'Export as Script Algorithm…')) self.toolbutton_export_to_script.addActions( [self.export_to_script_algorithm_action]) self.mToolbar.insertWidget(self.mActionExportImage, self.toolbutton_export_to_script) self.export_to_script_algorithm_action.triggered.connect( self.export_as_script_algorithm) self.mActionOpen.setIcon( QgsApplication.getThemeIcon('/mActionFileOpen.svg')) self.mActionSave.setIcon( QgsApplication.getThemeIcon('/mActionFileSave.svg')) self.mActionSaveAs.setIcon( QgsApplication.getThemeIcon('/mActionFileSaveAs.svg')) self.mActionSaveInProject.setIcon( QgsApplication.getThemeIcon('/mAddToProject.svg')) self.mActionZoomActual.setIcon( QgsApplication.getThemeIcon('/mActionZoomActual.svg')) self.mActionZoomIn.setIcon( QgsApplication.getThemeIcon('/mActionZoomIn.svg')) self.mActionZoomOut.setIcon( QgsApplication.getThemeIcon('/mActionZoomOut.svg')) self.mActionExportImage.setIcon( QgsApplication.getThemeIcon('/mActionSaveMapAsImage.svg')) self.mActionZoomToItems.setIcon( QgsApplication.getThemeIcon('/mActionZoomFullExtent.svg')) self.mActionExportPdf.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsPDF.svg')) self.mActionExportSvg.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsSVG.svg')) self.toolbutton_export_to_script.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsPython.svg')) self.mActionEditHelp.setIcon( QgsApplication.getThemeIcon('/mActionEditHelpContent.svg')) self.mActionRun.setIcon( QgsApplication.getThemeIcon('/mActionStart.svg')) self.addDockWidget(Qt.LeftDockWidgetArea, self.propertiesDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.inputsDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.algorithmsDock) self.tabifyDockWidget(self.inputsDock, self.algorithmsDock) self.inputsDock.raise_() self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) settings = QgsSettings() self.restoreState( settings.value("/Processing/stateModeler", QByteArray())) self.restoreGeometry( settings.value("/Processing/geometryModeler", QByteArray())) self.scene = ModelerScene(self, dialog=self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.view.setScene(self.scene) self.view.setAcceptDrops(True) self.view.ensureVisible(0, 0, 10, 10) self.view.scale(QgsApplication.desktop().logicalDpiX() / 96, QgsApplication.desktop().logicalDpiX() / 96) def _dragEnterEvent(event): if event.mimeData().hasText() or event.mimeData().hasFormat( 'application/x-vnd.qgis.qgis.algorithmid'): event.acceptProposedAction() else: event.ignore() def _dropEvent(event): def alg_dropped(algorithm_id, pos): alg = QgsApplication.processingRegistry().createAlgorithmById( algorithm_id) if alg is not None: self._addAlgorithm(alg, pos) else: assert False, algorithm_id def input_dropped(id, pos): if id in [ param.id() for param in QgsApplication.instance(). processingRegistry().parameterTypes() ]: self.addInputOfType(itemId, pos) if event.mimeData().hasFormat( 'application/x-vnd.qgis.qgis.algorithmid'): data = event.mimeData().data( 'application/x-vnd.qgis.qgis.algorithmid') stream = QDataStream(data, QIODevice.ReadOnly) algorithm_id = stream.readQString() QTimer.singleShot( 0, lambda id=algorithm_id, pos=self.view.mapToScene(event.pos( )): alg_dropped(id, pos)) event.accept() elif event.mimeData().hasText(): itemId = event.mimeData().text() QTimer.singleShot(0, lambda id=itemId, pos=self.view.mapToScene( event.pos()): input_dropped(id, pos)) event.accept() else: event.ignore() def _dragMoveEvent(event): if event.mimeData().hasText() or event.mimeData().hasFormat( 'application/x-vnd.qgis.qgis.algorithmid'): event.accept() else: event.ignore() def _wheelEvent(event): self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) # "Normal" mouse has an angle delta of 120, precision mouses provide data # faster, in smaller steps factor = 1.0 + (factor - 1.0) / 120.0 * abs(event.angleDelta().y()) if (event.modifiers() == Qt.ControlModifier): factor = 1.0 + (factor - 1.0) / 20.0 if event.angleDelta().y() < 0: factor = 1 / factor self.view.scale(factor, factor) def _enterEvent(e): QGraphicsView.enterEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mouseReleaseEvent(e): QGraphicsView.mouseReleaseEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mousePressEvent(e): if e.button() == Qt.MidButton: self.previousMousePos = e.pos() else: QGraphicsView.mousePressEvent(self.view, e) def _mouseMoveEvent(e): if e.buttons() == Qt.MidButton: offset = self.previousMousePos - e.pos() self.previousMousePos = e.pos() self.view.verticalScrollBar().setValue( self.view.verticalScrollBar().value() + offset.y()) self.view.horizontalScrollBar().setValue( self.view.horizontalScrollBar().value() + offset.x()) else: QGraphicsView.mouseMoveEvent(self.view, e) self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.view.dragEnterEvent = _dragEnterEvent self.view.dropEvent = _dropEvent self.view.dragMoveEvent = _dragMoveEvent self.view.wheelEvent = _wheelEvent self.view.enterEvent = _enterEvent self.view.mousePressEvent = _mousePressEvent self.view.mouseMoveEvent = _mouseMoveEvent def _mimeDataInput(items): mimeData = QMimeData() text = items[0].data(0, Qt.UserRole) mimeData.setText(text) return mimeData self.inputsTree.mimeData = _mimeDataInput self.inputsTree.setDragDropMode(QTreeWidget.DragOnly) self.inputsTree.setDropIndicatorShown(True) self.algorithms_model = ModelerToolboxModel( self, QgsApplication.processingRegistry()) self.algorithmTree.setToolboxProxyModel(self.algorithms_model) self.algorithmTree.setDragDropMode(QTreeWidget.DragOnly) self.algorithmTree.setDropIndicatorShown(True) filters = QgsProcessingToolboxProxyModel.Filters( QgsProcessingToolboxProxyModel.FilterModeler) if ProcessingConfig.getSetting( ProcessingConfig.SHOW_ALGORITHMS_KNOWN_ISSUES): filters |= QgsProcessingToolboxProxyModel.FilterShowKnownIssues self.algorithmTree.setFilters(filters) if hasattr(self.searchBox, 'setPlaceholderText'): self.searchBox.setPlaceholderText( QCoreApplication.translate('ModelerDialog', 'Search…')) if hasattr(self.textName, 'setPlaceholderText'): self.textName.setPlaceholderText(self.tr('Enter model name here')) if hasattr(self.textGroup, 'setPlaceholderText'): self.textGroup.setPlaceholderText(self.tr('Enter group name here')) # Connect signals and slots self.inputsTree.doubleClicked.connect(self.addInput) self.searchBox.textChanged.connect(self.algorithmTree.setFilterString) self.algorithmTree.doubleClicked.connect(self.addAlgorithm) # Ctrl+= should also trigger a zoom in action ctrlEquals = QShortcut(QKeySequence("Ctrl+="), self) ctrlEquals.activated.connect(self.zoomIn) self.mActionOpen.triggered.connect(self.openModel) self.mActionSave.triggered.connect(self.save) self.mActionSaveAs.triggered.connect(self.saveAs) self.mActionSaveInProject.triggered.connect(self.saveInProject) self.mActionZoomIn.triggered.connect(self.zoomIn) self.mActionZoomOut.triggered.connect(self.zoomOut) self.mActionZoomActual.triggered.connect(self.zoomActual) self.mActionZoomToItems.triggered.connect(self.zoomToItems) self.mActionExportImage.triggered.connect(self.exportAsImage) self.mActionExportPdf.triggered.connect(self.exportAsPdf) self.mActionExportSvg.triggered.connect(self.exportAsSvg) #self.mActionExportPython.triggered.connect(self.exportAsPython) self.mActionEditHelp.triggered.connect(self.editHelp) self.mActionRun.triggered.connect(self.runModel) if model is not None: self.model = model.create() self.model.setSourceFilePath(model.sourceFilePath()) self.textGroup.setText(self.model.group()) self.textName.setText(self.model.displayName()) self.repaintModel() else: self.model = QgsProcessingModelAlgorithm() self.model.setProvider( QgsApplication.processingRegistry().providerById('model')) self.update_variables_gui() self.fillInputsTree() self.view.centerOn(0, 0) self.help = None self.hasChanged = False def closeEvent(self, evt): settings = QgsSettings() settings.setValue("/Processing/stateModeler", self.saveState()) settings.setValue("/Processing/geometryModeler", self.saveGeometry()) if self.hasChanged: ret = QMessageBox.question( self, self.tr('Save Model?'), self. tr('There are unsaved changes in this model. Do you want to keep those?' ), QMessageBox.Save | QMessageBox.Cancel | QMessageBox.Discard, QMessageBox.Cancel) if ret == QMessageBox.Save: self.saveModel(False) evt.accept() elif ret == QMessageBox.Discard: evt.accept() else: evt.ignore() else: evt.accept() def editHelp(self): alg = self.model dlg = HelpEditionDialog(alg) dlg.exec_() if dlg.descriptions: self.model.setHelpContent(dlg.descriptions) self.hasChanged = True def update_variables_gui(self): variables_scope = QgsExpressionContextScope(self.tr('Model Variables')) for k, v in self.model.variables().items(): variables_scope.setVariable(k, v) variables_context = QgsExpressionContext() variables_context.appendScope(variables_scope) self.variables_editor.setContext(variables_context) self.variables_editor.setEditableScopeIndex(0) def variables_changed(self): self.model.setVariables(self.variables_editor.variablesInActiveScope()) def runModel(self): if len(self.model.childAlgorithms()) == 0: self.bar.pushMessage( "", self. tr("Model doesn't contain any algorithm and/or parameter and can't be executed" ), level=Qgis.Warning, duration=5) return dlg = AlgorithmDialog(self.model.create(), parent=iface.mainWindow()) dlg.exec_() def save(self): self.saveModel(False) def saveAs(self): self.saveModel(True) def saveInProject(self): if not self.can_save(): return self.model.setName(str(self.textName.text())) self.model.setGroup(str(self.textGroup.text())) self.model.setSourceFilePath(None) project_provider = QgsApplication.processingRegistry().providerById( PROJECT_PROVIDER_ID) project_provider.add_model(self.model) self.update_model.emit() self.bar.pushMessage("", self.tr("Model was saved inside current project"), level=Qgis.Success, duration=5) self.hasChanged = False QgsProject.instance().setDirty(True) def zoomIn(self): self.view.setTransformationAnchor(QGraphicsView.NoAnchor) point = self.view.mapToScene( QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) self.view.scale(factor, factor) self.view.centerOn(point) self.repaintModel() def zoomOut(self): self.view.setTransformationAnchor(QGraphicsView.NoAnchor) point = self.view.mapToScene( QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) factor = 1 / factor self.view.scale(factor, factor) self.view.centerOn(point) self.repaintModel() def zoomActual(self): point = self.view.mapToScene( QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) self.view.resetTransform() self.view.scale(QgsApplication.desktop().logicalDpiX() / 96, QgsApplication.desktop().logicalDpiX() / 96) self.view.centerOn(point) def zoomToItems(self): totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) self.view.fitInView(totalRect, Qt.KeepAspectRatio) def exportAsImage(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName( self, self.tr('Save Model As Image'), '', self.tr('PNG files (*.png *.PNG)')) if not filename: return if not filename.lower().endswith('.png'): filename += '.png' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) imgRect = QRectF(0, 0, totalRect.width(), totalRect.height()) img = QImage(totalRect.width(), totalRect.height(), QImage.Format_ARGB32_Premultiplied) img.fill(Qt.white) painter = QPainter() painter.setRenderHint(QPainter.Antialiasing) painter.begin(img) self.scene.render(painter, imgRect, totalRect) painter.end() img.save(filename) self.bar.pushMessage( "", self.tr( "Successfully exported model as image to <a href=\"{}\">{}</a>" ).format( QUrl.fromLocalFile(filename).toString(), QDir.toNativeSeparators(filename)), level=Qgis.Success, duration=5) self.repaintModel(controls=True) def exportAsPdf(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName( self, self.tr('Save Model As PDF'), '', self.tr('PDF files (*.pdf *.PDF)')) if not filename: return if not filename.lower().endswith('.pdf'): filename += '.pdf' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) printerRect = QRectF(0, 0, totalRect.width(), totalRect.height()) printer = QPrinter() printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(filename) printer.setPaperSize(QSizeF(printerRect.width(), printerRect.height()), QPrinter.DevicePixel) printer.setFullPage(True) painter = QPainter(printer) self.scene.render(painter, printerRect, totalRect) painter.end() self.bar.pushMessage( "", self.tr( "Successfully exported model as PDF to <a href=\"{}\">{}</a>"). format( QUrl.fromLocalFile(filename).toString(), QDir.toNativeSeparators(filename)), level=Qgis.Success, duration=5) self.repaintModel(controls=True) def exportAsSvg(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName( self, self.tr('Save Model As SVG'), '', self.tr('SVG files (*.svg *.SVG)')) if not filename: return if not filename.lower().endswith('.svg'): filename += '.svg' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) svgRect = QRectF(0, 0, totalRect.width(), totalRect.height()) svg = QSvgGenerator() svg.setFileName(filename) svg.setSize(QSize(totalRect.width(), totalRect.height())) svg.setViewBox(svgRect) svg.setTitle(self.model.displayName()) painter = QPainter(svg) self.scene.render(painter, svgRect, totalRect) painter.end() self.bar.pushMessage( "", self.tr( "Successfully exported model as SVG to <a href=\"{}\">{}</a>"). format( QUrl.fromLocalFile(filename).toString(), QDir.toNativeSeparators(filename)), level=Qgis.Success, duration=5) self.repaintModel(controls=True) def exportAsPython(self): filename, filter = QFileDialog.getSaveFileName( self, self.tr('Save Model As Python Script'), '', self.tr('Processing scripts (*.py *.PY)')) if not filename: return if not filename.lower().endswith('.py'): filename += '.py' text = self.model.asPythonCode() with codecs.open(filename, 'w', encoding='utf-8') as fout: fout.write(text) self.bar.pushMessage( "", self. tr("Successfully exported model as python script to <a href=\"{}\">{}</a>" ).format( QUrl.fromLocalFile(filename).toString(), QDir.toNativeSeparators(filename)), level=Qgis.Success, duration=5) def can_save(self): """ Tests whether a model can be saved, or if it is not yet valid :return: bool """ if str(self.textName.text()).strip() == '': self.bar.pushWarning( "", self.tr('Please a enter model name before saving')) return False return True def saveModel(self, saveAs): if not self.can_save(): return self.model.setName(str(self.textName.text())) self.model.setGroup(str(self.textGroup.text())) if self.model.sourceFilePath() and not saveAs: filename = self.model.sourceFilePath() else: filename, filter = QFileDialog.getSaveFileName( self, self.tr('Save Model'), ModelerUtils.modelsFolders()[0], self.tr('Processing models (*.model3 *.MODEL3)')) if filename: if not filename.endswith('.model3'): filename += '.model3' self.model.setSourceFilePath(filename) if filename: if not self.model.toFile(filename): if saveAs: QMessageBox.warning( self, self.tr('I/O error'), self.tr('Unable to save edits. Reason:\n {0}').format( str(sys.exc_info()[1]))) else: QMessageBox.warning( self, self.tr("Can't save model"), QCoreApplication. translate('QgsPluginInstallerInstallingDialog', ( "This model can't be saved in its original location (probably you do not " "have permission to do it). Please, use the 'Save as…' option." ))) return self.update_model.emit() if saveAs: self.bar.pushMessage( "", self.tr( "Model was correctly saved to <a href=\"{}\">{}</a>"). format( QUrl.fromLocalFile(filename).toString(), QDir.toNativeSeparators(filename)), level=Qgis.Success, duration=5) else: self.bar.pushMessage("", self.tr("Model was correctly saved"), level=Qgis.Success, duration=5) self.hasChanged = False def openModel(self): filename, selected_filter = QFileDialog.getOpenFileName( self, self.tr('Open Model'), ModelerUtils.modelsFolders()[0], self.tr('Processing models (*.model3 *.MODEL3)')) if filename: self.loadModel(filename) def loadModel(self, filename): alg = QgsProcessingModelAlgorithm() if alg.fromFile(filename): self.model = alg self.model.setProvider( QgsApplication.processingRegistry().providerById('model')) self.textGroup.setText(alg.group()) self.textName.setText(alg.name()) self.repaintModel() self.update_variables_gui() self.view.centerOn(0, 0) self.hasChanged = False else: QgsMessageLog.logMessage( self.tr('Could not load model {0}').format(filename), self.tr('Processing'), Qgis.Critical) QMessageBox.critical( self, self.tr('Open Model'), self.tr('The selected model could not be loaded.\n' 'See the log for more information.')) def repaintModel(self, controls=True): self.scene = ModelerScene(self, dialog=self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.scene.paintModel(self.model, controls) self.view.setScene(self.scene) def addInput(self): item = self.inputsTree.currentItem() param = item.data(0, Qt.UserRole) self.addInputOfType(param) def addInputOfType(self, paramType, pos=None): dlg = ModelerParameterDefinitionDialog(self.model, paramType) dlg.exec_() if dlg.param is not None: if pos is None: pos = self.getPositionForParameterItem() if isinstance(pos, QPoint): pos = QPointF(pos) component = QgsProcessingModelParameter(dlg.param.name()) component.setDescription(dlg.param.name()) component.setPosition(pos) self.model.addModelParameter(dlg.param, component) self.repaintModel() # self.view.ensureVisible(self.scene.getLastParameterItem()) self.hasChanged = True def getPositionForParameterItem(self): MARGIN = 20 BOX_WIDTH = 200 BOX_HEIGHT = 80 if len(self.model.parameterComponents()) > 0: maxX = max([ i.position().x() for i in list(self.model.parameterComponents().values()) ]) newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH) else: newX = MARGIN + BOX_WIDTH / 2 return QPointF(newX, MARGIN + BOX_HEIGHT / 2) def fillInputsTree(self): icon = QIcon(os.path.join(pluginPath, 'images', 'input.svg')) parametersItem = QTreeWidgetItem() parametersItem.setText(0, self.tr('Parameters')) sortedParams = sorted( QgsApplication.instance().processingRegistry().parameterTypes(), key=lambda pt: pt.name()) for param in sortedParams: if param.flags() & QgsProcessingParameterType.ExposeToModeler: paramItem = QTreeWidgetItem() paramItem.setText(0, param.name()) paramItem.setData(0, Qt.UserRole, param.id()) paramItem.setIcon(0, icon) paramItem.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) paramItem.setToolTip(0, param.description()) parametersItem.addChild(paramItem) self.inputsTree.addTopLevelItem(parametersItem) parametersItem.setExpanded(True) def addAlgorithm(self): algorithm = self.algorithmTree.selectedAlgorithm() if algorithm is not None: alg = QgsApplication.processingRegistry().createAlgorithmById( algorithm.id()) self._addAlgorithm(alg) def _addAlgorithm(self, alg, pos=None): dlg = ModelerParametersDialog(alg, self.model) if dlg.exec_(): alg = dlg.createAlgorithm() if pos is None: alg.setPosition(self.getPositionForAlgorithmItem()) else: alg.setPosition(pos) from processing.modeler.ModelerGraphicItem import ModelerGraphicItem for i, out in enumerate(alg.modelOutputs()): alg.modelOutput(out).setPosition( alg.position() + QPointF(ModelerGraphicItem.BOX_WIDTH, (i + 1.5) * ModelerGraphicItem.BOX_HEIGHT)) self.model.addChildAlgorithm(alg) self.repaintModel() self.hasChanged = True def getPositionForAlgorithmItem(self): MARGIN = 20 BOX_WIDTH = 200 BOX_HEIGHT = 80 if self.model.childAlgorithms(): maxX = max([ alg.position().x() for alg in list(self.model.childAlgorithms().values()) ]) maxY = max([ alg.position().y() for alg in list(self.model.childAlgorithms().values()) ]) newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH) newY = min(MARGIN + BOX_HEIGHT + maxY, self.CANVAS_SIZE - BOX_HEIGHT) else: newX = MARGIN + BOX_WIDTH / 2 newY = MARGIN * 2 + BOX_HEIGHT + BOX_HEIGHT / 2 return QPointF(newX, newY) def export_as_script_algorithm(self): dlg = ScriptEditorDialog(None) dlg.editor.setText('\n'.join( self.model.asPythonCode( QgsProcessing.PythonQgsProcessingAlgorithmSubclass, 4))) dlg.show()
class PyArchInitPlugin(object): HOME = os.environ['PYARCHINIT_HOME'] PARAMS_DICT = { 'SERVER': '', 'HOST': '', 'DATABASE': '', 'PASSWORD': '', 'PORT': '', 'USER': '', 'THUMB_PATH': '', 'EXPERIMENTAL': '' } path_rel = os.path.join(os.sep, str(HOME), 'pyarchinit_DB_folder', 'config.cfg') conf = open(path_rel, "r") data = conf.read() PARAMS_DICT = eval(data) # TODO: find a better way to settings config # if 'EXPERIMENTAL' in PARAMS_DICT: # PARAMS_DICT['EXPERIMENTAL'] = 'No' # f = open(path_rel, "w") # f.write(str(PARAMS_DICT)) # f.close() def __init__(self, iface): self.iface = iface userPluginPath = os.path.dirname(__file__) systemPluginPath = QgsApplication.prefixPath( ) + "/python/plugins/pyarchinit" overrideLocale = QgsSettings().value("locale/overrideFlag", QVariant) # .toBool() if not overrideLocale: localeFullName = QLocale.system().name() else: localeFullName = QgsSettings().value("locale/userLocale", QVariant) # .toString() if QFileInfo(userPluginPath).exists(): translationPath = userPluginPath + "/i18n/pyarchinit_plugin_" + localeFullName + ".qm" else: translationPath = systemPluginPath + "/i18n/pyarchinit_plugin_" + localeFullName + ".qm" self.localePath = translationPath if QFileInfo(self.localePath).exists(): self.translator = QTranslator() self.translator.load(self.localePath) QCoreApplication.installTranslator(self.translator) def initGui(self): settings = QgsSettings() icon_paius = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'pai_us.png')) self.action = QAction(QIcon(icon_paius), "pyArchInit Main Panel", self.iface.mainWindow()) self.action.triggered.connect(self.showHideDockWidget) # dock widget self.dockWidget = PyarchinitPluginDialog(self.iface) self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dockWidget) # TOOLBAR self.toolBar = self.iface.addToolBar("pyArchInit") self.toolBar.setObjectName("pyArchInit") self.toolBar.addAction(self.action) self.dataToolButton = QToolButton(self.toolBar) self.dataToolButton.setPopupMode(QToolButton.MenuButtonPopup) ###### Section dedicated to the basic data entry # add Actions data icon_site = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconSite.png')) self.actionSite = QAction(QIcon(icon_site), "Siti", self.iface.mainWindow()) self.actionSite.setWhatsThis("Siti") self.actionSite.triggered.connect(self.runSite) icon_US = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconSus.png')) self.actionUS = QAction(QIcon((icon_US)), u"US", self.iface.mainWindow()) self.actionUS.setWhatsThis(u"US") self.actionUS.triggered.connect(self.runUS) icon_Finds = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconFinds.png')) self.actionInr = QAction(QIcon(icon_Finds), "Reperti", self.iface.mainWindow()) self.actionInr.setWhatsThis("Reperti") self.actionInr.triggered.connect(self.runInr) icon_camp_exp = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'champion.png')) self.actionCampioni = QAction(QIcon(icon_camp_exp), "Campioni", self.iface.mainWindow()) self.actionCampioni.setWhatsThis("Campioni") self.actionCampioni.triggered.connect(self.runCampioni) icon_Lapidei = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconAlma.png')) self.actionLapidei = QAction(QIcon(icon_Lapidei), "Lapidei", self.iface.mainWindow()) self.actionLapidei.setWhatsThis("Lapidei") self.actionLapidei.triggered.connect(self.runLapidei) self.dataToolButton.addActions([ self.actionSite, self.actionUS, self.actionInr, self.actionCampioni, self.actionLapidei ]) self.dataToolButton.setDefaultAction(self.actionSite) self.toolBar.addWidget(self.dataToolButton) self.toolBar.addSeparator() ###### Section dedicated to the interpretations # add Actions interpretation self.interprToolButton = QToolButton(self.toolBar) self.interprToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_per = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconPer.png')) self.actionPer = QAction(QIcon(icon_per), "Periodizzazione", self.iface.mainWindow()) self.actionPer.setWhatsThis("Periodizzazione") self.actionPer.triggered.connect(self.runPer) icon_Struttura = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconStrutt.png')) self.actionStruttura = QAction(QIcon(icon_Struttura), "Strutture", self.iface.mainWindow()) self.actionPer.setWhatsThis("Strutture") self.actionStruttura.triggered.connect(self.runStruttura) self.interprToolButton.addActions( [self.actionStruttura, self.actionPer]) self.interprToolButton.setDefaultAction(self.actionStruttura) self.toolBar.addWidget(self.interprToolButton) self.toolBar.addSeparator() ###### Section dedicated to the funerary archaeology # add Actions funerary archaeology self.funeraryToolButton = QToolButton(self.toolBar) self.funeraryToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_Schedaind = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconIND.png')) self.actionSchedaind = QAction(QIcon(icon_Schedaind), "Individui", self.iface.mainWindow()) self.actionSchedaind.setWhatsThis("Individui") self.actionSchedaind.triggered.connect(self.runSchedaind) icon_Tafonomia = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconGrave.png')) self.actionTafonomia = QAction(QIcon(icon_Tafonomia), "Tafonomica/Sepolture", self.iface.mainWindow()) self.actionTafonomia.setWhatsThis("Tafonomica/Sepolture") self.actionTafonomia.triggered.connect(self.runTafonomia) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': icon_Detsesso = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconSesso.png')) self.actionDetsesso = QAction(QIcon(icon_Detsesso), "Determinazione Sesso", self.iface.mainWindow()) self.actionDetsesso.setWhatsThis("Determinazione del sesso") self.actionDetsesso.triggered.connect(self.runDetsesso) icon_Deteta = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconEta.png')) self.actionDeteta = QAction(QIcon(icon_Deteta), u"Determinazione dell'età", self.iface.mainWindow()) self.actionSchedaind.setWhatsThis(u"Determinazione dell'età") self.actionDeteta.triggered.connect(self.runDeteta) self.funeraryToolButton.addActions( [self.actionSchedaind, self.actionTafonomia]) self.funeraryToolButton.setDefaultAction(self.actionSchedaind) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.funeraryToolButton.addActions( [self.actionDetsesso, self.actionDeteta]) self.toolBar.addWidget(self.funeraryToolButton) self.toolBar.addSeparator() ###### Section dedicated to the topographical research if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.topoToolButton = QToolButton(self.toolBar) self.topoToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_UT = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconUT.png')) self.actionUT = QAction(QIcon(icon_UT), u"Unità Topografiche", self.iface.mainWindow()) self.actionUT.setWhatsThis(u"Unità Topografiche") self.actionUT.triggered.connect(self.runUT) self.topoToolButton.addActions([self.actionUT]) self.topoToolButton.setDefaultAction(self.actionUT) self.toolBar.addWidget(self.topoToolButton) self.toolBar.addSeparator() ###### Section dedicated to the documentation # add Actions documentation self.docToolButton = QToolButton(self.toolBar) self.docToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_documentazione = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'icondoc.png')) self.actionDocumentazione = QAction(QIcon(icon_documentazione), "Scheda Documentazione", self.iface.mainWindow()) self.actionDocumentazione.setWhatsThis("Documentazione") self.actionDocumentazione.triggered.connect(self.runDocumentazione) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': icon_imageViewer = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'photo.png')) self.actionimageViewer = QAction(QIcon(icon_imageViewer), "Gestione immagini", self.iface.mainWindow()) self.actionimageViewer.setWhatsThis("Gestione immagini") self.actionimageViewer.triggered.connect(self.runImageViewer) icon_Directory_export = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'directoryExp.png')) self.actionImages_Directory_export = QAction( QIcon(icon_Directory_export), "Esportazione immagini", self.iface.mainWindow()) self.actionImages_Directory_export.setWhatsThis( "Esportazione immagini") self.actionImages_Directory_export.triggered.connect( self.runImages_directory_export) icon_pdf_exp = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'pdf-icon.png')) self.actionpdfExp = QAction(QIcon(icon_pdf_exp), "Esportazione PDF", self.iface.mainWindow()) self.actionpdfExp.setWhatsThis("Esportazione PDF") self.actionpdfExp.triggered.connect(self.runPdfexp) self.docToolButton.addActions([self.actionDocumentazione]) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.docToolButton.addActions([ self.actionpdfExp, self.actionimageViewer, self.actionpdfExp, self.actionImages_Directory_export ]) self.docToolButton.setDefaultAction(self.actionDocumentazione) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.actionImages_Directory_export.setCheckable(True) self.actionpdfExp.setCheckable(True) self.actionimageViewer.setCheckable(True) self.toolBar.addWidget(self.docToolButton) self.toolBar.addSeparator() ###### Section dedicated to elaborations if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.elabToolButton = QToolButton(self.toolBar) self.elabToolButton.setPopupMode(QToolButton.MenuButtonPopup) # add Actions elaboration icon_Archeozoology = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconMegacero.png')) self.actionArcheozoology = QAction(QIcon(icon_Archeozoology), "Statistiche Archeozoologiche", self.iface.mainWindow()) self.actionArcheozoology.setWhatsThis( "Statistiche Archeozoologiche") self.actionArcheozoology.triggered.connect(self.runArcheozoology) icon_GisTimeController = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconTimeControll.png')) self.actionGisTimeController = QAction( QIcon(icon_GisTimeController), "Time Manager", self.iface.mainWindow()) self.actionGisTimeController.setWhatsThis("Time Manager") self.actionGisTimeController.triggered.connect( self.runGisTimeController) icon_Comparision = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'comparision.png')) self.actionComparision = QAction(QIcon(icon_Comparision), "Comparazione immagini", self.iface.mainWindow()) self.actionComparision.setWhatsThis("Comparazione immagini") self.actionComparision.triggered.connect(self.runComparision) self.elabToolButton.addActions([ self.actionArcheozoology, self.actionComparision, self.actionGisTimeController ]) self.elabToolButton.setDefaultAction(self.actionArcheozoology) self.toolBar.addWidget(self.elabToolButton) self.toolBar.addSeparator() ###### Section dedicated to the plugin management self.manageToolButton = QToolButton(self.toolBar) self.manageToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_thesaurus = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'thesaurusicon.png')) self.actionThesaurus = QAction(QIcon(icon_thesaurus), "Thesaurus sigle", self.iface.mainWindow()) self.actionThesaurus.setWhatsThis("Thesaurus sigle") self.actionThesaurus.triggered.connect(self.runThesaurus) icon_Con = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconConn.png')) self.actionConf = QAction(QIcon(icon_Con), "Configurazione plugin", self.iface.mainWindow()) self.actionConf.setWhatsThis("Configurazione plugin") self.actionConf.triggered.connect(self.runConf) icon_Dbmanagment = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'backup.png')) self.actionDbmanagment = QAction(QIcon(icon_Dbmanagment), "Gestione database", self.iface.mainWindow()) self.actionDbmanagment.setWhatsThis("Gestione database") self.actionDbmanagment.triggered.connect(self.runDbmanagment) icon_Info = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconInfo.png')) self.actionInfo = QAction(QIcon(icon_Info), "Plugin info", self.iface.mainWindow()) self.actionInfo.setWhatsThis("Plugin info") self.actionInfo.triggered.connect(self.runInfo) self.manageToolButton.addActions([ self.actionConf, self.actionThesaurus, self.actionDbmanagment, self.actionInfo ]) self.manageToolButton.setDefaultAction(self.actionConf) self.toolBar.addWidget(self.manageToolButton) self.toolBar.addSeparator() # menu self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionSite) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionUS) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionInr) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionCampioni) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionLapidei) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionStruttura) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionPer) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionSchedaind) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionTafonomia) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionDetsesso) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionDeteta) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionUT) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionDocumentazione) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionimageViewer) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionpdfExp) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionImages_Directory_export) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionArcheozoology) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionComparision) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionGisTimeController) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionConf) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionThesaurus) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionDbmanagment) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionInfo) # MENU self.menu = QMenu("pyArchInit") # self.pyarchinitSite = pyarchinit_Site(self.iface) self.menu.addActions([ self.actionSite, self.actionUS, self.actionInr, self.actionCampioni, self.actionLapidei ]) self.menu.addSeparator() self.menu.addActions([self.actionPer, self.actionStruttura]) self.menu.addSeparator() self.menu.addActions([self.actionTafonomia, self.actionSchedaind]) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.menu.addActions([self.actionDetsesso, self.actionDeteta]) self.menu.addSeparator() if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.menu.addActions([self.actionUT]) self.menu.addActions([self.actionDocumentazione]) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.menu.addActions([ self.actionimageViewer, self.actionpdfExp, self.actionImages_Directory_export ]) self.menu.addSeparator() if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.menu.addActions([ self.actionArcheozoology, self.actionComparision, self.actionGisTimeController ]) self.menu.addSeparator() self.menu.addActions([ self.actionConf, self.actionThesaurus, self.actionDbmanagment, self.actionInfo ]) menuBar = self.iface.mainWindow().menuBar() menuBar.addMenu(self.menu) ## def runSite(self): pluginGui = pyarchinit_Site(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runPer(self): pluginGui = pyarchinit_Periodizzazione(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runStruttura(self): pluginGui = pyarchinit_Struttura(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runUS(self): pluginGui = pyarchinit_US(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runInr(self): pluginGui = pyarchinit_Inventario_reperti(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runCampioni(self): pluginGui = pyarchinit_Campioni(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runLapidei(self): pluginGui = pyarchinit_Inventario_Lapidei(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runGisTimeController(self): pluginGui = pyarchinit_Gis_Time_Controller(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runConf(self): pluginConfGui = pyArchInitDialog_Config() pluginConfGui.show() self.pluginGui = pluginConfGui # save def runInfo(self): pluginInfoGui = pyArchInitDialog_Info() pluginInfoGui.show() self.pluginGui = pluginInfoGui # save def runImageViewer(self): pluginImageView = Main() pluginImageView.show() self.pluginGui = pluginImageView # save def runTafonomia(self): pluginTafonomia = pyarchinit_Tafonomia(self.iface) pluginTafonomia.show() self.pluginGui = pluginTafonomia # save def runSchedaind(self): pluginIndividui = pyarchinit_Schedaind(self.iface) pluginIndividui.show() self.pluginGui = pluginIndividui # save def runDetsesso(self): pluginSesso = pyarchinit_Detsesso(self.iface) pluginSesso.show() self.pluginGui = pluginSesso # save def runDeteta(self): pluginEta = pyarchinit_Deteta(self.iface) pluginEta.show() self.pluginGui = pluginEta # save def runArcheozoology(self): pluginArchezoology = pyarchinit_Archeozoology(self.iface) pluginArchezoology.show() self.pluginGui = pluginArchezoology # save def runUT(self): pluginUT = pyarchinit_UT(self.iface) pluginUT.show() self.pluginGui = pluginUT # save def runImages_directory_export(self): pluginImage_directory_export = pyarchinit_Images_directory_export() pluginImage_directory_export.show() self.pluginGui = pluginImage_directory_export # save def runComparision(self): pluginComparision = Comparision() pluginComparision.show() self.pluginGui = pluginComparision # save def runDbmanagment(self): pluginDbmanagment = pyarchinit_dbmanagment(self.iface) pluginDbmanagment.show() self.pluginGui = pluginDbmanagment # save def runPdfexp(self): pluginPdfexp = pyarchinit_pdf_export(self.iface) pluginPdfexp.show() self.pluginGui = pluginPdfexp # save def runThesaurus(self): pluginThesaurus = pyarchinit_Thesaurus(self.iface) pluginThesaurus.show() self.pluginGui = pluginThesaurus # save def runDocumentazione(self): pluginDocumentazione = pyarchinit_Documentazione(self.iface) pluginDocumentazione.show() self.pluginGui = pluginDocumentazione # save def unload(self): # Remove the plugin self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionSite) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionPer) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionStruttura) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionUS) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionInr) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionCampioni) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionLapidei) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionSchedaind) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionDocumentazione) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionDetsesso) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionDeteta) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionTafonomia) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionArcheozoology) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionUT) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionimageViewer) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionImages_Directory_export) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionpdfExp) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionComparision) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionGisTimeController) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionConf) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionThesaurus) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionInfo) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionDbmanagment) self.iface.removeToolBarIcon(self.actionSite) self.iface.removeToolBarIcon(self.actionPer) self.iface.removeToolBarIcon(self.actionStruttura) self.iface.removeToolBarIcon(self.actionUS) self.iface.removeToolBarIcon(self.actionInr) self.iface.removeToolBarIcon(self.actionCampioni) self.iface.removeToolBarIcon(self.actionLapidei) self.iface.removeToolBarIcon(self.actionTafonomia) self.iface.removeToolBarIcon(self.actionSchedaind) self.iface.removeToolBarIcon(self.actionDocumentazione) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.iface.removeToolBarIcon(self.actionDetsesso) self.iface.removeToolBarIcon(self.actionDeteta) self.iface.removeToolBarIcon(self.actionArcheozoology) self.iface.removeToolBarIcon(self.actionUT) # self.iface.removeToolBarIcon(self.actionUpd) self.iface.removeToolBarIcon(self.actionimageViewer) self.iface.removeToolBarIcon(self.actionImages_Directory_export) self.iface.removeToolBarIcon(self.actionpdfExp) self.iface.removeToolBarIcon(self.actionComparision) self.iface.removeToolBarIcon(self.actionGisTimeController) self.iface.removeToolBarIcon(self.actionConf) self.iface.removeToolBarIcon(self.actionThesaurus) self.iface.removeToolBarIcon(self.actionInfo) self.iface.removeToolBarIcon(self.actionDbmanagment) self.dockWidget.setVisible(False) self.iface.removeDockWidget(self.dockWidget) # remove tool bar del self.toolBar def showHideDockWidget(self): if self.dockWidget.isVisible(): self.dockWidget.hide() else: self.dockWidget.show()
class HffPlugin_s(object): HOME = os.environ['HFF_HOME'] PARAMS_DICT = {'SERVER': '', 'HOST': '', 'DATABASE': '', 'PASSWORD': '', 'PORT': '', 'USER': '', 'THUMB_PATH': '', 'THUMB_RESIZE': '', 'EXPERIMENTAL': ''} path_rel = os.path.join(os.sep, HOME, 'HFF_DB_folder', 'config.cfg') conf = open(path_rel, "rb+") data = conf.read() text = (b'THUMB_RESIZE') if text in data: pass else: conf.seek(-3,2) conf.read(1) conf.write(b"','THUMB_RESIZE' : 'insert path for the image resized'}") conf.close() PARAMS_DICT = eval(data) def __init__(self, iface): self.iface = iface userPluginPath = os.path.dirname(__file__) systemPluginPath = QgsApplication.prefixPath() + "/python/plugins/HFF" # overrideLocale = QgsSettings().value("locale/overrideFlag", QVariant) # .toBool() # if not overrideLocale: # localeFullName = QLocale.system().name() # else: # localeFullName = QgsSettings().value("locale/userLocale", QVariant) # .toString() # if QFileInfo(userPluginPath).exists(): # translationPath = userPluginPath + "/i18n/hff_system__plugin_" + localeFullName + ".qm" # else: # translationPath = systemPluginPath + "/i18n/hff_system__plugin_" + localeFullName + ".qm" # self.localePath = translationPath # if QFileInfo(self.localePath).exists(): # self.translator = QTranslator() # self.translator.load(self.localePath) # QCoreApplication.installTranslator(self.translator) def initGui(self): settings = QgsSettings() icon_paius = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'hfflogo.png')) self.action = QAction(QIcon(icon_paius), "HFF Main Panel", self.iface.mainWindow()) self.action.triggered.connect(self.showHideDockWidget) # dock widget self.dockWidget = HffPluginDialog(self.iface) self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dockWidget) # TOOLBAR self.toolBar = self.iface.addToolBar("HFF") self.toolBar.setObjectName("HFF") self.toolBar.addAction(self.action) self.dataToolButton = QToolButton(self.toolBar) self.dataToolButton.setPopupMode(QToolButton.MenuButtonPopup) self.toolBar.addSeparator() ###### Section dedicated to the basic data entry # add Actions data self.siteToolButton = QToolButton(self.toolBar) #self.siteToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_site = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'iconSite.png')) self.actionSite = QAction(QIcon(icon_site), "Site", self.iface.mainWindow()) self.actionSite.setWhatsThis("Site") self.actionSite.triggered.connect(self.runSite) self.siteToolButton.addActions([self.actionSite]) self.siteToolButton.setDefaultAction(self.actionSite) self.toolBar.addWidget(self.siteToolButton) self.toolBar.addSeparator() self.emeanaToolButton = QToolButton(self.toolBar) #self.emeanaToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_eamena = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'eamena.jpg')) self.actionEamena = QAction(QIcon(icon_eamena), "Eamena", self.iface.mainWindow()) self.actionEamena.setWhatsThis("Eamena") self.actionEamena.triggered.connect(self.runEamena) self.emeanaToolButton.addActions([self.actionEamena]) self.emeanaToolButton.setDefaultAction(self.actionEamena) self.toolBar.addWidget(self.emeanaToolButton) self.toolBar.addSeparator() ###### Section dedicated to the shipwreck # add Actions documentation self.ShipwreckToolButton = QToolButton(self.toolBar) icon_shipwreck = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'Shipwreck.png')) self.actionShipwreck = QAction(QIcon(icon_shipwreck), "Shipwreck", self.iface.mainWindow()) self.actionShipwreck.setWhatsThis("Shipwreck") self.actionShipwreck.triggered.connect(self.runShipwreck) self.ShipwreckToolButton.addActions([self.actionShipwreck]) self.ShipwreckToolButton.setDefaultAction(self.actionShipwreck) self.toolBar.addWidget(self.ShipwreckToolButton) self.toolBar.addSeparator() ###### Section dedicated to the UnderWater data entry # add Actions data icon_UW = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'snorkel.png')) self.actionUW = QAction(QIcon(icon_UW), "Divelog Form", self.iface.mainWindow()) self.actionUW.setWhatsThis("Divelog") self.actionUW.triggered.connect(self.runUW) icon_ANC = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'iconANC.png')) self.actionANC = QAction(QIcon(icon_ANC), "Anchor", self.iface.mainWindow()) self.actionANC.setWhatsThis("Anchor") self.actionANC.triggered.connect(self.runANC) icon_ART = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'radar.png')) self.actionART = QAction(QIcon(icon_ART), "Artefact", self.iface.mainWindow()) self.actionART.setWhatsThis("Artefact") self.actionART.triggered.connect(self.runART) icon_Pottery = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'pottery.png')) self.actionPottery = QAction(QIcon(icon_Pottery), "Pottery", self.iface.mainWindow()) self.actionPottery.setWhatsThis("Pottery") self.actionPottery.triggered.connect(self.runPottery) self.dataToolButton.addActions( [self.actionUW, self.actionART, self.actionANC, self.actionPottery]) self.dataToolButton.setDefaultAction(self.actionUW) self.toolBar.addWidget(self.dataToolButton) self.toolBar.addSeparator() ###### Section dedicated to the documentation # add Actions documentation self.docToolButton = QToolButton(self.toolBar) self.docToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_imageViewer = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'photo.png')) self.actionimageViewer = QAction(QIcon(icon_imageViewer), "Media manager", self.iface.mainWindow()) self.actionimageViewer.setWhatsThis("Media manager") self.actionimageViewer.triggered.connect(self.runImageViewer) icon_Directory_export = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'directoryExp.png')) self.actionImages_Directory_export = QAction(QIcon(icon_Directory_export), "Download image", self.iface.mainWindow()) self.actionImages_Directory_export.setWhatsThis("Download image") self.actionImages_Directory_export.triggered.connect(self.runImages_directory_export) icon_excel_exp = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'excel-export.png')) self.actionexcelExp = QAction(QIcon(icon_excel_exp), "Download EXCEL", self.iface.mainWindow()) self.actionexcelExp.setWhatsThis("Download EXCEL") self.actionexcelExp.triggered.connect(self.runPdfexp) self.docToolButton.addActions( [self.actionexcelExp, self.actionimageViewer, self.actionexcelExp, self.actionImages_Directory_export]) self.docToolButton.setDefaultAction(self.actionimageViewer) #if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.actionImages_Directory_export.setCheckable(True) self.actionexcelExp.setCheckable(True) self.actionimageViewer.setCheckable(True) self.toolBar.addWidget(self.docToolButton) self.toolBar.addSeparator() ###### Section dedicated to the plugin management self.manageToolButton = QToolButton(self.toolBar) self.manageToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_Con = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'iconConn.png')) self.actionConf = QAction(QIcon(icon_Con), "Config plugin", self.iface.mainWindow()) self.actionConf.setWhatsThis("Config plugin") self.actionConf.triggered.connect(self.runConf) icon_Dbmanagment = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'backup.png')) self.actionDbmanagment = QAction(QIcon(icon_Dbmanagment), "Database manager", self.iface.mainWindow()) self.actionDbmanagment.setWhatsThis("Database manager") self.actionDbmanagment.triggered.connect(self.runDbmanagment) icon_Info = '{}{}'.format(filepath, os.path.join(os.sep, 'resources', 'icons', 'iconInfo.png')) self.actionInfo = QAction(QIcon(icon_Info), "Plugin info", self.iface.mainWindow()) self.actionInfo.setWhatsThis("Plugin info") self.actionInfo.triggered.connect(self.runInfo) self.manageToolButton.addActions( [self.actionConf, self.actionDbmanagment, self.actionInfo]) self.manageToolButton.setDefaultAction(self.actionConf) self.toolBar.addWidget(self.manageToolButton) self.toolBar.addSeparator() # menu self.iface.addPluginToMenu("HFF - Survey UW Archaeological GIS Tools", self.actionUW) self.iface.addPluginToMenu("HFF - Survey UW Archaeological GIS Tools", self.actionANC) self.iface.addPluginToMenu("HFF - Survey UW Archaeological GIS Tools", self.actionART) self.iface.addPluginToMenu("HFF - Survey UW Archaeological GIS Tools", self.actionPottery) self.iface.addPluginToMenu("HFF - Survey UW Archaeological GIS Tools", self.actionShipwreck) self.iface.addPluginToMenu("HFF - Survey Terrestrial Archaeological GIS Tools", self.actionSite) self.iface.addPluginToMenu("HFF - Survey Terrestrial Archaeological GIS Tools", self.actionEamena) self.iface.addPluginToMenu("HFF - Media manager GIS Tools", self.actionimageViewer) self.iface.addPluginToMenu("HFF - Media manager GIS Tools", self.actionexcelExp) self.iface.addPluginToMenu("HFF - Media manager GIS Tools", self.actionImages_Directory_export) self.iface.addPluginToMenu("HFF - Config GIS Tools", self.actionConf) self.iface.addPluginToMenu("HFF - Config GIS Tools", self.actionDbmanagment) self.iface.addPluginToMenu("HFF - Info GIS Tools", self.actionInfo) # MENU self.menu = QMenu("HFF") self.menu.addActions([self.actionSite]) self.menu.addSeparator() self.menu.addActions([self.actionEamena]) self.menu.addSeparator() self.menu.addActions([self.actionShipwreck]) self.menu.addSeparator() self.menu.addActions([self.actionUW, self.actionART, self.actionANC, self.actionPottery]) self.menu.addActions([self.actionimageViewer, self.actionexcelExp, self.actionImages_Directory_export]) self.menu.addSeparator() self.menu.addActions([self.actionConf, self.actionDbmanagment, self.actionInfo]) menuBar = self.iface.mainWindow().menuBar() menuBar.addMenu(self.menu) ## def runSite(self): pluginGui = hff_system__Site(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runEamena(self): pluginGui = Eamena(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runUW(self): pluginGui = hff_system__UW(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runANC(self): pluginGui = hff_system__ANC(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runART(self): pluginGui = hff_system__ART(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runPottery(self): pluginGui = hff_system__Pottery(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runShipwreck(self): pluginGui = hff_system__Shipwreck(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runConf(self): pluginConfGui = HFF_systemDialog_Config() pluginConfGui.show() self.pluginGui = pluginConfGui # save def runInfo(self): pluginInfoGui = HFF_systemDialog_Info() pluginInfoGui.show() self.pluginGui = pluginInfoGui # save def runImageViewer(self): pluginImageView = Main() pluginImageView.show() self.pluginGui = pluginImageView # save def runImages_directory_export(self): pluginImage_directory_export = hff_system__Images_directory_export() pluginImage_directory_export.show() self.pluginGui = pluginImage_directory_export # save def runDbmanagment(self): pluginDbmanagment = hff_system__dbmanagment(self.iface) pluginDbmanagment.show() self.pluginGui = pluginDbmanagment # save def runPdfexp(self): pluginPdfexp = hff_system__excel_export(self.iface) pluginPdfexp.show() self.pluginGui = pluginPdfexp # save def unload(self): # Remove the plugin self.iface.removePluginMenu("HFF - Survey UW Archaeological GIS Tools", self.actionUW) self.iface.removePluginMenu("HFF - Survey UW Archaeological GIS Tools", self.actionANC) self.iface.removePluginMenu("HFF - Survey UW Archaeological GIS Tools", self.actionART) self.iface.removePluginMenu("HFF - Survey UW Archaeological GIS Tools", self.actionPottery) self.iface.removePluginMenu("HFF - Survey UW Archaeological GIS Tools", self.actionShipwreck) self.iface.removePluginMenu("HFF - Survey Terrestrial Archaeological GIS Tools", self.actionSite) self.iface.removePluginMenu("HFF - Survey Terrestrial Archaeological GIS Tools", self.actionEamena) self.iface.removePluginMenu("HFF - Media manager GIS Tools", self.actionimageViewer) self.iface.removePluginMenu("HFF - Media manager GIS Tools", self.actionImages_Directory_export) self.iface.removePluginMenu("HFF - Media manager GIS Tools", self.actionexcelExp) self.iface.removePluginMenu("HFF - Config GIS Tools", self.actionConf) self.iface.removePluginMenu("HFF - Info GIS Tools", self.actionInfo) self.iface.removePluginMenu("HFF - Config GIS Tools", self.actionDbmanagment) self.iface.removeToolBarIcon(self.actionUW) self.iface.removeToolBarIcon(self.actionART) self.iface.removeToolBarIcon(self.actionANC) self.iface.removeToolBarIcon(self.actionPottery) self.iface.removeToolBarIcon(self.actionShipwreck) self.iface.removeToolBarIcon(self.actionSite) self.iface.removeToolBarIcon(self.actionEamena) self.iface.removeToolBarIcon(self.actionimageViewer) self.iface.removeToolBarIcon(self.actionImages_Directory_export) self.iface.removeToolBarIcon(self.actionexcelExp) self.iface.removeToolBarIcon(self.actionConf) self.iface.removeToolBarIcon(self.actionInfo) self.iface.removeToolBarIcon(self.actionDbmanagment) self.dockWidget.setVisible(False) self.iface.removeDockWidget(self.dockWidget) # remove tool bar del self.toolBar def showHideDockWidget(self): if self.dockWidget.isVisible(): self.dockWidget.hide() else: self.dockWidget.show()