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 ModeFixedTemporalRange:
35       return range.isInfinite() || mFixedRange.isInfinite() || mFixedRange.overlaps( range );
36 
37     case ModeTemporalRangeFromDataProvider:
38       return true;
39   }
40   return true;
41 }
42 
calculateTemporalExtent(QgsMapLayer * layer) const43 QgsDateTimeRange QgsRasterLayerTemporalProperties::calculateTemporalExtent( QgsMapLayer *layer ) const
44 {
45   QgsRasterLayer *rasterLayer = qobject_cast< QgsRasterLayer *>( layer );
46   if ( !rasterLayer )
47     return QgsDateTimeRange();
48 
49   switch ( mMode )
50   {
51     case QgsRasterLayerTemporalProperties::ModeFixedTemporalRange:
52       return mFixedRange;
53 
54     case QgsRasterLayerTemporalProperties::ModeTemporalRangeFromDataProvider:
55       return rasterLayer->dataProvider()->temporalCapabilities()->availableTemporalRange();
56   }
57 
58   return QgsDateTimeRange();
59 }
60 
mode() const61 QgsRasterLayerTemporalProperties::TemporalMode QgsRasterLayerTemporalProperties::mode() const
62 {
63   return mMode;
64 }
65 
setMode(QgsRasterLayerTemporalProperties::TemporalMode mode)66 void QgsRasterLayerTemporalProperties::setMode( QgsRasterLayerTemporalProperties::TemporalMode mode )
67 {
68   if ( mMode == mode )
69     return;
70   mMode = mode;
71 }
72 
flags() const73 QgsTemporalProperty::Flags QgsRasterLayerTemporalProperties::flags() const
74 {
75   return mode() == ModeFixedTemporalRange ? QgsTemporalProperty::FlagDontInvalidateCachedRendersWhenRangeChanges : QgsTemporalProperty::Flags();
76 }
77 
intervalHandlingMethod() const78 QgsRasterDataProviderTemporalCapabilities::IntervalHandlingMethod QgsRasterLayerTemporalProperties::intervalHandlingMethod() const
79 {
80   return mIntervalHandlingMethod;
81 }
82 
setIntervalHandlingMethod(QgsRasterDataProviderTemporalCapabilities::IntervalHandlingMethod method)83 void QgsRasterLayerTemporalProperties::setIntervalHandlingMethod( QgsRasterDataProviderTemporalCapabilities::IntervalHandlingMethod method )
84 {
85   if ( mIntervalHandlingMethod == method )
86     return;
87   mIntervalHandlingMethod = method;
88 }
89 
setFixedTemporalRange(const QgsDateTimeRange & range)90 void  QgsRasterLayerTemporalProperties::setFixedTemporalRange( const QgsDateTimeRange &range )
91 {
92   mFixedRange = range;
93 }
94 
fixedTemporalRange() const95 const QgsDateTimeRange &QgsRasterLayerTemporalProperties::fixedTemporalRange() const
96 {
97   return mFixedRange;
98 }
99 
readXml(const QDomElement & element,const QgsReadWriteContext & context)100 bool QgsRasterLayerTemporalProperties::readXml( const QDomElement &element, const QgsReadWriteContext &context )
101 {
102   Q_UNUSED( context )
103   // TODO add support for raster layers with multi-temporal properties.
104 
105   QDomElement temporalNode = element.firstChildElement( QStringLiteral( "temporal" ) );
106 
107   setIsActive( temporalNode.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ).toInt() );
108 
109   mMode = static_cast< TemporalMode >( temporalNode.attribute( QStringLiteral( "mode" ), QStringLiteral( "0" ) ). toInt() );
110   mIntervalHandlingMethod = static_cast< QgsRasterDataProviderTemporalCapabilities::IntervalHandlingMethod >( temporalNode.attribute( QStringLiteral( "fetchMode" ), QStringLiteral( "0" ) ). toInt() );
111 
112   QDomNode rangeElement = temporalNode.namedItem( QStringLiteral( "fixedRange" ) );
113 
114   QDomNode begin = rangeElement.namedItem( QStringLiteral( "start" ) );
115   QDomNode end = rangeElement.namedItem( QStringLiteral( "end" ) );
116 
117   QDateTime beginDate = QDateTime::fromString( begin.toElement().text(), Qt::ISODate );
118   QDateTime endDate = QDateTime::fromString( end.toElement().text(), Qt::ISODate );
119 
120   QgsDateTimeRange range = QgsDateTimeRange( beginDate, endDate );
121   setFixedTemporalRange( range );
122 
123   return true;
124 }
125 
writeXml(QDomElement & element,QDomDocument & document,const QgsReadWriteContext & context)126 QDomElement QgsRasterLayerTemporalProperties::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context )
127 {
128   Q_UNUSED( context )
129   if ( element.isNull() )
130     return QDomElement();
131 
132   QDomElement temporalElement = document.createElement( QStringLiteral( "temporal" ) );
133   temporalElement.setAttribute( QStringLiteral( "enabled" ), isActive() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
134   temporalElement.setAttribute( QStringLiteral( "mode" ), QString::number( mMode ) );
135   temporalElement.setAttribute( QStringLiteral( "fetchMode" ), QString::number( mIntervalHandlingMethod ) );
136 
137   QDomElement rangeElement = document.createElement( QStringLiteral( "fixedRange" ) );
138 
139   QDomElement startElement = document.createElement( QStringLiteral( "start" ) );
140   QDomElement endElement = document.createElement( QStringLiteral( "end" ) );
141 
142   QDomText startText = document.createTextNode( mFixedRange.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
143   QDomText endText = document.createTextNode( mFixedRange.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
144   startElement.appendChild( startText );
145   endElement.appendChild( endText );
146   rangeElement.appendChild( startElement );
147   rangeElement.appendChild( endElement );
148 
149   temporalElement.appendChild( rangeElement );
150 
151   element.appendChild( temporalElement );
152 
153   return element;
154 }
155 
setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities * capabilities)156 void QgsRasterLayerTemporalProperties::setDefaultsFromDataProviderTemporalCapabilities( const QgsDataProviderTemporalCapabilities *capabilities )
157 {
158   if ( const QgsRasterDataProviderTemporalCapabilities *rasterCaps = dynamic_cast< const QgsRasterDataProviderTemporalCapabilities *>( capabilities ) )
159   {
160     setIsActive( rasterCaps->hasTemporalCapabilities() );
161     setFixedTemporalRange( rasterCaps->availableTemporalRange() );
162 
163     if ( rasterCaps->hasTemporalCapabilities() )
164     {
165       setMode( ModeTemporalRangeFromDataProvider );
166     }
167 
168     mIntervalHandlingMethod = rasterCaps->intervalHandlingMethod();
169   }
170 }
171