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 
18 #include "qgsrasterlayertemporalproperties.h"
19 #include "qgsrasterdataprovidertemporalcapabilities.h"
20 #include "qgsrasterlayer.h"
21 
QgsRasterLayerTemporalProperties(QObject * parent,bool enabled)22 QgsRasterLayerTemporalProperties::QgsRasterLayerTemporalProperties( QObject *parent, bool enabled )
23   :  QgsMapLayerTemporalProperties( parent, enabled )
24 {
25 }
26 
isVisibleInTemporalRange(const QgsDateTimeRange & range) const27 bool QgsRasterLayerTemporalProperties::isVisibleInTemporalRange( const QgsDateTimeRange &range ) const
28 {
29   if ( !isActive() )
30     return true;
31 
32   switch ( mMode )
33   {
34     case Qgis::RasterTemporalMode::FixedTemporalRange:
35       return range.isInfinite() || mFixedRange.isInfinite() || mFixedRange.overlaps( range );
36 
37     case Qgis::RasterTemporalMode::TemporalRangeFromDataProvider:
38     case Qgis::RasterTemporalMode::RedrawLayerOnly:
39       return true;
40   }
41   return true;
42 }
43 
calculateTemporalExtent(QgsMapLayer * layer) const44 QgsDateTimeRange QgsRasterLayerTemporalProperties::calculateTemporalExtent( QgsMapLayer *layer ) const
45 {
46   QgsRasterLayer *rasterLayer = qobject_cast< QgsRasterLayer *>( layer );
47   if ( !rasterLayer )
48     return QgsDateTimeRange();
49 
50   switch ( mMode )
51   {
52     case Qgis::RasterTemporalMode::FixedTemporalRange:
53       return mFixedRange;
54 
55     case Qgis::RasterTemporalMode::TemporalRangeFromDataProvider:
56       return rasterLayer->dataProvider()->temporalCapabilities()->availableTemporalRange();
57 
58     case Qgis::RasterTemporalMode::RedrawLayerOnly:
59       break;
60   }
61 
62   return QgsDateTimeRange();
63 }
64 
allTemporalRanges(QgsMapLayer * layer) const65 QList<QgsDateTimeRange> QgsRasterLayerTemporalProperties::allTemporalRanges( QgsMapLayer *layer ) const
66 {
67   QgsRasterLayer *rasterLayer = qobject_cast< QgsRasterLayer *>( layer );
68   if ( !rasterLayer )
69     return {};
70 
71   switch ( mMode )
72   {
73     case Qgis::RasterTemporalMode::FixedTemporalRange:
74       return { mFixedRange };
75 
76     case Qgis::RasterTemporalMode::TemporalRangeFromDataProvider:
77     {
78       const QList< QgsDateTimeRange > ranges = rasterLayer->dataProvider()->temporalCapabilities()->allAvailableTemporalRanges();
79       return ranges.empty() ? QList< QgsDateTimeRange > { rasterLayer->dataProvider()->temporalCapabilities()->availableTemporalRange() } : ranges;
80     }
81 
82     case Qgis::RasterTemporalMode::RedrawLayerOnly:
83       break;
84   }
85 
86   return {};
87 }
88 
mode() const89 Qgis::RasterTemporalMode QgsRasterLayerTemporalProperties::mode() const
90 {
91   return mMode;
92 }
93 
setMode(Qgis::RasterTemporalMode mode)94 void QgsRasterLayerTemporalProperties::setMode( Qgis::RasterTemporalMode mode )
95 {
96   if ( mMode == mode )
97     return;
98   mMode = mode;
99 }
100 
flags() const101 QgsTemporalProperty::Flags QgsRasterLayerTemporalProperties::flags() const
102 {
103   return mode() == Qgis::RasterTemporalMode::FixedTemporalRange ? QgsTemporalProperty::FlagDontInvalidateCachedRendersWhenRangeChanges : QgsTemporalProperty::Flags();
104 }
105 
intervalHandlingMethod() const106 Qgis::TemporalIntervalMatchMethod QgsRasterLayerTemporalProperties::intervalHandlingMethod() const
107 {
108   return mIntervalHandlingMethod;
109 }
110 
setIntervalHandlingMethod(Qgis::TemporalIntervalMatchMethod method)111 void QgsRasterLayerTemporalProperties::setIntervalHandlingMethod( Qgis::TemporalIntervalMatchMethod method )
112 {
113   if ( mIntervalHandlingMethod == method )
114     return;
115   mIntervalHandlingMethod = method;
116 }
117 
setFixedTemporalRange(const QgsDateTimeRange & range)118 void  QgsRasterLayerTemporalProperties::setFixedTemporalRange( const QgsDateTimeRange &range )
119 {
120   mFixedRange = range;
121 }
122 
fixedTemporalRange() const123 const QgsDateTimeRange &QgsRasterLayerTemporalProperties::fixedTemporalRange() const
124 {
125   return mFixedRange;
126 }
127 
readXml(const QDomElement & element,const QgsReadWriteContext & context)128 bool QgsRasterLayerTemporalProperties::readXml( const QDomElement &element, const QgsReadWriteContext &context )
129 {
130   Q_UNUSED( context )
131   // TODO add support for raster layers with multi-temporal properties.
132 
133   const QDomElement temporalNode = element.firstChildElement( QStringLiteral( "temporal" ) );
134 
135   setIsActive( temporalNode.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ).toInt() );
136 
137   mMode = static_cast< Qgis::RasterTemporalMode >( temporalNode.attribute( QStringLiteral( "mode" ), QStringLiteral( "0" ) ). toInt() );
138   mIntervalHandlingMethod = static_cast< Qgis::TemporalIntervalMatchMethod >( temporalNode.attribute( QStringLiteral( "fetchMode" ), QStringLiteral( "0" ) ). toInt() );
139 
140   const QDomNode rangeElement = temporalNode.namedItem( QStringLiteral( "fixedRange" ) );
141 
142   const QDomNode begin = rangeElement.namedItem( QStringLiteral( "start" ) );
143   const QDomNode end = rangeElement.namedItem( QStringLiteral( "end" ) );
144 
145   const QDateTime beginDate = QDateTime::fromString( begin.toElement().text(), Qt::ISODate );
146   const QDateTime endDate = QDateTime::fromString( end.toElement().text(), Qt::ISODate );
147 
148   const QgsDateTimeRange range = QgsDateTimeRange( beginDate, endDate );
149   setFixedTemporalRange( range );
150 
151   return true;
152 }
153 
writeXml(QDomElement & element,QDomDocument & document,const QgsReadWriteContext & context)154 QDomElement QgsRasterLayerTemporalProperties::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context )
155 {
156   Q_UNUSED( context )
157   if ( element.isNull() )
158     return QDomElement();
159 
160   QDomElement temporalElement = document.createElement( QStringLiteral( "temporal" ) );
161   temporalElement.setAttribute( QStringLiteral( "enabled" ), isActive() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
162   temporalElement.setAttribute( QStringLiteral( "mode" ), QString::number( static_cast< int >( mMode ) ) );
163   temporalElement.setAttribute( QStringLiteral( "fetchMode" ), QString::number( static_cast< int >( mIntervalHandlingMethod ) ) );
164 
165   QDomElement rangeElement = document.createElement( QStringLiteral( "fixedRange" ) );
166 
167   QDomElement startElement = document.createElement( QStringLiteral( "start" ) );
168   QDomElement endElement = document.createElement( QStringLiteral( "end" ) );
169 
170   const QDomText startText = document.createTextNode( mFixedRange.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
171   const QDomText endText = document.createTextNode( mFixedRange.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
172   startElement.appendChild( startText );
173   endElement.appendChild( endText );
174   rangeElement.appendChild( startElement );
175   rangeElement.appendChild( endElement );
176 
177   temporalElement.appendChild( rangeElement );
178 
179   element.appendChild( temporalElement );
180 
181   return element;
182 }
183 
setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities * capabilities)184 void QgsRasterLayerTemporalProperties::setDefaultsFromDataProviderTemporalCapabilities( const QgsDataProviderTemporalCapabilities *capabilities )
185 {
186   if ( const QgsRasterDataProviderTemporalCapabilities *rasterCaps = dynamic_cast< const QgsRasterDataProviderTemporalCapabilities *>( capabilities ) )
187   {
188     setIsActive( rasterCaps->hasTemporalCapabilities() );
189     setFixedTemporalRange( rasterCaps->availableTemporalRange() );
190 
191     if ( rasterCaps->hasTemporalCapabilities() )
192     {
193       setMode( Qgis::RasterTemporalMode::TemporalRangeFromDataProvider );
194     }
195 
196     mIntervalHandlingMethod = rasterCaps->intervalHandlingMethod();
197   }
198 }
199