1 /***************************************************************************
2 qgspostgresrastertemporalsettingswidget.cpp
3 ------------------
4 begin : March 2021
5 copyright : (C) 2021 by Nyall Dawson
6 email : nyall dot dawson at gmail 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 "qgspostgresrastertemporalsettingswidget.h"
19 #include "qgsmaplayer.h"
20 #include "qgsproject.h"
21 #include "qgsrasterlayer.h"
22 #include "qgsprojecttimesettings.h"
23 #include "qgsrasterlayertemporalproperties.h"
24 #include "qgsproviderregistry.h"
25 #include "qgsprovidermetadata.h"
26
QgsPostgresRasterTemporalSettingsWidget(QgsMapLayer * layer,QgsMapCanvas * canvas,QWidget * parent)27 QgsPostgresRasterTemporalSettingsWidget::QgsPostgresRasterTemporalSettingsWidget( QgsMapLayer *layer, QgsMapCanvas *canvas, QWidget *parent )
28 : QgsMapLayerConfigWidget( layer, canvas, parent )
29 , mRasterLayer( qobject_cast< QgsRasterLayer* >( layer ) )
30 {
31 Q_ASSERT( mRasterLayer );
32 Q_ASSERT( mRasterLayer->dataProvider() );
33 Q_ASSERT( mRasterLayer->providerType() == QLatin1String( "postgresraster" ) );
34
35 setupUi( this );
36
37 mPostgresRasterTemporalGroup->setEnabled( true );
38 mPostgresRasterTemporalGroup->setVisible( true );
39 mPostgresRasterTemporalGroup->setChecked( false );
40
41 mPostgresRasterTemporalFieldComboBox->setFilters( QgsFieldProxyModel::Filter::Date |
42 QgsFieldProxyModel::Filter::DateTime |
43 QgsFieldProxyModel::Filter::String );
44 mPostgresRasterTemporalFieldComboBox->setAllowEmptyFieldName( true );
45 connect( mPostgresRasterTemporalFieldComboBox, &QgsFieldComboBox::fieldChanged, this, [ = ]( const QString & fieldName )
46 {
47 mPostgresRasterDefaultTime->setEnabled( ! fieldName.isEmpty() );
48 } );
49 mPostgresRasterDefaultTime->setAllowNull( true );
50 mPostgresRasterDefaultTime->setEmpty();
51 mDefaultTimeStackedWidget->setCurrentIndex( 0 );
52
53 syncToLayer( mRasterLayer );
54 }
55
syncToLayer(QgsMapLayer * layer)56 void QgsPostgresRasterTemporalSettingsWidget::syncToLayer( QgsMapLayer *layer )
57 {
58 mRasterLayer = qobject_cast< QgsRasterLayer * >( layer );
59 const QgsFields fields { mRasterLayer->dataProvider()->fields() };
60 mPostgresRasterTemporalFieldComboBox->setFields( fields );
61
62 mDefaultTimeStackedWidget->setCurrentIndex( 0 );
63 mDefaultTimeComboBox->clear();
64
65 if ( mRasterLayer->dataProvider()->uri().hasParam( QStringLiteral( "temporalFieldIndex" ) ) )
66 {
67 bool ok;
68 const int fieldIdx { mRasterLayer->dataProvider()->uri().param( QStringLiteral( "temporalFieldIndex" ) ).toInt( &ok ) };
69 if ( ok && fields.exists( fieldIdx ) )
70 {
71 mPostgresRasterTemporalGroup->setChecked( true );
72 mPostgresRasterTemporalFieldComboBox->setField( fields.field( fieldIdx ).name() );
73
74 const QList< QgsDateTimeRange > allRanges = mRasterLayer->dataProvider()->temporalCapabilities()->allAvailableTemporalRanges();
75 if ( !allRanges.empty() && allRanges.size() < 50 )
76 {
77 // if an appropriate number of unique ranges is known, show a combo box with these options instead of the free-form
78 // date picker widget
79 mDefaultTimeStackedWidget->setCurrentIndex( 1 );
80 for ( const QgsDateTimeRange &range : allRanges )
81 {
82 mDefaultTimeComboBox->addItem( range.begin().toString( Qt::ISODate ), QVariant::fromValue( range.begin() ) );
83 }
84 }
85
86 if ( mRasterLayer->dataProvider()->uri().hasParam( QStringLiteral( "temporalDefaultTime" ) ) )
87 {
88 const QDateTime defaultDateTime { QDateTime::fromString( mRasterLayer->dataProvider()->uri().param( QStringLiteral( "temporalDefaultTime" ) ), Qt::DateFormat::ISODate ) };
89 if ( defaultDateTime.isValid() )
90 {
91 mPostgresRasterDefaultTime->setDateTime( defaultDateTime );
92
93 if ( const int index = mDefaultTimeComboBox->findData( QVariant::fromValue( defaultDateTime ) ); index >= 0 )
94 mDefaultTimeComboBox->setCurrentIndex( index );
95 else if ( mDefaultTimeComboBox->count() > 0 )
96 mDefaultTimeComboBox->setCurrentIndex( 0 );
97 }
98 }
99 }
100 }
101 }
102
apply()103 void QgsPostgresRasterTemporalSettingsWidget::apply()
104 {
105 QgsDataSourceUri uri { mRasterLayer->dataProvider()->uri() };
106 if ( mPostgresRasterTemporalGroup->isEnabled() &&
107 mPostgresRasterTemporalGroup->isChecked() &&
108 ! mPostgresRasterTemporalFieldComboBox->currentField().isEmpty() )
109 {
110 const QString originaUri { uri.uri() };
111 const int fieldIdx { mRasterLayer->dataProvider()->fields().lookupField( mPostgresRasterTemporalFieldComboBox->currentField() ) };
112 uri.removeParam( QStringLiteral( "temporalFieldIndex" ) );
113 uri.removeParam( QStringLiteral( "temporalDefaultTime" ) );
114 if ( fieldIdx >= 0 )
115 {
116 uri.setParam( QStringLiteral( "temporalFieldIndex" ), QString::number( fieldIdx ) );
117
118 QDateTime defaultDateTime;
119 if ( mDefaultTimeStackedWidget->currentIndex() == 0 )
120 {
121 if ( mPostgresRasterDefaultTime->dateTime().isValid() )
122 {
123 defaultDateTime = mPostgresRasterDefaultTime->dateTime();
124 }
125 }
126 else
127 {
128 if ( mDefaultTimeComboBox->currentData().isValid() )
129 {
130 defaultDateTime = mDefaultTimeComboBox->currentData().value< QDateTime >();
131 }
132 }
133
134 if ( defaultDateTime.isValid() )
135 {
136 const QTime defaultTime { defaultDateTime.time() };
137 // Set secs to 0
138 defaultDateTime.setTime( { defaultTime.hour(), defaultTime.minute(), 0 } );
139 uri.setParam( QStringLiteral( "temporalDefaultTime" ), defaultDateTime.toString( Qt::DateFormat::ISODate ) );
140 }
141
142 if ( uri.uri( ) != originaUri )
143 mRasterLayer->setDataSource( uri.uri(), mRasterLayer->name(), mRasterLayer->providerType(), QgsDataProvider::ProviderOptions() );
144 }
145 }
146 else if ( uri.hasParam( QStringLiteral( "temporalFieldIndex" ) ) )
147 {
148 uri.removeParam( QStringLiteral( "temporalFieldIndex" ) );
149 uri.removeParam( QStringLiteral( "temporalDefaultTime" ) );
150 mRasterLayer->setDataSource( uri.uri(), mRasterLayer->name(), mRasterLayer->providerType(), QgsDataProvider::ProviderOptions() );
151 }
152 }
153
154
155 //
156 // QgsPostgresRasterTemporalSettingsConfigWidgetFactory
157 //
158
supportLayerPropertiesDialog() const159 bool QgsPostgresRasterTemporalSettingsConfigWidgetFactory::supportLayerPropertiesDialog() const
160 {
161 return true;
162 }
163
supportsLayer(QgsMapLayer * layer) const164 bool QgsPostgresRasterTemporalSettingsConfigWidgetFactory::supportsLayer( QgsMapLayer *layer ) const
165 {
166 return layer && layer->isValid() && layer->providerType() == QLatin1String( "postgresraster" );
167 }
168
parentPage() const169 QgsMapLayerConfigWidgetFactory::ParentPage QgsPostgresRasterTemporalSettingsConfigWidgetFactory::parentPage() const
170 {
171 return ParentPage::Temporal;
172 }
173
createWidget(QgsMapLayer * layer,QgsMapCanvas * canvas,bool,QWidget * parent) const174 QgsMapLayerConfigWidget *QgsPostgresRasterTemporalSettingsConfigWidgetFactory::createWidget( QgsMapLayer *layer, QgsMapCanvas *canvas, bool, QWidget *parent ) const
175 {
176 return new QgsPostgresRasterTemporalSettingsWidget( layer, canvas, parent );
177 }
178