""" *************************************************************************** ExtentSelectionPanel.py --------------------- Date : August 2012 Copyright : (C) 2012 by Victor Olaya Email : volayaf at gmail dot com *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * *************************************************************************** """ __author__ = "Victor Olaya" __date__ = "August 2012" __copyright__ = "(C) 2012, Victor Olaya" import os import warnings from qgis.PyQt import uic from qgis.PyQt.QtWidgets import ( QMenu, QAction, QDialog, QVBoxLayout, QDialogButtonBox, QLabel, ) from qgis.PyQt.QtGui import QCursor from qgis.PyQt.QtCore import QCoreApplication, pyqtSignal from qgis.gui import QgsMapLayerComboBox from qgis.utils import iface from qgis.core import ( Qgis, QgsProcessingParameterDefinition, QgsProcessingParameters, QgsProject, QgsReferencedRectangle, QgsMapLayerProxyModel, ) from processing.gui.RectangleMapTool import RectangleMapTool from processing.core.ProcessingConfig import ProcessingConfig from processing.tools.dataobjects import createContext pluginPath = os.path.split(os.path.dirname(__file__))[0] with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning) WIDGET, BASE = uic.loadUiType( os.path.join(pluginPath, "ui", "widgetBaseSelector.ui") ) class LayerSelectionDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle(self.tr("Select Extent")) vl = QVBoxLayout() vl.addWidget(QLabel(self.tr("Use extent from"))) self.combo = QgsMapLayerComboBox() self.combo.setFilters( Qgis.LayerFilter.HasGeometry | Qgis.LayerFilter.RasterLayer | Qgis.LayerFilter.MeshLayer ) self.combo.setShowCrs( ProcessingConfig.getSetting(ProcessingConfig.SHOW_CRS_DEF) ) vl.addWidget(self.combo) self.button_box = QDialogButtonBox() self.button_box.setStandardButtons( QDialogButtonBox.StandardButton.Cancel | QDialogButtonBox.StandardButton.Ok ) self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.reject) vl.addWidget(self.button_box) self.setLayout(vl) def selected_layer(self): return self.combo.currentLayer() class ExtentSelectionPanel(BASE, WIDGET): hasChanged = pyqtSignal() def __init__(self, dialog, param): super().__init__(None) self.setupUi(self) self.leText.textChanged.connect(lambda: self.hasChanged.emit()) self.dialog = dialog self.param = param self.crs = QgsProject.instance().crs() if self.param.flags() & QgsProcessingParameterDefinition.Flag.FlagOptional: if hasattr(self.leText, "setPlaceholderText"): self.leText.setPlaceholderText( self.tr("[Leave blank to use min covering extent]") ) self.btnSelect.clicked.connect(self.selectExtent) if iface is not None: canvas = iface.mapCanvas() self.prevMapTool = canvas.mapTool() self.tool = RectangleMapTool(canvas) self.tool.rectangleCreated.connect(self.updateExtent) else: self.prevMapTool = None self.tool = None if param.defaultValue() is not None: context = createContext() rect = QgsProcessingParameters.parameterAsExtent( param, {param.name(): param.defaultValue()}, context ) crs = QgsProcessingParameters.parameterAsExtentCrs( param, {param.name(): param.defaultValue()}, context ) if not rect.isNull(): try: s = "{},{},{},{}".format( rect.xMinimum(), rect.xMaximum(), rect.yMinimum(), rect.yMaximum(), ) if crs.isValid(): s += " [" + crs.authid() + "]" self.crs = crs self.leText.setText(s) except: pass def selectExtent(self): popupmenu = QMenu() useCanvasExtentAction = QAction( QCoreApplication.translate("ExtentSelectionPanel", "Use Canvas Extent"), self.btnSelect, ) useLayerExtentAction = QAction( QCoreApplication.translate("ExtentSelectionPanel", "Use Layer Extent…"), self.btnSelect, ) selectOnCanvasAction = QAction( self.tr("Select Extent on Canvas"), self.btnSelect ) popupmenu.addAction(useCanvasExtentAction) popupmenu.addAction(selectOnCanvasAction) popupmenu.addSeparator() popupmenu.addAction(useLayerExtentAction) selectOnCanvasAction.triggered.connect(self.selectOnCanvas) useLayerExtentAction.triggered.connect(self.useLayerExtent) useCanvasExtentAction.triggered.connect(self.useCanvasExtent) if self.param.flags() & QgsProcessingParameterDefinition.Flag.FlagOptional: useMincoveringExtentAction = QAction( self.tr("Use Min Covering Extent from Input Layers"), self.btnSelect ) useMincoveringExtentAction.triggered.connect(self.useMinCoveringExtent) popupmenu.addAction(useMincoveringExtentAction) popupmenu.exec(QCursor.pos()) def useMinCoveringExtent(self): self.leText.setText("") def useLayerExtent(self): dlg = LayerSelectionDialog(self) if dlg.exec(): layer = dlg.selected_layer() self.setValueFromRect(QgsReferencedRectangle(layer.extent(), layer.crs())) def useCanvasExtent(self): self.setValueFromRect( QgsReferencedRectangle( iface.mapCanvas().extent(), iface.mapCanvas().mapSettings().destinationCrs(), ) ) def selectOnCanvas(self): canvas = iface.mapCanvas() canvas.setMapTool(self.tool) self.dialog.showMinimized() def updateExtent(self): r = self.tool.rectangle() self.setValueFromRect(r) def setValueFromRect(self, r): s = f"{r.xMinimum()},{r.xMaximum()},{r.yMinimum()},{r.yMaximum()}" try: self.crs = r.crs() except: self.crs = QgsProject.instance().crs() if self.crs.isValid(): s += " [" + self.crs.authid() + "]" self.leText.setText(s) self.tool.reset() canvas = iface.mapCanvas() canvas.setMapTool(self.prevMapTool) self.dialog.showNormal() self.dialog.raise_() self.dialog.activateWindow() def getValue(self): if str(self.leText.text()).strip() != "": return str(self.leText.text()) else: return None def setExtentFromString(self, s): self.leText.setText(s)