LCOV - code coverage report
Current view: top level - core - qgsruntimeprofiler.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 145 337 43.0 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :     qgsruntimeprofiler.cpp
       3                 :            :     ---------------------
       4                 :            :     begin                : June 2016
       5                 :            :     copyright            : (C) 2016 by Nathan Woodrow
       6                 :            :     email                : woodrow dot nathan at gmail dot com
       7                 :            :  ***************************************************************************
       8                 :            :  *                                                                         *
       9                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      10                 :            :  *   it under the terms of the GNU General Public License as published by  *
      11                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      12                 :            :  *   (at your option) any later version.                                   *
      13                 :            :  *                                                                         *
      14                 :            :  ***************************************************************************/
      15                 :            : #include "qgsruntimeprofiler.h"
      16                 :            : #include "qgslogger.h"
      17                 :            : #include "qgis.h"
      18                 :            : #include "qgsapplication.h"
      19                 :            : #include <QSet>
      20                 :            : #include <QThreadStorage>
      21                 :            : 
      22                 :            : QgsRuntimeProfiler *QgsRuntimeProfiler::sMainProfiler = nullptr;
      23                 :            : 
      24                 :            : 
      25                 :            : //
      26                 :            : // QgsRuntimeProfilerNode
      27                 :            : //
      28                 :            : 
      29                 :        981 : QgsRuntimeProfilerNode::QgsRuntimeProfilerNode( const QString &group, const QString &name )
      30                 :        981 :   : mName( name )
      31                 :        981 :   , mGroup( group )
      32                 :            : {
      33                 :            : 
      34                 :        981 : }
      35                 :            : 
      36                 :        981 : QgsRuntimeProfilerNode::~QgsRuntimeProfilerNode() = default;
      37                 :            : 
      38                 :       6956 : QStringList QgsRuntimeProfilerNode::fullParentPath() const
      39                 :            : {
      40                 :       6956 :   QStringList res;
      41                 :       6956 :   if ( mParent )
      42                 :            :   {
      43                 :       5004 :     res = mParent->fullParentPath();
      44                 :       5004 :     const QString parentName = mParent->data( Name ).toString();
      45                 :       5004 :     if ( !parentName.isEmpty() )
      46                 :       3052 :       res << parentName;
      47                 :       5004 :   }
      48                 :       6956 :   return res;
      49                 :       6956 : }
      50                 :            : 
      51                 :       6956 : QVariant QgsRuntimeProfilerNode::data( int role ) const
      52                 :            : {
      53                 :       6956 :   switch ( role )
      54                 :            :   {
      55                 :            :     case Qt::DisplayRole:
      56                 :            :     case Qt::ToolTipRole:
      57                 :            :     case Name:
      58                 :       5980 :       return mName;
      59                 :            : 
      60                 :            :     case Group:
      61                 :          0 :       return mGroup;
      62                 :            : 
      63                 :            :     case Elapsed:
      64                 :        976 :       return mElapsed;
      65                 :            : 
      66                 :            :     case ParentElapsed:
      67                 :          0 :       return mParent ? ( mParent->elapsed() > 0 ? mParent->elapsed() : mParent->totalElapsedTimeForChildren( mGroup ) ) : 0;
      68                 :            :   }
      69                 :          0 :   return QVariant();
      70                 :       6956 : }
      71                 :            : 
      72                 :        976 : void QgsRuntimeProfilerNode::addChild( std::unique_ptr<QgsRuntimeProfilerNode> child )
      73                 :            : {
      74                 :        976 :   if ( !child )
      75                 :          0 :     return;
      76                 :            : 
      77                 :            :   Q_ASSERT( !child->mParent );
      78                 :        976 :   child->mParent = this;
      79                 :            : 
      80                 :        976 :   mChildren.emplace_back( std::move( child ) );
      81                 :        976 : }
      82                 :            : 
      83                 :       7080 : int QgsRuntimeProfilerNode::indexOf( QgsRuntimeProfilerNode *child ) const
      84                 :            : {
      85                 :            :   Q_ASSERT( child->mParent == this );
      86                 :     158719 :   auto it = std::find_if( mChildren.begin(), mChildren.end(), [&]( const std::unique_ptr<QgsRuntimeProfilerNode> &p )
      87                 :            :   {
      88                 :     151639 :     return p.get() == child;
      89                 :            :   } );
      90                 :       7080 :   if ( it != mChildren.end() )
      91                 :       7080 :     return std::distance( mChildren.begin(), it );
      92                 :          0 :   return -1;
      93                 :       7080 : }
      94                 :            : 
      95                 :          0 : QgsRuntimeProfilerNode *QgsRuntimeProfilerNode::child( const QString &group, const QString &name )
      96                 :            : {
      97                 :          0 :   for ( auto &it : mChildren )
      98                 :            :   {
      99                 :          0 :     if ( it->data( Group ).toString() == group &&  it->data( Name ).toString() == name )
     100                 :          0 :       return it.get();
     101                 :            :   }
     102                 :          0 :   return nullptr;
     103                 :          0 : }
     104                 :            : 
     105                 :       6530 : QgsRuntimeProfilerNode *QgsRuntimeProfilerNode::childAt( int index )
     106                 :            : {
     107                 :            :   Q_ASSERT( static_cast< std::size_t >( index ) < mChildren.size() );
     108                 :       6530 :   return mChildren[ index ].get();
     109                 :            : }
     110                 :            : 
     111                 :          0 : void QgsRuntimeProfilerNode::clear()
     112                 :            : {
     113                 :          0 :   mChildren.clear();
     114                 :          0 : }
     115                 :            : 
     116                 :          0 : void QgsRuntimeProfilerNode::removeChildAt( int index )
     117                 :            : {
     118                 :            :   Q_ASSERT( static_cast< std::size_t >( index ) < mChildren.size() );
     119                 :          0 :   mChildren.erase( mChildren.begin() + index );
     120                 :          0 : }
     121                 :            : 
     122                 :        976 : void QgsRuntimeProfilerNode::start()
     123                 :            : {
     124                 :        976 :   mProfileTime.restart();
     125                 :        976 : }
     126                 :            : 
     127                 :        976 : void QgsRuntimeProfilerNode::stop()
     128                 :            : {
     129                 :        976 :   mElapsed = mProfileTime.elapsed() / 1000.0;
     130                 :        976 : }
     131                 :            : 
     132                 :          0 : void QgsRuntimeProfilerNode::setElapsed( double time )
     133                 :            : {
     134                 :          0 :   mElapsed = time;
     135                 :          0 : }
     136                 :            : 
     137                 :          0 : double QgsRuntimeProfilerNode::elapsed() const
     138                 :            : {
     139                 :          0 :   return mElapsed;
     140                 :            : }
     141                 :            : 
     142                 :          0 : double QgsRuntimeProfilerNode::totalElapsedTimeForChildren( const QString &group ) const
     143                 :            : {
     144                 :          0 :   double total = 0;
     145                 :          0 :   for ( auto &it : mChildren )
     146                 :            :   {
     147                 :          0 :     if ( it->data( Group ).toString() == group )
     148                 :          0 :       total += it->elapsed();
     149                 :            :   }
     150                 :        981 :   return total;
     151                 :          0 : }
     152                 :        981 : 
     153                 :            : //
     154                 :            : // QgsRuntimeProfiler
     155                 :            : //
     156                 :            : 
     157                 :          5 : QgsRuntimeProfiler::QgsRuntimeProfiler()
     158                 :          5 :   : mRootNode( std::make_unique< QgsRuntimeProfilerNode >( QString(), QString() ) )
     159                 :         10 : {
     160                 :            : 
     161                 :          5 : }
     162                 :            : 
     163                 :         10 : QgsRuntimeProfiler::~QgsRuntimeProfiler() = default;
     164                 :            : 
     165                 :       1803 : QgsRuntimeProfiler *QgsRuntimeProfiler::threadLocalInstance()
     166                 :            : {
     167                 :       1803 :   static QThreadStorage<QgsRuntimeProfiler> sInstances;
     168                 :       1803 :   QgsRuntimeProfiler *profiler = &sInstances.localData();
     169                 :            : 
     170                 :       1803 :   if ( !qApp || profiler->thread() == qApp->thread() )
     171                 :       1803 :     sMainProfiler = profiler;
     172                 :            : 
     173                 :       1803 :   if ( !profiler->mInitialized )
     174                 :          5 :     profiler->setupConnections();
     175                 :            : 
     176                 :       1803 :   return profiler;
     177                 :          0 : }
     178                 :            : 
     179                 :          0 : void QgsRuntimeProfiler::beginGroup( const QString &name )
     180                 :            : {
     181                 :          0 :   start( name );
     182                 :          0 : }
     183                 :            : 
     184                 :          0 : void QgsRuntimeProfiler::endGroup()
     185                 :            : {
     186                 :          0 :   end();
     187                 :          0 : }
     188                 :            : 
     189                 :          0 : QStringList QgsRuntimeProfiler::childGroups( const QString &parent, const QString &group ) const
     190                 :            : {
     191                 :          0 :   QgsRuntimeProfilerNode *parentNode = pathToNode( group, parent );
     192                 :          0 :   if ( !parentNode )
     193                 :          0 :     return QStringList();
     194                 :            : 
     195                 :          0 :   QStringList res;
     196                 :          0 :   res.reserve( parentNode->childCount() );
     197                 :          0 :   for ( int i = 0; i < parentNode->childCount(); ++i )
     198                 :            :   {
     199                 :          0 :     QgsRuntimeProfilerNode *child = parentNode->childAt( i );
     200                 :          0 :     if ( child->data( QgsRuntimeProfilerNode::Group ).toString() == group )
     201                 :          0 :       res << child->data( QgsRuntimeProfilerNode::Name ).toString();
     202                 :          0 :   }
     203                 :          0 :   return res;
     204                 :          0 : }
     205                 :            : 
     206                 :        976 : void QgsRuntimeProfiler::start( const QString &name, const QString &group )
     207                 :            : {
     208                 :        976 :   std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name );
     209                 :        976 :   node->start();
     210                 :            : 
     211                 :        976 :   QgsRuntimeProfilerNode *child = node.get();
     212                 :        976 :   if ( !mCurrentStack[ group ].empty() )
     213                 :            :   {
     214                 :        796 :     QgsRuntimeProfilerNode *parent = mCurrentStack[group ].top();
     215                 :            : 
     216                 :        796 :     const QModelIndex parentIndex = node2index( parent );
     217                 :        796 :     beginInsertRows( parentIndex, parent->childCount(), parent->childCount() );
     218                 :        796 :     parent->addChild( std::move( node ) );
     219                 :        796 :     endInsertRows();
     220                 :        796 :   }
     221                 :            :   else
     222                 :            :   {
     223                 :        180 :     beginInsertRows( QModelIndex(), mRootNode->childCount(), mRootNode->childCount() );
     224                 :        180 :     mRootNode->addChild( std::move( node ) );
     225                 :        180 :     endInsertRows();
     226                 :            :   }
     227                 :            : 
     228                 :        976 :   mCurrentStack[group].push( child );
     229                 :        976 :   emit started( group, child->fullParentPath(), name );
     230                 :            : 
     231                 :        976 :   if ( !mGroups.contains( group ) )
     232                 :            :   {
     233                 :          5 :     mGroups.insert( group );
     234                 :          5 :     emit groupAdded( group );
     235                 :          5 :   }
     236                 :        976 : }
     237                 :            : 
     238                 :        976 : void QgsRuntimeProfiler::end( const QString &group )
     239                 :            : {
     240                 :        976 :   if ( mCurrentStack[group].empty() )
     241                 :          0 :     return;
     242                 :            : 
     243                 :        976 :   QgsRuntimeProfilerNode *node = mCurrentStack[group].top();
     244                 :        976 :   mCurrentStack[group].pop();
     245                 :        976 :   node->stop();
     246                 :            : 
     247                 :        976 :   const QModelIndex nodeIndex = node2index( node );
     248                 :        976 :   const QModelIndex col2Index = index( nodeIndex.row(), 1, nodeIndex.parent() );
     249                 :        976 :   emit dataChanged( nodeIndex, nodeIndex );
     250                 :        976 :   emit dataChanged( col2Index, col2Index );
     251                 :            :   // parent item has data changed too, cos the overall time elapsed will have changed!
     252                 :        976 :   QModelIndex parentIndex = nodeIndex.parent();
     253                 :       2502 :   while ( parentIndex.isValid() )
     254                 :            :   {
     255                 :       1526 :     const QModelIndex parentCol2Index = index( parentIndex.row(), 1, parentIndex.parent() );
     256                 :       1526 :     emit dataChanged( parentIndex, parentIndex );
     257                 :       1526 :     emit dataChanged( parentCol2Index, parentCol2Index );
     258                 :       1526 :     parentIndex = parentIndex.parent();
     259                 :            :   }
     260                 :            : 
     261                 :        976 :   emit ended( group, node->fullParentPath(), node->data( QgsRuntimeProfilerNode::Name ).toString(), node->data( QgsRuntimeProfilerNode::Elapsed ).toDouble() );
     262                 :        976 : }
     263                 :            : 
     264                 :          0 : double QgsRuntimeProfiler::profileTime( const QString &name, const QString &group ) const
     265                 :            : {
     266                 :          0 :   QgsRuntimeProfilerNode *node = pathToNode( group, name );
     267                 :          0 :   if ( !node )
     268                 :          0 :     return 0;
     269                 :            : 
     270                 :          0 :   return node->data( QgsRuntimeProfilerNode::Elapsed ).toDouble();
     271                 :          0 : }
     272                 :            : 
     273                 :          0 : void QgsRuntimeProfiler::clear( const QString &group )
     274                 :            : {
     275                 :          0 :   for ( int row = mRootNode->childCount() - 1; row >= 0; row-- )
     276                 :            :   {
     277                 :          0 :     if ( mRootNode->childAt( row )->data( QgsRuntimeProfilerNode::Group ).toString() == group )
     278                 :            :     {
     279                 :          0 :       beginRemoveRows( QModelIndex(), row, row );
     280                 :          0 :       mRootNode->removeChildAt( row );
     281                 :          0 :       endRemoveRows();
     282                 :          0 :     }
     283                 :          0 :   }
     284                 :          0 : }
     285                 :            : 
     286                 :          0 : double QgsRuntimeProfiler::totalTime( const QString &group )
     287                 :            : {
     288                 :          0 :   if ( QgsRuntimeProfilerNode *node = pathToNode( group, QString() ) )
     289                 :          5 :     return node->elapsed();
     290                 :            : 
     291                 :          0 :   return 0;
     292                 :          0 : }
     293                 :            : 
     294                 :        156 : bool QgsRuntimeProfiler::groupIsActive( const QString &group ) const
     295                 :            : {
     296                 :        156 :   return !mCurrentStack.value( group ).empty();
     297                 :          0 : }
     298                 :            : 
     299                 :          0 : QString QgsRuntimeProfiler::translateGroupName( const QString &group )
     300                 :            : {
     301                 :          0 :   if ( group == QLatin1String( "startup" ) )
     302                 :          0 :     return tr( "Startup" );
     303                 :          0 :   else if ( group == QLatin1String( "projectload" ) )
     304                 :          0 :     return tr( "Project Load" );
     305                 :          0 :   else if ( group == QLatin1String( "render" ) )
     306                 :          0 :     return tr( "Map Render" );
     307                 :          0 :   return QString();
     308                 :          0 : }
     309                 :            : 
     310                 :       7506 : int QgsRuntimeProfiler::rowCount( const QModelIndex &parent ) const
     311                 :            : {
     312                 :       7506 :   QgsRuntimeProfilerNode *n = index2node( parent );
     313                 :       7506 :   if ( !n )
     314                 :          0 :     return 0;
     315                 :            : 
     316                 :       7506 :   return n->childCount();
     317                 :       7506 : }
     318                 :            : 
     319                 :       6530 : int QgsRuntimeProfiler::columnCount( const QModelIndex &parent ) const
     320                 :            : {
     321                 :       6530 :   Q_UNUSED( parent )
     322                 :       6530 :   return 2;
     323                 :            : }
     324                 :            : 
     325                 :       6530 : QModelIndex QgsRuntimeProfiler::index( int row, int column, const QModelIndex &parent ) const
     326                 :            : {
     327                 :      13060 :   if ( column < 0 || column >= columnCount( parent ) ||
     328                 :       6530 :        row < 0 || row >= rowCount( parent ) )
     329                 :          0 :     return QModelIndex();
     330                 :            : 
     331                 :       6530 :   QgsRuntimeProfilerNode *n = index2node( parent );
     332                 :       6530 :   if ( !n )
     333                 :          0 :     return QModelIndex(); // have no children
     334                 :            : 
     335                 :       6530 :   return createIndex( row, column, n->childAt( row ) );
     336                 :       6530 : }
     337                 :            : 
     338                 :       5004 : QModelIndex QgsRuntimeProfiler::parent( const QModelIndex &child ) const
     339                 :            : {
     340                 :       5004 :   if ( !child.isValid() )
     341                 :          0 :     return QModelIndex();
     342                 :            : 
     343                 :       5004 :   if ( QgsRuntimeProfilerNode *n = index2node( child ) )
     344                 :            :   {
     345                 :       5004 :     return indexOfParentNode( n->parent() ); // must not be null
     346                 :            :   }
     347                 :            :   else
     348                 :            :   {
     349                 :            :     Q_ASSERT( false );
     350                 :          0 :     return QModelIndex();
     351                 :            :   }
     352                 :       5004 : }
     353                 :            : 
     354                 :          0 : QVariant QgsRuntimeProfiler::data( const QModelIndex &index, int role ) const
     355                 :            : {
     356                 :          0 :   if ( !index.isValid() || index.column() > 2 )
     357                 :          0 :     return QVariant();
     358                 :            : 
     359                 :          0 :   QgsRuntimeProfilerNode *node = index2node( index );
     360                 :          0 :   if ( !node )
     361                 :          0 :     return QVariant();
     362                 :            : 
     363                 :          0 :   switch ( index.column() )
     364                 :            :   {
     365                 :            :     case 0:
     366                 :          0 :       return node->data( role );
     367                 :            : 
     368                 :            :     case 1:
     369                 :            :     {
     370                 :          0 :       switch ( role )
     371                 :            :       {
     372                 :            :         case Qt::DisplayRole:
     373                 :            :         case Qt::InitialSortOrderRole:
     374                 :          0 :           return node->data( QgsRuntimeProfilerNode::Elapsed );
     375                 :            : 
     376                 :            :         default:
     377                 :          0 :           break;
     378                 :            :       }
     379                 :          0 :       return node->data( role );
     380                 :            :     }
     381                 :            :   }
     382                 :          0 :   return QVariant();
     383                 :          0 : }
     384                 :            : 
     385                 :          0 : QVariant QgsRuntimeProfiler::headerData( int section, Qt::Orientation orientation, int role ) const
     386                 :            : {
     387                 :          0 :   switch ( role )
     388                 :            :   {
     389                 :            :     case Qt::DisplayRole:
     390                 :            :     {
     391                 :          0 :       if ( orientation == Qt::Horizontal )
     392                 :            :       {
     393                 :          0 :         switch ( section )
     394                 :            :         {
     395                 :            :           case 0:
     396                 :          0 :             return tr( "Task" );
     397                 :            :           case 1:
     398                 :          0 :             return tr( "Time (seconds)" );
     399                 :            :           default:
     400                 :          0 :             return QVariant();
     401                 :            :         }
     402                 :            :       }
     403                 :            :       else
     404                 :            :       {
     405                 :          0 :         return QVariant();
     406                 :            :       }
     407                 :            :     }
     408                 :            : 
     409                 :            :     default:
     410                 :          0 :       return QAbstractItemModel::headerData( section, orientation, role );
     411                 :            :   }
     412                 :          0 : }
     413                 :            : 
     414                 :          0 : void QgsRuntimeProfiler::otherProfilerStarted( const QString &group, const QStringList &path, const QString &name )
     415                 :            : {
     416                 :          0 :   QgsRuntimeProfilerNode *parentNode = mRootNode.get();
     417                 :          0 :   for ( const QString &part : path )
     418                 :            :   {
     419                 :          0 :     QgsRuntimeProfilerNode *child = parentNode->child( group, part );
     420                 :          0 :     if ( !child )
     421                 :            :     {
     422                 :          0 :       std::unique_ptr< QgsRuntimeProfilerNode > newChild = std::make_unique< QgsRuntimeProfilerNode >( group, part );
     423                 :            : 
     424                 :          0 :       const QModelIndex parentIndex = node2index( parentNode );
     425                 :          0 :       beginInsertRows( parentIndex, parentNode->childCount(), parentNode->childCount() );
     426                 :          0 :       QgsRuntimeProfilerNode *next = newChild.get();
     427                 :          0 :       parentNode->addChild( std::move( newChild ) );
     428                 :          0 :       endInsertRows();
     429                 :          0 :       parentNode = next;
     430                 :          0 :     }
     431                 :            :     else
     432                 :            :     {
     433                 :          0 :       parentNode = child;
     434                 :            :     }
     435                 :            :   }
     436                 :            : 
     437                 :          0 :   if ( parentNode->child( group, name ) )
     438                 :          0 :     return;
     439                 :            : 
     440                 :          0 :   const QModelIndex parentIndex = node2index( parentNode );
     441                 :          0 :   beginInsertRows( parentIndex, parentNode->childCount(), parentNode->childCount() );
     442                 :          0 :   parentNode->addChild( std::make_unique< QgsRuntimeProfilerNode >( group, name ) );
     443                 :          0 :   endInsertRows();
     444                 :            : 
     445                 :          0 :   if ( !mGroups.contains( group ) )
     446                 :            :   {
     447                 :          0 :     mGroups.insert( group );
     448                 :          0 :     emit groupAdded( group );
     449                 :          0 :   }
     450                 :          0 : }
     451                 :            : 
     452                 :          0 : void QgsRuntimeProfiler::otherProfilerEnded( const QString &group, const QStringList &path, const QString &name, double elapsed )
     453                 :            : {
     454                 :          0 :   QgsRuntimeProfilerNode *parentNode = mRootNode.get();
     455                 :          0 :   for ( const QString &part : path )
     456                 :            :   {
     457                 :          0 :     QgsRuntimeProfilerNode *child = parentNode->child( group, part );
     458                 :          0 :     if ( !child )
     459                 :            :     {
     460                 :          0 :       std::unique_ptr< QgsRuntimeProfilerNode > newChild = std::make_unique< QgsRuntimeProfilerNode >( group, part );
     461                 :            : 
     462                 :          0 :       const QModelIndex parentIndex = node2index( parentNode );
     463                 :          0 :       beginInsertRows( parentIndex, parentNode->childCount(), parentNode->childCount() );
     464                 :          0 :       QgsRuntimeProfilerNode *next = newChild.get();
     465                 :          0 :       parentNode->addChild( std::move( newChild ) );
     466                 :          0 :       endInsertRows();
     467                 :          0 :       parentNode = next;
     468                 :          0 :     }
     469                 :            :     else
     470                 :            :     {
     471                 :          0 :       parentNode = child;
     472                 :            :     }
     473                 :            :   }
     474                 :            : 
     475                 :          0 :   QgsRuntimeProfilerNode *destNode = parentNode->child( group, name );
     476                 :          0 :   if ( !destNode )
     477                 :            :   {
     478                 :          0 :     std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name );
     479                 :          0 :     destNode = node.get();
     480                 :          0 :     const QModelIndex parentIndex = node2index( parentNode );
     481                 :          0 :     beginInsertRows( parentIndex, parentNode->childCount(), parentNode->childCount() );
     482                 :          0 :     parentNode->addChild( std::move( node ) );
     483                 :          0 :     endInsertRows();
     484                 :          0 :   }
     485                 :            : 
     486                 :          0 :   destNode->setElapsed( elapsed );
     487                 :            : 
     488                 :          0 :   const QModelIndex nodeIndex = node2index( destNode );
     489                 :          0 :   const QModelIndex col2Index = index( nodeIndex.row(), 1, nodeIndex.parent() );
     490                 :          0 :   emit dataChanged( nodeIndex, nodeIndex );
     491                 :          0 :   emit dataChanged( col2Index, col2Index );
     492                 :            :   // parent item has data changed too, cos the overall time elapsed will have changed!
     493                 :          0 :   QModelIndex parentIndex = nodeIndex.parent();
     494                 :          0 :   while ( parentIndex.isValid() )
     495                 :            :   {
     496                 :          0 :     const QModelIndex parentCol2Index = index( parentIndex.row(), 1, parentIndex.parent() );
     497                 :          0 :     emit dataChanged( parentIndex, parentIndex );
     498                 :          0 :     emit dataChanged( parentCol2Index, parentCol2Index );
     499                 :          0 :     parentIndex = parentIndex.parent();
     500                 :            :   }
     501                 :          0 : }
     502                 :            : 
     503                 :          5 : void QgsRuntimeProfiler::setupConnections()
     504                 :            : {
     505                 :          5 :   mInitialized = true;
     506                 :            : 
     507                 :            :   Q_ASSERT( sMainProfiler );
     508                 :            : 
     509                 :          5 :   if ( sMainProfiler != this )
     510                 :            :   {
     511                 :          0 :     connect( this, &QgsRuntimeProfiler::started, sMainProfiler, &QgsRuntimeProfiler::otherProfilerStarted );
     512                 :          0 :     connect( this, &QgsRuntimeProfiler::ended, sMainProfiler, &QgsRuntimeProfiler::otherProfilerEnded );
     513                 :          0 :   }
     514                 :          5 : }
     515                 :            : 
     516                 :          0 : QgsRuntimeProfilerNode *QgsRuntimeProfiler::pathToNode( const QString &group, const QString &path ) const
     517                 :            : {
     518                 :          0 :   QStringList parts = path.split( '/' );
     519                 :          0 :   QgsRuntimeProfilerNode *res = mRootNode.get();
     520                 :          0 :   for ( const QString &part : parts )
     521                 :            :   {
     522                 :          0 :     if ( part.isEmpty() )
     523                 :          0 :       continue;
     524                 :            : 
     525                 :          0 :     res = res->child( group, part );
     526                 :          0 :     if ( !res )
     527                 :          0 :       break;
     528                 :            :   }
     529                 :          0 :   return res;
     530                 :          0 : }
     531                 :            : 
     532                 :          0 : QgsRuntimeProfilerNode *QgsRuntimeProfiler::pathToNode( const QString &group, const QStringList &path ) const
     533                 :            : {
     534                 :          0 :   QgsRuntimeProfilerNode *res = mRootNode.get();
     535                 :          0 :   for ( const QString &part : path )
     536                 :            :   {
     537                 :          0 :     res = res->child( group, part );
     538                 :          0 :     if ( !res )
     539                 :          0 :       break;
     540                 :            :   }
     541                 :          0 :   return res;
     542                 :            : }
     543                 :            : 
     544                 :       5800 : QModelIndex QgsRuntimeProfiler::node2index( QgsRuntimeProfilerNode *node ) const
     545                 :            : {
     546                 :       5800 :   if ( !node || !node->parent() )
     547                 :       1772 :     return QModelIndex(); // this is the only root item -> invalid index
     548                 :            : 
     549                 :       4028 :   QModelIndex parentIndex = node2index( node->parent() );
     550                 :            : 
     551                 :       4028 :   int row = node->parent()->indexOf( node );
     552                 :            :   Q_ASSERT( row >= 0 );
     553                 :       4028 :   return index( row, 0, parentIndex );
     554                 :       5800 : }
     555                 :            : 
     556                 :       5004 : QModelIndex QgsRuntimeProfiler::indexOfParentNode( QgsRuntimeProfilerNode *parentNode ) const
     557                 :            : {
     558                 :            :   Q_ASSERT( parentNode );
     559                 :            : 
     560                 :       5004 :   QgsRuntimeProfilerNode *grandParentNode = parentNode->parent();
     561                 :       5004 :   if ( !grandParentNode )
     562                 :       1952 :     return QModelIndex();  // root node -> invalid index
     563                 :            : 
     564                 :       3052 :   int row = grandParentNode->indexOf( parentNode );
     565                 :            :   Q_ASSERT( row >= 0 );
     566                 :            : 
     567                 :       3052 :   return createIndex( row, 0, parentNode );
     568                 :       5004 : }
     569                 :            : 
     570                 :      19040 : QgsRuntimeProfilerNode *QgsRuntimeProfiler::index2node( const QModelIndex &index ) const
     571                 :            : {
     572                 :      19040 :   if ( !index.isValid() )
     573                 :       5676 :     return mRootNode.get();
     574                 :            : 
     575                 :      13364 :   return reinterpret_cast<QgsRuntimeProfilerNode *>( index.internalPointer() );
     576                 :      19040 : }
     577                 :            : 
     578                 :            : 
     579                 :            : //
     580                 :            : // QgsScopedRuntimeProfile
     581                 :            : //
     582                 :            : 
     583                 :        821 : QgsScopedRuntimeProfile::QgsScopedRuntimeProfile( const QString &name, const QString &group )
     584                 :        821 :   : mGroup( group )
     585                 :            : {
     586                 :        821 :   QgsApplication::profiler()->start( name, mGroup );
     587                 :        821 : }
     588                 :            : 
     589                 :        821 : QgsScopedRuntimeProfile::~QgsScopedRuntimeProfile()
     590                 :            : {
     591                 :        821 :   QgsApplication::profiler()->end( mGroup );
     592                 :        821 : }
     593                 :            : 
     594                 :          0 : void QgsScopedRuntimeProfile::switchTask( const QString &name )
     595                 :            : {
     596                 :          0 :   QgsApplication::profiler()->end( mGroup );
     597                 :          0 :   QgsApplication::profiler()->start( name, mGroup );
     598                 :          0 : }

Generated by: LCOV version 1.14