QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsrasterlayertemporalproperties.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrasterlayertemporalproperties.cpp
3 ---------------
4 begin : February 2020
5 copyright : (C) 2020 by Samweli Mwakisambwe
6 email : samweli at kartoza dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
20#include "qgsrasterlayer.h"
21
23 : QgsMapLayerTemporalProperties( parent, enabled )
24{
25}
26
28{
29 if ( !isActive() )
30 return true;
31
32 switch ( mMode )
33 {
35 return range.isInfinite() || mFixedRange.isInfinite() || mFixedRange.overlaps( range );
36
38 {
39 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
40 {
41 if ( it.value().overlaps( range ) )
42 return true;
43 }
44 return false;
45 }
46
49 return true;
50 }
51 return true;
52}
53
55{
56 QgsRasterLayer *rasterLayer = qobject_cast< QgsRasterLayer *>( layer );
57 if ( !rasterLayer )
58 return QgsDateTimeRange();
59
60 switch ( mMode )
61 {
63 return mFixedRange;
64
67
69 {
70 QDateTime begin;
71 QDateTime end;
72 bool includeBeginning = true;
73 bool includeEnd = true;
74 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
75 {
76 if ( it.value().begin() < begin || !begin.isValid() )
77 {
78 begin = it.value().begin();
79 includeBeginning = it.value().includeBeginning();
80 }
81 else if ( !includeBeginning && it.value().begin() == begin && it.value().includeBeginning() )
82 {
83 includeBeginning = true;
84 }
85 if ( it.value().end() > end || !end.isValid() )
86 {
87 end = it.value().end();
88 includeEnd = it.value().includeEnd();
89 }
90 else if ( !includeEnd && it.value().end() == end && it.value().includeEnd() )
91 {
92 includeEnd = true;
93 }
94 }
95 return QgsDateTimeRange( begin, end, includeBeginning, includeEnd );
96 }
97
99 break;
100 }
101
102 return QgsDateTimeRange();
103}
104
106{
107 QgsRasterLayer *rasterLayer = qobject_cast< QgsRasterLayer *>( layer );
108
109 switch ( mMode )
110 {
112 return { mFixedRange };
113
115 {
116 QList<QgsDateTimeRange> results;
117 results.reserve( mRangePerBand.size() );
118 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
119 {
120 results.append( it.value() );
121 }
122 return results;
123 }
124
126 {
127 if ( !rasterLayer || !rasterLayer->dataProvider() )
128 return {};
129
130 const QList< QgsDateTimeRange > ranges = rasterLayer->dataProvider()->temporalCapabilities()->allAvailableTemporalRanges();
131 return ranges.empty() ? QList< QgsDateTimeRange > { rasterLayer->dataProvider()->temporalCapabilities()->availableTemporalRange() } : ranges;
132 }
133
135 break;
136 }
137
138 return {};
139}
140
142{
143 return mMode;
144}
145
147{
148 if ( mMode == mode )
149 return;
150 mMode = mode;
151}
152
154{
155 switch ( mMode )
156 {
159
164 }
166}
167
169{
170 return mIntervalHandlingMethod;
171}
172
174{
175 if ( mIntervalHandlingMethod == method )
176 return;
177 mIntervalHandlingMethod = method;
178}
179
181{
182 mFixedRange = range;
183}
184
186{
187 return mFixedRange;
188}
189
191{
192 return mRangePerBand;
193}
194
195void QgsRasterLayerTemporalProperties::setFixedRangePerBand( const QMap<int, QgsDateTimeRange> &ranges )
196{
197 if ( mRangePerBand == ranges )
198 return;
199
200 mRangePerBand = ranges;
201 emit changed();
202}
203
205{
206 switch ( mMode )
207 {
211 return -1;
212
214 {
215 // find the latest-most band which matches the map range
216 int currentMatchingBand = -1;
217 QgsDateTimeRange currentMatchingRange;
218 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
219 {
220 if ( it.value().overlaps( range ) )
221 {
222 if ( currentMatchingRange.isInfinite()
223 || ( it.value().includeEnd() && it.value().end() >= currentMatchingRange.end() ) // cppcheck-suppress mismatchingContainerExpression
224 || ( !currentMatchingRange.includeEnd() && it.value().end() >= currentMatchingRange.end() ) ) // cppcheck-suppress mismatchingContainerExpression
225 {
226 currentMatchingBand = it.key();
227 currentMatchingRange = it.value();
228 }
229 }
230 }
231 return currentMatchingBand;
232 }
233 }
235}
236
237bool QgsRasterLayerTemporalProperties::readXml( const QDomElement &element, const QgsReadWriteContext &context )
238{
239 Q_UNUSED( context )
240 // TODO add support for raster layers with multi-temporal properties.
241
242 const QDomElement temporalNode = element.firstChildElement( QStringLiteral( "temporal" ) );
243
244 setIsActive( temporalNode.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ).toInt() );
245
246 mMode = static_cast< Qgis::RasterTemporalMode >( temporalNode.attribute( QStringLiteral( "mode" ), QStringLiteral( "0" ) ). toInt() );
247 mIntervalHandlingMethod = static_cast< Qgis::TemporalIntervalMatchMethod >( temporalNode.attribute( QStringLiteral( "fetchMode" ), QStringLiteral( "0" ) ). toInt() );
248
249 switch ( mMode )
250 {
252 {
253 const QDomNode rangeElement = temporalNode.namedItem( QStringLiteral( "fixedRange" ) );
254
255 const QDomNode begin = rangeElement.namedItem( QStringLiteral( "start" ) );
256 const QDomNode end = rangeElement.namedItem( QStringLiteral( "end" ) );
257
258 const QDateTime beginDate = QDateTime::fromString( begin.toElement().text(), Qt::ISODate );
259 const QDateTime endDate = QDateTime::fromString( end.toElement().text(), Qt::ISODate );
260
261 const QgsDateTimeRange range = QgsDateTimeRange( beginDate, endDate );
262 setFixedTemporalRange( range );
263 break;
264 }
265
267 {
268 mRangePerBand.clear();
269
270 const QDomNodeList ranges = temporalNode.firstChildElement( QStringLiteral( "ranges" ) ).childNodes();
271 for ( int i = 0; i < ranges.size(); ++i )
272 {
273 const QDomElement rangeElement = ranges.at( i ).toElement();
274 const int band = rangeElement.attribute( QStringLiteral( "band" ) ).toInt();
275 const QDateTime begin = QDateTime::fromString( rangeElement.attribute( QStringLiteral( "begin" ) ), Qt::ISODate );
276 const QDateTime end = QDateTime::fromString( rangeElement.attribute( QStringLiteral( "end" ) ), Qt::ISODate );
277 const bool includeBeginning = rangeElement.attribute( QStringLiteral( "includeBeginning" ) ).toInt();
278 const bool includeEnd = rangeElement.attribute( QStringLiteral( "includeEnd" ) ).toInt();
279 mRangePerBand.insert( band, QgsDateTimeRange( begin, end, includeBeginning, includeEnd ) );
280 }
281 break;
282 }
283
286 break;
287 }
288
289 return true;
290}
291
292QDomElement QgsRasterLayerTemporalProperties::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context )
293{
294 Q_UNUSED( context )
295 if ( element.isNull() )
296 return QDomElement();
297
298 QDomElement temporalElement = document.createElement( QStringLiteral( "temporal" ) );
299 temporalElement.setAttribute( QStringLiteral( "enabled" ), isActive() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
300 temporalElement.setAttribute( QStringLiteral( "mode" ), QString::number( static_cast< int >( mMode ) ) );
301 temporalElement.setAttribute( QStringLiteral( "fetchMode" ), QString::number( static_cast< int >( mIntervalHandlingMethod ) ) );
302
303 switch ( mMode )
304 {
306 {
307
308 QDomElement rangeElement = document.createElement( QStringLiteral( "fixedRange" ) );
309
310 QDomElement startElement = document.createElement( QStringLiteral( "start" ) );
311 QDomElement endElement = document.createElement( QStringLiteral( "end" ) );
312
313 const QDomText startText = document.createTextNode( mFixedRange.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
314 const QDomText endText = document.createTextNode( mFixedRange.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
315 startElement.appendChild( startText );
316 endElement.appendChild( endText );
317 rangeElement.appendChild( startElement );
318 rangeElement.appendChild( endElement );
319
320 temporalElement.appendChild( rangeElement );
321 break;
322 }
323
325 {
326 QDomElement ranges = document.createElement( QStringLiteral( "ranges" ) );
327 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
328 {
329 QDomElement range = document.createElement( QStringLiteral( "range" ) );
330 range.setAttribute( QStringLiteral( "band" ), it.key() );
331 range.setAttribute( QStringLiteral( "begin" ), it.value().begin().toString( Qt::ISODate ) );
332 range.setAttribute( QStringLiteral( "end" ), it.value().end().toString( Qt::ISODate ) );
333 range.setAttribute( QStringLiteral( "includeBeginning" ), it.value().includeBeginning() ? "1" : "0" );
334 range.setAttribute( QStringLiteral( "includeEnd" ), it.value().includeEnd() ? "1" : "0" );
335 ranges.appendChild( range );
336 }
337 temporalElement.appendChild( ranges );
338 break;
339 }
340
343 break;
344 }
345
346 element.appendChild( temporalElement );
347
348 return element;
349}
350
352{
353 if ( const QgsRasterDataProviderTemporalCapabilities *rasterCaps = dynamic_cast< const QgsRasterDataProviderTemporalCapabilities *>( capabilities ) )
354 {
355 setIsActive( rasterCaps->hasTemporalCapabilities() );
356 setFixedTemporalRange( rasterCaps->availableTemporalRange() );
357
358 if ( rasterCaps->hasTemporalCapabilities() )
359 {
361 }
362
363 mIntervalHandlingMethod = rasterCaps->intervalHandlingMethod();
364 }
365}
TemporalIntervalMatchMethod
Method to use when resolving a temporal range to a data provider layer or band.
Definition: qgis.h:2157
RasterTemporalMode
Raster layer temporal modes.
Definition: qgis.h:2143
@ RedrawLayerOnly
Redraw the layer when temporal range changes, but don't apply any filtering. Useful when raster symbo...
@ FixedRangePerBand
Layer has a fixed temporal range per band (since QGIS 3.38)
@ TemporalRangeFromDataProvider
Mode when raster layer delegates temporal range handling to the dataprovider.
@ FixedTemporalRange
Mode when temporal properties have fixed start and end datetimes.
Base class for handling properties relating to a data provider's temporal capabilities.
Base class for storage of map layer temporal properties.
Base class for all map layer types.
Definition: qgsmaplayer.h:75
Implementation of data provider temporal properties for QgsRasterDataProviders.
QList< QgsDateTimeRange > allAvailableTemporalRanges() const
Returns a list of all valid datetime ranges for which temporal data is available from the provider.
const QgsDateTimeRange & availableTemporalRange() const
Returns the overall datetime range extent from which temporal data is available from the provider.
QgsRasterDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
QDomElement writeXml(QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context) override
Writes the properties to a DOM element, to be used later with readXml().
void setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities *capabilities) override
Sets the layers temporal settings to appropriate defaults based on a provider's temporal capabilities...
bool isVisibleInTemporalRange(const QgsDateTimeRange &range) const override
Returns true if the layer should be visible and rendered for the specified time range.
QgsTemporalProperty::Flags flags() const override
Returns flags associated to the temporal property.
Qgis::TemporalIntervalMatchMethod intervalHandlingMethod() const
Returns the desired method to use when resolving a temporal interval to matching layers or bands in t...
void setIntervalHandlingMethod(Qgis::TemporalIntervalMatchMethod method)
Sets the desired method to use when resolving a temporal interval to matching layers or bands in the ...
Qgis::RasterTemporalMode mode() const
Returns the temporal properties mode.
int bandForTemporalRange(QgsRasterLayer *layer, const QgsDateTimeRange &range) const
Returns the band corresponding to the specified range.
QList< QgsDateTimeRange > allTemporalRanges(QgsMapLayer *layer) const override
Attempts to calculate the overall list of all temporal extents which are contained in the specified l...
void setMode(Qgis::RasterTemporalMode mode)
Sets the temporal properties mode.
QgsRasterLayerTemporalProperties(QObject *parent=nullptr, bool enabled=false)
Constructor for QgsRasterLayerTemporalProperties, with the specified parent object.
void setFixedTemporalRange(const QgsDateTimeRange &range)
Sets a temporal range to apply to the whole layer.
void setFixedRangePerBand(const QMap< int, QgsDateTimeRange > &ranges)
Sets the fixed temporal range for each band.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context) override
Reads temporal properties from a DOM element previously written by writeXml().
QMap< int, QgsDateTimeRange > fixedRangePerBand() const
Returns the fixed temporal range for each band.
const QgsDateTimeRange & fixedTemporalRange() const
Returns the fixed temporal range for the layer.
QgsDateTimeRange calculateTemporalExtent(QgsMapLayer *layer) const override
Attempts to calculate the overall temporal extent for the specified layer, using the settings defined...
Represents a raster layer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
The class is used as a container of context for various read/write operations on other objects.
void changed()
Emitted when the temporal properties have changed.
bool isActive() const
Returns true if the temporal property is active.
void setIsActive(bool active)
Sets whether the temporal property is active.
@ FlagDontInvalidateCachedRendersWhenRangeChanges
Any cached rendering will not be invalidated when temporal range context is modified.
T begin() const
Returns the beginning of the range.
Definition: qgsrange.h:444
T end() const
Returns the upper bound of the range.
Definition: qgsrange.h:451
bool overlaps(const QgsTemporalRange< T > &other) const
Returns true if this range overlaps another range.
Definition: qgsrange.h:569
bool includeEnd() const
Returns true if the end is inclusive, or false if the end is exclusive.
Definition: qgsrange.h:466
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition: qgsrange.h:480
#define BUILTIN_UNREACHABLE
Definition: qgis.h:5853
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition: qgsrange.h:742