mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-09 00:08:52 -04:00
281 lines
10 KiB
Python
281 lines
10 KiB
Python
"""
|
|
***************************************************************************
|
|
BatchInputSelectionPanel.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
|
|
from pathlib import Path
|
|
|
|
from qgis.PyQt.QtCore import pyqtSignal, QCoreApplication
|
|
from qgis.PyQt.QtWidgets import (
|
|
QWidget,
|
|
QHBoxLayout,
|
|
QMenu,
|
|
QPushButton,
|
|
QLineEdit,
|
|
QSizePolicy,
|
|
QAction,
|
|
QFileDialog,
|
|
)
|
|
from qgis.PyQt.QtGui import QCursor
|
|
|
|
from qgis.core import (
|
|
QgsMapLayer,
|
|
QgsRasterLayer,
|
|
QgsSettings,
|
|
QgsProject,
|
|
QgsProcessing,
|
|
QgsProcessingUtils,
|
|
QgsProcessingParameterMultipleLayers,
|
|
QgsProcessingParameterRasterLayer,
|
|
QgsProcessingParameterVectorLayer,
|
|
QgsProcessingParameterMeshLayer,
|
|
QgsProcessingParameterPointCloudLayer,
|
|
QgsProcessingParameterFeatureSource,
|
|
QgsProcessingParameterMapLayer,
|
|
)
|
|
|
|
from processing.gui.MultipleInputDialog import MultipleInputDialog
|
|
|
|
from processing.tools import dataobjects
|
|
|
|
|
|
class BatchInputSelectionPanel(QWidget):
|
|
valueChanged = pyqtSignal()
|
|
|
|
def __init__(self, param, row, col, dialog):
|
|
super().__init__(None)
|
|
self.param = param
|
|
self.dialog = dialog
|
|
self.row = row
|
|
self.col = col
|
|
self.horizontalLayout = QHBoxLayout(self)
|
|
self.horizontalLayout.setSpacing(0)
|
|
self.horizontalLayout.setMargin(0)
|
|
self.text = QLineEdit()
|
|
self.text.setObjectName("text")
|
|
self.text.setMinimumWidth(300)
|
|
self.setValue("")
|
|
self.text.editingFinished.connect(self.textEditingFinished)
|
|
self.text.setSizePolicy(
|
|
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding
|
|
)
|
|
self.horizontalLayout.addWidget(self.text)
|
|
self.pushButton = QPushButton()
|
|
self.pushButton.setText("…")
|
|
self.pushButton.clicked.connect(self.showPopupMenu)
|
|
self.horizontalLayout.addWidget(self.pushButton)
|
|
self.setLayout(self.horizontalLayout)
|
|
|
|
def _panel(self):
|
|
return self.dialog.mainWidget()
|
|
|
|
def _table(self):
|
|
return self._panel().tblParameters
|
|
|
|
def showPopupMenu(self):
|
|
popupmenu = QMenu()
|
|
|
|
if not (
|
|
isinstance(self.param, QgsProcessingParameterMultipleLayers)
|
|
and self.param.layerType == dataobjects.TYPE_FILE
|
|
):
|
|
selectLayerAction = QAction(
|
|
QCoreApplication.translate(
|
|
"BatchInputSelectionPanel", "Select from Open Layers…"
|
|
),
|
|
self.pushButton,
|
|
)
|
|
selectLayerAction.triggered.connect(self.showLayerSelectionDialog)
|
|
popupmenu.addAction(selectLayerAction)
|
|
|
|
selectFileAction = QAction(
|
|
QCoreApplication.translate("BatchInputSelectionPanel", "Select Files…"),
|
|
self.pushButton,
|
|
)
|
|
selectFileAction.triggered.connect(self.showFileSelectionDialog)
|
|
popupmenu.addAction(selectFileAction)
|
|
|
|
selectDirectoryAction = QAction(
|
|
QCoreApplication.translate("BatchInputSelectionPanel", "Select Directory…"),
|
|
self.pushButton,
|
|
)
|
|
selectDirectoryAction.triggered.connect(self.showDirectorySelectionDialog)
|
|
popupmenu.addAction(selectDirectoryAction)
|
|
|
|
popupmenu.exec(QCursor.pos())
|
|
|
|
def showLayerSelectionDialog(self):
|
|
layers = []
|
|
if isinstance(self.param, QgsProcessingParameterRasterLayer) or (
|
|
isinstance(self.param, QgsProcessingParameterMultipleLayers)
|
|
and self.param.layerType() == QgsProcessing.SourceType.TypeRaster
|
|
):
|
|
layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance())
|
|
elif isinstance(self.param, QgsProcessingParameterVectorLayer):
|
|
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance())
|
|
elif isinstance(self.param, QgsProcessingParameterMapLayer):
|
|
layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance())
|
|
elif isinstance(self.param, QgsProcessingParameterMeshLayer) or (
|
|
isinstance(self.param, QgsProcessingParameterMultipleLayers)
|
|
and self.param.layerType() == QgsProcessing.SourceType.TypeMesh
|
|
):
|
|
layers = QgsProcessingUtils.compatibleMeshLayers(QgsProject.instance())
|
|
elif isinstance(self.param, QgsProcessingParameterPointCloudLayer) or (
|
|
isinstance(self.param, QgsProcessingParameterMultipleLayers)
|
|
and self.param.layerType() == QgsProcessing.SourceType.TypePointCloud
|
|
):
|
|
layers = QgsProcessingUtils.compatiblePointCloudLayers(
|
|
QgsProject.instance()
|
|
)
|
|
else:
|
|
datatypes = [QgsProcessing.SourceType.TypeVectorAnyGeometry]
|
|
if isinstance(self.param, QgsProcessingParameterFeatureSource):
|
|
datatypes = self.param.dataTypes()
|
|
elif isinstance(self.param, QgsProcessingParameterMultipleLayers):
|
|
datatypes = [self.param.layerType()]
|
|
|
|
if QgsProcessing.SourceType.TypeVectorAnyGeometry not in datatypes:
|
|
layers = QgsProcessingUtils.compatibleVectorLayers(
|
|
QgsProject.instance(), datatypes
|
|
)
|
|
else:
|
|
layers = QgsProcessingUtils.compatibleVectorLayers(
|
|
QgsProject.instance()
|
|
)
|
|
|
|
dlg = MultipleInputDialog([layer.name() for layer in layers])
|
|
dlg.exec()
|
|
|
|
def generate_layer_id(layer):
|
|
# prefer layer name if unique
|
|
if (
|
|
len([l for l in layers if l.name().lower() == layer.name().lower()])
|
|
== 1
|
|
):
|
|
return layer.name()
|
|
else:
|
|
# otherwise fall back to layer id
|
|
return layer.id()
|
|
|
|
if dlg.selectedoptions is not None:
|
|
selected = dlg.selectedoptions
|
|
if len(selected) == 1:
|
|
self.setValue(generate_layer_id(layers[selected[0]]))
|
|
else:
|
|
if isinstance(self.param, QgsProcessingParameterMultipleLayers):
|
|
self.text.setText(";".join(layers[idx].id() for idx in selected))
|
|
else:
|
|
rowdif = len(selected) - (self._table().rowCount() - self.row)
|
|
for i in range(rowdif):
|
|
self._panel().addRow()
|
|
for i, layeridx in enumerate(selected):
|
|
self._table().cellWidget(i + self.row, self.col).setValue(
|
|
generate_layer_id(layers[layeridx])
|
|
)
|
|
|
|
def showFileSelectionDialog(self):
|
|
self.showFileDialog(seldir=False)
|
|
|
|
def showDirectorySelectionDialog(self):
|
|
self.showFileDialog(seldir=True)
|
|
|
|
def showFileDialog(self, seldir):
|
|
settings = QgsSettings()
|
|
text = str(self.text.text())
|
|
if os.path.isdir(text):
|
|
path = text
|
|
elif not seldir and os.path.isdir(os.path.dirname(text)):
|
|
path = os.path.dirname(text)
|
|
elif settings.contains("/Processing/LastInputPath"):
|
|
path = str(settings.value("/Processing/LastInputPath"))
|
|
else:
|
|
path = ""
|
|
|
|
if not seldir:
|
|
ret, selected_filter = QFileDialog.getOpenFileNames(
|
|
self, self.tr("Select Files"), path, self.param.createFileFilter()
|
|
)
|
|
else:
|
|
ret = QFileDialog.getExistingDirectory(
|
|
self, self.tr("Select Directory"), path
|
|
)
|
|
|
|
if ret:
|
|
if seldir:
|
|
settings.setValue("/Processing/LastInputPath", ret)
|
|
|
|
files = []
|
|
for pp in Path(ret).rglob("*"):
|
|
if not pp.is_file():
|
|
continue
|
|
|
|
p = pp.as_posix()
|
|
|
|
if (
|
|
isinstance(self.param, QgsProcessingParameterRasterLayer)
|
|
or (
|
|
isinstance(self.param, QgsProcessingParameterMultipleLayers)
|
|
and self.param.layerType()
|
|
== QgsProcessing.SourceType.TypeRaster
|
|
)
|
|
) and not QgsRasterLayer.isValidRasterFileName(p):
|
|
continue
|
|
|
|
files.append(p)
|
|
|
|
if not files:
|
|
return
|
|
|
|
else:
|
|
files = list(ret)
|
|
settings.setValue(
|
|
"/Processing/LastInputPath", os.path.dirname(str(files[0]))
|
|
)
|
|
|
|
for i, filename in enumerate(files):
|
|
files[i] = dataobjects.getRasterSublayer(filename, self.param)
|
|
if len(files) == 1:
|
|
self.text.setText(files[0])
|
|
self.textEditingFinished()
|
|
else:
|
|
if isinstance(self.param, QgsProcessingParameterMultipleLayers):
|
|
self.text.setText(";".join(str(f) for f in files))
|
|
else:
|
|
rowdif = len(files) - (self._table().rowCount() - self.row)
|
|
for i in range(rowdif):
|
|
self._panel().addRow()
|
|
for i, f in enumerate(files):
|
|
self._table().cellWidget(i + self.row, self.col).setValue(f)
|
|
|
|
def textEditingFinished(self):
|
|
self._value = self.text.text()
|
|
self.valueChanged.emit()
|
|
|
|
def getValue(self):
|
|
return self._value if self._value else None
|
|
|
|
def setValue(self, value):
|
|
self._value = value
|
|
if isinstance(value, QgsMapLayer):
|
|
self.text.setText(value.name())
|
|
else: # should be basestring
|
|
self.text.setText(value)
|
|
self.valueChanged.emit()
|