36#include "moc_qgsrasterlayertemporalpropertieswidget.cpp"
38using namespace Qt::StringLiterals;
48 mFixedRangeLowerExpression = u
"make_datetime(%1,1,1,0,0,0) + make_interval(days:=@band)"_s.arg( QDate::currentDate().year() );
49 mFixedRangeUpperExpression = u
"make_datetime(%1,1,1,23,59,59) + make_interval(days:=@band)"_s.arg( QDate::currentDate().year() );
51 mExtraWidgetLayout =
new QVBoxLayout();
52 mExtraWidgetLayout->setContentsMargins( 0, 0, 0, 0 );
53 mExtraWidgetLayout->addStretch();
54 mExtraWidgetContainer->setLayout( mExtraWidgetLayout );
56 if ( mLayer->dataProvider() && mLayer->dataProvider()->temporalCapabilities()->hasTemporalCapabilities() )
85 mFixedRangePerBandModel =
new QgsRasterBandFixedTemporalRangeModel(
this );
86 mBandRangesTable->verticalHeader()->setVisible(
false );
87 mBandRangesTable->setModel( mFixedRangePerBandModel );
88 QgsFixedTemporalRangeDelegate *tableDelegate =
new QgsFixedTemporalRangeDelegate( mBandRangesTable );
89 mBandRangesTable->setItemDelegateForColumn( 1, tableDelegate );
90 mBandRangesTable->setItemDelegateForColumn( 2, tableDelegate );
92 connect( mModeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsRasterLayerTemporalPropertiesWidget::modeChanged );
94 connect( mTemporalGroupBox, &QGroupBox::toggled,
this, &QgsRasterLayerTemporalPropertiesWidget::temporalGroupBoxChecked );
96 mFixedDateTimeEdit->setDisplayFormat( u
"yyyy-MM-dd HH:mm:ss"_s );
97 mStartTemporalDateTimeEdit->setDisplayFormat( u
"yyyy-MM-dd HH:mm:ss"_s );
98 mEndTemporalDateTimeEdit->setDisplayFormat( u
"yyyy-MM-dd HH:mm:ss"_s );
99 mOffsetDateTimeEdit->setDisplayFormat( u
"yyyy-MM-dd HH:mm:ss"_s );
101 QMenu *calculateFixedRangePerBandMenu =
new QMenu( mCalculateFixedRangePerBandButton );
102 mCalculateFixedRangePerBandButton->setMenu( calculateFixedRangePerBandMenu );
103 mCalculateFixedRangePerBandButton->setPopupMode( QToolButton::InstantPopup );
104 QAction *calculateLowerAction =
new QAction(
"Calculate Beginning by Expression…", calculateFixedRangePerBandMenu );
105 calculateFixedRangePerBandMenu->addAction( calculateLowerAction );
106 connect( calculateLowerAction, &QAction::triggered,
this, [
this] { calculateRangeByExpression(
false ); } );
107 QAction *calculateUpperAction =
new QAction(
"Calculate End by Expression…", calculateFixedRangePerBandMenu );
108 calculateFixedRangePerBandMenu->addAction( calculateUpperAction );
109 connect( calculateUpperAction, &QAction::triggered,
this, [
this] { calculateRangeByExpression(
true ); } );
117 mLayer->temporalProperties()->setIsActive( mTemporalGroupBox->isChecked() );
122 temporalProperties->
setBandNumber( mBandComboBox->currentBand() );
124 switch ( temporalProperties->
mode() )
162 mModeComboBox->setCurrentIndex( mModeComboBox->findData( QVariant::fromValue( temporalProperties->
mode() ) ) );
163 switch ( temporalProperties->
mode() )
166 mStackedWidget->setCurrentWidget( mPageAutomatic );
169 mStackedWidget->setCurrentWidget( mPageFixedDateTime );
172 mStackedWidget->setCurrentWidget( mPageFixedRange );
175 mStackedWidget->setCurrentWidget( mPageRedrawOnly );
178 mStackedWidget->setCurrentWidget( mPageFixedRangePerBand );
181 mStackedWidget->setCurrentWidget( mPageRepresentsTemporalValues );
187 mWidgetFixedRangePerBand->hide();
188 mFixedRangePerBandLabel->setText( tr(
"This mode cannot be used with a multi-band renderer." ) );
191 mBandComboBox->setLayer( mLayer );
192 mBandComboBox->setBand( temporalProperties->
bandNumber() );
198 mFixedRangePerBandModel->setLayerData( mLayer, temporalProperties->
fixedRangePerBand() );
199 mBandRangesTable->horizontalHeader()->setSectionResizeMode( 0, QHeaderView::Stretch );
200 mBandRangesTable->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::Stretch );
201 mBandRangesTable->horizontalHeader()->setSectionResizeMode( 2, QHeaderView::Stretch );
209 mTemporalGroupBox->setChecked( temporalProperties->
isActive() );
213 widget->syncToLayer( mLayer );
219 mExtraWidgets << widget;
220 mExtraWidgetLayout->insertWidget( mExtraWidgetLayout->count() - 1, widget );
223void QgsRasterLayerTemporalPropertiesWidget::temporalGroupBoxChecked(
bool checked )
227 widget->emit dynamicTemporalControlToggled( checked );
231void QgsRasterLayerTemporalPropertiesWidget::modeChanged()
233 if ( mModeComboBox->currentData().isValid() )
238 mStackedWidget->setCurrentWidget( mPageAutomatic );
241 mStackedWidget->setCurrentWidget( mPageFixedDateTime );
244 mStackedWidget->setCurrentWidget( mPageFixedRange );
247 mStackedWidget->setCurrentWidget( mPageRedrawOnly );
250 mStackedWidget->setCurrentWidget( mPageFixedRangePerBand );
253 mStackedWidget->setCurrentWidget( mPageRepresentsTemporalValues );
259void QgsRasterLayerTemporalPropertiesWidget::calculateRangeByExpression(
bool isUpper )
261 QgsExpressionContext expressionContext;
262 QgsExpressionContextScope *bandScope =
new QgsExpressionContextScope();
263 bandScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"band"_s, 1,
true,
false, tr(
"Band number" ) ) );
264 bandScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"band_name"_s, mLayer->dataProvider()->displayBandName( 1 ),
true,
false, tr(
"Band name" ) ) );
265 bandScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"band_description"_s, mLayer->dataProvider()->bandDescription( 1 ),
true,
false, tr(
"Band description" ) ) );
271 QgsExpressionBuilderDialog dlg = QgsExpressionBuilderDialog(
nullptr, isUpper ? mFixedRangeUpperExpression : mFixedRangeLowerExpression,
this, u
"generic"_s, expressionContext );
272 dlg.
setExpectedOutputFormat( !isUpper ? tr(
"Temporal range start date / time" ) : tr(
"Temporal range end date / time" ) );
274 QList<QPair<QString, QVariant>> bandChoices;
275 for (
int band = 1; band <= mLayer->bandCount(); ++band )
277 bandChoices << qMakePair( mLayer->dataProvider()->displayBandName( band ), band );
289 exp.prepare( &expressionContext );
290 for (
int band = 1; band <= mLayer->bandCount(); ++band )
293 bandScope->
setVariable( u
"band_name"_s, mLayer->dataProvider()->displayBandName( band ) );
294 bandScope->
setVariable( u
"band_description"_s, mLayer->dataProvider()->bandDescription( band ) );
296 const QVariant res = exp.evaluate( &expressionContext );
297 mFixedRangePerBandModel->setData( mFixedRangePerBandModel->index( band - 1, isUpper ? 2 : 1 ), res, Qt::EditRole );
302QgsExpressionContext QgsRasterLayerTemporalPropertiesWidget::createExpressionContextForBand(
int band )
const
304 QgsExpressionContext context;
306 QgsExpressionContextScope *bandScope =
new QgsExpressionContextScope();
307 bandScope->
addVariable( QgsExpressionContextScope::StaticVariable( u
"band"_s, band,
true,
false, tr(
"Band number" ) ) );
309 QgsExpressionContextScope::StaticVariable( u
"band_name"_s, ( mLayer && mLayer->dataProvider() ) ? mLayer->dataProvider()->displayBandName( band ) : QString(),
true,
false, tr(
"Band name" ) )
312 QgsExpressionContextScope::StaticVariable( u
"band_description"_s, ( mLayer && mLayer->dataProvider() ) ? mLayer->dataProvider()->bandDescription( band ) : QString(),
true,
false, tr(
"Band description" ) )
325QgsRasterBandFixedTemporalRangeModel::QgsRasterBandFixedTemporalRangeModel( QObject *parent )
326 : QAbstractItemModel( parent )
329int QgsRasterBandFixedTemporalRangeModel::columnCount(
const QModelIndex & )
const
334int QgsRasterBandFixedTemporalRangeModel::rowCount(
const QModelIndex &parent )
const
336 if ( parent.isValid() )
341QModelIndex QgsRasterBandFixedTemporalRangeModel::index(
int row,
int column,
const QModelIndex &parent )
const
343 if ( hasIndex( row, column, parent ) )
345 return createIndex( row, column, row );
348 return QModelIndex();
351QModelIndex QgsRasterBandFixedTemporalRangeModel::parent(
const QModelIndex &child )
const
354 return QModelIndex();
357Qt::ItemFlags QgsRasterBandFixedTemporalRangeModel::flags(
const QModelIndex &index )
const
359 if ( !index.isValid() )
360 return Qt::ItemFlags();
362 if ( index.row() < 0 || index.row() >= mBandCount || index.column() < 0 || index.column() >= columnCount() )
363 return Qt::ItemFlags();
365 switch ( index.column() )
368 return Qt::ItemFlag::ItemIsEnabled;
371 return Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsEditable | Qt::ItemFlag::ItemIsSelectable;
376 return Qt::ItemFlags();
379QVariant QgsRasterBandFixedTemporalRangeModel::data(
const QModelIndex &index,
int role )
const
381 if ( !index.isValid() )
384 if ( index.row() < 0 || index.row() >= mBandCount || index.column() < 0 || index.column() >= columnCount() )
387 const int band = index.row() + 1;
392 case Qt::DisplayRole:
394 case Qt::ToolTipRole:
396 switch ( index.column() )
399 return mBandNames.value( band, QString::number( band ) );
402 return range.
begin().isValid() ? range.
begin() : QVariant();
405 return range.
end().isValid() ? range.
end() : QVariant();
413 case Qt::TextAlignmentRole:
415 switch ( index.column() )
418 return static_cast<Qt::Alignment::Int
>( Qt::AlignLeft | Qt::AlignVCenter );
422 return static_cast<Qt::Alignment::Int
>( Qt::AlignRight | Qt::AlignVCenter );
435QVariant QgsRasterBandFixedTemporalRangeModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
437 if ( role == Qt::DisplayRole && orientation == Qt::Horizontal )
444 return tr(
"Begin" );
451 return QAbstractItemModel::headerData( section, orientation, role );
454bool QgsRasterBandFixedTemporalRangeModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
456 if ( !index.isValid() )
459 if ( index.row() > mBandCount || index.row() < 0 )
462 const int band = index.row() + 1;
469 const QDateTime newValue = value.toDateTime();
470 if ( !newValue.isValid() )
473 switch ( index.column() )
478 emit dataChanged( index, index, QVector<int>() << role );
484 emit dataChanged( index, index, QVector<int>() << role );
500void QgsRasterBandFixedTemporalRangeModel::setLayerData(
QgsRasterLayer *layer,
const QMap<int, QgsDateTimeRange> &ranges )
508 for (
int band = 1; band <= mBandCount; ++band )
520QgsFixedTemporalRangeDelegate::QgsFixedTemporalRangeDelegate( QObject *parent )
521 : QStyledItemDelegate( parent )
524QWidget *QgsFixedTemporalRangeDelegate::createEditor( QWidget *parent,
const QStyleOptionViewItem &,
const QModelIndex & )
const
531void QgsFixedTemporalRangeDelegate::setModelData( QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index )
const
533 if (
QgsDateTimeEdit *dateTimeEdit = qobject_cast<QgsDateTimeEdit *>( editor ) )
535 model->setData( index, dateTimeEdit->dateTime() );
TemporalUnit
Temporal units.
@ Milliseconds
Milliseconds.
RasterTemporalMode
Raster layer temporal modes.
@ RepresentsTemporalValues
Pixel values represent an datetime.
@ 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.
@ TemporalRangeFromDataProvider
Mode when raster layer delegates temporal range handling to the dataprovider.
@ FixedTemporalRange
Mode when temporal properties have fixed start and end datetimes.
@ FixedDateTime
Layer has a fixed date time instant.
@ UsesMultipleBands
The renderer utilizes multiple raster bands for color data (note that alpha bands are not considered ...
static QgsRasterRendererRegistry * rasterRendererRegistry()
Returns the application's raster renderer registry, used for managing raster layer renderers.
A QDateTimeEdit with the capability of setting/reading null date/times.
void setAllowNull(bool allowNull)
Determines if the widget allows setting null date/time.
void setExpectedOutputFormat(const QString &expected)
Set the expected format string, which is shown in the dialog.
QgsExpressionBuilderWidget * expressionBuilder()
The builder widget that is used by the dialog.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
A representation of the interval between two datetime values.
double originalDuration() const
Returns the original interval duration.
Qgis::TemporalUnit originalUnit() const
Returns the original interval temporal unit.
QString displayBandName(int bandNumber) const
Generates a friendly, descriptive name for the specified bandNumber.
Implementation of map layer temporal properties for raster layers.
QDateTime temporalRepresentationOffset() const
Returns the temporal offset, which is a fixed datetime which should be added to individual pixel valu...
void setTemporalRepresentationOffset(const QDateTime &offset)
Sets the temporal offset, which is a fixed datetime which should be added to individual pixel values ...
const QgsInterval & temporalRepresentationScale() const
Returns the scale, which is an interval factor which should be applied to individual pixel values fro...
Qgis::RasterTemporalMode mode() const
Returns the temporal properties mode.
void setAccumulatePixels(bool accumulate)
Sets whether pixels will be accumulated over time (i.e.
void setTemporalRepresentationScale(const QgsInterval &scale)
Sets the scale, which is an interval factor which should be applied to individual pixel values from t...
bool accumulatePixels() const
Returns true if pixels will be accumulated over time (i.e.
void setMode(Qgis::RasterTemporalMode mode)
Sets the temporal properties mode.
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.
QMap< int, QgsDateTimeRange > fixedRangePerBand() const
Returns the fixed temporal range for each band.
int bandNumber() const
Returns the band number from which temporal values should be taken.
const QgsDateTimeRange & fixedTemporalRange() const
Returns the fixed temporal range for the layer.
void setBandNumber(int number)
Sets the band number from which temporal values should be taken.
Represents a raster layer.
int bandCount() const
Returns the number of bands in this layer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
bool isActive() const
Returns true if the temporal property is active.
T begin() const
Returns the beginning of the range.
T end() const
Returns the upper bound of the range.
bool includeEnd() const
Returns true if the end is inclusive, or false if the end is exclusive.
bool includeBeginning() const
Returns true if the beginning is inclusive, or false if the beginning is exclusive.
static Q_INVOKABLE QString toString(Qgis::DistanceUnit unit)
Returns a translated string representing a distance unit.
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.