QGIS/python/plugins/processing/gui/ConfigDialog.py

487 lines
17 KiB
Python
Raw Normal View History

2012-10-05 23:28:47 +02:00
# -*- coding: utf-8 -*-
"""
***************************************************************************
ConfigDialog.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. *
* *
***************************************************************************
"""
2016-09-21 18:24:26 +02:00
from builtins import str
from builtins import range
2012-10-05 23:28:47 +02:00
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'
2012-10-05 23:28:47 +02:00
# This will get replaced with a git SHA1 when you do a git archive
2012-10-05 23:28:47 +02:00
__revision__ = '$Format:%H$'
import os
2016-04-29 11:39:26 +02:00
from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt, QEvent
2016-04-22 10:38:48 +02:00
from qgis.PyQt.QtWidgets import (QFileDialog,
2016-04-29 11:39:26 +02:00
QStyle,
QMessageBox,
QStyledItemDelegate,
QLineEdit,
QWidget,
QToolButton,
QHBoxLayout,
2016-09-05 09:49:36 +10:00
QComboBox,
QPushButton,
QApplication)
2016-04-22 10:38:48 +02:00
from qgis.PyQt.QtGui import (QIcon,
2016-04-29 11:39:26 +02:00
QStandardItemModel,
QStandardItem,
QCursor)
from qgis.gui import (QgsDoubleSpinBox,
QgsSpinBox,
QgsOptionsPageWidget)
from qgis.core import NULL, QgsApplication, QgsSettings
2017-07-30 21:51:22 +02:00
from qgis.utils import OverrideCursor
2016-03-23 00:55:36 +03:00
from processing.core.ProcessingConfig import (ProcessingConfig,
settingsWatcher,
Setting)
from processing.core.Processing import Processing
from processing.gui.DirectorySelectorDialog import DirectorySelectorDialog
2017-03-03 20:44:03 +01:00
from processing.gui.menus import defaultMenuEntries, menusSettingsGroup
2012-09-15 18:25:25 +03:00
pluginPath = os.path.split(os.path.dirname(__file__))[0]
2015-05-18 21:04:20 +03:00
WIDGET, BASE = uic.loadUiType(
os.path.join(pluginPath, 'ui', 'DlgConfig.ui'))
class ConfigOptionsPage(QgsOptionsPageWidget):
def __init__(self, parent):
super(ConfigOptionsPage, self).__init__(parent)
self.config_widget = ConfigDialog()
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.setMargin(0)
self.setLayout(layout)
layout.addWidget(self.config_widget)
self.setObjectName('processingOptions')
def apply(self):
self.config_widget.accept()
2015-05-18 21:04:20 +03:00
class ConfigDialog(BASE, WIDGET):
def __init__(self):
2015-05-18 21:04:20 +03:00
super(ConfigDialog, self).__init__(None)
self.setupUi(self)
2015-05-18 21:04:20 +03:00
self.groupIcon = QIcon()
self.groupIcon.addPixmap(self.style().standardPixmap(
QStyle.SP_DirClosedIcon), QIcon.Normal, QIcon.Off)
self.groupIcon.addPixmap(self.style().standardPixmap(
QStyle.SP_DirOpenIcon), QIcon.Normal, QIcon.On)
2012-09-15 18:25:25 +03:00
2012-12-01 20:22:21 +02:00
if hasattr(self.searchBox, 'setPlaceholderText'):
self.searchBox.setPlaceholderText(self.tr('Search...'))
2012-12-01 20:22:21 +02:00
self.model = QStandardItemModel()
self.tree.setModel(self.model)
self.delegate = SettingDelegate()
self.tree.setItemDelegateForColumn(1, self.delegate)
self.searchBox.textChanged.connect(self.textChanged)
self.fillTree()
2013-05-01 23:45:20 +02:00
self.saveMenus = False
self.tree.expanded.connect(self.itemExpanded)
2012-09-15 18:25:25 +03:00
def textChanged(self):
2016-09-21 18:24:26 +02:00
text = str(self.searchBox.text().lower())
self._filterItem(self.model.invisibleRootItem(), text)
if text:
self.tree.expandAll()
else:
self.tree.collapseAll()
def _filterItem(self, item, text):
if item.hasChildren():
show = False
2016-09-21 18:24:26 +02:00
for i in range(item.rowCount()):
child = item.child(i)
showChild = self._filterItem(child, text)
show = (showChild or show)
2016-03-23 05:43:59 +03:00
self.tree.setRowHidden(item.row(), item.index().parent(), not show)
return show
elif isinstance(item, QStandardItem):
hide = bool(text) and (text not in item.text().lower())
2016-03-23 05:43:59 +03:00
self.tree.setRowHidden(item.row(), item.index().parent(), hide)
return not hide
2012-09-15 18:25:25 +03:00
def fillTree(self):
self.fillTreeUsingProviders()
def fillTreeUsingProviders(self):
2012-09-15 18:25:25 +03:00
self.items = {}
self.model.clear()
self.model.setHorizontalHeaderLabels([self.tr('Setting'),
self.tr('Value')])
2013-08-12 20:44:27 +02:00
settings = ProcessingConfig.getSettings()
rootItem = self.model.invisibleRootItem()
"""
Filter 'General', 'Models' and 'Scripts' items
"""
priorityKeys = [self.tr('General'), self.tr('Models'), self.tr('Scripts')]
for group in priorityKeys:
groupItem = QStandardItem(group)
2013-08-12 20:44:27 +02:00
icon = ProcessingConfig.getGroupIcon(group)
groupItem.setIcon(icon)
groupItem.setEditable(False)
emptyItem = QStandardItem()
emptyItem.setEditable(False)
rootItem.insertRow(0, [groupItem, emptyItem])
2017-05-15 19:01:15 +10:00
if not group in settings:
continue
# add menu item only if it has any search matches
2012-09-15 18:25:25 +03:00
for setting in settings[group]:
if setting.hidden or setting.name.startswith("MENU_"):
2012-09-15 18:25:25 +03:00
continue
labelItem = QStandardItem(setting.description)
labelItem.setIcon(icon)
labelItem.setEditable(False)
self.items[setting] = SettingItem(setting)
groupItem.insertRow(0, [labelItem, self.items[setting]])
"""
Filter 'Providers' items
"""
providersItem = QStandardItem(self.tr('Providers'))
icon = QgsApplication.getThemeIcon("/processingAlgorithm.svg")
providersItem.setIcon(icon)
providersItem.setEditable(False)
emptyItem = QStandardItem()
emptyItem.setEditable(False)
rootItem.insertRow(0, [providersItem, emptyItem])
2016-09-21 18:24:26 +02:00
for group in list(settings.keys()):
if group in priorityKeys or group == menusSettingsGroup:
continue
groupItem = QStandardItem(group)
2013-08-12 20:44:27 +02:00
icon = ProcessingConfig.getGroupIcon(group)
groupItem.setIcon(icon)
groupItem.setEditable(False)
for setting in settings[group]:
if setting.hidden:
continue
labelItem = QStandardItem(setting.description)
labelItem.setIcon(icon)
labelItem.setEditable(False)
self.items[setting] = SettingItem(setting)
groupItem.insertRow(0, [labelItem, self.items[setting]])
emptyItem = QStandardItem()
emptyItem.setEditable(False)
providersItem.appendRow([groupItem, emptyItem])
"""
Filter 'Menus' items
"""
self.menusItem = QStandardItem(self.tr('Menus'))
icon = QIcon(os.path.join(pluginPath, 'images', 'menu.png'))
self.menusItem.setIcon(icon)
self.menusItem.setEditable(False)
emptyItem = QStandardItem()
emptyItem.setEditable(False)
rootItem.insertRow(0, [self.menusItem, emptyItem])
button = QPushButton(self.tr('Reset to defaults'))
button.clicked.connect(self.resetMenusToDefaults)
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(button)
layout.addStretch()
widget = QWidget()
widget.setLayout(layout)
self.tree.setIndexWidget(emptyItem.index(), widget)
for provider in QgsApplication.processingRegistry().providers():
providerDescription = provider.name()
groupItem = QStandardItem(providerDescription)
icon = provider.icon()
groupItem.setIcon(icon)
groupItem.setEditable(False)
for alg in provider.algorithms():
algItem = QStandardItem(alg.displayName())
algItem.setIcon(icon)
algItem.setEditable(False)
try:
settingMenu = ProcessingConfig.settings["MENU_" + alg.id()]
settingButton = ProcessingConfig.settings["BUTTON_" + alg.id()]
settingIcon = ProcessingConfig.settings["ICON_" + alg.id()]
except:
continue
self.items[settingMenu] = SettingItem(settingMenu)
self.items[settingButton] = SettingItem(settingButton)
self.items[settingIcon] = SettingItem(settingIcon)
menuLabelItem = QStandardItem("Menu path")
menuLabelItem.setEditable(False)
buttonLabelItem = QStandardItem("Add button in toolbar")
buttonLabelItem.setEditable(False)
iconLabelItem = QStandardItem("Icon")
iconLabelItem.setEditable(False)
emptyItem = QStandardItem()
emptyItem.setEditable(False)
algItem.insertRow(0, [menuLabelItem, self.items[settingMenu]])
algItem.insertRow(0, [buttonLabelItem, self.items[settingButton]])
algItem.insertRow(0, [iconLabelItem, self.items[settingIcon]])
groupItem.insertRow(0, [algItem, emptyItem])
emptyItem = QStandardItem()
emptyItem.setEditable(False)
self.menusItem.appendRow([groupItem, emptyItem])
self.tree.sortByColumn(0, Qt.AscendingOrder)
self.adjustColumns()
2012-09-15 18:25:25 +03:00
def resetMenusToDefaults(self):
for provider in QgsApplication.processingRegistry().providers():
for alg in provider.algorithms():
d = defaultMenuEntries.get(alg.id(), "")
setting = ProcessingConfig.settings["MENU_" + alg.id()]
item = self.items[setting]
item.setData(d, Qt.EditRole)
self.saveMenus = True
def accept(self):
qsettings = QgsSettings()
2016-09-21 18:24:26 +02:00
for setting in list(self.items.keys()):
if setting.group != menusSettingsGroup or self.saveMenus:
if isinstance(setting.value, bool):
setting.setValue(self.items[setting].checkState() == Qt.Checked)
else:
try:
setting.setValue(str(self.items[setting].text()))
except ValueError as e:
QMessageBox.warning(self, self.tr('Wrong value'),
2017-03-04 16:23:36 +01:00
self.tr('Wrong value for parameter "{0}":\n\n{1}').format(setting.description, str(e)))
return
setting.save(qsettings)
2017-07-30 21:51:22 +02:00
with OverrideCursor(Qt.WaitCursor):
for p in QgsApplication.processingRegistry().providers():
p.refreshAlgorithms()
settingsWatcher.settingsChanged.emit()
2012-09-15 18:25:25 +03:00
def itemExpanded(self, idx):
if idx == self.menusItem.index():
self.saveMenus = True
self.adjustColumns()
def adjustColumns(self):
self.tree.resizeColumnToContents(0)
self.tree.resizeColumnToContents(1)
2012-09-15 18:25:25 +03:00
class SettingItem(QStandardItem):
def __init__(self, setting):
QStandardItem.__init__(self)
2012-09-15 18:25:25 +03:00
self.setting = setting
self.setData(setting, Qt.UserRole)
if isinstance(setting.value, bool):
self.setCheckable(True)
self.setEditable(False)
2012-09-15 18:25:25 +03:00
if setting.value:
self.setCheckState(Qt.Checked)
else:
self.setCheckState(Qt.Unchecked)
else:
self.setData(setting.value, Qt.EditRole)
class SettingDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
def createEditor(self, parent, options, index):
setting = index.model().data(index, Qt.UserRole)
if setting.valuetype == Setting.FOLDER:
return FileDirectorySelector(parent)
elif setting.valuetype == Setting.FILE:
return FileDirectorySelector(parent, True)
elif setting.valuetype == Setting.SELECTION:
combo = QComboBox(parent)
combo.addItems(setting.options)
return combo
elif setting.valuetype == Setting.MULTIPLE_FOLDERS:
return MultipleDirectorySelector(parent)
else:
value = self.convertValue(index.model().data(index, Qt.EditRole))
2016-09-21 18:24:26 +02:00
if isinstance(value, int):
spnBox = QgsSpinBox(parent)
spnBox.setRange(-999999999, 999999999)
return spnBox
elif isinstance(value, float):
spnBox = QgsDoubleSpinBox(parent)
spnBox.setRange(-999999999.999999, 999999999.999999)
spnBox.setDecimals(6)
return spnBox
2016-09-21 18:24:26 +02:00
elif isinstance(value, str):
return QLineEdit(parent)
def setEditorData(self, editor, index):
value = self.convertValue(index.model().data(index, Qt.EditRole))
setting = index.model().data(index, Qt.UserRole)
if setting.valuetype == Setting.SELECTION:
editor.setCurrentIndex(editor.findText(value))
else:
editor.setText(value)
def setModelData(self, editor, model, index):
value = self.convertValue(index.model().data(index, Qt.EditRole))
setting = index.model().data(index, Qt.UserRole)
if setting.valuetype == Setting.SELECTION:
model.setData(index, editor.currentText(), Qt.EditRole)
else:
2016-09-21 18:24:26 +02:00
if isinstance(value, str):
model.setData(index, editor.text(), Qt.EditRole)
else:
model.setData(index, editor.value(), Qt.EditRole)
def sizeHint(self, option, index):
return QgsSpinBox().sizeHint()
def eventFilter(self, editor, event):
if event.type() == QEvent.FocusOut and hasattr(editor, 'canFocusOut'):
if not editor.canFocusOut:
return False
return QStyledItemDelegate.eventFilter(self, editor, event)
def convertValue(self, value):
2016-05-13 17:49:09 +02:00
if value is None or value == NULL:
return ""
try:
return int(value)
except:
try:
return float(value)
except:
2016-09-21 18:24:26 +02:00
return str(value)
class FileDirectorySelector(QWidget):
def __init__(self, parent=None, selectFile=False):
QWidget.__init__(self, parent)
# create gui
self.btnSelect = QToolButton()
self.btnSelect.setText(self.tr('...'))
self.lineEdit = QLineEdit()
self.hbl = QHBoxLayout()
self.hbl.setMargin(0)
self.hbl.setSpacing(0)
self.hbl.addWidget(self.lineEdit)
self.hbl.addWidget(self.btnSelect)
self.setLayout(self.hbl)
self.canFocusOut = False
self.selectFile = selectFile
self.setFocusPolicy(Qt.StrongFocus)
self.btnSelect.clicked.connect(self.select)
def select(self):
lastDir = ''
if not self.selectFile:
selectedPath = QFileDialog.getExistingDirectory(None,
self.tr('Select directory'), lastDir,
QFileDialog.ShowDirsOnly)
2012-09-15 18:25:25 +03:00
else:
selectedPath, selected_filter = QFileDialog.getOpenFileName(None,
self.tr('Select file'), lastDir, self.tr('All files (*.*)')
)
if not selectedPath:
return
self.lineEdit.setText(selectedPath)
self.canFocusOut = True
def text(self):
return self.lineEdit.text()
def setText(self, value):
self.lineEdit.setText(value)
class MultipleDirectorySelector(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
# create gui
self.btnSelect = QToolButton()
self.btnSelect.setText(self.tr('...'))
self.lineEdit = QLineEdit()
self.hbl = QHBoxLayout()
self.hbl.setMargin(0)
self.hbl.setSpacing(0)
self.hbl.addWidget(self.lineEdit)
self.hbl.addWidget(self.btnSelect)
self.setLayout(self.hbl)
self.canFocusOut = False
self.setFocusPolicy(Qt.StrongFocus)
self.btnSelect.clicked.connect(self.select)
def select(self):
text = self.lineEdit.text()
if text != '':
items = text.split(';')
dlg = DirectorySelectorDialog(None, items)
if dlg.exec_():
text = dlg.value()
self.lineEdit.setText(text)
self.canFocusOut = True
def text(self):
return self.lineEdit.text()
def setText(self, value):
self.lineEdit.setText(value)