35#include "moc_qgsrasterlayertemporalpropertieswidget.cpp"
45 mFixedRangeLowerExpression = QStringLiteral(
"make_datetime(%1,1,1,0,0,0) + make_interval(days:=@band)" ).arg( QDate::currentDate().year() );
46 mFixedRangeUpperExpression = QStringLiteral(
"make_datetime(%1,1,1,23,59,59) + make_interval(days:=@band)" ).arg( QDate::currentDate().year() );
48 mExtraWidgetLayout =
new QVBoxLayout();
49 mExtraWidgetLayout->setContentsMargins( 0, 0, 0, 0 );
50 mExtraWidgetLayout->addStretch();
51 mExtraWidgetContainer->setLayout( mExtraWidgetLayout );
53 if ( mLayer->dataProvider() && mLayer->dataProvider()->temporalCapabilities()->hasTemporalCapabilities() )
83 mFixedRangePerBandModel =
new QgsRasterBandFixedTemporalRangeModel(
this );
84 mBandRangesTable->verticalHeader()->setVisible(
false );
85 mBandRangesTable->setModel( mFixedRangePerBandModel );
86 QgsFixedTemporalRangeDelegate *tableDelegate =
new QgsFixedTemporalRangeDelegate( mBandRangesTable );
87 mBandRangesTable->setItemDelegateForColumn( 1, tableDelegate );
88 mBandRangesTable->setItemDelegateForColumn( 2, tableDelegate );
90 connect( mModeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsRasterLayerTemporalPropertiesWidget::modeChanged );
92 connect( mTemporalGroupBox, &QGroupBox::toggled,
this, &QgsRasterLayerTemporalPropertiesWidget::temporalGroupBoxChecked );
94 mFixedDateTimeEdit->setDisplayFormat( QStringLiteral(
"yyyy-MM-dd HH:mm:ss" ) );
95 mStartTemporalDateTimeEdit->setDisplayFormat( QStringLiteral(
"yyyy-MM-dd HH:mm:ss" ) );
96 mEndTemporalDateTimeEdit->setDisplayFormat( QStringLiteral(
"yyyy-MM-dd HH:mm:ss" ) );
97 mOffsetDateTimeEdit->setDisplayFormat( QStringLiteral(
"yyyy-MM-dd HH:mm:ss" ) );
99 QMenu *calculateFixedRangePerBandMenu =
new QMenu( mCalculateFixedRangePerBandButton );
100 mCalculateFixedRangePerBandButton->setMenu( calculateFixedRangePerBandMenu );
101 mCalculateFixedRangePerBandButton->setPopupMode( QToolButton::InstantPopup );
102 QAction *calculateLowerAction =
new QAction(
"Calculate Beginning by Expression…", calculateFixedRangePerBandMenu );
103 calculateFixedRangePerBandMenu->addAction( calculateLowerAction );
104 connect( calculateLowerAction, &QAction::triggered,
this, [
this] {
105 calculateRangeByExpression(
false );
107 QAction *calculateUpperAction =
new QAction(
"Calculate End by Expression…", calculateFixedRangePerBandMenu );
108 calculateFixedRangePerBandMenu->addAction( calculateUpperAction );
109 connect( calculateUpperAction, &QAction::triggered,
this, [
this] {
110 calculateRangeByExpression(
true );
119 mLayer->temporalProperties()->setIsActive( mTemporalGroupBox->isChecked() );
124 temporalProperties->
setBandNumber( mBandComboBox->currentBand() );
126 switch ( temporalProperties->
mode() )
164 mModeComboBox->setCurrentIndex( mModeComboBox->findData( QVariant::fromValue( temporalProperties->
mode() ) ) );
165 switch ( temporalProperties->
mode() )
168 mStackedWidget->setCurrentWidget( mPageAutomatic );
171 mStackedWidget->setCurrentWidget( mPageFixedDateTime );
174 mStackedWidget->setCurrentWidget( mPageFixedRange );
177 mStackedWidget->setCurrentWidget( mPageRedrawOnly );
180 mStackedWidget->setCurrentWidget( mPageFixedRangePerBand );
183 mStackedWidget->setCurrentWidget( mPageRepresentsTemporalValues );
189 mWidgetFixedRangePerBand->hide();
190 mFixedRangePerBandLabel->setText( tr(
"This mode cannot be used with a multi-band renderer." ) );
193 mBandComboBox->setLayer( mLayer );
194 mBandComboBox->setBand( temporalProperties->
bandNumber() );
200 mFixedRangePerBandModel->setLayerData( mLayer, temporalProperties->
fixedRangePerBand() );
201 mBandRangesTable->horizontalHeader()->setSectionResizeMode( 0, QHeaderView::Stretch );
202 mBandRangesTable->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::Stretch );
203 mBandRangesTable->horizontalHeader()->setSectionResizeMode( 2, QHeaderView::Stretch );
211 mTemporalGroupBox->setChecked( temporalProperties->
isActive() );
215 widget->syncToLayer( mLayer );
221 mExtraWidgets << widget;
222 mExtraWidgetLayout->insertWidget( mExtraWidgetLayout->count() - 1, widget );
225void QgsRasterLayerTemporalPropertiesWidget::temporalGroupBoxChecked(
bool checked )
229 widget->emit dynamicTemporalControlToggled( checked );
233void QgsRasterLayerTemporalPropertiesWidget::modeChanged()
235 if ( mModeComboBox->currentData().isValid() )
240 mStackedWidget->setCurrentWidget( mPageAutomatic );
243 mStackedWidget->setCurrentWidget( mPageFixedDateTime );
246 mStackedWidget->setCurrentWidget( mPageFixedRange );
249 mStackedWidget->setCurrentWidget( mPageRedrawOnly );
252 mStackedWidget->setCurrentWidget( mPageFixedRangePerBand );
255 mStackedWidget->setCurrentWidget( mPageRepresentsTemporalValues );
261void QgsRasterLayerTemporalPropertiesWidget::calculateRangeByExpression(
bool isUpper )
263 QgsExpressionContext expressionContext;
264 QgsExpressionContextScope *bandScope =
new QgsExpressionContextScope();
265 bandScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"band" ), 1,
true,
false, tr(
"Band number" ) ) );
266 bandScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"band_name" ), mLayer->dataProvider()->displayBandName( 1 ),
true,
false, tr(
"Band name" ) ) );
267 bandScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"band_description" ), mLayer->dataProvider()->bandDescription( 1 ),
true,
false, tr(
"Band description" ) ) );
271 expressionContext.
setHighlightedVariables( { QStringLiteral(
"band" ), QStringLiteral(
"band_name" ), QStringLiteral(
"band_description" ) } );
273 QgsExpressionBuilderDialog dlg = QgsExpressionBuilderDialog(
nullptr, isUpper ? mFixedRangeUpperExpression : mFixedRangeLowerExpression,
this, QStringLiteral(
"generic" ), expressionContext );
274 dlg.
setExpectedOutputFormat( !isUpper ? tr(
"Temporal range start date / time" ) : tr(
"Temporal range end date / time" ) );
276 QList<QPair<QString, QVariant>> bandChoices;
277 for (
int band = 1; band <= mLayer->bandCount(); ++band )
279 bandChoices << qMakePair( mLayer->dataProvider()->displayBandName( band ), band );
282 return createExpressionContextForBand( value.toInt() );
293 exp.prepare( &expressionContext );
294 for (
int band = 1; band <= mLayer->bandCount(); ++band )
296 bandScope->
setVariable( QStringLiteral(
"band" ), band );
297 bandScope->
setVariable( QStringLiteral(
"band_name" ), mLayer->dataProvider()->displayBandName( band ) );
298 bandScope->
setVariable( QStringLiteral(
"band_description" ), mLayer->dataProvider()->bandDescription( band ) );
300 const QVariant res = exp.evaluate( &expressionContext );
301 mFixedRangePerBandModel->setData( mFixedRangePerBandModel->index( band - 1, isUpper ? 2 : 1 ), res, Qt::EditRole );
306QgsExpressionContext QgsRasterLayerTemporalPropertiesWidget::createExpressionContextForBand(
int band )
const
308 QgsExpressionContext context;
310 QgsExpressionContextScope *bandScope =
new QgsExpressionContextScope();
311 bandScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"band" ), band,
true,
false, tr(
"Band number" ) ) );
312 bandScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"band_name" ), ( mLayer && mLayer->dataProvider() ) ? mLayer->dataProvider()->displayBandName( band ) : QString(),
true,
false, tr(
"Band name" ) ) );
313 bandScope->
addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral(
"band_description" ), ( mLayer && mLayer->dataProvider() ) ? mLayer->dataProvider()->bandDescription( band ) : QString(),
true,
false, tr(
"Band description" ) ) );
315 context.
setHighlightedVariables( { QStringLiteral(
"band" ), QStringLiteral(
"band_name" ), QStringLiteral(
"band_description" ) } );
325QgsRasterBandFixedTemporalRangeModel::QgsRasterBandFixedTemporalRangeModel( QObject *parent )
326 : QAbstractItemModel( parent )
330int QgsRasterBandFixedTemporalRangeModel::columnCount(
const QModelIndex & )
const
335int QgsRasterBandFixedTemporalRangeModel::rowCount(
const QModelIndex &parent )
const
337 if ( parent.isValid() )
342QModelIndex QgsRasterBandFixedTemporalRangeModel::index(
int row,
int column,
const QModelIndex &parent )
const
344 if ( hasIndex( row, column, parent ) )
346 return createIndex( row, column, row );
349 return QModelIndex();
352QModelIndex QgsRasterBandFixedTemporalRangeModel::parent(
const QModelIndex &child )
const
355 return QModelIndex();
358Qt::ItemFlags QgsRasterBandFixedTemporalRangeModel::flags(
const QModelIndex &index )
const
360 if ( !index.isValid() )
361 return Qt::ItemFlags();
363 if ( index.row() < 0 || index.row() >= mBandCount || index.column() < 0 || index.column() >= columnCount() )
364 return Qt::ItemFlags();
366 switch ( index.column() )
369 return Qt::ItemFlag::ItemIsEnabled;
372 return Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsEditable | Qt::ItemFlag::ItemIsSelectable;
377 return Qt::ItemFlags();
380QVariant QgsRasterBandFixedTemporalRangeModel::data(
const QModelIndex &index,
int role )
const
382 if ( !index.isValid() )
385 if ( index.row() < 0 || index.row() >= mBandCount || index.column() < 0 || index.column() >= columnCount() )
388 const int band = index.row() + 1;
393 case Qt::DisplayRole:
395 case Qt::ToolTipRole:
397 switch ( index.column() )
400 return mBandNames.value( band, QString::number( band ) );
403 return range.
begin().isValid() ? range.
begin() : QVariant();
406 return range.
end().isValid() ? range.
end() : QVariant();
414 case Qt::TextAlignmentRole:
416 switch ( index.column() )
419 return static_cast<Qt::Alignment::Int
>( Qt::AlignLeft | Qt::AlignVCenter );
423 return static_cast<Qt::Alignment::Int
>( Qt::AlignRight | Qt::AlignVCenter );
436QVariant QgsRasterBandFixedTemporalRangeModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
438 if ( role == Qt::DisplayRole && orientation == Qt::Horizontal )
445 return tr(
"Begin" );
452 return QAbstractItemModel::headerData( section, orientation, role );
455bool QgsRasterBandFixedTemporalRangeModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
457 if ( !index.isValid() )
460 if ( index.row() > mBandCount || index.row() < 0 )
463 const int band = index.row() + 1;
470 const QDateTime newValue = value.toDateTime();
471 if ( !newValue.isValid() )
474 switch ( index.column() )
479 emit dataChanged( index, index, QVector<int>() << role );
485 emit dataChanged( index, index, QVector<int>() << role );
501void QgsRasterBandFixedTemporalRangeModel::setLayerData(
QgsRasterLayer *layer,
const QMap<int, QgsDateTimeRange> &ranges )
509 for (
int band = 1; band <= mBandCount; ++band )
521QgsFixedTemporalRangeDelegate::QgsFixedTemporalRangeDelegate( QObject *parent )
522 : QStyledItemDelegate( parent )
526QWidget *QgsFixedTemporalRangeDelegate::createEditor( QWidget *parent,
const QStyleOptionViewItem &,
const QModelIndex & )
const
533void QgsFixedTemporalRangeDelegate::setModelData( QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index )
const
535 if (
QgsDateTimeEdit *dateTimeEdit = qobject_cast<QgsDateTimeEdit *>( editor ) )
537 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.