* Introduce QgsLayerTreeCustomNode to handle items in QgsLayerTree which are not layers nor layer groups (e.g., a custom profile source from a web service to the Elevation Profile layer tree); make QgsAbstractProfileSource and its generator classes get an id in the constructor, so that subclasses don't need to deal with source ids (source ids from the generators are already in use, whereas source id from source subclasses will be used to link sources to QgsLayerTreeCustomNodes, and will be used to retrieve sources from source registry)
* [elevation] Add/remove nodes to Elevation's layer tree when registering/unregistering profile sources via QgsProfileSourceRegistry
* [elevation] Add updateCanvasSources() to Elevation Profile widget, so that after changes in the elevation layer tree, the canvas gets an updated list of profile sources, taking profile sources (i.e., from custom nodes) into account. Add QgsProfileSourceRegistry::findSourceById() for getting profile sources by id from the registry.
* [elevation] Allow for setting a display name for custom profile sources (to be displayed as layer tree node name)
* [elevation] Refactor profile source handling in Layout Elevation Profile widget, so that after changes in the elevation layer tree, the canvas gets an updated list of profile sources, taking profile sources (i.e., from custom nodes) into account. Adjust QgsLayerTreeGroup to be able to find layers and custom nodes, as well as order layer and custom nodes inside a group (only direct children).
* [elevation] Profile Source Registry improvements:
+ Avoid registering a source if its id is already registered,
+ New method to unregister a source by id, deprecating the unregister by source object.
* [tests] Add tests for QgsLayerTreeCustomNode
* [tests] add tests for legacy Elevation Profile sources and for legacy Layout Profile items:
+ make sure we keep the API untouched and mark some stuff as legacy (e.g., pure virtual methods in QgsAbstractProfileSource need to have a default implementation and making them pure virtual is postponed until QGIS 5.0),
+ add insertCustomNode(index, node) method to QgsLayerTreeGroup, so that we can set up the custom node before adding it to the layer tree, because if we add it with no custom properties set (e.g., for the elevation profile custom node), it will trigger plot updates but it won't be found due to a still missing custom property.
* [elevation] Make sure legacy layer ordering in canvas, layout item profile, and layer tree are kept (i.e., keep API untouched). Make profile source ordering works in the most expected way: canvas, layout item profile, and layer tree are in the same order, and sources are only reversed right before passing them to renderers. Add unit tests.
* [tests] Custom node for custom Elevation profiles: make sure layout item sources are stored in and read from the project
* Address review on custom nodes for elevation profile's tree view
This commit adds a virtual method to QgsMapLayer to enable the creation of custom
elevation profiles for any type of layer.
The methods returns a pointer to a helper class of type
QgsAbstractProfileSource which is a factory for profile generators
(cf. documentation for QgsAbstractProfileSource).
Existing layers that derive from QgsAbstractProfileSource just override
this method returning a *this* pointer.
As the method is *sipified* it can be used in python to declare custom
profile source for classes derived from PluginLayer (ownership of the
QgsAbstractProfileSource must then be managed on the python side).
QgsChunkedEntity gets a capability to update an existing sub-entity for a node
by loading the node again, creating a new 3D entity, and then discarding the old
entity in favor of the new one.
QgsPointCloudLayer gets a new signal - emitted whenever a particular node's
attribute values get changed.
These two are combined for point cloud layer's 3D chunked entity: whenever there
are edits to the point cloud data, instead of doing big hard reload of the whole
point cloud, we only update entities of the few nodes that were modified.
This greatly improves the user experience of point cloud editing (no "flashing"
of the 3D view while loading everything from scratch), and it improves how quickly
the changes can be seen.
* Add label rendering into VPC tiles
* Move tile labels rendering into QgsPointCloudExtentRenderer
* Rework showLabels flag once more & connect it to widget
* Add widget for label TextFormat WIP
* Rework and fix text format widget issues
* Improve default text format used in VPC labels
* Fix banned keywords issue
* Fix QgsTextFormat review issue
* Fix labels drawing efficiency issue
* Fix formating issues
* Fix review issues
In this mode, the user can specify a QGIS expression for the
lower and upper value corresponding to raster bands, using
variables like @band, @band_name and @band_description.
E.g
@band * 100
Can be used when each band represents a 100 m vertical slice
of data.
The expression will be evaluated when required to determine
the actual elevation range corresponding to each band.
This differs from the existing "Fixed Elevation Range Per Band"
mode in that "Fixed Elevation Range Per Band" requires users
to manually enter an elevation for each band separately,
and these values are then treated as constants. That mode works
best for rasters with non-regular steps in the band
elevation values, while this new mode is better for regular
band elevation steps
The original workaround was only supposed to apply to QList/
QVector of QVariantMaps. By replacing them all in sip we
break mapping of signals defined in c++ which are emitted
by Python code.
Fixes exceptions after running processing algorithms in Qt6
builds.