mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-10 00:04:23 -04:00
260 lines
9.4 KiB
Python
260 lines
9.4 KiB
Python
"""
|
|
***************************************************************************
|
|
MultipleInputDialog.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 pathlib import Path
|
|
|
|
from qgis.core import (
|
|
QgsSettings,
|
|
QgsProcessing,
|
|
QgsVectorFileWriter,
|
|
QgsProviderRegistry,
|
|
QgsProcessingModelChildParameterSource,
|
|
)
|
|
from qgis.PyQt import uic
|
|
from qgis.PyQt.QtCore import Qt, QByteArray, QCoreApplication
|
|
from qgis.PyQt.QtWidgets import (
|
|
QDialog,
|
|
QAbstractItemView,
|
|
QPushButton,
|
|
QDialogButtonBox,
|
|
QFileDialog,
|
|
)
|
|
from qgis.PyQt.QtGui import QStandardItemModel, QStandardItem
|
|
|
|
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", "DlgMultipleSelection.ui")
|
|
)
|
|
|
|
|
|
class MultipleInputDialog(BASE, WIDGET):
|
|
|
|
def __init__(self, options, selectedoptions=None, datatype=None):
|
|
super().__init__(None)
|
|
self.setupUi(self)
|
|
self.datatype = datatype
|
|
self.model = None
|
|
|
|
self.options = []
|
|
for i, option in enumerate(options):
|
|
if option is None or isinstance(option, str):
|
|
self.options.append((i, option))
|
|
else:
|
|
self.options.append((option[0], option[1]))
|
|
|
|
self.selectedoptions = selectedoptions or []
|
|
|
|
# Additional buttons
|
|
self.btnSelectAll = QPushButton(self.tr("Select All"))
|
|
self.buttonBox.addButton(
|
|
self.btnSelectAll, QDialogButtonBox.ButtonRole.ActionRole
|
|
)
|
|
self.btnClearSelection = QPushButton(self.tr("Clear Selection"))
|
|
self.buttonBox.addButton(
|
|
self.btnClearSelection, QDialogButtonBox.ButtonRole.ActionRole
|
|
)
|
|
self.btnToggleSelection = QPushButton(self.tr("Toggle Selection"))
|
|
self.buttonBox.addButton(
|
|
self.btnToggleSelection, QDialogButtonBox.ButtonRole.ActionRole
|
|
)
|
|
if self.datatype is not None:
|
|
btnAddFile = QPushButton(
|
|
QCoreApplication.translate("MultipleInputDialog", "Add File(s)…")
|
|
)
|
|
btnAddFile.clicked.connect(self.addFiles)
|
|
self.buttonBox.addButton(btnAddFile, QDialogButtonBox.ButtonRole.ActionRole)
|
|
|
|
btnAddDir = QPushButton(
|
|
QCoreApplication.translate("MultipleInputDialog", "Add Directory…")
|
|
)
|
|
btnAddDir.clicked.connect(self.addDirectory)
|
|
self.buttonBox.addButton(btnAddDir, QDialogButtonBox.ButtonRole.ActionRole)
|
|
|
|
self.btnSelectAll.clicked.connect(lambda: self.selectAll(True))
|
|
self.btnClearSelection.clicked.connect(lambda: self.selectAll(False))
|
|
self.btnToggleSelection.clicked.connect(self.toggleSelection)
|
|
|
|
self.settings = QgsSettings()
|
|
self.restoreGeometry(
|
|
self.settings.value("/Processing/multipleInputDialogGeometry", QByteArray())
|
|
)
|
|
|
|
self.lstLayers.setSelectionMode(
|
|
QAbstractItemView.SelectionMode.ExtendedSelection
|
|
)
|
|
self.lstLayers.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
|
|
|
|
self.populateList()
|
|
self.finished.connect(self.saveWindowGeometry)
|
|
|
|
def saveWindowGeometry(self):
|
|
self.settings.setValue(
|
|
"/Processing/multipleInputDialogGeometry", self.saveGeometry()
|
|
)
|
|
|
|
def populateList(self):
|
|
self.model = QStandardItemModel()
|
|
for value, text in self.options:
|
|
item = QStandardItem(text)
|
|
item.setData(value, Qt.ItemDataRole.UserRole)
|
|
item.setCheckState(
|
|
Qt.CheckState.Checked
|
|
if value in self.selectedoptions
|
|
else Qt.CheckState.Unchecked
|
|
)
|
|
item.setCheckable(True)
|
|
item.setDropEnabled(False)
|
|
self.model.appendRow(item)
|
|
|
|
# add extra options (e.g. manually added layers)
|
|
for t in [o for o in self.selectedoptions if not isinstance(o, int)]:
|
|
if isinstance(t, QgsProcessingModelChildParameterSource):
|
|
item = QStandardItem(t.staticValue())
|
|
else:
|
|
item = QStandardItem(t)
|
|
item.setData(item.text(), Qt.ItemDataRole.UserRole)
|
|
item.setCheckState(Qt.CheckState.Checked)
|
|
item.setCheckable(True)
|
|
item.setDropEnabled(False)
|
|
self.model.appendRow(item)
|
|
|
|
self.lstLayers.setModel(self.model)
|
|
|
|
def accept(self):
|
|
self.selectedoptions = []
|
|
model = self.lstLayers.model()
|
|
for i in range(model.rowCount()):
|
|
item = model.item(i)
|
|
if item.checkState() == Qt.CheckState.Checked:
|
|
self.selectedoptions.append(item.data(Qt.ItemDataRole.UserRole))
|
|
QDialog.accept(self)
|
|
|
|
def reject(self):
|
|
self.selectedoptions = None
|
|
QDialog.reject(self)
|
|
|
|
def getItemsToModify(self):
|
|
items = []
|
|
if len(self.lstLayers.selectedIndexes()) > 1:
|
|
for i in self.lstLayers.selectedIndexes():
|
|
items.append(self.model.itemFromIndex(i))
|
|
else:
|
|
for i in range(self.model.rowCount()):
|
|
items.append(self.model.item(i))
|
|
return items
|
|
|
|
def selectAll(self, value):
|
|
for item in self.getItemsToModify():
|
|
item.setCheckState(
|
|
Qt.CheckState.Checked if value else Qt.CheckState.Unchecked
|
|
)
|
|
|
|
def toggleSelection(self):
|
|
for item in self.getItemsToModify():
|
|
checked = item.checkState() == Qt.CheckState.Checked
|
|
item.setCheckState(
|
|
Qt.CheckState.Unchecked if checked else Qt.CheckState.Checked
|
|
)
|
|
|
|
def getFileFilter(self, datatype):
|
|
"""
|
|
Returns a suitable file filter pattern for the specified parameter definition
|
|
:param param:
|
|
:return:
|
|
"""
|
|
if datatype == QgsProcessing.SourceType.TypeRaster:
|
|
return QgsProviderRegistry.instance().fileRasterFilters()
|
|
elif datatype == QgsProcessing.SourceType.TypeFile:
|
|
return self.tr("All files (*.*)")
|
|
else:
|
|
exts = QgsVectorFileWriter.supportedFormatExtensions()
|
|
for i in range(len(exts)):
|
|
exts[i] = self.tr("{0} files (*.{1})").format(
|
|
exts[i].upper(), exts[i].lower()
|
|
)
|
|
return self.tr("All files (*.*)") + ";;" + ";;".join(exts)
|
|
|
|
def addFiles(self):
|
|
filter = self.getFileFilter(self.datatype)
|
|
|
|
settings = QgsSettings()
|
|
path = str(settings.value("/Processing/LastInputPath"))
|
|
|
|
ret, selected_filter = QFileDialog.getOpenFileNames(
|
|
self, self.tr("Select File(s)"), path, filter
|
|
)
|
|
if ret:
|
|
files = list(ret)
|
|
settings.setValue(
|
|
"/Processing/LastInputPath", os.path.dirname(str(files[0]))
|
|
)
|
|
for filename in files:
|
|
item = QStandardItem(filename)
|
|
item.setData(filename, Qt.ItemDataRole.UserRole)
|
|
item.setCheckState(Qt.CheckState.Checked)
|
|
item.setCheckable(True)
|
|
item.setDropEnabled(False)
|
|
self.model.appendRow(item)
|
|
|
|
def addDirectory(self):
|
|
settings = QgsSettings()
|
|
path = str(settings.value("/Processing/LastInputPath"))
|
|
|
|
ret = QFileDialog.getExistingDirectory(self, self.tr("Select File(s)"), path)
|
|
if ret:
|
|
exts = []
|
|
|
|
if self.datatype == QgsProcessing.SourceType.TypeVector:
|
|
exts = QgsVectorFileWriter.supportedFormatExtensions()
|
|
elif self.datatype == QgsProcessing.SourceType.TypeRaster:
|
|
for t in (
|
|
QgsProviderRegistry.instance().fileRasterFilters().split(";;")[1:]
|
|
):
|
|
for e in t[t.index("(") + 1 : -1].split(" "):
|
|
if e != "*.*" and e.startswith("*."):
|
|
exts.append(e[2:])
|
|
|
|
files = []
|
|
for pp in Path(ret).rglob("*"):
|
|
if not pp.is_file():
|
|
continue
|
|
|
|
if exts and pp.suffix[1:] not in exts:
|
|
continue
|
|
|
|
p = pp.as_posix()
|
|
|
|
files.append(p)
|
|
|
|
settings.setValue("/Processing/LastInputPath", ret)
|
|
|
|
for filename in files:
|
|
item = QStandardItem(filename)
|
|
item.setData(filename, Qt.ItemDataRole.UserRole)
|
|
item.setCheckState(Qt.CheckState.Checked)
|
|
item.setCheckable(True)
|
|
item.setDropEnabled(False)
|
|
self.model.appendRow(item)
|