2013-10-23 20:13:59 +03:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
"""
|
|
|
|
***************************************************************************
|
|
|
|
FieldsCalculatorDialog.py
|
|
|
|
---------------------
|
|
|
|
Date : October 2013
|
|
|
|
Copyright : (C) 2013 by Alexander Bruy
|
|
|
|
Email : alexander dot bruy 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
|
2013-10-23 20:13:59 +03:00
|
|
|
|
|
|
|
__author__ = 'Alexander Bruy'
|
|
|
|
__date__ = 'October 2013'
|
|
|
|
__copyright__ = '(C) 2013, Alexander Bruy'
|
|
|
|
|
|
|
|
# This will get replaced with a git SHA1 when you do a git archive
|
|
|
|
|
|
|
|
__revision__ = '$Format:%H$'
|
|
|
|
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
|
2016-04-29 11:39:26 +02:00
|
|
|
from qgis.PyQt import uic
|
2017-03-03 20:39:17 +01:00
|
|
|
from qgis.PyQt.QtCore import Qt
|
2016-04-22 10:38:48 +02:00
|
|
|
from qgis.PyQt.QtWidgets import QDialog, QFileDialog, QApplication, QMessageBox
|
|
|
|
from qgis.PyQt.QtGui import QCursor
|
2017-03-03 20:39:17 +01:00
|
|
|
from qgis.core import (QgsExpressionContextUtils,
|
|
|
|
QgsProcessingFeedback,
|
2017-04-05 14:37:06 +10:00
|
|
|
QgsSettings,
|
|
|
|
QgsProcessingUtils,
|
2017-04-24 14:35:50 +10:00
|
|
|
QgsMapLayerProxyModel,
|
|
|
|
QgsMessageLog)
|
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
|
|
|
from qgis.gui import QgsEncodingFileDialog
|
2013-10-23 20:13:59 +03:00
|
|
|
|
|
|
|
from processing.core.ProcessingConfig import ProcessingConfig
|
|
|
|
from processing.core.ProcessingLog import ProcessingLog
|
2017-03-22 17:17:14 +02:00
|
|
|
from processing.gui.AlgorithmExecutor import execute
|
2013-10-23 20:13:59 +03:00
|
|
|
from processing.tools import dataobjects
|
2014-06-10 19:34:45 +02:00
|
|
|
from processing.gui.Postprocessing import handleAlgorithmResults
|
2013-10-23 20:13:59 +03:00
|
|
|
|
2015-05-18 21:04:20 +03:00
|
|
|
pluginPath = os.path.dirname(__file__)
|
|
|
|
WIDGET, BASE = uic.loadUiType(
|
|
|
|
os.path.join(pluginPath, 'DlgFieldsCalculator.ui'))
|
2013-10-23 20:13:59 +03:00
|
|
|
|
|
|
|
|
2017-01-06 20:04:00 +10:00
|
|
|
class FieldCalculatorFeedback(QgsProcessingFeedback):
|
|
|
|
"""
|
|
|
|
Directs algorithm feedback to an algorithm dialog
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, dialog):
|
|
|
|
QgsProcessingFeedback.__init__(self)
|
|
|
|
self.dialog = dialog
|
|
|
|
|
|
|
|
def reportError(self, msg):
|
|
|
|
self.dialog.error(msg)
|
|
|
|
|
|
|
|
|
2015-05-18 21:04:20 +03:00
|
|
|
class FieldsCalculatorDialog(BASE, WIDGET):
|
2015-08-22 14:29:41 +02:00
|
|
|
|
2013-10-23 20:13:59 +03:00
|
|
|
def __init__(self, alg):
|
2015-05-18 21:04:20 +03:00
|
|
|
super(FieldsCalculatorDialog, self).__init__(None)
|
2014-11-21 09:10:08 +01:00
|
|
|
self.setupUi(self)
|
2013-10-23 20:13:59 +03:00
|
|
|
|
2017-01-06 20:04:00 +10:00
|
|
|
self.feedback = FieldCalculatorFeedback(self)
|
2017-03-28 14:32:55 +10:00
|
|
|
self.feedback.progressChanged.connect(self.setPercentage)
|
2017-01-06 20:04:00 +10:00
|
|
|
|
2013-10-23 20:13:59 +03:00
|
|
|
self.executed = False
|
|
|
|
self.alg = alg
|
|
|
|
self.layer = None
|
|
|
|
|
2017-04-05 18:35:40 +10:00
|
|
|
self.cmbInputLayer.setFilters(QgsMapLayerProxyModel.VectorLayer)
|
|
|
|
self.cmbInputLayer.layerChanged.connect(self.updateLayer)
|
2013-10-23 20:13:59 +03:00
|
|
|
self.btnBrowse.clicked.connect(self.selectFile)
|
|
|
|
self.mNewFieldGroupBox.toggled.connect(self.toggleExistingGroup)
|
|
|
|
self.mUpdateExistingGroupBox.toggled.connect(self.toggleNewGroup)
|
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
|
|
|
self.mOutputFieldTypeComboBox.currentIndexChanged.connect(self.setupSpinboxes)
|
2013-10-23 20:13:59 +03:00
|
|
|
|
|
|
|
# Default values for field width and precision
|
|
|
|
self.mOutputFieldWidthSpinBox.setValue(10)
|
|
|
|
self.mOutputFieldPrecisionSpinBox.setValue(3)
|
|
|
|
|
|
|
|
# Output is a shapefile, so limit maximum field name length
|
|
|
|
self.mOutputFieldNameLineEdit.setMaxLength(10)
|
|
|
|
|
|
|
|
self.manageGui()
|
|
|
|
|
|
|
|
def manageGui(self):
|
2014-03-26 19:25:07 +02:00
|
|
|
if hasattr(self.leOutputFile, 'setPlaceholderText'):
|
|
|
|
self.leOutputFile.setPlaceholderText(
|
|
|
|
self.tr('[Save to temporary file]'))
|
|
|
|
|
2013-10-23 20:13:59 +03:00
|
|
|
self.mOutputFieldTypeComboBox.blockSignals(True)
|
2015-10-12 09:30:25 +02:00
|
|
|
for t in self.alg.type_names:
|
2013-10-23 20:13:59 +03:00
|
|
|
self.mOutputFieldTypeComboBox.addItem(t)
|
|
|
|
self.mOutputFieldTypeComboBox.blockSignals(False)
|
2015-05-20 11:08:42 +03:00
|
|
|
self.builder.loadRecent('fieldcalc')
|
|
|
|
|
2016-09-29 13:36:29 +02:00
|
|
|
self.initContext()
|
2017-04-05 18:35:40 +10:00
|
|
|
self.updateLayer(self.cmbInputLayer.currentLayer())
|
2013-10-23 20:13:59 +03:00
|
|
|
|
2016-09-29 13:36:29 +02:00
|
|
|
def initContext(self):
|
|
|
|
exp_context = self.builder.expressionContext()
|
2017-01-06 10:21:47 +08:00
|
|
|
exp_context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(self.layer))
|
2016-02-28 12:45:43 +11:00
|
|
|
exp_context.lastScope().setVariable("row_number", 1)
|
|
|
|
exp_context.setHighlightedVariables(["row_number"])
|
|
|
|
self.builder.setExpressionContext(exp_context)
|
2016-10-22 09:03:24 +10:00
|
|
|
|
2017-04-05 18:35:40 +10:00
|
|
|
def updateLayer(self, layer):
|
|
|
|
self.layer = layer
|
2016-09-29 13:36:29 +02:00
|
|
|
self.builder.setLayer(self.layer)
|
|
|
|
self.builder.loadFieldNames()
|
2013-10-23 20:13:59 +03:00
|
|
|
self.populateFields()
|
|
|
|
|
|
|
|
def setupSpinboxes(self, index):
|
|
|
|
if index != 0:
|
|
|
|
self.mOutputFieldPrecisionSpinBox.setEnabled(False)
|
|
|
|
else:
|
|
|
|
self.mOutputFieldPrecisionSpinBox.setEnabled(True)
|
|
|
|
|
|
|
|
if index == 0:
|
|
|
|
self.mOutputFieldWidthSpinBox.setRange(1, 20)
|
|
|
|
self.mOutputFieldWidthSpinBox.setValue(10)
|
|
|
|
self.mOutputFieldPrecisionSpinBox.setRange(0, 15)
|
|
|
|
self.mOutputFieldPrecisionSpinBox.setValue(3)
|
|
|
|
elif index == 1:
|
|
|
|
self.mOutputFieldWidthSpinBox.setRange(1, 10)
|
|
|
|
self.mOutputFieldWidthSpinBox.setValue(10)
|
|
|
|
elif index == 2:
|
|
|
|
self.mOutputFieldWidthSpinBox.setRange(1, 255)
|
|
|
|
self.mOutputFieldWidthSpinBox.setValue(80)
|
|
|
|
else:
|
|
|
|
self.mOutputFieldWidthSpinBox.setEnabled(False)
|
|
|
|
self.mOutputFieldPrecisionSpinBox.setEnabled(False)
|
|
|
|
|
|
|
|
def selectFile(self):
|
|
|
|
output = self.alg.getOutputFromName('OUTPUT_LAYER')
|
|
|
|
fileFilter = output.getFileFilter(self.alg)
|
|
|
|
|
2017-03-03 20:39:17 +01:00
|
|
|
settings = QgsSettings()
|
2013-10-23 20:13:59 +03:00
|
|
|
if settings.contains('/Processing/LastOutputPath'):
|
|
|
|
path = settings.value('/Processing/LastOutputPath')
|
|
|
|
else:
|
|
|
|
path = ProcessingConfig.getSetting(ProcessingConfig.OUTPUT_FOLDER)
|
|
|
|
lastEncoding = settings.value('/Processing/encoding', 'System')
|
|
|
|
fileDialog = QgsEncodingFileDialog(self,
|
|
|
|
self.tr('Save file'),
|
|
|
|
path,
|
|
|
|
fileFilter,
|
|
|
|
lastEncoding)
|
|
|
|
fileDialog.setFileMode(QFileDialog.AnyFile)
|
|
|
|
fileDialog.setAcceptMode(QFileDialog.AcceptSave)
|
2016-10-04 15:45:10 +07:00
|
|
|
fileDialog.setOption(QFileDialog.DontConfirmOverwrite, False)
|
2013-10-23 20:13:59 +03:00
|
|
|
if fileDialog.exec_() == QDialog.Accepted:
|
|
|
|
files = fileDialog.selectedFiles()
|
2016-09-21 18:24:26 +02:00
|
|
|
encoding = str(fileDialog.encoding())
|
2013-10-23 20:13:59 +03:00
|
|
|
output.encoding = encoding
|
2016-09-21 18:24:26 +02:00
|
|
|
filename = str(files[0])
|
|
|
|
selectedFileFilter = str(fileDialog.selectedNameFilter())
|
2013-10-23 20:13:59 +03:00
|
|
|
if not filename.lower().endswith(
|
2015-06-22 09:52:42 +02:00
|
|
|
tuple(re.findall("\*(\.[a-z]{1,10})", fileFilter))):
|
|
|
|
ext = re.search("\*(\.[a-z]{1,10})", selectedFileFilter)
|
2013-10-23 20:13:59 +03:00
|
|
|
if ext:
|
|
|
|
filename = filename + ext.group(1)
|
|
|
|
self.leOutputFile.setText(filename)
|
|
|
|
settings.setValue('/Processing/LastOutputPath',
|
|
|
|
os.path.dirname(filename))
|
|
|
|
settings.setValue('/Processing/encoding', encoding)
|
|
|
|
|
|
|
|
def toggleExistingGroup(self, toggled):
|
|
|
|
self.mUpdateExistingGroupBox.setChecked(not toggled)
|
|
|
|
|
|
|
|
def toggleNewGroup(self, toggled):
|
|
|
|
self.mNewFieldGroupBox.setChecked(not toggled)
|
|
|
|
|
|
|
|
def populateFields(self):
|
|
|
|
if self.layer is None:
|
|
|
|
return
|
2016-10-27 14:30:18 +02:00
|
|
|
|
2016-10-27 14:28:36 +02:00
|
|
|
self.mExistingFieldComboBox.clear()
|
2016-08-04 07:37:22 +10:00
|
|
|
fields = self.layer.fields()
|
2013-10-23 20:13:59 +03:00
|
|
|
for f in fields:
|
|
|
|
self.mExistingFieldComboBox.addItem(f.name())
|
|
|
|
|
|
|
|
def setParamValues(self):
|
|
|
|
if self.mUpdateExistingGroupBox.isChecked():
|
|
|
|
fieldName = self.mExistingFieldComboBox.currentText()
|
|
|
|
else:
|
|
|
|
fieldName = self.mOutputFieldNameLineEdit.text()
|
|
|
|
|
2017-04-05 18:35:40 +10:00
|
|
|
layer = self.cmbInputLayer.currentLayer()
|
2013-10-23 20:13:59 +03:00
|
|
|
|
|
|
|
self.alg.setParameterValue('INPUT_LAYER', layer)
|
|
|
|
self.alg.setParameterValue('FIELD_NAME', fieldName)
|
|
|
|
self.alg.setParameterValue('FIELD_TYPE',
|
2015-08-22 14:29:41 +02:00
|
|
|
self.mOutputFieldTypeComboBox.currentIndex())
|
2013-10-23 20:13:59 +03:00
|
|
|
self.alg.setParameterValue('FIELD_LENGTH',
|
2015-08-22 14:29:41 +02:00
|
|
|
self.mOutputFieldWidthSpinBox.value())
|
2013-10-23 20:13:59 +03:00
|
|
|
self.alg.setParameterValue('FIELD_PRECISION',
|
2015-08-22 14:29:41 +02:00
|
|
|
self.mOutputFieldPrecisionSpinBox.value())
|
2013-10-23 20:13:59 +03:00
|
|
|
self.alg.setParameterValue('NEW_FIELD',
|
2015-08-22 14:29:41 +02:00
|
|
|
self.mNewFieldGroupBox.isChecked())
|
2013-10-23 20:13:59 +03:00
|
|
|
self.alg.setParameterValue('FORMULA', self.builder.expressionText())
|
2015-06-22 09:52:42 +02:00
|
|
|
self.alg.setOutputValue('OUTPUT_LAYER', self.leOutputFile.text().strip() or None)
|
2015-04-28 09:19:58 +02:00
|
|
|
|
|
|
|
msg = self.alg.checkParameterValuesBeforeExecuting()
|
|
|
|
if msg:
|
|
|
|
QMessageBox.warning(
|
|
|
|
self, self.tr('Unable to execute algorithm'), msg)
|
|
|
|
return False
|
2013-10-23 20:13:59 +03:00
|
|
|
return True
|
|
|
|
|
|
|
|
def accept(self):
|
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
|
|
|
keepOpen = ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN)
|
2013-10-23 20:13:59 +03:00
|
|
|
try:
|
|
|
|
if self.setParamValues():
|
|
|
|
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
2017-04-24 14:35:50 +10:00
|
|
|
ProcessingLog.addToLog(self.alg.getAsCommand())
|
2014-11-21 09:10:08 +01:00
|
|
|
|
2017-04-26 14:33:53 +10:00
|
|
|
context = dataobjects.createContext()
|
|
|
|
self.executed = execute(self.alg, context, self.feedback)
|
2014-11-21 09:10:08 +01:00
|
|
|
if self.executed:
|
2014-06-10 19:34:45 +02:00
|
|
|
handleAlgorithmResults(self.alg,
|
2017-04-26 14:33:53 +10:00
|
|
|
context,
|
2017-01-06 20:04:00 +10:00
|
|
|
self.feedback,
|
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
|
|
|
not keepOpen)
|
2014-11-21 09:10:08 +01:00
|
|
|
if not keepOpen:
|
|
|
|
QDialog.reject(self)
|
|
|
|
finally:
|
2013-10-23 20:13:59 +03:00
|
|
|
QApplication.restoreOverrideCursor()
|
|
|
|
|
|
|
|
def reject(self):
|
|
|
|
self.executed = False
|
|
|
|
QDialog.reject(self)
|
|
|
|
|
|
|
|
def setPercentage(self, i):
|
|
|
|
self.progressBar.setValue(i)
|
|
|
|
|
|
|
|
def error(self, text):
|
2014-11-21 09:10:08 +01:00
|
|
|
QMessageBox.critical(self, "Error", text)
|
2017-04-26 12:52:23 +10:00
|
|
|
QgsMessageLog.logMessage(text, self.tr('Processing'), QgsMessageLog.CRITICAL)
|