QGIS/python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py
2016-10-27 14:36:31 +02:00

240 lines
9.4 KiB
Python

# -*- 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. *
* *
***************************************************************************
"""
from builtins import str
__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
from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt, QSettings
from qgis.PyQt.QtWidgets import QDialog, QFileDialog, QApplication, QMessageBox
from qgis.PyQt.QtGui import QCursor
from qgis.core import QgsExpressionContext, QgsExpressionContextUtils
from qgis.gui import QgsEncodingFileDialog
from processing.core.ProcessingConfig import ProcessingConfig
from processing.core.ProcessingLog import ProcessingLog
from processing.gui.AlgorithmExecutor import runalg
from processing.tools import dataobjects
from processing.gui.Postprocessing import handleAlgorithmResults
pluginPath = os.path.dirname(__file__)
WIDGET, BASE = uic.loadUiType(
os.path.join(pluginPath, 'DlgFieldsCalculator.ui'))
class FieldsCalculatorDialog(BASE, WIDGET):
def __init__(self, alg):
super(FieldsCalculatorDialog, self).__init__(None)
self.setupUi(self)
self.executed = False
self.alg = alg
self.layer = None
self.cmbInputLayer.currentIndexChanged.connect(self.updateLayer)
self.btnBrowse.clicked.connect(self.selectFile)
self.mNewFieldGroupBox.toggled.connect(self.toggleExistingGroup)
self.mUpdateExistingGroupBox.toggled.connect(self.toggleNewGroup)
self.mOutputFieldTypeComboBox.currentIndexChanged.connect(self.setupSpinboxes)
# 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):
if hasattr(self.leOutputFile, 'setPlaceholderText'):
self.leOutputFile.setPlaceholderText(
self.tr('[Save to temporary file]'))
self.mOutputFieldTypeComboBox.blockSignals(True)
for t in self.alg.type_names:
self.mOutputFieldTypeComboBox.addItem(t)
self.mOutputFieldTypeComboBox.blockSignals(False)
self.cmbInputLayer.blockSignals(True)
layers = dataobjects.getVectorLayers()
for layer in layers:
self.cmbInputLayer.addItem(layer.name())
self.cmbInputLayer.blockSignals(False)
self.builder.loadRecent('fieldcalc')
self.initContext()
self.updateLayer()
def initContext(self):
exp_context = self.builder.expressionContext()
exp_context.appendScope(QgsExpressionContextUtils.globalScope())
exp_context.appendScope(QgsExpressionContextUtils.projectScope())
exp_context.appendScope(QgsExpressionContextUtils.layerScope(self.layer))
exp_context.lastScope().setVariable("row_number", 1)
exp_context.setHighlightedVariables(["row_number"])
self.builder.setExpressionContext(exp_context)
def updateLayer(self):
self.layer = dataobjects.getObject(self.cmbInputLayer.currentText())
self.builder.setLayer(self.layer)
self.builder.loadFieldNames()
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)
settings = QSettings()
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)
fileDialog.setOption(QFileDialog.DontConfirmOverwrite, False)
if fileDialog.exec_() == QDialog.Accepted:
files = fileDialog.selectedFiles()
encoding = str(fileDialog.encoding())
output.encoding = encoding
filename = str(files[0])
selectedFileFilter = str(fileDialog.selectedNameFilter())
if not filename.lower().endswith(
tuple(re.findall("\*(\.[a-z]{1,10})", fileFilter))):
ext = re.search("\*(\.[a-z]{1,10})", selectedFileFilter)
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
self.mExistingFieldComboBox.clear()
fields = self.layer.fields()
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()
layer = dataobjects.getObjectFromName(self.cmbInputLayer.currentText())
self.alg.setParameterValue('INPUT_LAYER', layer)
self.alg.setParameterValue('FIELD_NAME', fieldName)
self.alg.setParameterValue('FIELD_TYPE',
self.mOutputFieldTypeComboBox.currentIndex())
self.alg.setParameterValue('FIELD_LENGTH',
self.mOutputFieldWidthSpinBox.value())
self.alg.setParameterValue('FIELD_PRECISION',
self.mOutputFieldPrecisionSpinBox.value())
self.alg.setParameterValue('NEW_FIELD',
self.mNewFieldGroupBox.isChecked())
self.alg.setParameterValue('FORMULA', self.builder.expressionText())
self.alg.setOutputValue('OUTPUT_LAYER', self.leOutputFile.text().strip() or None)
msg = self.alg.checkParameterValuesBeforeExecuting()
if msg:
QMessageBox.warning(
self, self.tr('Unable to execute algorithm'), msg)
return False
return True
def accept(self):
keepOpen = ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN)
try:
if self.setParamValues():
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
ProcessingLog.addToLog(ProcessingLog.LOG_ALGORITHM,
self.alg.getAsCommand())
self.executed = runalg(self.alg, self)
if self.executed:
handleAlgorithmResults(self.alg,
self,
not keepOpen)
if not keepOpen:
QDialog.reject(self)
finally:
QApplication.restoreOverrideCursor()
def reject(self):
self.executed = False
QDialog.reject(self)
def setPercentage(self, i):
self.progressBar.setValue(i)
def setText(self, text):
pass
def error(self, text):
QMessageBox.critical(self, "Error", text)
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, text)