ExtentSelectionPanel.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. """
  2. ***************************************************************************
  3. ExtentSelectionPanel.py
  4. ---------------------
  5. Date : August 2012
  6. Copyright : (C) 2012 by Victor Olaya
  7. Email : volayaf at gmail dot com
  8. ***************************************************************************
  9. * *
  10. * This program is free software; you can redistribute it and/or modify *
  11. * it under the terms of the GNU General Public License as published by *
  12. * the Free Software Foundation; either version 2 of the License, or *
  13. * (at your option) any later version. *
  14. * *
  15. ***************************************************************************
  16. """
  17. __author__ = 'Victor Olaya'
  18. __date__ = 'August 2012'
  19. __copyright__ = '(C) 2012, Victor Olaya'
  20. import os
  21. import warnings
  22. from qgis.PyQt import uic
  23. from qgis.PyQt.QtWidgets import (
  24. QMenu,
  25. QAction,
  26. QDialog,
  27. QVBoxLayout,
  28. QDialogButtonBox,
  29. QLabel
  30. )
  31. from qgis.PyQt.QtGui import QCursor
  32. from qgis.PyQt.QtCore import QCoreApplication, pyqtSignal
  33. from qgis.gui import QgsMapLayerComboBox
  34. from qgis.utils import iface
  35. from qgis.core import (Qgis,
  36. QgsProcessingParameterDefinition,
  37. QgsProcessingParameters,
  38. QgsProject,
  39. QgsReferencedRectangle,
  40. QgsMapLayerProxyModel)
  41. from processing.gui.RectangleMapTool import RectangleMapTool
  42. from processing.core.ProcessingConfig import ProcessingConfig
  43. from processing.tools.dataobjects import createContext
  44. pluginPath = os.path.split(os.path.dirname(__file__))[0]
  45. with warnings.catch_warnings():
  46. warnings.filterwarnings("ignore", category=DeprecationWarning)
  47. WIDGET, BASE = uic.loadUiType(
  48. os.path.join(pluginPath, 'ui', 'widgetBaseSelector.ui'))
  49. class LayerSelectionDialog(QDialog):
  50. def __init__(self, parent=None):
  51. super().__init__(parent)
  52. self.setWindowTitle(self.tr('Select Extent'))
  53. vl = QVBoxLayout()
  54. vl.addWidget(QLabel(self.tr('Use extent from')))
  55. self.combo = QgsMapLayerComboBox()
  56. self.combo.setFilters(
  57. Qgis.LayerFilter.HasGeometry | Qgis.LayerFilter.RasterLayer | Qgis.LayerFilter.MeshLayer)
  58. self.combo.setShowCrs(ProcessingConfig.getSetting(ProcessingConfig.SHOW_CRS_DEF))
  59. vl.addWidget(self.combo)
  60. self.button_box = QDialogButtonBox()
  61. self.button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok)
  62. self.button_box.accepted.connect(self.accept)
  63. self.button_box.rejected.connect(self.reject)
  64. vl.addWidget(self.button_box)
  65. self.setLayout(vl)
  66. def selected_layer(self):
  67. return self.combo.currentLayer()
  68. class ExtentSelectionPanel(BASE, WIDGET):
  69. hasChanged = pyqtSignal()
  70. def __init__(self, dialog, param):
  71. super().__init__(None)
  72. self.setupUi(self)
  73. self.leText.textChanged.connect(lambda: self.hasChanged.emit())
  74. self.dialog = dialog
  75. self.param = param
  76. self.crs = QgsProject.instance().crs()
  77. if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
  78. if hasattr(self.leText, 'setPlaceholderText'):
  79. self.leText.setPlaceholderText(
  80. self.tr('[Leave blank to use min covering extent]'))
  81. self.btnSelect.clicked.connect(self.selectExtent)
  82. if iface is not None:
  83. canvas = iface.mapCanvas()
  84. self.prevMapTool = canvas.mapTool()
  85. self.tool = RectangleMapTool(canvas)
  86. self.tool.rectangleCreated.connect(self.updateExtent)
  87. else:
  88. self.prevMapTool = None
  89. self.tool = None
  90. if param.defaultValue() is not None:
  91. context = createContext()
  92. rect = QgsProcessingParameters.parameterAsExtent(param, {param.name(): param.defaultValue()}, context)
  93. crs = QgsProcessingParameters.parameterAsExtentCrs(param, {param.name(): param.defaultValue()}, context)
  94. if not rect.isNull():
  95. try:
  96. s = '{},{},{},{}'.format(
  97. rect.xMinimum(), rect.xMaximum(), rect.yMinimum(), rect.yMaximum())
  98. if crs.isValid():
  99. s += ' [' + crs.authid() + ']'
  100. self.crs = crs
  101. self.leText.setText(s)
  102. except:
  103. pass
  104. def selectExtent(self):
  105. popupmenu = QMenu()
  106. useCanvasExtentAction = QAction(
  107. QCoreApplication.translate("ExtentSelectionPanel", 'Use Canvas Extent'),
  108. self.btnSelect)
  109. useLayerExtentAction = QAction(
  110. QCoreApplication.translate("ExtentSelectionPanel", 'Use Layer Extent…'),
  111. self.btnSelect)
  112. selectOnCanvasAction = QAction(
  113. self.tr('Select Extent on Canvas'), self.btnSelect)
  114. popupmenu.addAction(useCanvasExtentAction)
  115. popupmenu.addAction(selectOnCanvasAction)
  116. popupmenu.addSeparator()
  117. popupmenu.addAction(useLayerExtentAction)
  118. selectOnCanvasAction.triggered.connect(self.selectOnCanvas)
  119. useLayerExtentAction.triggered.connect(self.useLayerExtent)
  120. useCanvasExtentAction.triggered.connect(self.useCanvasExtent)
  121. if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
  122. useMincoveringExtentAction = QAction(
  123. self.tr('Use Min Covering Extent from Input Layers'),
  124. self.btnSelect)
  125. useMincoveringExtentAction.triggered.connect(
  126. self.useMinCoveringExtent)
  127. popupmenu.addAction(useMincoveringExtentAction)
  128. popupmenu.exec_(QCursor.pos())
  129. def useMinCoveringExtent(self):
  130. self.leText.setText('')
  131. def useLayerExtent(self):
  132. dlg = LayerSelectionDialog(self)
  133. if dlg.exec_():
  134. layer = dlg.selected_layer()
  135. self.setValueFromRect(QgsReferencedRectangle(layer.extent(), layer.crs()))
  136. def useCanvasExtent(self):
  137. self.setValueFromRect(QgsReferencedRectangle(iface.mapCanvas().extent(),
  138. iface.mapCanvas().mapSettings().destinationCrs()))
  139. def selectOnCanvas(self):
  140. canvas = iface.mapCanvas()
  141. canvas.setMapTool(self.tool)
  142. self.dialog.showMinimized()
  143. def updateExtent(self):
  144. r = self.tool.rectangle()
  145. self.setValueFromRect(r)
  146. def setValueFromRect(self, r):
  147. s = '{},{},{},{}'.format(
  148. r.xMinimum(), r.xMaximum(), r.yMinimum(), r.yMaximum())
  149. try:
  150. self.crs = r.crs()
  151. except:
  152. self.crs = QgsProject.instance().crs()
  153. if self.crs.isValid():
  154. s += ' [' + self.crs.authid() + ']'
  155. self.leText.setText(s)
  156. self.tool.reset()
  157. canvas = iface.mapCanvas()
  158. canvas.setMapTool(self.prevMapTool)
  159. self.dialog.showNormal()
  160. self.dialog.raise_()
  161. self.dialog.activateWindow()
  162. def getValue(self):
  163. if str(self.leText.text()).strip() != '':
  164. return str(self.leText.text())
  165. else:
  166. return None
  167. def setExtentFromString(self, s):
  168. self.leText.setText(s)