Create FieldMapper GeoAlgorithm

This commit is contained in:
arnaud.morvan@camptocamp.com 2015-01-22 14:52:52 +01:00
parent 88c928af56
commit 9e51488a88
8 changed files with 1056 additions and 0 deletions

View File

@ -478,6 +478,7 @@
<file>themes/default/cadtools/perpendicular.png</file>
<file>themes/default/mIconSuccess.png</file>
<file>themes/default/bubble.svg</file>
<file>themes/default/mIconClear.png</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>

View File

@ -0,0 +1,137 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
FieldsMapper.py
---------------------
Date : October 2014
Copyright : (C) 2014 by Arnaud Morvan
Email : arnaud dot morvan at camptocamp 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__ = 'Arnaud Morvan'
__date__ = 'October 2014'
__copyright__ = '(C) 2014, Arnaud Morvan'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from qgis.core import QgsField, QgsExpression, QgsFeature
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import \
GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector
from .fieldsmapping import ParameterFieldsMapping
from .ui.FieldsMapperDialogs import (FieldsMapperParametersDialog,
FieldsMapperModelerParametersDialog)
class FieldsMapper(GeoAlgorithm):
INPUT_LAYER = 'INPUT_LAYER'
FIELDS_MAPPING = 'FIELDS_MAPPING'
OUTPUT_LAYER = 'OUTPUT_LAYER'
def __init__(self):
GeoAlgorithm.__init__(self)
self.mapping = None
def defineCharacteristics(self):
self.name = 'Refactor fields'
self.group = 'Vector table tools'
self.addParameter(ParameterVector(self.INPUT_LAYER,
self.tr('Input layer'),
[ParameterVector.VECTOR_TYPE_ANY], False))
self.addParameter(ParameterFieldsMapping(self.FIELDS_MAPPING,
self.tr('Fields mapping'), self.INPUT_LAYER))
self.addOutput(OutputVector(self.OUTPUT_LAYER,
self.tr('Output layer')))
def getCustomParametersDialog(self):
return FieldsMapperParametersDialog(self)
def getCustomModelerParametersDialog(self, modelAlg, algIndex=None):
return FieldsMapperModelerParametersDialog(self, modelAlg, algIndex)
def processAlgorithm(self, progress):
layer = self.getParameterValue(self.INPUT_LAYER)
mapping = self.getParameterValue(self.FIELDS_MAPPING)
output = self.getOutputFromName(self.OUTPUT_LAYER)
layer = dataobjects.getObjectFromUri(layer)
provider = layer.dataProvider()
fields = []
expressions = []
for field_def in mapping:
fields.append(QgsField(name=field_def['name'],
type=field_def['type'],
len=field_def['length'],
prec=field_def['precision']))
expression = QgsExpression(field_def['expression'])
if expression.hasParserError():
raise GeoAlgorithmExecutionException(
self.tr(u'Parser error in expression "{}": {}')
.format(unicode(field_def['expression']),
unicode(expression.parserErrorString())))
expression.prepare(provider.fields())
if expression.hasEvalError():
raise GeoAlgorithmExecutionException(
self.tr(u'Evaluation error in expression "{}": {}')
.format(unicode(field_def['expression']),
unicode(expression.evalErrorString())))
expressions.append(expression)
writer = output.getVectorWriter(fields,
provider.geometryType(),
layer.crs())
# Create output vector layer with new attributes
error = ''
calculationSuccess = True
inFeat = QgsFeature()
outFeat = QgsFeature()
features = vector.features(layer)
count = len(features)
for current, inFeat in enumerate(features):
rownum = current + 1
outFeat.setGeometry(inFeat.geometry())
attrs = []
for i in xrange(0, len(mapping)):
field_def = mapping[i]
expression = expressions[i]
expression.setCurrentRowNumber(rownum)
value = expression.evaluate(inFeat)
if expression.hasEvalError():
calculationSuccess = False
error = expression.evalErrorString()
break
attrs.append(value)
outFeat.setAttributes(attrs)
writer.addFeature(outFeat)
current += 1
progress.setPercentage(100 * current / float(count))
del writer
if not calculationSuccess:
raise GeoAlgorithmExecutionException(
self.tr('An error occurred while evaluating the calculation'
' string:\n') + error)

View File

@ -125,6 +125,7 @@ from SetRasterStyle import SetRasterStyle
from SelectByExpression import SelectByExpression
from HypsometricCurves import HypsometricCurves
from SplitLinesWithLines import SplitLinesWithLines
from processing.algs.qgis.FieldsMapper import FieldsMapper
import processing.resources_rc
@ -171,6 +172,7 @@ class QGISAlgorithmProvider(AlgorithmProvider):
SetVectorStyle(), SetRasterStyle(),
SelectByExpression(), HypsometricCurves(),
SplitLinesWithLines(), CreateConstantRaster(),
FieldsMapper(),
]
if hasMatplotlib:

View File

@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
FieldsMapper.py
---------------------
Date : October 2014
Copyright : (C) 2014 by Arnaud Morvan
Email : arnaud dot morvan at camptocamp 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__ = 'Arnaud Morvan'
__date__ = 'October 2014'
__copyright__ = '(C) 2014, Arnaud Morvan'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from processing.core.parameters import Parameter
class ParameterFieldsMapping(Parameter):
def __init__(self, name='', description='', parent=None):
Parameter.__init__(self, name, description)
self.parent = parent
self.value = []
def getValueAsCommandLineParameter(self):
return '"' + unicode(self.value) + '"'
def setValue(self, value):
if value is None:
return False
if isinstance(value, list):
self.value = value
return True
if isinstance(value, unicode):
try:
self.value = eval(value)
return True
except Exception as e:
print unicode(e) # display error in console
return False
return False

View File

@ -0,0 +1,140 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
FieldsMapper.py
---------------------
Date : October 2014
Copyright : (C) 2014 by Arnaud Morvan
Email : arnaud dot morvan at camptocamp 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__ = 'Arnaud Morvan'
__date__ = 'October 2014'
__copyright__ = '(C) 2014, Arnaud Morvan'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from PyQt4.QtGui import QComboBox, QSpacerItem
from processing.core.parameters import ParameterVector
from processing.tools import dataobjects
from processing.gui.ParametersPanel import ParametersPanel
from processing.gui.AlgorithmDialog import AlgorithmDialog, AlgorithmDialogBase
from processing.modeler.ModelerParametersDialog import ModelerParametersDialog
from processing.algs.qgis.fieldsmapping import ParameterFieldsMapping
from .FieldsMappingPanel import FieldsMappingPanel
class FieldsMapperParametersPanel(ParametersPanel):
def __init__(self, parent, alg):
ParametersPanel.__init__(self, parent, alg)
item = self.layoutMain.itemAt(self.layoutMain.count() - 1)
if isinstance(item, QSpacerItem):
self.layoutMain.removeItem(item)
item = None
def getWidgetFromParameter(self, param):
if isinstance(param, ParameterFieldsMapping):
item = FieldsMappingPanel()
if param.parent in self.dependentItems:
items = self.dependentItems[param.parent]
else:
items = []
self.dependentItems[param.parent] = items
items.append(param.name)
parent = self.alg.getParameterFromName(param.parent)
if isinstance(parent, ParameterVector):
layers = dataobjects.getVectorLayers(parent.shapetype)
else:
layers = dataobjects.getTables()
if len(layers) > 0:
item.setLayer(layers[0])
return item
return ParametersPanel.getWidgetFromParameter(self, param)
def updateDependentFields(self):
sender = self.sender()
if not isinstance(sender, QComboBox):
return
if not sender.name in self.dependentItems:
return
layer = sender.itemData(sender.currentIndex())
children = self.dependentItems[sender.name]
for child in children:
widget = self.valueItems[child]
if isinstance(widget, FieldsMappingPanel):
widget.setLayer(layer)
def somethingDependsOnThisParameter(self, parent):
for param in self.alg.parameters:
if isinstance(param, ParameterFieldsMapping):
if param.parent == parent.name:
return True
return False
class FieldsMapperParametersDialog(AlgorithmDialog):
def __init__(self, alg):
AlgorithmDialogBase.__init__(self, alg)
self.alg = alg
self.mainWidget = FieldsMapperParametersPanel(self, alg)
self.setMainWidget()
def setParamValue(self, param, widget, alg=None):
if isinstance(param, ParameterFieldsMapping):
return param.setValue(widget.value())
return AlgorithmDialog.setParamValue(self, param, widget, alg)
class FieldsMapperModelerParametersDialog(ModelerParametersDialog):
def __init__(self, alg, model, algName=None):
ModelerParametersDialog.__init__(self, alg, model, algName)
paramsLayout = self.paramPanel.layout()
item = paramsLayout.itemAt(paramsLayout.count() - 1)
if isinstance(item, QSpacerItem):
paramsLayout.removeItem(item)
item = None
def getWidgetFromParameter(self, param):
if isinstance(param, ParameterFieldsMapping):
return FieldsMappingPanel()
return ModelerParametersDialog.getWidgetFromParameter(self, param)
def setPreviousValues(self):
ModelerParametersDialog.setPreviousValues(self)
if self._algName is not None:
alg = self.model.algs[self._algName]
for param in alg.algorithm.parameters:
if isinstance(param, ParameterFieldsMapping):
widget = self.valueItems[param.name]
value = alg.params[param.name]
if isinstance(value, unicode):
# convert to list because of ModelerAlgorithme.resolveValue behavior with lists
value = eval(value)
widget.setValue(value)
def setParamValue(self, alg, param, widget):
if isinstance(param, ParameterFieldsMapping):
# convert to unicode because of ModelerAlgorithme.resolveValue behavior with lists
alg.params[param.name] = unicode(widget.value())
return True
return ModelerParametersDialog.setParamValue(self, alg, param, widget)

View File

@ -0,0 +1,466 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
FieldsMappingWidget.py
---------------------
Date : October 2014
Copyright : (C) 2014 by Arnaud Morvan
Email : arnaud dot morvan at camptocamp 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__ = 'Arnaud Morvan'
__date__ = 'October 2014'
__copyright__ = '(C) 2014, Arnaud Morvan'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from collections import OrderedDict
from PyQt4 import QtCore, QtGui
from qgis.core import QgsExpression
from qgis.gui import QgsFieldExpressionWidget
from processing.tools import dataobjects
from .ui_widgetFieldsMapping import Ui_Form
class FieldsMappingModel(QtCore.QAbstractTableModel):
fieldTypes = OrderedDict([
(QtCore.QVariant.Int, "Integer"),
(QtCore.QVariant.Double, "Double"),
(QtCore.QVariant.String, "String"),
(QtCore.QVariant.Date, "Date")])
columns = [
{'name': 'name', 'type': QtCore.QVariant.String},
{'name': 'type', 'type': QtCore.QVariant.Type},
{'name': 'length', 'type': QtCore.QVariant.Int},
{'name': 'precision', 'type': QtCore.QVariant.Int},
# {'name': 'comment', 'type': QtCore.QVariant.String},
{'name': 'expression', 'type': QgsExpression}]
def __init__(self, parent=None):
super(FieldsMappingModel, self).__init__(parent)
self._mapping = []
self._errors = []
self._layer = None
def mapping(self):
return self._mapping
def setMapping(self, value):
self.beginResetModel()
self._mapping = value
self.testAllExpressions()
self.endResetModel()
def testAllExpressions(self):
self._errors = [None for i in xrange(0, len(self._mapping))]
for row in xrange(0, len(self._mapping)):
self.testExpression(row)
def testExpression(self, row):
self._errors[row] = None
field = self._mapping[row]
expression = QgsExpression(field['expression'])
if expression.hasParserError():
self._errors[row] = expression.parserErrorString()
return
if self._layer is None:
return
dp = self._layer.dataProvider()
for feature in dp.getFeatures():
expression.evaluate(feature, dp.fields())
if expression.hasEvalError():
self._errors[row] = expression.evalErrorString()
return
break
def layer(self):
return self._layer
def setLayer(self, layer):
self._layer = layer
self.testAllExpressions()
def columnCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return len(self.columns)
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return self._mapping.__len__()
def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole:
if orientation == QtCore.Qt.Horizontal:
return self.columns[section]['name'].title()
if orientation == QtCore.Qt.Vertical:
return section
def flags(self, index):
flags = (QtCore.Qt.ItemIsSelectable
+ QtCore.Qt.ItemIsEditable
+ QtCore.Qt.ItemIsEnabled)
return QtCore.Qt.ItemFlags(flags)
def data(self, index, role=QtCore.Qt.DisplayRole):
column = index.column()
if role == QtCore.Qt.DisplayRole:
field = self._mapping[index.row()]
column_def = self.columns[column]
value = field[column_def['name']]
fieldType = column_def['type']
if fieldType == QtCore.QVariant.Type:
if value == 0:
return ''
return self.fieldTypes[value]
return value
if role == QtCore.Qt.EditRole:
field = self._mapping[index.row()]
column_def = self.columns[column]
value = field[column_def['name']]
return value
if role == QtCore.Qt.TextAlignmentRole:
fieldType = self.columns[column]['type']
if fieldType in [QtCore.QVariant.Int]:
hAlign = QtCore.Qt.AlignRight
else:
hAlign = QtCore.Qt.AlignLeft
return hAlign + QtCore.Qt.AlignVCenter
if role == QtCore.Qt.ForegroundRole:
column_def = self.columns[column]
if column_def['name'] == 'expression':
brush = QtGui.QBrush()
if self._errors[index.row()]:
brush.setColor(QtCore.Qt.red)
else:
brush.setColor(QtCore.Qt.black)
return brush
if role == QtCore.Qt.ToolTipRole:
column_def = self.columns[column]
if column_def['name'] == 'expression':
return self._errors[index.row()]
def setData(self, index, value, role=QtCore.Qt.EditRole):
if role == QtCore.Qt.EditRole:
field = self._mapping[index.row()]
column = index.column()
column_def = self.columns[column]
field[column_def['name']] = value
if column_def['name'] == 'expression':
self.testExpression(index.row())
self.dataChanged.emit(index, index)
return True
def insertRows(self, row, count, index=QtCore.QModelIndex()):
self.beginInsertRows(index, row, row + count - 1)
for i in xrange(0, count):
field = self.newField()
self._mapping.insert(row + i, field)
self._errors.insert(row + i, None)
self.testExpression(row)
self.endInsertRows()
return True
def removeRows(self, row, count, index=QtCore.QModelIndex()):
self.beginRemoveRows(index, row, row + count - 1)
for i in xrange(row + count - 1, row + 1):
self._mapping.pop(i)
self._errors.pop(i)
self.endRemoveRows()
return True
def newField(self, field=None):
if field is None:
return {'name': '',
'type': QtCore.QVariant.Invalid,
'length': 0,
'precision': 0,
'expression': ''}
return {'name': field.name(),
'type': field.type(),
'length': field.length(),
'precision': field.precision(),
'expression': field.name()}
def loadLayerFields(self, layer):
self.beginResetModel()
self._mapping = []
if layer is not None:
dp = layer.dataProvider()
for field in dp.fields():
self._mapping.append(self.newField(field))
self.testAllExpressions()
self.endResetModel()
class FieldDelegate(QtGui.QStyledItemDelegate):
def __init__(self, parent=None):
super(FieldDelegate, self).__init__(parent)
def createEditor(self, parent, option, index):
column = index.column()
fieldType = FieldsMappingModel.columns[column]['type']
if fieldType == QtCore.QVariant.Type:
editor = QtGui.QComboBox(parent)
for key, text in FieldsMappingModel.fieldTypes.iteritems():
editor.addItem(text, key)
elif fieldType == QgsExpression:
editor = QgsFieldExpressionWidget(parent)
editor.setLayer(index.model().layer())
# editor.fieldChanged.connect(self.on_expression_fieldChange)
else:
editor = QtGui.QStyledItemDelegate.createEditor(self, parent, option, index)
editor.setAutoFillBackground(True)
return editor
def setEditorData(self, editor, index):
if not editor:
return
column = index.column()
value = index.model().data(index, QtCore.Qt.EditRole)
fieldType = FieldsMappingModel.columns[column]['type']
if fieldType == QtCore.QVariant.Type:
editor.setCurrentIndex(editor.findData(value))
elif fieldType == QgsExpression:
editor.setField(value)
else:
QtGui.QStyledItemDelegate.setEditorData(self, editor, index)
def setModelData(self, editor, model, index):
if not editor:
return
column = index.column()
fieldType = FieldsMappingModel.columns[column]['type']
if fieldType == QtCore.QVariant.Type:
value = editor.itemData(editor.currentIndex())
model.setData(index, value)
elif fieldType == QgsExpression:
(value, isExpression, isValid) = editor.currentField()
model.setData(index, value)
else:
QtGui.QStyledItemDelegate.setModelData(self, editor, model, index)
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
def on_expression_fieldChange(self, fieldName, isValid):
# self.commitData.emit(self.sender())
pass
class FieldsMappingPanel(QtGui.QWidget, Ui_Form):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.addButton.setIcon(
QtGui.QIcon(':/images/themes/default/mActionAdd.svg'))
self.deleteButton.setIcon(
QtGui.QIcon(':/images/themes/default/mActionRemove.svg'))
self.upButton.setIcon(
QtGui.QIcon(':/images/themes/default/mActionArrowUp.png'))
self.downButton.setIcon(
QtGui.QIcon(':/images/themes/default/mActionArrowDown.png'))
self.resetButton.setIcon(
QtGui.QIcon(':/images/themes/default/mIconClear.png'))
self.model = FieldsMappingModel()
self.fieldsView.setModel(self.model)
self.model.rowsInserted.connect(self.on_model_rowsInserted)
self.fieldsView.setItemDelegate(FieldDelegate())
self.updateLayerCombo()
def setLayer(self, layer):
self.model.setLayer(layer)
if self.model.rowCount() == 0:
self.on_resetButton_clicked()
else:
dlg = QtGui.QMessageBox(self)
dlg.setText("Do you want to reset the field mapping?")
dlg.setStandardButtons(
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes
+ QtGui.QMessageBox.No))
dlg.setDefaultButton(QtGui.QMessageBox.No)
if dlg.exec_() == QtGui.QMessageBox.Yes:
self.on_resetButton_clicked()
def value(self):
return self.model.mapping()
def setValue(self, value):
self.model.setMapping(value)
@QtCore.pyqtSlot(bool, name='on_addButton_clicked')
def on_addButton_clicked(self, checked=False):
rowCount = self.model.rowCount()
self.model.insertRows(rowCount, 1)
index = self.model.index(rowCount, 0)
self.fieldsView.selectionModel().select(index,
QtGui.QItemSelectionModel.SelectionFlags(QtGui.QItemSelectionModel.Clear
+ QtGui.QItemSelectionModel.Select
+ QtGui.QItemSelectionModel.Current
+ QtGui.QItemSelectionModel.Rows))
self.fieldsView.scrollTo(index)
self.fieldsView.scrollTo(index)
@QtCore.pyqtSlot(bool, name='on_deleteButton_clicked')
def on_deleteButton_clicked(self, checked=False):
sel = self.fieldsView.selectionModel()
if not sel.hasSelection():
return
indexes = sel.selectedRows()
for index in indexes:
self.model.removeRows(index.row(), 1)
@QtCore.pyqtSlot(bool, name='on_upButton_clicked')
def on_upButton_clicked(self, checked=False):
sel = self.fieldsView.selectionModel()
if not sel.hasSelection():
return
row = sel.selectedRows()[0].row()
if row == 0:
return
self.model.insertRows(row - 1, 1)
for column in xrange(0, self.model.columnCount()):
srcIndex = self.model.index(row + 1, column)
dstIndex = self.model.index(row - 1, column)
value = self.model.data(srcIndex, QtCore.Qt.EditRole)
self.model.setData(dstIndex, value, QtCore.Qt.EditRole)
self.model.removeRows(row + 1, 1)
sel.select(self.model.index(row - 1, 0),
QtGui.QItemSelectionModel.SelectionFlags(QtGui.QItemSelectionModel.Clear
+ QtGui.QItemSelectionModel.Select
+ QtGui.QItemSelectionModel.Current
+ QtGui.QItemSelectionModel.Rows))
@QtCore.pyqtSlot(bool, name='on_downButton_clicked')
def on_downButton_clicked(self, checked=False):
sel = self.fieldsView.selectionModel()
if not sel.hasSelection():
return
row = sel.selectedRows()[0].row()
if row == self.model.rowCount() - 1:
return
self.model.insertRows(row + 2, 1)
for column in xrange(0, self.model.columnCount()):
srcIndex = self.model.index(row, column)
dstIndex = self.model.index(row + 2, column)
value = self.model.data(srcIndex, QtCore.Qt.EditRole)
self.model.setData(dstIndex, value, QtCore.Qt.EditRole)
self.model.removeRows(row, 1)
sel.select(self.model.index(row + 1, 0),
QtGui.QItemSelectionModel.SelectionFlags(QtGui.QItemSelectionModel.Clear
+ QtGui.QItemSelectionModel.Select
+ QtGui.QItemSelectionModel.Current
+ QtGui.QItemSelectionModel.Rows))
@QtCore.pyqtSlot(bool, name='on_resetButton_clicked')
def on_resetButton_clicked(self, checked=False):
self.model.loadLayerFields(self.model.layer())
self.openPersistentEditor(
self.model.index(0, 0),
self.model.index(self.model.rowCount() - 1,
self.model.columnCount() - 1))
self.resizeColumns()
def resizeColumns(self):
header = self.fieldsView.horizontalHeader()
header.resizeSections(QtGui.QHeaderView.ResizeToContents)
for section in xrange(0, header.count()):
size = header.sectionSize(section)
fieldType = FieldsMappingModel.columns[section]['type']
if fieldType == QgsExpression:
header.resizeSection(section, size + 100)
else:
header.resizeSection(section, size + 20)
def openPersistentEditor(self, topLeft, bottomRight):
return
for row in xrange(topLeft.row(), bottomRight.row() + 1):
for column in xrange(topLeft.column(), bottomRight.column() + 1):
self.fieldsView.openPersistentEditor(self.model.index(row, column))
editor = self.fieldsView.indexWidget(self.model.index(row, column))
if isinstance(editor, QtGui.QLineEdit):
editor.deselect()
if isinstance(editor, QtGui.QSpinBox):
lineEdit = editor.findChild(QtGui.QLineEdit)
lineEdit.setAlignment(QtCore.Qt.AlignRight or QtCore.Qt.AlignVCenter)
lineEdit.deselect()
def on_model_rowsInserted(self, parent, start, end):
self.openPersistentEditor(
self.model.index(start, 0),
self.model.index(end, self.model.columnCount() - 1))
def updateLayerCombo(self):
layers = dataobjects.getVectorLayers()
layers.sort(key = lambda lay: lay.name())
for layer in layers:
self.layerCombo.addItem(layer.name(), layer)
@QtCore.pyqtSlot(bool, name='on_loadLayerFieldsButton_clicked')
def on_loadLayerFieldsButton_clicked(self, checked=False):
layer = self.layerCombo.itemData(self.layerCombo.currentIndex())
if layer is None:
return
self.model.loadLayerFields(layer)

View File

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'widgetFieldsMapping.ui'
#
# Created: Tue Jan 20 10:14:41 2015
# by: PyQt4 UI code generator 4.10.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(590, 552)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
Form.setSizePolicy(sizePolicy)
self.verticalLayout_2 = QtGui.QVBoxLayout(Form)
self.verticalLayout_2.setMargin(0)
self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.fieldsView = QtGui.QTableView(Form)
self.fieldsView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
self.fieldsView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self.fieldsView.setObjectName(_fromUtf8("fieldsView"))
self.horizontalLayout.addWidget(self.fieldsView)
self.buttonLayout = QtGui.QVBoxLayout()
self.buttonLayout.setObjectName(_fromUtf8("buttonLayout"))
self.addButton = QtGui.QToolButton(Form)
self.addButton.setObjectName(_fromUtf8("addButton"))
self.buttonLayout.addWidget(self.addButton)
self.deleteButton = QtGui.QToolButton(Form)
self.deleteButton.setObjectName(_fromUtf8("deleteButton"))
self.buttonLayout.addWidget(self.deleteButton)
self.upButton = QtGui.QToolButton(Form)
self.upButton.setObjectName(_fromUtf8("upButton"))
self.buttonLayout.addWidget(self.upButton)
self.downButton = QtGui.QToolButton(Form)
self.downButton.setObjectName(_fromUtf8("downButton"))
self.buttonLayout.addWidget(self.downButton)
self.resetButton = QtGui.QToolButton(Form)
self.resetButton.setObjectName(_fromUtf8("resetButton"))
self.buttonLayout.addWidget(self.resetButton)
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.buttonLayout.addItem(spacerItem)
self.horizontalLayout.addLayout(self.buttonLayout)
self.verticalLayout_2.addLayout(self.horizontalLayout)
self.loadFromLayerLayout = QtGui.QHBoxLayout()
self.loadFromLayerLayout.setObjectName(_fromUtf8("loadFromLayerLayout"))
self.loadFromLayerLabel = QtGui.QLabel(Form)
self.loadFromLayerLabel.setObjectName(_fromUtf8("loadFromLayerLabel"))
self.loadFromLayerLayout.addWidget(self.loadFromLayerLabel)
self.layerCombo = QtGui.QComboBox(Form)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.layerCombo.sizePolicy().hasHeightForWidth())
self.layerCombo.setSizePolicy(sizePolicy)
self.layerCombo.setObjectName(_fromUtf8("layerCombo"))
self.loadFromLayerLayout.addWidget(self.layerCombo)
self.loadLayerFieldsButton = QtGui.QPushButton(Form)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.loadLayerFieldsButton.sizePolicy().hasHeightForWidth())
self.loadLayerFieldsButton.setSizePolicy(sizePolicy)
self.loadLayerFieldsButton.setObjectName(_fromUtf8("loadLayerFieldsButton"))
self.loadFromLayerLayout.addWidget(self.loadLayerFieldsButton)
self.verticalLayout_2.addLayout(self.loadFromLayerLayout)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(_translate("Form", "Fields", None))
self.addButton.setToolTip(_translate("Form", "Add new field", None))
self.addButton.setText(_translate("Form", "add", None))
self.deleteButton.setToolTip(_translate("Form", "Delete selected field", None))
self.deleteButton.setText(_translate("Form", "delete", None))
self.upButton.setToolTip(_translate("Form", "Move selected field up", None))
self.upButton.setText(_translate("Form", "up", None))
self.downButton.setToolTip(_translate("Form", "Move selected field down", None))
self.downButton.setText(_translate("Form", "down", None))
self.resetButton.setToolTip(_translate("Form", "Reset all fields", None))
self.resetButton.setText(_translate("Form", "reset", None))
self.loadFromLayerLabel.setText(_translate("Form", "Load fields from layer", None))
self.loadLayerFieldsButton.setToolTip(_translate("Form", "Load fields from selected layer", None))
self.loadLayerFieldsButton.setText(_translate("Form", "Load fields", None))

View File

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>590</width>
<height>552</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Fields</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTableView" name="fieldsView">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="buttonLayout">
<item>
<widget class="QToolButton" name="addButton">
<property name="toolTip">
<string>Add new field</string>
</property>
<property name="text">
<string>add</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="deleteButton">
<property name="toolTip">
<string>Delete selected field</string>
</property>
<property name="text">
<string>delete</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="upButton">
<property name="toolTip">
<string>Move selected field up</string>
</property>
<property name="text">
<string>up</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="downButton">
<property name="toolTip">
<string>Move selected field down</string>
</property>
<property name="text">
<string>down</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="resetButton">
<property name="toolTip">
<string>Reset all fields</string>
</property>
<property name="text">
<string>reset</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="loadFromLayerLayout">
<item>
<widget class="QLabel" name="loadFromLayerLabel">
<property name="text">
<string>Load fields from layer</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="layerCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="loadLayerFieldsButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Load fields from selected layer</string>
</property>
<property name="text">
<string>Load fields</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>