1 /***************************************************************************
2 qgsmeshdatasetgroupstore.cpp
3 ---------------------
4 begin : June 2020
5 copyright : (C) 2020 by Vincent Cloarec
6 email : vcloarec 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 "qgsmeshdatasetgroupstore.h"
19 #include "qgsmeshlayer.h"
20 #include "qgsmeshlayerutils.h"
21 #include "qgsapplication.h"
22 #include "qgsmeshvirtualdatasetgroup.h"
23 #include "qgslogger.h"
24
datasetGroupIndexes() const25 QList<int> QgsMeshDatasetGroupStore::datasetGroupIndexes() const
26 {
27 return mRegistery.keys();
28 }
29
enabledDatasetGroupIndexes() const30 QList<int> QgsMeshDatasetGroupStore::enabledDatasetGroupIndexes() const
31 {
32 return mDatasetGroupTreeRootItem->enabledDatasetGroupIndexes();
33 }
34
datasetGroupCount() const35 int QgsMeshDatasetGroupStore::datasetGroupCount() const
36 {
37 return mRegistery.count();
38 }
39
extraDatasetGroupCount() const40 int QgsMeshDatasetGroupStore::extraDatasetGroupCount() const
41 {
42 return mExtraDatasets->datasetGroupCount();
43 }
44
QgsMeshDatasetGroupStore(QgsMeshLayer * layer)45 QgsMeshDatasetGroupStore::QgsMeshDatasetGroupStore( QgsMeshLayer *layer ):
46 mLayer( layer ),
47 mExtraDatasets( new QgsMeshExtraDatasetStore ),
48 mDatasetGroupTreeRootItem( new QgsMeshDatasetGroupTreeItem )
49 {}
50
setPersistentProvider(QgsMeshDataProvider * provider,const QStringList & extraDatasetUri)51 void QgsMeshDatasetGroupStore::setPersistentProvider( QgsMeshDataProvider *provider, const QStringList &extraDatasetUri )
52 {
53 removePersistentProvider();
54 mPersistentProvider = provider;
55 if ( !mPersistentProvider )
56 return;
57 for ( const QString &uri : extraDatasetUri )
58 mPersistentProvider->addDataset( uri );
59
60 onPersistentDatasetAdded( mPersistentProvider->datasetGroupCount() );
61
62 checkDatasetConsistency( mPersistentProvider );
63 removeUnregisteredItemFromTree();
64
65 //Once everything is in place, initialize the extra dataset groups
66 if ( mExtraDatasets )
67 {
68 const int groupCount = mExtraDatasets->datasetGroupCount();
69 for ( int i = 0; i < groupCount; ++i )
70 if ( mExtraDatasets->datasetGroup( i ) )
71 mExtraDatasets->datasetGroup( i )->initialize();
72 }
73
74 mExtraDatasets->updateTemporalCapabilities();
75
76 connect( mPersistentProvider, &QgsMeshDataProvider::datasetGroupsAdded, this, &QgsMeshDatasetGroupStore::onPersistentDatasetAdded );
77 }
78
datasetGroup(int index) const79 QgsMeshDatasetGroupStore::DatasetGroup QgsMeshDatasetGroupStore::datasetGroup( int index ) const
80 {
81 if ( mRegistery.contains( index ) )
82 return mRegistery[index];
83 else
84 return DatasetGroup{nullptr, -1};
85 }
86
addPersistentDatasets(const QString & path)87 bool QgsMeshDatasetGroupStore::addPersistentDatasets( const QString &path )
88 {
89 if ( !mPersistentProvider )
90 return false;
91 return mPersistentProvider->addDataset( path ) ;
92 }
93
addDatasetGroup(QgsMeshDatasetGroup * group)94 bool QgsMeshDatasetGroupStore::addDatasetGroup( QgsMeshDatasetGroup *group )
95 {
96 if ( !mExtraDatasets && !mLayer )
97 return false;
98
99 switch ( group->dataType() )
100 {
101 case QgsMeshDatasetGroupMetadata::DataOnFaces:
102 if ( ! group->checkValueCountPerDataset( mLayer->meshFaceCount() ) )
103 return false;
104 break;
105 case QgsMeshDatasetGroupMetadata::DataOnVertices:
106 if ( ! group->checkValueCountPerDataset( mLayer->meshVertexCount() ) )
107 return false;
108 break;
109 case QgsMeshDatasetGroupMetadata::DataOnVolumes:
110 return false; // volume not supported for extra dataset
111 break;
112 case QgsMeshDatasetGroupMetadata::DataOnEdges:
113 if ( ! group->checkValueCountPerDataset( mLayer->meshEdgeCount() ) )
114 return false;
115 break;
116 }
117
118 int nativeIndex = mExtraDatasets->addDatasetGroup( group );
119 int groupIndex = registerDatasetGroup( DatasetGroup{mExtraDatasets.get(), nativeIndex} );
120 QList<int> groupIndexes;
121 groupIndexes.append( groupIndex );
122 createDatasetGroupTreeItems( groupIndexes );
123 syncItemToDatasetGroup( groupIndex );
124
125 emit datasetGroupsAdded( groupIndexes );
126
127 return true;
128 }
129
resetDatasetGroupTreeItem()130 void QgsMeshDatasetGroupStore::resetDatasetGroupTreeItem()
131 {
132 mDatasetGroupTreeRootItem.reset( new QgsMeshDatasetGroupTreeItem );
133 createDatasetGroupTreeItems( datasetGroupIndexes() );
134 QList<int> groupIndexes = datasetGroupIndexes();
135 for ( int groupIndex : groupIndexes )
136 syncItemToDatasetGroup( groupIndex );
137 }
138
datasetGroupTreeItem() const139 QgsMeshDatasetGroupTreeItem *QgsMeshDatasetGroupStore::datasetGroupTreeItem() const
140 {
141 return mDatasetGroupTreeRootItem.get();
142 }
143
setDatasetGroupTreeItem(QgsMeshDatasetGroupTreeItem * rootItem)144 void QgsMeshDatasetGroupStore::setDatasetGroupTreeItem( QgsMeshDatasetGroupTreeItem *rootItem )
145 {
146 if ( rootItem )
147 mDatasetGroupTreeRootItem.reset( rootItem->clone() );
148 else
149 mDatasetGroupTreeRootItem.reset();
150
151 unregisterGroupNotPresentInTree();
152 }
153
datasetGroupMetadata(const QgsMeshDatasetIndex & index) const154 QgsMeshDatasetGroupMetadata QgsMeshDatasetGroupStore::datasetGroupMetadata( const QgsMeshDatasetIndex &index ) const
155 {
156 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
157 if ( group.first )
158 return group.first->datasetGroupMetadata( group.second );
159 else
160 return QgsMeshDatasetGroupMetadata();
161 }
162
datasetCount(int groupIndex) const163 int QgsMeshDatasetGroupStore::datasetCount( int groupIndex ) const
164 {
165 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
166 if ( group.first )
167 return group.first->datasetCount( group.second );
168 else
169 return 0;
170 }
171
datasetMetadata(const QgsMeshDatasetIndex & index) const172 QgsMeshDatasetMetadata QgsMeshDatasetGroupStore::datasetMetadata( const QgsMeshDatasetIndex &index ) const
173 {
174 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
175 if ( group.first )
176 return group.first->datasetMetadata( QgsMeshDatasetIndex( group.second, index.dataset() ) );
177 else
178 return QgsMeshDatasetMetadata();
179 }
180
datasetValue(const QgsMeshDatasetIndex & index,int valueIndex) const181 QgsMeshDatasetValue QgsMeshDatasetGroupStore::datasetValue( const QgsMeshDatasetIndex &index, int valueIndex ) const
182 {
183 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
184 if ( group.first )
185 return group.first->datasetValue( QgsMeshDatasetIndex( group.second, index.dataset() ), valueIndex );
186 else
187 return QgsMeshDatasetValue();
188 }
189
datasetValues(const QgsMeshDatasetIndex & index,int valueIndex,int count) const190 QgsMeshDataBlock QgsMeshDatasetGroupStore::datasetValues( const QgsMeshDatasetIndex &index, int valueIndex, int count ) const
191 {
192 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
193 if ( group.first )
194 return group.first->datasetValues( QgsMeshDatasetIndex( group.second, index.dataset() ), valueIndex, count );
195 else
196 return QgsMeshDataBlock();
197 }
198
dataset3dValues(const QgsMeshDatasetIndex & index,int faceIndex,int count) const199 QgsMesh3dDataBlock QgsMeshDatasetGroupStore::dataset3dValues( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
200 {
201 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
202 if ( group.first )
203 return group.first->dataset3dValues( QgsMeshDatasetIndex( group.second, index.dataset() ), faceIndex, count );
204 else
205 return QgsMesh3dDataBlock();
206 }
207
areFacesActive(const QgsMeshDatasetIndex & index,int faceIndex,int count) const208 QgsMeshDataBlock QgsMeshDatasetGroupStore::areFacesActive( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
209 {
210 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
211 if ( group.first )
212 return group.first->areFacesActive( QgsMeshDatasetIndex( group.second, index.dataset() ), faceIndex, count );
213 else
214 return QgsMeshDataBlock();
215 }
216
isFaceActive(const QgsMeshDatasetIndex & index,int faceIndex) const217 bool QgsMeshDatasetGroupStore::isFaceActive( const QgsMeshDatasetIndex &index, int faceIndex ) const
218 {
219 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
220 if ( group.first )
221 return group.first->isFaceActive( QgsMeshDatasetIndex( group.second, index.dataset() ), faceIndex );
222 else
223 return false;
224 }
225
datasetIndexAtTime(qint64 time,int groupIndex,QgsMeshDataProviderTemporalCapabilities::MatchingTemporalDatasetMethod method) const226 QgsMeshDatasetIndex QgsMeshDatasetGroupStore::datasetIndexAtTime(
227 qint64 time,
228 int groupIndex, QgsMeshDataProviderTemporalCapabilities::MatchingTemporalDatasetMethod method ) const
229 {
230 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
231 if ( !group.first )
232 return QgsMeshDatasetIndex();
233
234 const QDateTime &referenceTime = mPersistentProvider ? mPersistentProvider->temporalCapabilities()->referenceTime() : QDateTime();
235
236 return QgsMeshDatasetIndex( groupIndex,
237 group.first->datasetIndexAtTime( referenceTime, group.second, time, method ).dataset() );
238 }
239
datasetIndexInTimeInterval(qint64 time1,qint64 time2,int groupIndex) const240 QList<QgsMeshDatasetIndex> QgsMeshDatasetGroupStore::datasetIndexInTimeInterval(
241 qint64 time1,
242 qint64 time2,
243 int groupIndex ) const
244 {
245 const QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
246 if ( !group.first )
247 return QList<QgsMeshDatasetIndex>();
248
249 const QDateTime &referenceTime = mPersistentProvider ? mPersistentProvider->temporalCapabilities()->referenceTime() : QDateTime();
250
251 const QList<QgsMeshDatasetIndex> datasetIndexes = group.first->datasetIndexInTimeInterval( referenceTime, group.second, time1, time2 );
252
253 QList<QgsMeshDatasetIndex> ret;
254 ret.reserve( datasetIndexes.count() );
255
256 for ( const QgsMeshDatasetIndex &sourceDatasetIndex : datasetIndexes )
257 ret.append( QgsMeshDatasetIndex( groupIndex, sourceDatasetIndex.dataset() ) );
258
259 return ret;
260 }
261
datasetRelativeTime(const QgsMeshDatasetIndex & index) const262 qint64 QgsMeshDatasetGroupStore::datasetRelativeTime( const QgsMeshDatasetIndex &index ) const
263 {
264 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
265 if ( !group.first || group.second < 0 )
266 return INVALID_MESHLAYER_TIME;
267
268 QgsMeshDatasetIndex nativeIndex( group.second, index.dataset() );
269
270 if ( group.first == mPersistentProvider )
271 return mPersistentProvider->temporalCapabilities()->datasetTime( nativeIndex );
272 else if ( group.first == mExtraDatasets.get() )
273 return mExtraDatasets->datasetRelativeTime( nativeIndex );
274
275 return INVALID_MESHLAYER_TIME;
276
277 }
278
hasTemporalCapabilities() const279 bool QgsMeshDatasetGroupStore::hasTemporalCapabilities() const
280 {
281 return ( mPersistentProvider && mPersistentProvider->temporalCapabilities()->hasTemporalCapabilities() ) ||
282 ( mExtraDatasets && mExtraDatasets->hasTemporalCapabilities() );
283 }
284
writeXml(QDomDocument & doc,const QgsReadWriteContext & context)285 QDomElement QgsMeshDatasetGroupStore::writeXml( QDomDocument &doc, const QgsReadWriteContext &context )
286 {
287 Q_UNUSED( context );
288 QDomElement storeElement = doc.createElement( QStringLiteral( "mesh-dataset-groups-store" ) );
289 storeElement.appendChild( mDatasetGroupTreeRootItem->writeXml( doc, context ) );
290
291 QMap < int, DatasetGroup>::const_iterator it = mRegistery.constBegin();
292 while ( it != mRegistery.constEnd() )
293 {
294 QDomElement elemDataset;
295 if ( it.value().first == mPersistentProvider )
296 {
297 elemDataset = doc.createElement( QStringLiteral( "mesh-dataset" ) );
298 elemDataset.setAttribute( QStringLiteral( "global-index" ), it.key() );
299 elemDataset.setAttribute( QStringLiteral( "source-type" ), QStringLiteral( "persitent-provider" ) );
300 elemDataset.setAttribute( QStringLiteral( "source-index" ), it.value().second );
301 }
302 else if ( it.value().first == mExtraDatasets.get() )
303 {
304 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( it.key() );
305 if ( item )
306 {
307 elemDataset = mExtraDatasets->writeXml( it.value().second, doc, context );
308 if ( !elemDataset.isNull() )
309 elemDataset.setAttribute( QStringLiteral( "global-index" ), it.key() );
310 }
311 }
312
313 if ( !elemDataset.isNull() )
314 storeElement.appendChild( elemDataset );
315 ++it;
316 }
317
318 return storeElement;
319 }
320
readXml(const QDomElement & storeElem,const QgsReadWriteContext & context)321 void QgsMeshDatasetGroupStore::readXml( const QDomElement &storeElem, const QgsReadWriteContext &context )
322 {
323 Q_UNUSED( context );
324 mRegistery.clear();
325 QDomElement datasetElem = storeElem.firstChildElement( "mesh-dataset" );
326 QMap<int, QgsMeshDatasetGroup *> extraDatasetGroups;
327 while ( !datasetElem.isNull() )
328 {
329 int globalIndex = datasetElem.attribute( QStringLiteral( "global-index" ) ).toInt();
330 int sourceIndex = -1;
331 QgsMeshDatasetSourceInterface *source = nullptr;
332 const QString sourceType = datasetElem.attribute( QStringLiteral( "source-type" ) );
333 if ( sourceType == QLatin1String( "persitent-provider" ) )
334 {
335 source = mPersistentProvider;
336 sourceIndex = datasetElem.attribute( QStringLiteral( "source-index" ) ).toInt();
337 mPersistentExtraDatasetGroupIndexes.append( globalIndex );
338 }
339 else if ( sourceType == QLatin1String( "virtual" ) )
340 {
341 source = mExtraDatasets.get();
342 QString name = datasetElem.attribute( QStringLiteral( "name" ) );
343 QString formula = datasetElem.attribute( QStringLiteral( "formula" ) );
344 qint64 startTime = datasetElem.attribute( QStringLiteral( "start-time" ) ).toLongLong();
345 qint64 endTime = datasetElem.attribute( QStringLiteral( "end-time" ) ).toLongLong();
346
347 QgsMeshDatasetGroup *dsg = new QgsMeshVirtualDatasetGroup( name, formula, mLayer, startTime, endTime );
348 extraDatasetGroups[globalIndex] = dsg;
349 sourceIndex = mExtraDatasets->addDatasetGroup( dsg );
350 }
351 else
352 {
353 QgsDebugMsg( QStringLiteral( "Unhandled source-type: %1." ).arg( sourceType ) );
354 }
355 if ( source )
356 {
357 mRegistery[globalIndex] = DatasetGroup{source, sourceIndex};
358 }
359
360 datasetElem = datasetElem.nextSiblingElement( QStringLiteral( "mesh-dataset" ) );
361 }
362
363 QDomElement rootTreeItemElem = storeElem.firstChildElement( QStringLiteral( "mesh-dataset-group-tree-item" ) );
364 if ( !rootTreeItemElem.isNull() )
365 setDatasetGroupTreeItem( new QgsMeshDatasetGroupTreeItem( rootTreeItemElem, context ) );
366 }
367
globalDatasetGroupIndexInSource(QgsMeshDatasetSourceInterface * source,int nativeGroupIndex) const368 int QgsMeshDatasetGroupStore::globalDatasetGroupIndexInSource( QgsMeshDatasetSourceInterface *source, int nativeGroupIndex ) const
369 {
370 for ( QMap<int, DatasetGroup>::const_iterator it = mRegistery.cbegin(); it != mRegistery.cend(); ++it )
371 {
372 if ( it.value().first == source && it.value().second == nativeGroupIndex )
373 return it.key();
374 }
375
376 return -1;
377 }
378
saveDatasetGroup(QString filePath,int groupIndex,QString driver)379 bool QgsMeshDatasetGroupStore::saveDatasetGroup( QString filePath, int groupIndex, QString driver )
380 {
381 DatasetGroup group = datasetGroup( groupIndex );
382
383 bool fail = true;
384 if ( group.first && group.second >= 0 )
385 fail = mPersistentProvider->persistDatasetGroup( filePath, driver, group.first, group.second );
386
387 if ( !fail )
388 {
389 eraseDatasetGroup( group );
390 group.first = mPersistentProvider;
391 group.second = mPersistentProvider->datasetGroupCount() - 1;
392 mRegistery[groupIndex] = group;
393 //update the item type
394 if ( mDatasetGroupTreeRootItem )
395 {
396 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex );
397 if ( item )
398 item->setPersistentDatasetGroup( filePath );
399 }
400 }
401
402 return fail;
403 }
404
onPersistentDatasetAdded(int count)405 void QgsMeshDatasetGroupStore::onPersistentDatasetAdded( int count )
406 {
407 Q_ASSERT( mPersistentProvider );
408
409 int providerTotalCount = mPersistentProvider->datasetGroupCount();
410 int providerBeginIndex = mPersistentProvider->datasetGroupCount() - count;
411 QList<int> newGroupIndexes;
412 for ( int i = providerBeginIndex; i < providerTotalCount; ++i )
413 {
414 if ( i < mPersistentExtraDatasetGroupIndexes.count() )
415 mRegistery[mPersistentExtraDatasetGroupIndexes.at( i )] = DatasetGroup( mPersistentProvider, i );
416 else
417 newGroupIndexes.append( registerDatasetGroup( DatasetGroup{mPersistentProvider, i} ) );
418 }
419
420 if ( !newGroupIndexes.isEmpty() )
421 {
422 createDatasetGroupTreeItems( newGroupIndexes );
423 mPersistentExtraDatasetGroupIndexes.append( newGroupIndexes );
424
425 for ( int groupIndex : std::as_const( newGroupIndexes ) )
426 syncItemToDatasetGroup( groupIndex );
427
428 emit datasetGroupsAdded( newGroupIndexes );
429 }
430 }
431
removePersistentProvider()432 void QgsMeshDatasetGroupStore::removePersistentProvider()
433 {
434 if ( !mPersistentProvider )
435 return;
436
437 disconnect( mPersistentProvider, &QgsMeshDataProvider::datasetGroupsAdded, this, &QgsMeshDatasetGroupStore::onPersistentDatasetAdded );
438
439 QMap < int, DatasetGroup>::iterator it = mRegistery.begin();
440 while ( it != mRegistery.end() )
441 {
442 if ( it.value().first == mPersistentProvider )
443 it = mRegistery.erase( it );
444 else
445 ++it;
446 }
447
448 mPersistentProvider = nullptr;
449 }
450
newIndex()451 int QgsMeshDatasetGroupStore::newIndex()
452 {
453 int index = 0;
454 QMap < int, DatasetGroup>::iterator it = mRegistery.begin();
455 while ( it != mRegistery.end() )
456 {
457 if ( index <= it.key() )
458 index = it.key() + 1;
459 ++it;
460 }
461 return index;
462 }
463
registerDatasetGroup(const QgsMeshDatasetGroupStore::DatasetGroup & group)464 int QgsMeshDatasetGroupStore::registerDatasetGroup( const QgsMeshDatasetGroupStore::DatasetGroup &group )
465 {
466 int groupIndex = newIndex();
467 mRegistery[newIndex()] = group;
468 return groupIndex;
469 }
470
eraseDatasetGroup(const QgsMeshDatasetGroupStore::DatasetGroup & group)471 void QgsMeshDatasetGroupStore::eraseDatasetGroup( const QgsMeshDatasetGroupStore::DatasetGroup &group )
472 {
473 if ( group.first == mPersistentProvider )
474 return; //removing persistent dataset group from the store is not allowed
475 else if ( group.first == mExtraDatasets.get() )
476 eraseExtraDataset( group.second );
477 }
478
eraseExtraDataset(int indexInExtraStore)479 void QgsMeshDatasetGroupStore::eraseExtraDataset( int indexInExtraStore )
480 {
481 mExtraDatasets->removeDatasetGroup( indexInExtraStore );
482
483 //search dataset with index greater than indexInExtraStore and decrement it
484 QMap < int, DatasetGroup>::iterator it = mRegistery.begin();
485 while ( it != mRegistery.end() )
486 {
487 int localIndex = it.value().second;
488 if ( it.value().first == mExtraDatasets.get() && localIndex > indexInExtraStore )
489 it->second = localIndex - 1;
490 ++it;
491 }
492 }
493
nativeIndexToGroupIndex(QgsMeshDatasetSourceInterface * source,int nativeIndex)494 int QgsMeshDatasetGroupStore::nativeIndexToGroupIndex( QgsMeshDatasetSourceInterface *source, int nativeIndex )
495 {
496 QMap < int, DatasetGroup>::const_iterator it = mRegistery.constBegin();
497 while ( it != mRegistery.constEnd() )
498 {
499 if ( it.value() == DatasetGroup{source, nativeIndex} )
500 return it.key();
501 ++it;
502 }
503 return -1;
504 }
505
checkDatasetConsistency(QgsMeshDatasetSourceInterface * source)506 void QgsMeshDatasetGroupStore::checkDatasetConsistency( QgsMeshDatasetSourceInterface *source )
507 {
508 // check if datasets of source are present, if not, add them
509 QList<int> indexes;
510 for ( int i = 0; i < source->datasetGroupCount(); ++i )
511 if ( nativeIndexToGroupIndex( source, i ) == -1 )
512 indexes.append( registerDatasetGroup( DatasetGroup{source, i} ) );
513
514 if ( !indexes.isEmpty() )
515 createDatasetGroupTreeItems( indexes );
516
517 for ( int globalIndex : mRegistery.keys() )
518 {
519 if ( mRegistery.value( globalIndex ).first == source )
520 syncItemToDatasetGroup( globalIndex );
521 }
522 }
523
removeUnregisteredItemFromTree()524 void QgsMeshDatasetGroupStore::removeUnregisteredItemFromTree()
525 {
526 QList<QgsMeshDatasetGroupTreeItem *> itemsToCheck;
527 QList<int> indexItemToRemove;
528 for ( int i = 0; i < mDatasetGroupTreeRootItem->childCount(); ++i )
529 itemsToCheck.append( mDatasetGroupTreeRootItem->child( i ) );
530
531 while ( !itemsToCheck.isEmpty() )
532 {
533 QgsMeshDatasetGroupTreeItem *item = itemsToCheck.takeFirst();
534 int globalIndex = item->datasetGroupIndex();
535 if ( !mRegistery.contains( globalIndex ) )
536 indexItemToRemove.append( globalIndex );
537 for ( int i = 0; i < item->childCount(); ++i )
538 itemsToCheck.append( item->child( i ) );
539 }
540
541 for ( int i : indexItemToRemove )
542 {
543 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( i );
544 if ( item )
545 item->parentItem()->removeChild( item );
546 }
547 }
548
unregisterGroupNotPresentInTree()549 void QgsMeshDatasetGroupStore::unregisterGroupNotPresentInTree()
550 {
551 if ( !mDatasetGroupTreeRootItem )
552 {
553 mRegistery.clear();
554 return;
555 }
556
557 QMap < int, DatasetGroup>::iterator it = mRegistery.begin();
558 while ( it != mRegistery.end() )
559 {
560 DatasetGroup datasetGroup = it.value();
561 int globalIndex = it.key();
562 if ( ! mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( globalIndex ) // Not in the tree item
563 && datasetGroup.first != mPersistentProvider ) // and not persistent
564 {
565 it = mRegistery.erase( it ); //remove from registery
566 eraseDatasetGroup( datasetGroup ); //remove from where the dataset group is stored
567 }
568 else
569 ++it;
570 }
571 }
572
syncItemToDatasetGroup(int groupIndex)573 void QgsMeshDatasetGroupStore::syncItemToDatasetGroup( int groupIndex )
574 {
575 if ( !mDatasetGroupTreeRootItem )
576 return;
577 DatasetGroup group = datasetGroup( groupIndex );
578 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex );
579 if ( group.first == mPersistentProvider && mPersistentProvider )
580 {
581 QgsMeshDatasetGroupMetadata meta = mPersistentProvider->datasetGroupMetadata( group.second );
582 if ( item )
583 item->setPersistentDatasetGroup( meta.uri() );
584 }
585 else if ( group.first == mExtraDatasets.get() )
586 {
587 if ( item )
588 item->setDatasetGroup( mExtraDatasets->datasetGroup( group.second ) );
589 }
590 }
591
createDatasetGroupTreeItems(const QList<int> & indexes)592 void QgsMeshDatasetGroupStore::createDatasetGroupTreeItems( const QList<int> &indexes )
593 {
594 QMap<QString, QgsMeshDatasetGroupTreeItem *> mNameToItem;
595
596 for ( int i = 0; i < indexes.count(); ++i )
597 {
598 int groupIndex = indexes.at( i );
599 const QgsMeshDatasetGroupMetadata meta = datasetGroupMetadata( groupIndex );
600 const QString name = meta.name();
601 const QStringList subdatasets = name.split( '/' );
602
603 QString displayName = name;
604 QgsMeshDatasetGroupTreeItem *parent = mDatasetGroupTreeRootItem.get();
605
606 if ( subdatasets.size() == 2 )
607 {
608 auto it = mNameToItem.find( subdatasets[0] );
609 if ( it == mNameToItem.end() )
610 QgsDebugMsg( QStringLiteral( "Unable to find parent group for %1." ).arg( name ) );
611 else
612 {
613 displayName = subdatasets[1];
614 parent = it.value();
615 }
616 }
617 else if ( subdatasets.size() != 1 )
618 QgsDebugMsg( QStringLiteral( "Ignoring too deep child group name %1." ).arg( name ) );
619
620 QgsMeshDatasetGroupTreeItem *item = new QgsMeshDatasetGroupTreeItem( displayName, name, meta.isVector(), groupIndex );
621 parent->appendChild( item );
622 if ( mNameToItem.contains( name ) )
623 QgsDebugMsg( QStringLiteral( "Group %1 is not unique" ).arg( displayName ) );
624 mNameToItem[name] = item;
625 }
626 }
627
addDatasetGroup(QgsMeshDatasetGroup * datasetGroup)628 int QgsMeshExtraDatasetStore::addDatasetGroup( QgsMeshDatasetGroup *datasetGroup )
629 {
630 int groupIndex = mGroups.size();
631 mGroups.push_back( std::unique_ptr<QgsMeshDatasetGroup>( datasetGroup ) );
632
633 if ( datasetGroup->datasetCount() > 1 )
634 {
635 mTemporalCapabilities->setHasTemporalCapabilities( true );
636 for ( int i = 0; i < datasetGroup->datasetCount(); ++i )
637 mTemporalCapabilities->addDatasetTime( groupIndex, datasetGroup->datasetMetadata( i ).time() );
638 }
639
640 return mGroups.size() - 1;
641 }
642
removeDatasetGroup(int index)643 void QgsMeshExtraDatasetStore::removeDatasetGroup( int index )
644 {
645 if ( index < datasetGroupCount() )
646 mGroups.erase( mGroups.begin() + index );
647
648
649 updateTemporalCapabilities();
650 }
651
hasTemporalCapabilities() const652 bool QgsMeshExtraDatasetStore::hasTemporalCapabilities() const
653 {
654 return mTemporalCapabilities->hasTemporalCapabilities();
655 }
656
datasetRelativeTime(QgsMeshDatasetIndex index)657 quint64 QgsMeshExtraDatasetStore::datasetRelativeTime( QgsMeshDatasetIndex index )
658 {
659 return mTemporalCapabilities->datasetTime( index );
660 }
661
description(int groupIndex) const662 QString QgsMeshExtraDatasetStore::description( int groupIndex ) const
663 {
664 if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) )
665 return mGroups.at( groupIndex )->description();
666 else
667 return QString();
668 }
669
datasetGroup(int groupIndex) const670 QgsMeshDatasetGroup *QgsMeshExtraDatasetStore::datasetGroup( int groupIndex ) const
671 {
672 if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) )
673 return mGroups[groupIndex].get();
674 else
675 return nullptr;
676 }
677
addDataset(const QString & uri)678 bool QgsMeshExtraDatasetStore::addDataset( const QString &uri )
679 {
680 Q_UNUSED( uri );
681 return false;
682 }
683
extraDatasets() const684 QStringList QgsMeshExtraDatasetStore::extraDatasets() const
685 {
686 return QStringList();
687 }
688
datasetGroupCount() const689 int QgsMeshExtraDatasetStore::datasetGroupCount() const
690 {
691 return mGroups.size();
692 }
693
datasetCount(int groupIndex) const694 int QgsMeshExtraDatasetStore::datasetCount( int groupIndex ) const
695 {
696 if ( groupIndex >= 0 && groupIndex < datasetGroupCount() )
697 return mGroups.at( groupIndex )->datasetCount();
698 else
699 return 0;
700 }
701
datasetGroupMetadata(int groupIndex) const702 QgsMeshDatasetGroupMetadata QgsMeshExtraDatasetStore::datasetGroupMetadata( int groupIndex ) const
703 {
704 if ( groupIndex >= 0 && groupIndex < datasetGroupCount() )
705 return mGroups.at( groupIndex )->groupMetadata();
706 else
707 return QgsMeshDatasetGroupMetadata();
708 }
709
datasetMetadata(QgsMeshDatasetIndex index) const710 QgsMeshDatasetMetadata QgsMeshExtraDatasetStore::datasetMetadata( QgsMeshDatasetIndex index ) const
711 {
712 int groupIndex = index.group();
713 if ( index.isValid() && groupIndex < datasetGroupCount() )
714 {
715 int datasetIndex = index.dataset();
716 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
717 if ( datasetIndex < group->datasetCount() )
718 return group->datasetMetadata( datasetIndex );
719 }
720 return QgsMeshDatasetMetadata();
721 }
722
datasetValue(QgsMeshDatasetIndex index,int valueIndex) const723 QgsMeshDatasetValue QgsMeshExtraDatasetStore::datasetValue( QgsMeshDatasetIndex index, int valueIndex ) const
724 {
725 int groupIndex = index.group();
726 if ( index.isValid() && groupIndex < datasetGroupCount() )
727 {
728 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
729 int datasetIndex = index.dataset();
730 if ( datasetIndex < group->datasetCount() )
731 return group->dataset( datasetIndex )->datasetValue( valueIndex );
732 }
733
734 return QgsMeshDatasetValue();
735 }
736
datasetValues(QgsMeshDatasetIndex index,int valueIndex,int count) const737 QgsMeshDataBlock QgsMeshExtraDatasetStore::datasetValues( QgsMeshDatasetIndex index, int valueIndex, int count ) const
738 {
739 int groupIndex = index.group();
740 if ( index.isValid() && groupIndex < datasetGroupCount() )
741 {
742 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
743 int datasetIndex = index.dataset();
744 if ( datasetIndex < group->datasetCount() )
745 return group->dataset( datasetIndex )->datasetValues( group->isScalar(), valueIndex, count );
746 }
747
748 return QgsMeshDataBlock();
749 }
750
dataset3dValues(QgsMeshDatasetIndex index,int faceIndex,int count) const751 QgsMesh3dDataBlock QgsMeshExtraDatasetStore::dataset3dValues( QgsMeshDatasetIndex index, int faceIndex, int count ) const
752 {
753 // Not supported for now
754 Q_UNUSED( index )
755 Q_UNUSED( faceIndex )
756 Q_UNUSED( count )
757 return QgsMesh3dDataBlock();
758 }
759
isFaceActive(QgsMeshDatasetIndex index,int faceIndex) const760 bool QgsMeshExtraDatasetStore::isFaceActive( QgsMeshDatasetIndex index, int faceIndex ) const
761 {
762 int groupIndex = index.group();
763 if ( index.isValid() && groupIndex < datasetGroupCount() )
764 {
765 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
766 int datasetIndex = index.dataset();
767 if ( datasetIndex < group->datasetCount() )
768 return group->dataset( datasetIndex )->isActive( faceIndex );
769 }
770
771 return false;
772 }
773
areFacesActive(QgsMeshDatasetIndex index,int faceIndex,int count) const774 QgsMeshDataBlock QgsMeshExtraDatasetStore::areFacesActive( QgsMeshDatasetIndex index, int faceIndex, int count ) const
775 {
776 int groupIndex = index.group();
777 if ( index.isValid() && groupIndex < datasetGroupCount() )
778 {
779 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
780 int datasetIndex = index.dataset();
781 if ( datasetIndex < group->datasetCount() )
782 return group->dataset( datasetIndex )->areFacesActive( faceIndex, count );
783 }
784 return QgsMeshDataBlock();
785 }
786
persistDatasetGroup(const QString & outputFilePath,const QString & outputDriver,const QgsMeshDatasetGroupMetadata & meta,const QVector<QgsMeshDataBlock> & datasetValues,const QVector<QgsMeshDataBlock> & datasetActive,const QVector<double> & times)787 bool QgsMeshExtraDatasetStore::persistDatasetGroup( const QString &outputFilePath,
788 const QString &outputDriver,
789 const QgsMeshDatasetGroupMetadata &meta,
790 const QVector<QgsMeshDataBlock> &datasetValues,
791 const QVector<QgsMeshDataBlock> &datasetActive,
792 const QVector<double> × )
793 {
794 Q_UNUSED( outputFilePath )
795 Q_UNUSED( outputDriver )
796 Q_UNUSED( meta )
797 Q_UNUSED( datasetValues )
798 Q_UNUSED( datasetActive )
799 Q_UNUSED( times )
800 return true; // not implemented/supported
801 }
802
persistDatasetGroup(const QString & outputFilePath,const QString & outputDriver,QgsMeshDatasetSourceInterface * source,int datasetGroupIndex)803 bool QgsMeshExtraDatasetStore::persistDatasetGroup( const QString &outputFilePath,
804 const QString &outputDriver,
805 QgsMeshDatasetSourceInterface *source,
806 int datasetGroupIndex )
807 {
808 Q_UNUSED( outputFilePath )
809 Q_UNUSED( outputDriver )
810 Q_UNUSED( source )
811 Q_UNUSED( datasetGroupIndex )
812 return true; // not implemented/supported
813 }
814
writeXml(int groupIndex,QDomDocument & doc,const QgsReadWriteContext & context)815 QDomElement QgsMeshExtraDatasetStore::writeXml( int groupIndex, QDomDocument &doc, const QgsReadWriteContext &context )
816 {
817 if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) && mGroups[groupIndex] )
818 return mGroups[groupIndex]->writeXml( doc, context );
819 else
820 return QDomElement();
821 }
822
updateTemporalCapabilities()823 void QgsMeshExtraDatasetStore::updateTemporalCapabilities()
824 {
825 //update temporal capabilitie
826 mTemporalCapabilities->clear();
827 bool hasTemporal = false;
828 for ( size_t g = 0; g < mGroups.size(); ++g )
829 {
830 const QgsMeshDatasetGroup *group = mGroups[g].get();
831 hasTemporal |= group->datasetCount() > 1;
832 for ( int i = 0; i < group->datasetCount(); ++i )
833 mTemporalCapabilities->addDatasetTime( g, group->datasetMetadata( i ).time() );
834 }
835
836 mTemporalCapabilities->setHasTemporalCapabilities( hasTemporal );
837 }
838