20 #include <QThreadStorage>
44 const QString parentName = mParent->
data(
Name ).toString();
45 if ( !parentName.isEmpty() )
77 Q_ASSERT( !
child->mParent );
78 child->mParent =
this;
80 mChildren.emplace_back( std::move(
child ) );
85 Q_ASSERT(
child->mParent ==
this );
86 auto it = std::find_if( mChildren.begin(), mChildren.end(), [&](
const std::unique_ptr<QgsRuntimeProfilerNode> &p )
88 return p.get() == child;
90 if ( it != mChildren.end() )
91 return std::distance( mChildren.begin(), it );
97 for (
auto &it : mChildren )
99 if ( it->data(
Group ).toString() == group && it->data(
Name ).toString() == name )
107 Q_ASSERT(
static_cast< std::size_t
>( index ) < mChildren.size() );
108 return mChildren[ index ].get();
118 Q_ASSERT(
static_cast< std::size_t
>( index ) < mChildren.size() );
119 mChildren.erase( mChildren.begin() + index );
124 mProfileTime.restart();
129 mElapsed = mProfileTime.elapsed() / 1000.0;
145 for (
auto &it : mChildren )
147 if ( it->data(
Group ).toString() == group )
148 total += it->elapsed();
167 static QThreadStorage<QgsRuntimeProfiler> sInstances;
170 if ( !qApp || profiler->thread() == qApp->thread() )
171 sMainProfiler = profiler;
173 if ( !profiler->mInitialized )
174 profiler->setupConnections();
193 return QStringList();
197 for (
int i = 0; i < parentNode->
childCount(); ++i )
208 std::unique_ptr< QgsRuntimeProfilerNode > node = qgis::make_unique< QgsRuntimeProfilerNode >( group, name );
212 if ( !mCurrentStack[ group ].empty() )
216 const QModelIndex parentIndex = node2index(
parent );
217 beginInsertRows( parentIndex,
parent->childCount(),
parent->childCount() );
218 parent->addChild( std::move( node ) );
223 beginInsertRows( QModelIndex(), mRootNode->childCount(), mRootNode->childCount() );
224 mRootNode->addChild( std::move( node ) );
228 mCurrentStack[group].push( child );
231 if ( !mGroups.contains( group ) )
233 mGroups.insert( group );
240 if ( mCurrentStack[group].empty() )
244 mCurrentStack[group].pop();
247 const QModelIndex nodeIndex = node2index( node );
248 const QModelIndex col2Index =
index( nodeIndex.row(), 1, nodeIndex.parent() );
249 emit dataChanged( nodeIndex, nodeIndex );
250 emit dataChanged( col2Index, col2Index );
252 QModelIndex parentIndex = nodeIndex.parent();
253 while ( parentIndex.isValid() )
255 const QModelIndex parentCol2Index =
index( parentIndex.row(), 1, parentIndex.parent() );
256 emit dataChanged( parentIndex, parentIndex );
257 emit dataChanged( parentCol2Index, parentCol2Index );
258 parentIndex = parentIndex.parent();
275 for (
int row = mRootNode->childCount() - 1; row >= 0; row-- )
279 beginRemoveRows( QModelIndex(), row, row );
280 mRootNode->removeChildAt( row );
289 return node->elapsed();
296 return !mCurrentStack.value( group ).empty();
301 if ( group == QLatin1String(
"startup" ) )
302 return tr(
"Startup" );
303 else if ( group == QLatin1String(
"projectload" ) )
304 return tr(
"Project Load" );
305 else if ( group == QLatin1String(
"render" ) )
306 return tr(
"Map Render" );
329 return QModelIndex();
333 return QModelIndex();
335 return createIndex( row, column, n->
childAt( row ) );
340 if ( !child.isValid() )
341 return QModelIndex();
345 return indexOfParentNode( n->parent() );
350 return QModelIndex();
363 switch (
index.column() )
366 return node->
data( role );
372 case Qt::DisplayRole:
373 case Qt::InitialSortOrderRole:
379 return node->
data( role );
389 case Qt::DisplayRole:
391 if ( orientation == Qt::Horizontal )
398 return tr(
"Time (seconds)" );
410 return QAbstractItemModel::headerData( section, orientation, role );
414 void QgsRuntimeProfiler::otherProfilerStarted(
const QString &group,
const QStringList &path,
const QString &name )
417 for (
const QString &part : path )
422 std::unique_ptr< QgsRuntimeProfilerNode > newChild = qgis::make_unique< QgsRuntimeProfilerNode >( group, part );
424 const QModelIndex parentIndex = node2index( parentNode );
427 parentNode->
addChild( std::move( newChild ) );
437 if ( parentNode->
child( group, name ) )
440 const QModelIndex parentIndex = node2index( parentNode );
442 parentNode->
addChild( qgis::make_unique< QgsRuntimeProfilerNode >( group, name ) );
445 if ( !mGroups.contains( group ) )
447 mGroups.insert( group );
452 void QgsRuntimeProfiler::otherProfilerEnded(
const QString &group,
const QStringList &path,
const QString &name,
double elapsed )
455 for (
const QString &part : path )
460 std::unique_ptr< QgsRuntimeProfilerNode > newChild = qgis::make_unique< QgsRuntimeProfilerNode >( group, part );
462 const QModelIndex parentIndex = node2index( parentNode );
465 parentNode->
addChild( std::move( newChild ) );
478 std::unique_ptr< QgsRuntimeProfilerNode > node = qgis::make_unique< QgsRuntimeProfilerNode >( group, name );
479 destNode = node.get();
480 const QModelIndex parentIndex = node2index( parentNode );
482 parentNode->
addChild( std::move( node ) );
488 const QModelIndex nodeIndex = node2index( destNode );
489 const QModelIndex col2Index =
index( nodeIndex.row(), 1, nodeIndex.parent() );
490 emit dataChanged( nodeIndex, nodeIndex );
491 emit dataChanged( col2Index, col2Index );
493 QModelIndex parentIndex = nodeIndex.parent();
494 while ( parentIndex.isValid() )
496 const QModelIndex parentCol2Index =
index( parentIndex.row(), 1, parentIndex.parent() );
497 emit dataChanged( parentIndex, parentIndex );
498 emit dataChanged( parentCol2Index, parentCol2Index );
499 parentIndex = parentIndex.parent();
503 void QgsRuntimeProfiler::setupConnections()
507 Q_ASSERT( sMainProfiler );
509 if ( sMainProfiler !=
this )
511 connect(
this, &QgsRuntimeProfiler::started, sMainProfiler, &QgsRuntimeProfiler::otherProfilerStarted );
512 connect(
this, &QgsRuntimeProfiler::ended, sMainProfiler, &QgsRuntimeProfiler::otherProfilerEnded );
518 QStringList parts = path.split(
'/' );
520 for (
const QString &part : parts )
522 if ( part.isEmpty() )
525 res = res->
child( group, part );
532 QgsRuntimeProfilerNode *QgsRuntimeProfiler::pathToNode(
const QString &group,
const QStringList &path )
const
535 for (
const QString &part : path )
537 res = res->
child( group, part );
546 if ( !node || !node->
parent() )
547 return QModelIndex();
549 QModelIndex parentIndex = node2index( node->
parent() );
552 Q_ASSERT( row >= 0 );
553 return index( row, 0, parentIndex );
558 Q_ASSERT( parentNode );
561 if ( !grandParentNode )
562 return QModelIndex();
564 int row = grandParentNode->
indexOf( parentNode );
565 Q_ASSERT( row >= 0 );
567 return createIndex( row, 0, parentNode );
572 if ( !
index.isValid() )
573 return mRootNode.get();