Example #1
0
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()
Example #2
0
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()
Example #3
0
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()
Example #4
0
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()