Skip to content
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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QGIS Quick library [dockerdeps] #6490

Closed
wants to merge 31 commits into from

Conversation

PeterPetrik
Copy link
Contributor

[FEATURE] Introduction of QGIS Quick library

This adds a new library for creation of applications based on Qt Quick
framework.
It contains reusable QML / Qt Quick components based on QGIS core library.
The initial work introduces MapCanvas, FeatureForm, ScaleBar and various other
components.

To enable compilation of the library, use WITH_QUICK=TRUE

Further documentation of the library is located in doc/qgsquick.dox

For background information see the associated QEP:
qgis/QGIS-Enhancement-Proposals#109

The initial implementation is largely based on the work of Matthias Kuhn
and Marco Bernasocchi on QField project - kudos to them for the great job!

Also thanks to my colleagues Martin Dobias and Viktor Sklencar.

Work co-funded by Yorkshire Dales National Park.

This adds a new library for creation of applications based on Qt Quick
framework.
It contains reusable QML / Qt Quick components based on QGIS core
library.
The initial work introduces MapCanvas, FeatureForm, ScaleBar and various
other components.

To enable compilation of the library, use WITH_QUICK=TRUE

Further documentation of the library is located in doc/qgsquick.dox

For background information see the associated QEP:
qgis/QGIS-Enhancement-Proposals#109

The initial implementation is largely based on the work of Matthias Kuhn
and Marco Bernasocchi on QField probject - kudos to them for the great
job!
@3nids
Copy link
Member

3nids commented Feb 28, 2018

Have you considered building this on Travis too?
Do you know/think if it's a considerable overload in build time?

If you want to build it, you'll have to adapt the dependencies Dockerfile and the cmake command

@nyalldawson
Copy link
Collaborator

Phenomenal stuff!

There's a lot of code here -- not sure who/how this should be reviewed. Is there areas in particular you'd like someone to look over?

@NathanW2
Copy link
Member

NathanW2 commented Feb 28, 2018 via email

@m-kuhn
Copy link
Member

m-kuhn commented Mar 1, 2018

Nice one.

I'll definitely have a look at this, I hope I find the time soon. But (at least) another pair of eyes on this would be great as well !

@3nids 3nids changed the title QGIS Quick library QGIS Quick library [dockerdeps] Mar 2, 2018
@3nids
Copy link
Member

3nids commented Mar 2, 2018

@PeterPetrik I added a small trick so that the Docker deps image is saved on the hub (thanks to having [dockerdeps] in the PR title.

@PeterPetrik
Copy link
Contributor Author

@3nids nice! thanks

@3nids 3nids closed this Mar 2, 2018
@3nids 3nids reopened this Mar 2, 2018
@3nids
Copy link
Member

3nids commented Mar 2, 2018

Sorry for the mess, it's a bit more complicated than I thought (Travis yml file doesn't support having complex definition of variables). Will see if I can address this in a separate PR.
I have force push to remove my commits, sorry again.

@3nids 3nids removed the 3.2 label Mar 14, 2018
@3nids 3nids added this to the 3.2 milestone Mar 14, 2018
@PeterPetrik
Copy link
Contributor Author

Hi @m-kuhn, do you have any other outstanding issues with this PR? I have seen QField release-0.10.12 4 days ago and I am concerned that this work will diverge from QField. There is also PR for QField that uses all QgsQuick classes instead of their QField 1-1 equivalents and PR for osgeo4A to package QgsQuick.

@m-kuhn
Copy link
Member

m-kuhn commented Apr 13, 2018

@PeterPetrik as already communicated by mail, the size and diversity in the code make it a non-trivial job to review this PR. I am quite happy with the infrastructure (library, cmake, plugin code) and would merge those immediately if they were in a self-contained PR.
For the rest of it, I planned some time early next week to try a diff-based approach and hopefully get a better idea of the state.

Copy link
Member

@m-kuhn m-kuhn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First batch of additional comments.
Some of them are things that would be good to grep for in your code, I probably didn't find all their ocurrences (QDebug, usage of gps and btn) or do an internal review on your side (comprehensive usage of translatable strings)

property bool allowRememberAttribute: false // when adding new feature, add checkbox to be able to save the same value for the next feature as default
property QgsQuick.Project project

property var saveBtnIcon: QgsQuick.Utils.getThemeIcon( "ic_save_white" )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either use saveIcon or saveButtonIcon


property QgsQuick.AttributeFormModel model
property alias toolbarVisible: toolbar.visible
property bool allowRememberAttribute: false // when adding new feature, add checkbox to be able to save the same value for the next feature as default
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a plan to do something doxygen-alike for qml documentation? Would be great if we had a stable format for api docs right from the beginning.

Copy link
Contributor Author

@PeterPetrik PeterPetrik Apr 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great, but it would take a bit of investigation on how to do it properly, what tool to use to generate the docs etc. I would rather keep it for future enhancement

Similar topic is code-style for qml files (astyle)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I did a quick search and I think Qt does it via .qdoc files (not within the qml files). Let's keep eyes open and postpone this.

*/
Rectangle {
width: parent.width
height: parent.height
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason to use width and height instead of anchors.fill?

property var widget: EditorWidget
property var field: Field
property var constraintValid: ConstraintValid
property var homePath: form.project ? form.project.homePath : ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be better to use null/undefined instead of an empty string if the project is not available? I can't think of a situation, where it's desired to silently assume that the homepath is an empty string.

property var homePath: form.project ? form.project.homePath : ""

active: widget !== 'Hidden'
source: 'qgsquick' + widget.toLowerCase() + '.qml'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it not required to specify the subdirectory here (editor)? How are they found?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels a bit like black magic to me. Especially since this is targetted at standalone apps which will probably ship their own packaging code.

//! Feature fieds's roles
enum FeatureRoles
{
ElementType = Qt::UserRole + 1, //!< Element type
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those documentation are pretty much stating the obvious... In general it's preferable to add a bit more than copying the name.


Q_ENUM( FeatureRoles )

//! create new attribute form model
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capitalization

: QStandardItemModel( 0, 1, parent )
, mFeatureModel( nullptr )
, mLayer( nullptr )
, mTemporaryContainer( nullptr )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initialize in header


QgsQuickAttributeFormModelBase::~QgsQuickAttributeFormModelBase()
{
delete mTemporaryContainer;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::unique_ptr?

Q_INVOKABLE void create();

//! Return attribute value with name
Q_INVOKABLE QVariant attribute( const QString &name );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this method be const?

QSGNode *QgsQuickFeatureHighlight::updatePaintNode( QSGNode *n, QQuickItem::UpdatePaintNodeData * )
{
if ( !mDirty || !mMapSettings )
return n;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original code has a single return statement at the end of the method. This prevents from accidentially introducing memory leaks, especially if the code deals with new and delete as here. Plus it allows copy elison of the return value on any compiler. Is there a good reason to change the code from this schema?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But here we return a pointer, not returning a value, so I am not sure where the copy elision would be used here...?

My reason for changing the code was that flat code is better than nested code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I don't think elison will be triggered in this particular case here.

Just saying, this was a consciuos design choice I did here concerning safety (memory leaks) and a style that will lead to elison with every recent compiler (in suitable scenarios). I'm not sure "better" code is better here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm sorry I fail to understand the point about safety (+elision) ... I must be missing something.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent some thoughts on this again, in-depth explanations follow further down. I'm ok with leaving that as is. But hope that such changes are not very widespread within this pull request because they make reviewing quite a bit harder in this huge PR here, which is also the reason why I reacted a bit picky.

Safety


func()
{
  do_something();
  // if some in the future adds a new here
  while ( i )
  {
    if (some_condition()) return;
  }
  // and a matching delete which he expects to be executed
  // we've got a memory leak
}

However I meanwhile tend to accept that guard conditions at the beginning of a method (as in this case) are acceptable as they are less prone for such misinterpretation.

Elision:

Just read a bit more on that. My previous statement was based on a quote I had in mind (stack overflow or so) "all recent compilers support copy elision if you have a single variable definition at the beginning of the function and a single return statement.". That's not entirely true (probably my memory is not perfect ;) ), NRVO can also work with multiple exit points, but it has to be done consistently. That was mainly a reason for the "single exit point" in general and not regarding this particular example.


// TODO: this is very crude conversion! QgsQuickHighlightsNode should accept any type of geometry
QVector<QgsPoint> points;
for ( auto it = geom.vertices_begin(); it != geom.vertices_end(); ++it )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a const version for this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is only a const version...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok 👍

@m-kuhn
Copy link
Member

m-kuhn commented Apr 18, 2018

I see there are a lot of very good approaches in this pull request and I really like that there are unit tests coming right along with it 👍

Due to the current state of this code and the sheer size of this pull request, I'd like to re-raise the question if we can split this up into batches.

I think it shouldn't be too hard.
First a basic version with just the map canvas and the Cmake and plugin infrastructure
Then things like editors / attribute form, highlights, scale bar, ... other things in further additional pull requests.
Then finally the app that glues everything together.

I must admit, I feel a bit uncomfortable with this review because of several reasons which have been outlined already.
I tried to use meld to check for the differences with the original version locally, but it's quite difficult (because many things moved at the same time: file names, class names, code style, comments) so it's not easy to see which code changes need review and which ones are just "style". Plus it requires to click through each of the files individually.
Additionally this context is missing on github pull reuqest (because the code changed the repository) and this makes it even harder. Given that I'll have to redo this again once comments have been adressed makes it a tedious task.

Would it be possible to switch to a different merge and review schema here?

@PeterPetrik
Copy link
Contributor Author

Thank you for the review @m-kuhn.

In order to speed up the review process, I will create multiple PRs as proposed. But I am afraid I do not have time to modify associated QField PRs. Do you want to address the issues you raised from the second review in this PR, or in the new PRs?

@m-kuhn
Copy link
Member

m-kuhn commented Apr 20, 2018

Thanks @PeterPetrik this sounds good 👍

I would suggest to address the review comments and then opening the new pull requests with the adapted code.

No worries for QField, I don't think it makes sense to adjust code there before all the pull requests here are locked in.

@PeterPetrik
Copy link
Contributor Author

Addressed the review comments and opening the new pull requests with the adapted code. Closing this one

PeterPetrik added a commit to PeterPetrik/QGIS that referenced this pull request Apr 26, 2018
This pull request is a subset of qgis#6490

This adds a new library for creation of applications based on Qt Quick
framework.
It contains reusable QML / Qt Quick components based on QGIS core
library.
The initial work introduces MapCanvas

To enable compilation of the library, use WITH_QUICK=TRUE

Further documentation of the library is located in doc/qgsquick.dox

For background information see the associated QEP:
qgis/QGIS-Enhancement-Proposals#109

The initial implementation is largely based on the work of Matthias Kuhn
and Marco Bernasocchi on QField probject - kudos to them for the great
job!
@PeterPetrik PeterPetrik deleted the qgis-quick-library branch June 29, 2018 10:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants