Skip to content
Permalink
Browse files

Merge branch 'master' into patch-2

  • Loading branch information
DelazJ committed Aug 24, 2018
2 parents 399bbf1 + 31fadd1 commit 40223db87d1026e201f070e5e9c6dc29f7dcbd59
Showing with 846 additions and 116 deletions.
  1. +86 −0 python/core/auto_generated/qgsgeometryfixes.sip.in
  2. +10 −3 python/core/auto_generated/qgsvectorlayer.sip.in
  3. +1 −0 python/core/core_auto.sip
  4. +3 −0 python/testing/__init__.py
  5. +1 −1 resources/function_help/json/array
  6. +1 −1 resources/function_help/json/array_append
  7. +1 −1 resources/function_help/json/array_cat
  8. +1 −1 resources/function_help/json/array_distinct
  9. +2 −2 resources/function_help/json/array_foreach
  10. +1 −1 resources/function_help/json/array_insert
  11. +1 −1 resources/function_help/json/array_prepend
  12. +1 −1 resources/function_help/json/array_remove_all
  13. +1 −1 resources/function_help/json/array_remove_at
  14. +1 −1 resources/function_help/json/array_reverse
  15. +8 −8 resources/function_help/json/array_slice
  16. +2 −2 resources/function_help/json/generate_series
  17. +1 −1 resources/function_help/json/map
  18. +1 −1 resources/function_help/json/map_akeys
  19. +1 −1 resources/function_help/json/map_avals
  20. +1 −1 resources/function_help/json/map_concat
  21. +1 −1 resources/function_help/json/map_delete
  22. +1 −1 resources/function_help/json/map_insert
  23. +2 −2 resources/function_help/json/regexp_matches
  24. +2 −2 resources/function_help/json/string_to_array
  25. +22 −2 src/app/qgsvectorlayerproperties.cpp
  26. +2 −0 src/core/CMakeLists.txt
  27. +28 −13 src/core/expression/qgsexpression.cpp
  28. +52 −0 src/core/qgsgeometryfixes.cpp
  29. +105 −0 src/core/qgsgeometryfixes.h
  30. +43 −3 src/core/qgsvectorlayer.cpp
  31. +13 −4 src/core/qgsvectorlayer.h
  32. +7 −7 src/gui/qgsexpressionbuilderwidget.cpp
  33. +398 −47 src/ui/qgsvectorlayerpropertiesbase.ui
  34. +6 −6 tests/src/core/testqgsexpression.cpp
  35. +39 −0 tests/src/python/test_qgsvectorlayer.py
@@ -0,0 +1,86 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsgeometryfixes.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsGeometryFixes
{
%Docstring

The QgsGeometryFixes class contains options to automatically adjust geometries to
constraints on a layer.

.. versionadded:: 3.4
%End

%TypeHeaderCode
#include "qgsgeometryfixes.h"
%End
public:

QgsGeometryFixes();
%Docstring
Create a new QgsGeometryFixes object.
%End

bool removeDuplicateNodes() const;
%Docstring
Automatically remove duplicate nodes on all geometries which are edited on this layer.

.. versionadded:: 3.4
%End

void setRemoveDuplicateNodes( bool value );
%Docstring
Automatically remove duplicate nodes on all geometries which are edited on this layer.

.. versionadded:: 3.4
%End

double geometryPrecision() const;
%Docstring
The precision in which geometries on this layer should be saved.
Geometries which are edited on this layer will be rounded to multiples of this value (snap to grid).
Set to 0.0 to disable.

.. versionadded:: 3.4
%End

void setGeometryPrecision( double value );
%Docstring
The precision in which geometries on this layer should be saved.
Geometries which are edited on this layer will be rounded to multiples of this value (snap to grid).
Set to 0.0 to disable.

.. versionadded:: 3.4
%End

bool isActive() const;
%Docstring
Determines if at least one fix is enabled.

.. versionadded:: 3.4
%End

void apply( QgsGeometry &geometry ) const;
%Docstring
Apply any fixes configured on this class to ``geometry``.

.. versionadded:: 3.4
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsgeometryfixes.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -1062,7 +1062,7 @@ Query the layer for the features which intersect the specified rectangle.
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 );


bool updateFeature( const QgsFeature &feature, bool skipDefaultValues = false );
bool updateFeature( QgsFeature &feature, bool skipDefaultValues = false );
%Docstring
Updates an existing ``feature`` in the layer, replacing the attributes and geometry for the feature
with matching QgsFeature.id() with the attributes and geometry from ``feature``.
@@ -1498,7 +1498,7 @@ Make layer read-only (editing disabled) or not
:return: false if the layer is in editing yet
%End

bool changeGeometry( QgsFeatureId fid, const QgsGeometry &geometry, bool skipDefaultValue = false );
bool changeGeometry( QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue = false );
%Docstring
Changes a feature's ``geometry`` within the layer's edit buffer
(but does not immediately commit the changes). The ``fid`` argument
@@ -2223,6 +2223,13 @@ it.
Test if an edit command is active

.. versionadded:: 3.0
%End

QgsGeometryFixes *geometryFixes() const;
%Docstring
Configuration and logic to apply automatically on any edit happening on this layer.

.. versionadded:: 3.4
%End

public slots:
@@ -2590,7 +2597,7 @@ Emitted when the feature count for symbols on this layer has been recalculated.
Sets the extent
%End

private: // Private methods
private:
QgsVectorLayer( const QgsVectorLayer &rhs );
};

@@ -53,6 +53,7 @@
%Include auto_generated/qgsfields.sip
%Include auto_generated/qgsfileutils.sip
%Include auto_generated/qgsfontutils.sip
%Include auto_generated/qgsgeometryfixes.sip
%Include auto_generated/qgsgeometrysimplifier.sip
%Include auto_generated/qgshistogram.sip
%Include auto_generated/qgshtmlutils.sip
@@ -196,6 +196,9 @@ def assertFilesEqual(self, filepath_expected, filepath_result):
diff = list(diff)
self.assertEqual(0, len(diff), ''.join(diff))

def assertGeometriesEqual(self, geom0, geom1, geom0_id='geometry 1', geom1_id='geometry 2', precision=14, topo_equal_check=False):
self.checkGeometriesEqual(geom0, geom1, geom0_id, geom1_id, use_asserts=True, precision=precision, topo_equal_check=topo_equal_check)

def checkGeometriesEqual(self, geom0, geom1, geom0_id, geom1_id, use_asserts=False, precision=14, topo_equal_check=False):
""" Checks whether two geometries are the same - using either a strict check of coordinates (up to given precision)
or by using topological equality (where e.g. a polygon with clockwise is equal to a polygon with counter-clockwise
@@ -7,6 +7,6 @@
{"arg":"value1", "syntaxOnly": true},
{"arg":"value2", "syntaxOnly": true},
{"arg":"value", "descOnly": true, "description":"a value"}],
"examples": [ { "expression":"array(2,10)", "returns":"array: 2, 10"}
"examples": [ { "expression":"array(2,10)", "returns":"[ 2, 10 ]"}
]
}
@@ -4,5 +4,5 @@
"description": "Returns an array with the given value added at the end.",
"arguments": [ {"arg":"array","description":"an array"},
{"arg":"value","description":"the value to add"}],
"examples": [ { "expression":"array_append(array(1,2,3),4)", "returns":"array: 1,2,3,4"}]
"examples": [ { "expression":"array_append(array(1,2,3),4)", "returns":"[ 1, 2, 3, 4 ]"}]
}
@@ -7,6 +7,6 @@
{"arg":"array1", "syntaxOnly": true},
{"arg":"array2", "syntaxOnly": true},
{"arg":"array", "descOnly": true, "description":"an array"}],
"examples": [ { "expression":"array_cat(array(1,2),array(2,3))", "returns":"array: 1,2,2,3"}
"examples": [ { "expression":"array_cat(array(1,2),array(2,3))", "returns":"[ 1, 2, 2, 3 ]"}
]
}
@@ -4,6 +4,6 @@
"description": "Returns an array containing distinct values of the given array.",
"arguments": [
{"arg":"array","description":"an array"}],
"examples": [ { "expression":"array_distinct(array(1,2,3,2,1))", "returns":"array: 1,2,3"}
"examples": [ { "expression":"array_distinct(array(1,2,3,2,1))", "returns":"[ 1, 2, 3 ]"}
]
}
@@ -7,7 +7,7 @@
{"arg":"expression","description":"an expression to evaluate on each item. The variable `@element` will be replaced by the current value."}
],
"examples": [
{ "expression": "array_foreach(array('a','b','c'),upper(@element))", "returns":"array: 'A', 'B', 'C'"},
{ "expression": "array_foreach(array(1,2,3),@element + 10)", "returns":"array: 11, 12, 13"}
{ "expression": "array_foreach(array('a','b','c'),upper(@element))", "returns":"[ 'A', 'B', 'C' ]"},
{ "expression": "array_foreach(array(1,2,3),@element + 10)", "returns":"[ 11, 12, 13 ]"}
]
}
@@ -5,5 +5,5 @@
"arguments": [ {"arg":"array","description":"an array"},
{"arg":"pos","description":"the position where to add (0 based)"},
{"arg":"value","description":"the value to add"}],
"examples": [ { "expression":"array_insert(array(1,2,3),1,100)", "returns":"array: 1,100,2,3"}]
"examples": [ { "expression":"array_insert(array(1,2,3),1,100)", "returns":"[ 1, 100, 2, 3 ]"}]
}
@@ -4,5 +4,5 @@
"description": "Returns an array with the given value added at the beginning.",
"arguments": [ {"arg":"array","description":"an array"},
{"arg":"value","description":"the value to add"}],
"examples": [ { "expression":"array_prepend(array(1,2,3),0)", "returns":"array: 0,1,2,3"}]
"examples": [ { "expression":"array_prepend(array(1,2,3),0)", "returns":"[ 0, 1, 2, 3 ]"}]
}
@@ -4,5 +4,5 @@
"description": "Returns an array with all the entries of the given value removed.",
"arguments": [ {"arg":"array","description":"an array"},
{"arg":"value","description":"the values to remove"}],
"examples": [ { "expression":"array_remove_all(array('a','b','c','b'),'b')", "returns":"array: 'a','c'"}]
"examples": [ { "expression":"array_remove_all(array('a','b','c','b'),'b')", "returns":"[ 'a', 'c' ]"}]
}
@@ -4,5 +4,5 @@
"description": "Returns an array with the given index removed.",
"arguments": [ {"arg":"array","description":"an array"},
{"arg":"pos","description":"the position to remove (0 based)"}],
"examples": [ { "expression":"array_remove_at(array(1,2,3),1)", "returns":"array: 1,3"}]
"examples": [ { "expression":"array_remove_at(array(1,2,3),1)", "returns":"[ 1, 3 ]"}]
}
@@ -3,5 +3,5 @@
"type": "function",
"description": "Returns the given array with array values in reversed order.",
"arguments": [ {"arg":"array","description":"an array"} ],
"examples": [ { "expression":"array_reverse(array(2,4,0,10))", "returns":"array: 10,0,4,2"}]
"examples": [ { "expression":"array_reverse(array(2,4,0,10))", "returns":"[ 10, 0, 4, 2 ]"}]
}
@@ -17,35 +17,35 @@
],
"examples": [{
"expression": "array_slice(array(1,2,3,4,5),0,3)",
"returns": "array: 1,2,3,4"
"returns": "[ 1, 2, 3, 4 ]"
},
{
"expression": "array_slice(array(1,2,3,4,5),0,-1)",
"returns": "array: 1,2,3,4,5"
"returns": "[ 1, 2, 3, 4, 5 ]"
},
{
"expression": "array_slice(array(1,2,3,4,5),-5,-1)",
"returns": "array: 1,2,3,4,5"
"returns": "[ 1, 2, 3, 4, 5 ]"
},
{
"expression": "array_slice(array(1,2,3,4,5),0,0)",
"returns": "array: 1"
"returns": "[ 1 ]"
},
{
"expression": "array_slice(array(1,2,3,4,5),-2,-1)",
"returns": "array: 4,5"
"returns": "[ 4, 5 ]"
},
{
"expression": "array_slice(array(1,2,3,4,5),-1,-1)",
"returns": "array: 5"
"returns": "[ 5 ]"
},
{
"expression": "array_slice(array('Dufour','Valmiera','Chugiak','Brighton'),1,2)",
"returns": "array: 'Valmiera','Chugiak'"
"returns": "[ 'Valmiera', 'Chugiak' ]"
},
{
"expression": "array_slice(array_slice(array('Dufour','Valmiera','Chugiak','Brighton'),-2,-1)",
"returns": "array: 'Chugiak','Brighton'"
"returns": "[ 'Chugiak', 'Brighton' ]"
}
]
}
@@ -7,7 +7,7 @@
{"arg":"stop", "description":"value that ends the sequence once reached"},
{"arg":"step","optional":true,"default":"1","description":"value used as the increment between values"}
],
"examples": [ { "expression":"generate_series(1,5)", "returns":"array: 1, 2, 3, 4, 5"},
{ "expression":"generate_series(5,1,-1)", "returns":"array: 5, 4, 3, 2, 1"}
"examples": [ { "expression":"generate_series(1,5)", "returns":"[ 1, 2, 3, 4, 5 ]"},
{ "expression":"generate_series(5,1,-1)", "returns":"[ 5, 4, 3, 2, 1 ]"}
]
}
@@ -10,6 +10,6 @@
{"arg":"value2", "syntaxOnly": true},
{"arg":"key", "descOnly": true, "description":"a key (string)"},
{"arg":"value", "descOnly": true, "description":"a value"}],
"examples": [ { "expression":"map('1','one','2', 'two')", "returns":"map: 1: 'one', 2: 'two'"}
"examples": [ { "expression":"map('1','one','2', 'two')", "returns":"{ '1': 'one', '2': 'two' }"}
]
}
@@ -3,5 +3,5 @@
"type": "function",
"description": "Returns all the keys of a map as an array.",
"arguments": [ {"arg":"map","description":"a map"}],
"examples": [ { "expression":"map_akeys(map('1','one','2','two'))", "returns":"array: '1', '2'"}]
"examples": [ { "expression":"map_akeys(map('1','one','2','two'))", "returns":"[ '1', '2' ]"}]
}
@@ -3,5 +3,5 @@
"type": "function",
"description": "Returns all the values of a map as an array.",
"arguments": [ {"arg":"map","description":"a map"}],
"examples": [ { "expression":"map_avals(map('1','one','2','two'))", "returns":"array: 'one', 'two'"}]
"examples": [ { "expression":"map_avals(map('1','one','2','two'))", "returns":"[ 'one', 'two' ]"}]
}
@@ -7,6 +7,6 @@
{"arg":"map1", "syntaxOnly": true},
{"arg":"map2", "syntaxOnly": true},
{"arg":"map", "descOnly": true, "description":"a map"}],
"examples": [ { "expression":"map_concat(map('1','one', '2','overridden'),map('2','two', '3','three'))", "returns":"map: 1: 'one, 2: 'two', 3: 'three'"}
"examples": [ { "expression":"map_concat(map('1','one', '2','overridden'),map('2','two', '3','three'))", "returns":"{ '1': 'one, '2': 'two', '3': 'three' }"}
]
}
@@ -4,5 +4,5 @@
"description": "Returns a map with the given key and its corresponding value deleted.",
"arguments": [ {"arg":"map","description":"a map"},
{"arg":"key","description":"the key to delete"}],
"examples": [ { "expression":"map_delete(map('1','one','2','two'),'2')", "returns":"map: 1: 'one'"}]
"examples": [ { "expression":"map_delete(map('1','one','2','two'),'2')", "returns":"{ '1': 'one' }"}]
}
@@ -5,5 +5,5 @@
"arguments": [ {"arg":"map","description":"a map"},
{"arg":"key","description":"the key to add"},
{"arg":"value","description":"the value to add"}],
"examples": [ { "expression":"map_insert(map('1','one'),'3','three')", "returns":"map: 1: 'one', 3: 'three'"}]
"examples": [ { "expression":"map_insert(map('1','one'),'3','three')", "returns":"{ '1': 'one', '3': 'three' }"}]
}
@@ -6,7 +6,7 @@
{"arg":"string", "description":"the string to capture groups from against the regular expression"},
{"arg":"regex","description":"the regular expression used to capture groups"},
{"arg":"empty_value","optional":true,"default":"''","description":"the optional string to use as replacement for empty (zero length) matches"}],
"examples": [ { "expression":"regexp_matches('QGIS=>rocks','(.*)=>(.*)')", "returns":"array: 'QGIS', 'rocks'"},
{ "expression":"regexp_matches('key=>','(.*)=>(.*)','empty value')", "returns":"array: 'key', 'empty value'"}
"examples": [ { "expression":"regexp_matches('QGIS=>rocks','(.*)=>(.*)')", "returns":"[ 'QGIS', 'rocks' ]"},
{ "expression":"regexp_matches('key=>','(.*)=>(.*)','empty value')", "returns":"[ 'key', 'empty value' ]"}
]
}
@@ -6,7 +6,7 @@
{"arg":"string", "description":"the input string"},
{"arg":"delimiter","optional":true,"default":"','","description":"the string delimiter used to split the input string"},
{"arg":"empty_value","optional":true,"default":"''","description":"the optional string to use as replacement for empty (zero length) matches"}],
"examples": [ { "expression":"string_to_array('1,2,3',',')", "returns":"array: '1', '2', '3'"},
{ "expression":"string_to_array('1,,3',',','0')", "returns":"array: '1', '0', '3'"}
"examples": [ { "expression":"string_to_array('1,2,3',',')", "returns":"[ '1', '2', '3' ]"},
{ "expression":"string_to_array('1,,3',',','0')", "returns":"[ '1', '0', '3' ]"}
]
}
@@ -62,6 +62,7 @@
#include "qgsnewauxiliaryfielddialog.h"
#include "qgslabelinggui.h"
#include "qgssymbollayer.h"
#include "qgsgeometryfixes.h"

#include "layertree/qgslayertreelayer.h"
#include "qgslayertree.h"
@@ -289,9 +290,9 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(

//insert existing join info
const QList< QgsVectorLayerJoinInfo > &joins = mLayer->vectorJoins();
for ( int i = 0; i < joins.size(); ++i )
for ( const QgsVectorLayerJoinInfo &join : joins )
{
addJoinToTreeWidget( joins[i] );
addJoinToTreeWidget( join );
}

mOldJoins = mLayer->vectorJoins();
@@ -423,6 +424,22 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(

updateAuxiliaryStoragePage();

if ( mLayer->isSpatial() )
{
mRemoveDuplicateNodesCheckbox->setEnabled( true );
mGeometryPrecisionSpinBox->setEnabled( true );

mRemoveDuplicateNodesCheckbox->setChecked( mLayer->geometryFixes()->removeDuplicateNodes() );
mGeometryPrecisionSpinBox->setValue( mLayer->geometryFixes()->geometryPrecision() );

mGeometryPrecisionSpinBox->setSuffix( QStringLiteral( " [%1]" ).arg( QgsUnitTypes::toAbbreviatedString( mLayer->crs().mapUnits() ) ) );
}
else
{
mRemoveDuplicateNodesCheckbox->setEnabled( false );
mGeometryPrecisionSpinBox->setEnabled( false );
}

optionsStackedWidget_CurrentChanged( mOptStackedWidget->currentIndex() );
}

@@ -761,6 +778,9 @@ void QgsVectorLayerProperties::apply()
mVector3DWidget->apply();
#endif

mLayer->geometryFixes()->setRemoveDuplicateNodes( mRemoveDuplicateNodesCheckbox->isChecked() );
mLayer->geometryFixes()->setGeometryPrecision( mGeometryPrecisionSpinBox->value() );

// update symbology
emit refreshLegend( mLayer->id() );

0 comments on commit 40223db

Please sign in to comment.
You can’t perform that action at this time.