New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Empower plugins with more functionalities #5189
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang-tidy made some suggestions
src/core/utils/featureutils.cpp
Outdated
@@ -27,9 +27,9 @@ FeatureUtils::FeatureUtils( QObject *parent ) | |||
{ | |||
} | |||
|
|||
QgsFeature FeatureUtils::initFeature( QgsVectorLayer *layer, QgsGeometry geometry ) | |||
QgsFeature FeatureUtils::createFeature( QgsVectorLayer *layer, QgsGeometry geometry ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: the parameter 'geometry' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
src/core/utils/featureutils.h:33:
- static Q_INVOKABLE QgsFeature createFeature( QgsVectorLayer *layer = nullptr, QgsGeometry geometry = QgsGeometry() );
+ static Q_INVOKABLE QgsFeature createFeature( QgsVectorLayer *layer = nullptr, const QgsGeometry& geometry = QgsGeometry() );
QgsFeature FeatureUtils::createFeature( QgsVectorLayer *layer, QgsGeometry geometry ) | |
QgsFeature FeatureUtils::createFeature( QgsVectorLayer *layer, const QgsGeometry& geometry ) |
{ | ||
QgsFeature f( layer->fields() ); | ||
QgsFeature f( layer ? layer->fields() : QgsFields() ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: implicit conversion 'QgsVectorLayer *' -> bool [readability-implicit-bool-conversion]
QgsFeature f( layer ? layer->fields() : QgsFields() ); | |
QgsFeature f( layer != nullptr ? layer->fields() : QgsFields() ); |
{ | ||
QgsFeature f( layer->fields() ); | ||
QgsFeature f( layer ? layer->fields() : QgsFields() ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: variable name 'f' is too short, expected at least 3 characters [readability-identifier-length]
QgsFeature f( layer ? layer->fields() : QgsFields() );
^
public: | ||
FeatureIterator( QgsVectorLayer *layer = nullptr, const QgsFeatureRequest &request = QgsFeatureRequest() ) | ||
{ | ||
if ( layer ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: implicit conversion 'QgsVectorLayer *' -> bool [readability-implicit-bool-conversion]
if ( layer ) | |
if ( layer != nullptr ) |
@@ -26,7 +26,7 @@ TEST_CASE( "FeatureUtils" ) | |||
|
|||
QgsGeometry geometry = QgsGeometry::fromWkt( QStringLiteral( "Polygon (((8 8, 9 8, 8 9, 8 8)))" ) ); | |||
|
|||
QgsFeature f = FeatureUtils::initFeature( vl.get(), geometry ); | |||
QgsFeature f = FeatureUtils::createFeature( vl.get(), geometry ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: variable 'f' of type 'QgsFeature' can be declared 'const' [misc-const-correctness]
QgsFeature f = FeatureUtils::createFeature( vl.get(), geometry ); | |
QgsFeature const f = FeatureUtils::createFeature( vl.get(), geometry ); |
@@ -26,7 +26,7 @@ | |||
|
|||
QgsGeometry geometry = QgsGeometry::fromWkt( QStringLiteral( "Polygon (((8 8, 9 8, 8 9, 8 8)))" ) ); | |||
|
|||
QgsFeature f = FeatureUtils::initFeature( vl.get(), geometry ); | |||
QgsFeature f = FeatureUtils::createFeature( vl.get(), geometry ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: variable name 'f' is too short, expected at least 3 characters [readability-identifier-length]
QgsFeature f = FeatureUtils::createFeature( vl.get(), geometry );
^
馃帀 Ta-daaa, freshly created APKs are available for 761669f: arm64-android |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang-tidy made some suggestions
@@ -199,6 +199,15 @@ QString LayerUtils::fieldType( const QgsField &field ) | |||
return QVariant( field.type() ).typeName(); | |||
} | |||
|
|||
bool LayerUtils::addFeature( QgsVectorLayer *layer, QgsFeature feature ) | |||
{ | |||
if ( layer ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: implicit conversion 'QgsVectorLayer *' -> bool [readability-implicit-bool-conversion]
if ( layer ) | |
if ( layer != nullptr ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me
This PR enables plugins to do the following:
The invoke.patch changes are being upstreamed, but since we're on 3.36 for now, we can enjoy vcpkg's patching powers 馃挭
Upstream PRs:
Iterating through features is done like this:
Editing a feature attribute is done like this:
Creating a new feature, editing an attribute, and adding to a layer is done like this:
Some more information to explain/justify some of the choices done here.
First, QML Javascript engine does not allow for non-const parameter by reference. This means that any C++ function that has a non-const & parameter can't be made Q_INVOKABLE. In practice, this is most impactful for the feature iterator here because we can't simply expose the QgsFeatureIterator::nextFeature( QgsFeature &feature ). It's a good lesson learned that is good to internalize now as we move forward :)
To deal with this, I've come up with a FeatureIterator which is Javascript friendly, with a bool hasNext() function and a QgsFeature next() function. I settled on this form after researching what kind of iterator template there is out there for Javascript.
This could eventually be upstreamed into QgsFeatureIterator itself. Looking at Qt's QList iterator for example, it does support Java-style iterators with hasNext() / next() / etc. (https://doc.qt.io/qt-6/java-style-iterators.html#java-style-iterators). This is a discussion that's worth having upstream as to whether we want this or not there.
Also, for the record, QML's Javascript engine does not have the capability to expand an object type via Object.prototype.my_function() = function {}, so adding functions to a given QObject or QGadget requires us to do it on the C++ side of things.
Finally, QML's Javascript engine does not allow the creation of objects directly in Javascript (other than via Qt.createComponent / Qt.createQmlObject which is not super graceful). This is why for e.g. Qt has a Qt.point() function to create a point object. That's why for e.g. we can't go let request = QgsFeatureRequest(...) on the Javascript side of things.