LCOV - code coverage report
Current view: top level - core/layout - qgslayoutmanager.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 13 347 3.7 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :     qgslayoutmanager.cpp
       3                 :            :     --------------------
       4                 :            :     Date                 : January 2017
       5                 :            :     Copyright            : (C) 2017 Nyall Dawson
       6                 :            :     Email                : nyall dot dawson 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                 :            : 
      16                 :            : #include "qgslayoutmanager.h"
      17                 :            : #include "qgslayout.h"
      18                 :            : #include "qgsproject.h"
      19                 :            : #include "qgslogger.h"
      20                 :            : #include "qgslayoutundostack.h"
      21                 :            : #include "qgsprintlayout.h"
      22                 :            : #include "qgsreport.h"
      23                 :            : #include "qgscompositionconverter.h"
      24                 :            : #include "qgsreadwritecontext.h"
      25                 :            : #include "qgsstyleentityvisitor.h"
      26                 :            : #include "qgsruntimeprofiler.h"
      27                 :            : #include <QMessageBox>
      28                 :            : 
      29                 :          5 : QgsLayoutManager::QgsLayoutManager( QgsProject *project )
      30                 :          5 :   : QObject( project )
      31                 :          5 :   , mProject( project )
      32                 :         10 : {
      33                 :            : 
      34                 :          5 : }
      35                 :            : 
      36                 :          6 : QgsLayoutManager::~QgsLayoutManager()
      37                 :          6 : {
      38                 :          3 :   clear();
      39                 :          6 : }
      40                 :            : 
      41                 :          0 : bool QgsLayoutManager::addLayout( QgsMasterLayoutInterface *layout )
      42                 :            : {
      43                 :          0 :   if ( !layout || mLayouts.contains( layout ) )
      44                 :          0 :     return false;
      45                 :            : 
      46                 :            :   // check for duplicate name
      47                 :          0 :   for ( QgsMasterLayoutInterface *l : std::as_const( mLayouts ) )
      48                 :            :   {
      49                 :          0 :     if ( l->name() == layout->name() )
      50                 :            :     {
      51                 :          0 :       delete layout;
      52                 :          0 :       return false;
      53                 :            :     }
      54                 :            :   }
      55                 :            : 
      56                 :            :   // ugly, but unavoidable for interfaces...
      57                 :          0 :   if ( QgsPrintLayout *l = dynamic_cast< QgsPrintLayout * >( layout ) )
      58                 :            :   {
      59                 :          0 :     connect( l, &QgsPrintLayout::nameChanged, this, [this, l]( const QString & newName )
      60                 :            :     {
      61                 :          0 :       emit layoutRenamed( l, newName );
      62                 :          0 :     } );
      63                 :          0 :   }
      64                 :          0 :   else if ( QgsReport *r = dynamic_cast< QgsReport * >( layout ) )
      65                 :            :   {
      66                 :          0 :     connect( r, &QgsReport::nameChanged, this, [this, r]( const QString & newName )
      67                 :            :     {
      68                 :          0 :       emit layoutRenamed( r, newName );
      69                 :          0 :     } );
      70                 :          0 :   }
      71                 :            : 
      72                 :          0 :   emit layoutAboutToBeAdded( layout->name() );
      73                 :          0 :   mLayouts << layout;
      74                 :          0 :   emit layoutAdded( layout->name() );
      75                 :          0 :   mProject->setDirty( true );
      76                 :          0 :   return true;
      77                 :          0 : }
      78                 :            : 
      79                 :          0 : bool QgsLayoutManager::removeLayout( QgsMasterLayoutInterface *layout )
      80                 :            : {
      81                 :          0 :   if ( !layout )
      82                 :          0 :     return false;
      83                 :            : 
      84                 :          0 :   if ( !mLayouts.contains( layout ) )
      85                 :          0 :     return false;
      86                 :            : 
      87                 :          0 :   QString name = layout->name();
      88                 :          0 :   emit layoutAboutToBeRemoved( name );
      89                 :          0 :   mLayouts.removeAll( layout );
      90                 :          0 :   delete layout;
      91                 :          0 :   emit layoutRemoved( name );
      92                 :          0 :   mProject->setDirty( true );
      93                 :          0 :   return true;
      94                 :          0 : }
      95                 :            : 
      96                 :         11 : void QgsLayoutManager::clear()
      97                 :            : {
      98                 :         11 :   const QList< QgsMasterLayoutInterface * > layouts = mLayouts;
      99                 :         11 :   for ( QgsMasterLayoutInterface *l : layouts )
     100                 :            :   {
     101                 :          0 :     removeLayout( l );
     102                 :            :   }
     103                 :         11 : }
     104                 :            : 
     105                 :          0 : QList<QgsMasterLayoutInterface *> QgsLayoutManager::layouts() const
     106                 :            : {
     107                 :          0 :   return mLayouts;
     108                 :            : }
     109                 :            : 
     110                 :          0 : QList<QgsPrintLayout *> QgsLayoutManager::printLayouts() const
     111                 :            : {
     112                 :          0 :   QList<QgsPrintLayout *> result;
     113                 :          0 :   const QList<QgsMasterLayoutInterface *> _layouts( mLayouts );
     114                 :          0 :   result.reserve( _layouts.size() );
     115                 :          0 :   for ( const auto &layout : _layouts )
     116                 :            :   {
     117                 :          0 :     QgsPrintLayout *_item( dynamic_cast<QgsPrintLayout *>( layout ) );
     118                 :          0 :     if ( _item )
     119                 :          0 :       result.push_back( _item );
     120                 :            :   }
     121                 :          0 :   return result;
     122                 :          0 : }
     123                 :            : 
     124                 :          0 : QgsMasterLayoutInterface *QgsLayoutManager::layoutByName( const QString &name ) const
     125                 :            : {
     126                 :          0 :   for ( QgsMasterLayoutInterface *l : mLayouts )
     127                 :            :   {
     128                 :          0 :     if ( l->name() == name )
     129                 :          0 :       return l;
     130                 :            :   }
     131                 :          0 :   return nullptr;
     132                 :          0 : }
     133                 :            : 
     134                 :          0 : bool QgsLayoutManager::readXml( const QDomElement &element, const QDomDocument &doc )
     135                 :            : {
     136                 :          0 :   clear();
     137                 :            : 
     138                 :          0 :   QDomElement layoutsElem = element;
     139                 :          0 :   if ( element.tagName() != QLatin1String( "Layouts" ) )
     140                 :            :   {
     141                 :          0 :     layoutsElem = element.firstChildElement( QStringLiteral( "Layouts" ) );
     142                 :          0 :   }
     143                 :          0 :   if ( layoutsElem.isNull() )
     144                 :            :   {
     145                 :            :     // handle legacy projects
     146                 :          0 :     layoutsElem = doc.documentElement();
     147                 :          0 :   }
     148                 :            : 
     149                 :            :   //restore each composer
     150                 :          0 :   bool result = true;
     151                 :          0 :   QDomNodeList composerNodes = element.elementsByTagName( QStringLiteral( "Composer" ) );
     152                 :          0 :   QgsScopedRuntimeProfile profile( tr( "Loading QGIS 2.x compositions" ), QStringLiteral( "projectload" ) );
     153                 :          0 :   for ( int i = 0; i < composerNodes.size(); ++i )
     154                 :            :   {
     155                 :            :     // This legacy title is the Composer "title" (that can be overridden by the Composition "name")
     156                 :          0 :     QString legacyTitle = composerNodes.at( i ).toElement().attribute( QStringLiteral( "title" ) );
     157                 :            :     // Convert compositions to layouts
     158                 :          0 :     QDomNodeList compositionNodes = composerNodes.at( i ).toElement().elementsByTagName( QStringLiteral( "Composition" ) );
     159                 :          0 :     for ( int j = 0; j < compositionNodes.size(); ++j )
     160                 :            :     {
     161                 :          0 :       std::unique_ptr< QgsPrintLayout > l( QgsCompositionConverter::createLayoutFromCompositionXml( compositionNodes.at( j ).toElement(), mProject ) );
     162                 :          0 :       if ( l )
     163                 :            :       {
     164                 :          0 :         if ( l->name().isEmpty() )
     165                 :          0 :           l->setName( legacyTitle );
     166                 :            : 
     167                 :            :         // some 2.x projects could end in a state where they had duplicated layout names. This is strictly forbidden in 3.x
     168                 :            :         // so check for duplicate name in layouts already added
     169                 :          0 :         int id = 2;
     170                 :          0 :         bool isDuplicateName = false;
     171                 :          0 :         QString originalName = l->name();
     172                 :          0 :         do
     173                 :            :         {
     174                 :          0 :           isDuplicateName = false;
     175                 :          0 :           for ( QgsMasterLayoutInterface *layout : std::as_const( mLayouts ) )
     176                 :            :           {
     177                 :          0 :             if ( l->name() == layout->name() )
     178                 :            :             {
     179                 :          0 :               isDuplicateName = true;
     180                 :          0 :               break;
     181                 :            :             }
     182                 :            :           }
     183                 :          0 :           if ( isDuplicateName )
     184                 :            :           {
     185                 :          0 :             l->setName( QStringLiteral( "%1 %2" ).arg( originalName ).arg( id ) );
     186                 :          0 :             id++;
     187                 :          0 :           }
     188                 :          0 :         }
     189                 :          0 :         while ( isDuplicateName );
     190                 :            : 
     191                 :          0 :         bool added = addLayout( l.release() );
     192                 :          0 :         result = added && result;
     193                 :          0 :       }
     194                 :          0 :     }
     195                 :          0 :   }
     196                 :            : 
     197                 :          0 :   QgsReadWriteContext context;
     198                 :          0 :   context.setPathResolver( mProject->pathResolver() );
     199                 :            : 
     200                 :          0 :   profile.switchTask( tr( "Creating layouts" ) );
     201                 :            : 
     202                 :            :   // restore layouts
     203                 :          0 :   const QDomNodeList layoutNodes = layoutsElem.childNodes();
     204                 :          0 :   for ( int i = 0; i < layoutNodes.size(); ++i )
     205                 :            :   {
     206                 :          0 :     if ( layoutNodes.at( i ).nodeName() != QLatin1String( "Layout" ) )
     207                 :          0 :       continue;
     208                 :            : 
     209                 :          0 :     const QString layoutName = layoutNodes.at( i ).toElement().attribute( QStringLiteral( "name" ) );
     210                 :          0 :     QgsScopedRuntimeProfile profile( layoutName, QStringLiteral( "projectload" ) );
     211                 :            : 
     212                 :          0 :     std::unique_ptr< QgsPrintLayout > l = std::make_unique< QgsPrintLayout >( mProject );
     213                 :          0 :     l->undoStack()->blockCommands( true );
     214                 :          0 :     if ( !l->readLayoutXml( layoutNodes.at( i ).toElement(), doc, context ) )
     215                 :            :     {
     216                 :          0 :       result = false;
     217                 :          0 :       continue;
     218                 :            :     }
     219                 :          0 :     l->undoStack()->blockCommands( false );
     220                 :          0 :     if ( !addLayout( l.release() ) )
     221                 :            :     {
     222                 :          0 :       result = false;
     223                 :          0 :     }
     224                 :          0 :   }
     225                 :            :   //reports
     226                 :          0 :   profile.switchTask( tr( "Creating reports" ) );
     227                 :          0 :   const QDomNodeList reportNodes = element.elementsByTagName( QStringLiteral( "Report" ) );
     228                 :          0 :   for ( int i = 0; i < reportNodes.size(); ++i )
     229                 :            :   {
     230                 :          0 :     const QString layoutName = reportNodes.at( i ).toElement().attribute( QStringLiteral( "name" ) );
     231                 :          0 :     QgsScopedRuntimeProfile profile( layoutName, QStringLiteral( "projectload" ) );
     232                 :            : 
     233                 :          0 :     std::unique_ptr< QgsReport > r = std::make_unique< QgsReport >( mProject );
     234                 :          0 :     if ( !r->readLayoutXml( reportNodes.at( i ).toElement(), doc, context ) )
     235                 :            :     {
     236                 :          0 :       result = false;
     237                 :          0 :       continue;
     238                 :            :     }
     239                 :          0 :     if ( !addLayout( r.release() ) )
     240                 :            :     {
     241                 :          0 :       result = false;
     242                 :          0 :     }
     243                 :          0 :   }
     244                 :          0 :   return result;
     245                 :          0 : }
     246                 :            : 
     247                 :          0 : QDomElement QgsLayoutManager::writeXml( QDomDocument &doc ) const
     248                 :            : {
     249                 :          0 :   QDomElement layoutsElem = doc.createElement( QStringLiteral( "Layouts" ) );
     250                 :            : 
     251                 :          0 :   QgsReadWriteContext context;
     252                 :          0 :   context.setPathResolver( mProject->pathResolver() );
     253                 :          0 :   for ( QgsMasterLayoutInterface *l : mLayouts )
     254                 :            :   {
     255                 :          0 :     QDomElement layoutElem = l->writeLayoutXml( doc, context );
     256                 :          0 :     layoutsElem.appendChild( layoutElem );
     257                 :          0 :   }
     258                 :          0 :   return layoutsElem;
     259                 :          0 : }
     260                 :            : 
     261                 :          0 : QgsMasterLayoutInterface *QgsLayoutManager::duplicateLayout( const QgsMasterLayoutInterface *layout, const QString &newName )
     262                 :            : {
     263                 :          0 :   if ( !layout )
     264                 :          0 :     return nullptr;
     265                 :            : 
     266                 :          0 :   std::unique_ptr< QgsMasterLayoutInterface > newLayout( layout->clone() );
     267                 :          0 :   if ( !newLayout )
     268                 :            :   {
     269                 :          0 :     return nullptr;
     270                 :            :   }
     271                 :            : 
     272                 :          0 :   newLayout->setName( newName );
     273                 :          0 :   QgsMasterLayoutInterface *l = newLayout.get();
     274                 :          0 :   if ( !addLayout( newLayout.release() ) )
     275                 :            :   {
     276                 :          0 :     return nullptr;
     277                 :            :   }
     278                 :            :   else
     279                 :            :   {
     280                 :          0 :     return l;
     281                 :            :   }
     282                 :          0 : }
     283                 :            : 
     284                 :          0 : QString QgsLayoutManager::generateUniqueTitle( QgsMasterLayoutInterface::Type type ) const
     285                 :            : {
     286                 :          0 :   QStringList names;
     287                 :          0 :   names.reserve( mLayouts.size() );
     288                 :          0 :   for ( QgsMasterLayoutInterface *l : mLayouts )
     289                 :            :   {
     290                 :          0 :     names << l->name();
     291                 :            :   }
     292                 :          0 :   QString name;
     293                 :          0 :   int id = 1;
     294                 :          0 :   while ( name.isEmpty() || names.contains( name ) )
     295                 :          0 :   {
     296                 :          0 :     switch ( type )
     297                 :            :     {
     298                 :            :       case QgsMasterLayoutInterface::PrintLayout:
     299                 :          0 :         name = tr( "Layout %1" ).arg( id );
     300                 :          0 :         break;
     301                 :            :       case QgsMasterLayoutInterface::Report:
     302                 :          0 :         name = tr( "Report %1" ).arg( id );
     303                 :          0 :         break;
     304                 :            :     }
     305                 :          0 :     id++;
     306                 :            :   }
     307                 :          0 :   return name;
     308                 :          0 : }
     309                 :            : 
     310                 :          0 : bool QgsLayoutManager::accept( QgsStyleEntityVisitorInterface *visitor ) const
     311                 :            : {
     312                 :          0 :   if ( mLayouts.empty() )
     313                 :          0 :     return true;
     314                 :            : 
     315                 :            :   // NOTE: if visitEnter returns false it means "don't visit the layouts", not "abort all further visitations"
     316                 :          0 :   if ( !visitor->visitEnter( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::Layouts, QStringLiteral( "layouts" ), tr( "Layouts" ) ) ) )
     317                 :          0 :     return true;
     318                 :            : 
     319                 :          0 :   for ( QgsMasterLayoutInterface *l : mLayouts )
     320                 :            :   {
     321                 :          0 :     if ( !l->layoutAccept( visitor ) )
     322                 :          0 :       return false;
     323                 :            :   }
     324                 :            : 
     325                 :          0 :   if ( !visitor->visitExit( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::Layouts, QStringLiteral( "layouts" ), tr( "Layouts" ) ) ) )
     326                 :          0 :     return false;
     327                 :            : 
     328                 :          0 :   return true;
     329                 :          0 : }
     330                 :            : 
     331                 :            : 
     332                 :            : 
     333                 :            : //
     334                 :            : // QgsLayoutManagerModel
     335                 :            : //
     336                 :            : 
     337                 :          0 : QgsLayoutManagerModel::QgsLayoutManagerModel( QgsLayoutManager *manager, QObject *parent )
     338                 :          0 :   : QAbstractListModel( parent )
     339                 :          0 :   , mLayoutManager( manager )
     340                 :          0 : {
     341                 :          0 :   connect( mLayoutManager, &QgsLayoutManager::layoutAboutToBeAdded, this, &QgsLayoutManagerModel::layoutAboutToBeAdded );
     342                 :          0 :   connect( mLayoutManager, &QgsLayoutManager::layoutAdded, this, &QgsLayoutManagerModel::layoutAdded );
     343                 :          0 :   connect( mLayoutManager, &QgsLayoutManager::layoutAboutToBeRemoved, this, &QgsLayoutManagerModel::layoutAboutToBeRemoved );
     344                 :          0 :   connect( mLayoutManager, &QgsLayoutManager::layoutRemoved, this, &QgsLayoutManagerModel::layoutRemoved );
     345                 :          0 :   connect( mLayoutManager, &QgsLayoutManager::layoutRenamed, this, &QgsLayoutManagerModel::layoutRenamed );
     346                 :          0 : }
     347                 :            : 
     348                 :          0 : int QgsLayoutManagerModel::rowCount( const QModelIndex &parent ) const
     349                 :            : {
     350                 :          0 :   Q_UNUSED( parent )
     351                 :          0 :   return ( mLayoutManager ? mLayoutManager->layouts().count() : 0 ) + ( mAllowEmpty ? 1 : 0 );
     352                 :          0 : }
     353                 :            : 
     354                 :          0 : QVariant QgsLayoutManagerModel::data( const QModelIndex &index, int role ) const
     355                 :            : {
     356                 :          0 :   if ( index.row() < 0 || index.row() >= rowCount( QModelIndex() ) )
     357                 :          0 :     return QVariant();
     358                 :            : 
     359                 :          0 :   const bool isEmpty = index.row() == 0 && mAllowEmpty;
     360                 :          0 :   const int layoutRow = mAllowEmpty ? index.row() - 1 : index.row();
     361                 :            : 
     362                 :          0 :   switch ( role )
     363                 :            :   {
     364                 :            :     case Qt::DisplayRole:
     365                 :            :     case Qt::ToolTipRole:
     366                 :            :     case Qt::EditRole:
     367                 :          0 :       return !isEmpty && mLayoutManager ? mLayoutManager->layouts().at( layoutRow )->name() : QVariant();
     368                 :            : 
     369                 :            :     case LayoutRole:
     370                 :            :     {
     371                 :          0 :       if ( isEmpty || !mLayoutManager )
     372                 :          0 :         return QVariant();
     373                 :          0 :       else if ( QgsLayout *l = dynamic_cast< QgsLayout * >( mLayoutManager->layouts().at( layoutRow ) ) )
     374                 :          0 :         return QVariant::fromValue( l );
     375                 :          0 :       else if ( QgsReport *r = dynamic_cast< QgsReport * >( mLayoutManager->layouts().at( layoutRow ) ) )
     376                 :          0 :         return QVariant::fromValue( r );
     377                 :            :       else
     378                 :          0 :         return QVariant();
     379                 :            :     }
     380                 :            : 
     381                 :            :     case Qt::DecorationRole:
     382                 :            :     {
     383                 :          0 :       return isEmpty || !mLayoutManager ? QIcon() : mLayoutManager->layouts().at( layoutRow )->icon();
     384                 :            :     }
     385                 :            : 
     386                 :            :     default:
     387                 :          0 :       return QVariant();
     388                 :            :   }
     389                 :          0 : }
     390                 :            : 
     391                 :          0 : bool QgsLayoutManagerModel::setData( const QModelIndex &index, const QVariant &value, int role )
     392                 :            : {
     393                 :          0 :   if ( !index.isValid() || role != Qt::EditRole )
     394                 :            :   {
     395                 :          0 :     return false;
     396                 :            :   }
     397                 :          0 :   if ( index.row() >= mLayoutManager->layouts().count() )
     398                 :            :   {
     399                 :          0 :     return false;
     400                 :            :   }
     401                 :            : 
     402                 :          0 :   if ( index.row() == 0 && mAllowEmpty )
     403                 :          0 :     return false;
     404                 :            : 
     405                 :          0 :   if ( value.toString().isEmpty() )
     406                 :          0 :     return false;
     407                 :            : 
     408                 :          0 :   QgsMasterLayoutInterface *layout = layoutFromIndex( index );
     409                 :          0 :   if ( !layout )
     410                 :          0 :     return false;
     411                 :            : 
     412                 :            :   //has name changed?
     413                 :          0 :   bool changed = layout->name() != value.toString();
     414                 :          0 :   if ( !changed )
     415                 :          0 :     return true;
     416                 :            : 
     417                 :            :   //check if name already exists
     418                 :          0 :   QStringList layoutNames;
     419                 :          0 :   const QList< QgsMasterLayoutInterface * > layouts = QgsProject::instance()->layoutManager()->layouts();
     420                 :          0 :   for ( QgsMasterLayoutInterface *l : layouts )
     421                 :            :   {
     422                 :          0 :     layoutNames << l->name();
     423                 :            :   }
     424                 :          0 :   if ( layoutNames.contains( value.toString() ) )
     425                 :            :   {
     426                 :            :     //name exists!
     427                 :          0 :     QMessageBox::warning( nullptr, tr( "Rename Layout" ), tr( "There is already a layout named “%1”." ).arg( value.toString() ) );
     428                 :          0 :     return false;
     429                 :            :   }
     430                 :            : 
     431                 :          0 :   layout->setName( value.toString() );
     432                 :          0 :   return true;
     433                 :          0 : }
     434                 :            : 
     435                 :          0 : Qt::ItemFlags QgsLayoutManagerModel::flags( const QModelIndex &index ) const
     436                 :            : {
     437                 :          0 :   Qt::ItemFlags flags = QAbstractListModel::flags( index );
     438                 :            : #if 0 // double-click is now used for opening the layout
     439                 :            :   if ( index.isValid() )
     440                 :            :   {
     441                 :            :     return flags | Qt::ItemIsEditable;
     442                 :            :   }
     443                 :            :   else
     444                 :            :   {
     445                 :            :     return flags;
     446                 :            :   }
     447                 :            : #endif
     448                 :          0 :   return flags;
     449                 :            : }
     450                 :            : 
     451                 :          0 : QgsMasterLayoutInterface *QgsLayoutManagerModel::layoutFromIndex( const QModelIndex &index ) const
     452                 :            : {
     453                 :          0 :   if ( index.row() == 0 && mAllowEmpty )
     454                 :          0 :     return nullptr;
     455                 :            : 
     456                 :          0 :   if ( QgsPrintLayout *l = qobject_cast< QgsPrintLayout * >( qvariant_cast<QObject *>( data( index, LayoutRole ) ) ) )
     457                 :          0 :     return l;
     458                 :          0 :   else if ( QgsReport *r = qobject_cast< QgsReport * >( qvariant_cast<QObject *>( data( index, LayoutRole ) ) ) )
     459                 :          0 :     return r;
     460                 :            :   else
     461                 :          0 :     return nullptr;
     462                 :          0 : }
     463                 :            : 
     464                 :          0 : QModelIndex QgsLayoutManagerModel::indexFromLayout( QgsMasterLayoutInterface *layout ) const
     465                 :            : {
     466                 :          0 :   if ( !mLayoutManager )
     467                 :            :   {
     468                 :          0 :     return QModelIndex();
     469                 :            :   }
     470                 :            : 
     471                 :          0 :   const int r = mLayoutManager->layouts().indexOf( layout );
     472                 :          0 :   if ( r < 0 )
     473                 :          0 :     return QModelIndex();
     474                 :            : 
     475                 :          0 :   QModelIndex idx = index( mAllowEmpty ? r + 1 : r, 0, QModelIndex() );
     476                 :          0 :   if ( idx.isValid() )
     477                 :            :   {
     478                 :          0 :     return idx;
     479                 :            :   }
     480                 :            : 
     481                 :          0 :   return QModelIndex();
     482                 :          0 : }
     483                 :            : 
     484                 :          0 : void QgsLayoutManagerModel::setAllowEmptyLayout( bool allowEmpty )
     485                 :            : {
     486                 :          0 :   if ( allowEmpty == mAllowEmpty )
     487                 :          0 :     return;
     488                 :            : 
     489                 :          0 :   if ( allowEmpty )
     490                 :            :   {
     491                 :          0 :     beginInsertRows( QModelIndex(), 0, 0 );
     492                 :          0 :     mAllowEmpty = true;
     493                 :          0 :     endInsertRows();
     494                 :          0 :   }
     495                 :            :   else
     496                 :            :   {
     497                 :          0 :     beginRemoveRows( QModelIndex(), 0, 0 );
     498                 :          0 :     mAllowEmpty = false;
     499                 :          0 :     endRemoveRows();
     500                 :            :   }
     501                 :          0 : }
     502                 :            : 
     503                 :          0 : void QgsLayoutManagerModel::layoutAboutToBeAdded( const QString & )
     504                 :            : {
     505                 :          0 :   int row = mLayoutManager->layouts().count() + ( mAllowEmpty ? 1 : 0 );
     506                 :          0 :   beginInsertRows( QModelIndex(), row, row );
     507                 :          0 : }
     508                 :            : 
     509                 :          0 : void QgsLayoutManagerModel::layoutAboutToBeRemoved( const QString &name )
     510                 :            : {
     511                 :          0 :   QgsMasterLayoutInterface *l = mLayoutManager->layoutByName( name );
     512                 :          0 :   int row = mLayoutManager->layouts().indexOf( l ) + ( mAllowEmpty ? 1 : 0 );
     513                 :          0 :   if ( row >= 0 )
     514                 :          0 :     beginRemoveRows( QModelIndex(), row, row );
     515                 :          0 : }
     516                 :            : 
     517                 :          0 : void QgsLayoutManagerModel::layoutAdded( const QString & )
     518                 :            : {
     519                 :          0 :   endInsertRows();
     520                 :          0 : }
     521                 :            : 
     522                 :          0 : void QgsLayoutManagerModel::layoutRemoved( const QString & )
     523                 :            : {
     524                 :          0 :   endRemoveRows();
     525                 :          0 : }
     526                 :            : 
     527                 :          0 : void QgsLayoutManagerModel::layoutRenamed( QgsMasterLayoutInterface *layout, const QString & )
     528                 :            : {
     529                 :          0 :   int row = mLayoutManager->layouts().indexOf( layout ) + ( mAllowEmpty ? 1 : 0 );
     530                 :          0 :   QModelIndex index = createIndex( row, 0 );
     531                 :          0 :   emit dataChanged( index, index, QVector<int>() << Qt::DisplayRole );
     532                 :          0 : }
     533                 :            : 
     534                 :            : //
     535                 :            : // QgsLayoutManagerProxyModel
     536                 :            : //
     537                 :            : 
     538                 :          0 : QgsLayoutManagerProxyModel::QgsLayoutManagerProxyModel( QObject *parent )
     539                 :          0 :   : QSortFilterProxyModel( parent )
     540                 :          0 : {
     541                 :          0 :   setDynamicSortFilter( true );
     542                 :          0 :   sort( 0 );
     543                 :          0 :   setSortCaseSensitivity( Qt::CaseInsensitive );
     544                 :          0 : }
     545                 :            : 
     546                 :          0 : bool QgsLayoutManagerProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
     547                 :            : {
     548                 :          0 :   const QString leftText = sourceModel()->data( left, Qt::DisplayRole ).toString();
     549                 :          0 :   const QString rightText = sourceModel()->data( right, Qt::DisplayRole ).toString();
     550                 :          0 :   if ( leftText.isEmpty() )
     551                 :          0 :     return true;
     552                 :          0 :   if ( rightText.isEmpty() )
     553                 :          0 :     return false;
     554                 :            : 
     555                 :          0 :   return QString::localeAwareCompare( leftText, rightText ) < 0;
     556                 :          0 : }
     557                 :            : 
     558                 :          0 : bool QgsLayoutManagerProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
     559                 :            : {
     560                 :          0 :   QgsLayoutManagerModel *model = qobject_cast< QgsLayoutManagerModel * >( sourceModel() );
     561                 :          0 :   if ( !model )
     562                 :          0 :     return false;
     563                 :            : 
     564                 :          0 :   QgsMasterLayoutInterface *layout = model->layoutFromIndex( model->index( sourceRow, 0, sourceParent ) );
     565                 :          0 :   if ( !layout )
     566                 :          0 :     return model->allowEmptyLayout();
     567                 :            : 
     568                 :          0 :   if ( !mFilterString.trimmed().isEmpty() )
     569                 :            :   {
     570                 :          0 :     if ( !layout->name().contains( mFilterString, Qt::CaseInsensitive ) )
     571                 :          0 :       return false;
     572                 :          0 :   }
     573                 :            : 
     574                 :          0 :   switch ( layout->layoutType() )
     575                 :            :   {
     576                 :            :     case QgsMasterLayoutInterface::PrintLayout:
     577                 :          0 :       return mFilters & FilterPrintLayouts;
     578                 :            :     case QgsMasterLayoutInterface::Report:
     579                 :          0 :       return mFilters & FilterReports;
     580                 :            :   }
     581                 :          0 :   return false;
     582                 :          0 : }
     583                 :            : 
     584                 :          0 : QgsLayoutManagerProxyModel::Filters QgsLayoutManagerProxyModel::filters() const
     585                 :            : {
     586                 :          0 :   return mFilters;
     587                 :            : }
     588                 :            : 
     589                 :          0 : void QgsLayoutManagerProxyModel::setFilters( Filters filters )
     590                 :            : {
     591                 :          0 :   mFilters = filters;
     592                 :          0 :   invalidateFilter();
     593                 :          0 : }
     594                 :            : 
     595                 :          0 : void QgsLayoutManagerProxyModel::setFilterString( const QString &filter )
     596                 :            : {
     597                 :          0 :   mFilterString = filter;
     598                 :          0 :   invalidateFilter();
     599                 :          0 : }

Generated by: LCOV version 1.14