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

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :     qgsapplication.cpp - Accessors for application-wide data
       3                 :            :      --------------------------------------
       4                 :            :     Date                 : 02-Jan-2006
       5                 :            :     Copyright            : (C) 2006 by Tom Elwertowski
       6                 :            :     Email                : telwertowski at users dot sourceforge dot net
       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 "qgsapplication.h"
      17                 :            : #include "qgsauthmanager.h"
      18                 :            : #include "qgslocalizeddatapathregistry.h"
      19                 :            : #include "qgsdataitemproviderregistry.h"
      20                 :            : #include "qgsexception.h"
      21                 :            : #include "qgsgeometry.h"
      22                 :            : #include "qgsannotationitemregistry.h"
      23                 :            : #include "qgslayoutitemregistry.h"
      24                 :            : #include "qgslogger.h"
      25                 :            : #include "qgsproject.h"
      26                 :            : #include "qgsnetworkaccessmanager.h"
      27                 :            : #include "qgsnetworkcontentfetcherregistry.h"
      28                 :            : #include "qgsnetworkreply.h"
      29                 :            : #include "qgsproviderregistry.h"
      30                 :            : #include "qgsexpression.h"
      31                 :            : #include "qgsactionscoperegistry.h"
      32                 :            : #include "qgsruntimeprofiler.h"
      33                 :            : #include "qgstaskmanager.h"
      34                 :            : #include "qgsnumericformatregistry.h"
      35                 :            : #include "qgsfieldformatterregistry.h"
      36                 :            : #include "qgsscalebarrendererregistry.h"
      37                 :            : #include "qgssvgcache.h"
      38                 :            : #include "qgsimagecache.h"
      39                 :            : #include "qgssourcecache.h"
      40                 :            : #include "qgscolorschemeregistry.h"
      41                 :            : #include "qgspainteffectregistry.h"
      42                 :            : #include "qgsprojectstorageregistry.h"
      43                 :            : #include "qgsrasterrendererregistry.h"
      44                 :            : #include "qgsrendererregistry.h"
      45                 :            : #include "qgspointcloudrendererregistry.h"
      46                 :            : #include "qgscoordinatereferencesystemregistry.h"
      47                 :            : #include "qgssymbollayerregistry.h"
      48                 :            : #include "qgssymbollayerutils.h"
      49                 :            : #include "qgscalloutsregistry.h"
      50                 :            : #include "qgspluginlayerregistry.h"
      51                 :            : #include "qgsclassificationmethodregistry.h"
      52                 :            : #include "qgsmessagelog.h"
      53                 :            : #include "qgsannotationregistry.h"
      54                 :            : #include "qgssettings.h"
      55                 :            : #include "qgstiledownloadmanager.h"
      56                 :            : #include "qgsunittypes.h"
      57                 :            : #include "qgsuserprofile.h"
      58                 :            : #include "qgsuserprofilemanager.h"
      59                 :            : #include "qgsreferencedgeometry.h"
      60                 :            : #include "qgs3drendererregistry.h"
      61                 :            : #include "qgs3dsymbolregistry.h"
      62                 :            : #include "qgslayoutrendercontext.h"
      63                 :            : #include "qgssqliteutils.h"
      64                 :            : #include "qgsstyle.h"
      65                 :            : #include "qgsprojutils.h"
      66                 :            : #include "qgsvaliditycheckregistry.h"
      67                 :            : #include "qgsnewsfeedparser.h"
      68                 :            : #include "qgsbookmarkmanager.h"
      69                 :            : #include "qgsstylemodel.h"
      70                 :            : #include "qgsconnectionregistry.h"
      71                 :            : #include "qgsremappingproxyfeaturesink.h"
      72                 :            : #include "qgsmeshlayer.h"
      73                 :            : #include "qgsfeaturestore.h"
      74                 :            : #include "qgslocator.h"
      75                 :            : #include "qgsreadwritelocker.h"
      76                 :            : 
      77                 :            : #include "gps/qgsgpsconnectionregistry.h"
      78                 :            : #include "processing/qgsprocessingregistry.h"
      79                 :            : #include "processing/models/qgsprocessingmodelchildparametersource.h"
      80                 :            : #include "processing/models/qgsprocessingmodelchilddependency.h"
      81                 :            : 
      82                 :            : #include "layout/qgspagesizeregistry.h"
      83                 :            : 
      84                 :            : #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
      85                 :            : #include <QDesktopWidget>
      86                 :            : #endif
      87                 :            : #include <QDir>
      88                 :            : #include <QFile>
      89                 :            : #include <QFileInfo>
      90                 :            : #include <QFileOpenEvent>
      91                 :            : #include <QMessageBox>
      92                 :            : #include <QPalette>
      93                 :            : #include <QProcess>
      94                 :            : #include <QProcessEnvironment>
      95                 :            : #include <QIcon>
      96                 :            : #include <QPixmap>
      97                 :            : #include <QThreadPool>
      98                 :            : #include <QLocale>
      99                 :            : #include <QStyle>
     100                 :            : #include <QLibraryInfo>
     101                 :            : #include <QStandardPaths>
     102                 :            : #include <QRegularExpression>
     103                 :            : #include <QTextStream>
     104                 :            : #include <QScreen>
     105                 :            : #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
     106                 :            : #include <QRecursiveMutex>
     107                 :            : #endif
     108                 :            : 
     109                 :            : #ifndef Q_OS_WIN
     110                 :            : #include <netinet/in.h>
     111                 :            : #include <pwd.h>
     112                 :            : #else
     113                 :            : #include <winsock.h>
     114                 :            : #include <windows.h>
     115                 :            : #include <lmcons.h>
     116                 :            : #define SECURITY_WIN32
     117                 :            : #include <security.h>
     118                 :            : #ifdef _MSC_VER
     119                 :            : #pragma comment( lib, "Secur32.lib" )
     120                 :            : #endif
     121                 :            : #endif
     122                 :            : 
     123                 :            : #include "qgsconfig.h"
     124                 :            : 
     125                 :            : #include <gdal.h>
     126                 :            : #include <ogr_api.h>
     127                 :            : #include <cpl_conv.h> // for setting gdal options
     128                 :            : #include <sqlite3.h>
     129                 :            : #include <mutex>
     130                 :            : 
     131                 :            : #include <proj.h>
     132                 :            : 
     133                 :            : 
     134                 :            : #define CONN_POOL_MAX_CONCURRENT_CONNS      4
     135                 :            : 
     136                 :            : QObject *ABISYM( QgsApplication::mFileOpenEventReceiver ) = nullptr;
     137                 :            : bool ABISYM( QgsApplication::mInitialized ) = false;
     138                 :            : bool ABISYM( QgsApplication::mRunningFromBuildDir ) = false;
     139                 :            : const char *QgsApplication::QGIS_ORGANIZATION_NAME = "QGIS";
     140                 :            : const char *QgsApplication::QGIS_ORGANIZATION_DOMAIN = "qgis.org";
     141                 :            : const char *QgsApplication::QGIS_APPLICATION_NAME = "QGIS3";
     142                 :            : QgsApplication::ApplicationMembers *QgsApplication::sApplicationMembers = nullptr;
     143                 :            : QgsAuthManager *QgsApplication::sAuthManager = nullptr;
     144                 :            : int ABISYM( QgsApplication::sMaxThreads ) = -1;
     145                 :            : 
     146                 :          0 : Q_GLOBAL_STATIC( QStringList, sFileOpenEventList )
     147                 :         23 : Q_GLOBAL_STATIC( QString, sPrefixPath )
     148                 :         36 : Q_GLOBAL_STATIC( QString, sPluginPath )
     149                 :        213 : Q_GLOBAL_STATIC( QString, sPkgDataPath )
     150                 :         22 : Q_GLOBAL_STATIC( QString, sLibraryPath )
     151                 :         22 : Q_GLOBAL_STATIC( QString, sLibexecPath )
     152                 :          0 : Q_GLOBAL_STATIC( QString, sQmlImportPath )
     153                 :         38 : Q_GLOBAL_STATIC( QString, sThemeName )
     154                 :         27 : Q_GLOBAL_STATIC( QString, sProfilePath )
     155                 :            : 
     156                 :         75 : Q_GLOBAL_STATIC( QStringList, sDefaultSvgPaths )
     157                 :         22 : Q_GLOBAL_STATIC( QgsStringMap, sSystemEnvVars )
     158                 :        152 : Q_GLOBAL_STATIC( QString, sConfigPath )
     159                 :            : 
     160                 :         37 : Q_GLOBAL_STATIC( QString, sBuildSourcePath )
     161                 :            : #if defined(_MSC_VER) && !defined(USING_NMAKE) && !defined(USING_NINJA)
     162                 :            : Q_GLOBAL_STATIC( QString, sCfgIntDir )
     163                 :            : #endif
     164                 :         87 : Q_GLOBAL_STATIC( QString, sBuildOutputPath )
     165                 :         18 : Q_GLOBAL_STATIC( QStringList, sGdalSkipList )
     166                 :          0 : Q_GLOBAL_STATIC( QStringList, sDeferredSkippedGdalDrivers )
     167                 :         26 : Q_GLOBAL_STATIC( QString, sAuthDbDirPath )
     168                 :            : 
     169                 :          7 : Q_GLOBAL_STATIC( QString, sUserName )
     170                 :         38 : Q_GLOBAL_STATIC( QString, sUserFullName )
     171                 :         21 : Q_GLOBAL_STATIC_WITH_ARGS( QString, sPlatformName, ( "desktop" ) )
     172                 :         30 : Q_GLOBAL_STATIC( QString, sTranslation )
     173                 :            : 
     174                 :          5 : QgsApplication::QgsApplication( int &argc, char **argv, bool GUIenabled, const QString &profileFolder, const QString &platformName )
     175                 :          5 :   : QApplication( argc, argv, GUIenabled )
     176                 :         10 : {
     177                 :          5 :   *sPlatformName() = platformName;
     178                 :            : 
     179                 :          5 :   if ( *sTranslation() != QLatin1String( "C" ) )
     180                 :            :   {
     181                 :          5 :     mQgisTranslator = new QTranslator();
     182                 :         10 :     if ( mQgisTranslator->load( QStringLiteral( "qgis_" ) + *sTranslation(), i18nPath() ) )
     183                 :            :     {
     184                 :          0 :       installTranslator( mQgisTranslator );
     185                 :          0 :     }
     186                 :            :     else
     187                 :            :     {
     188                 :          5 :       QgsDebugMsgLevel( QStringLiteral( "loading of qgis translation failed %1/qgis_%2" ).arg( i18nPath(), *sTranslation() ), 2 );
     189                 :            :     }
     190                 :            : 
     191                 :            :     /* Translation file for Qt.
     192                 :            :      * The strings from the QMenuBar context section are used by Qt/Mac to shift
     193                 :            :      * the About, Preferences and Quit items to the Mac Application menu.
     194                 :            :      * These items must be translated identically in both qt_ and qgis_ files.
     195                 :            :      */
     196                 :          5 :     mQtTranslator = new QTranslator();
     197                 :         10 :     if ( mQtTranslator->load( QStringLiteral( "qt_" ) + *sTranslation(), QLibraryInfo::location( QLibraryInfo::TranslationsPath ) ) )
     198                 :            :     {
     199                 :          0 :       installTranslator( mQtTranslator );
     200                 :          0 :     }
     201                 :            :     else
     202                 :            :     {
     203                 :          5 :       QgsDebugMsgLevel( QStringLiteral( "loading of qt translation failed %1/qt_%2" ).arg( QLibraryInfo::location( QLibraryInfo::TranslationsPath ), *sTranslation() ), 2 );
     204                 :            :     }
     205                 :          5 :   }
     206                 :            : 
     207                 :          5 :   mApplicationMembers = new ApplicationMembers();
     208                 :            : 
     209                 :          5 :   *sProfilePath() = profileFolder;
     210                 :          5 : }
     211                 :            : 
     212                 :          7 : void QgsApplication::init( QString profileFolder )
     213                 :            : {
     214                 :          7 :   if ( profileFolder.isEmpty() )
     215                 :            :   {
     216                 :          7 :     if ( getenv( "QGIS_CUSTOM_CONFIG_PATH" ) )
     217                 :            :     {
     218                 :          0 :       profileFolder = getenv( "QGIS_CUSTOM_CONFIG_PATH" );
     219                 :          0 :     }
     220                 :            :     else
     221                 :            :     {
     222                 :          7 :       profileFolder = QStandardPaths::standardLocations( QStandardPaths::AppDataLocation ).value( 0 );
     223                 :            :     }
     224                 :            :     // This will normally get here for custom scripts that use QgsApplication.
     225                 :            :     // This doesn't get this hit for QGIS Desktop because we setup the profile via main
     226                 :          7 :     QString rootProfileFolder = QgsUserProfileManager::resolveProfilesFolder( profileFolder );
     227                 :          7 :     QgsUserProfileManager manager( rootProfileFolder );
     228                 :          7 :     QgsUserProfile *profile = manager.getProfile();
     229                 :          7 :     profileFolder = profile->folder();
     230                 :          7 :     delete profile;
     231                 :          7 :   }
     232                 :            : 
     233                 :          7 :   *sProfilePath() = profileFolder;
     234                 :            : 
     235                 :            :   static std::once_flag sMetaTypesRegistered;
     236                 :         12 :   std::call_once( sMetaTypesRegistered, []
     237                 :            :   {
     238                 :          5 :     qRegisterMetaType<QgsGeometry::Error>( "QgsGeometry::Error" );
     239                 :          5 :     qRegisterMetaType<QgsProcessingFeatureSourceDefinition>( "QgsProcessingFeatureSourceDefinition" );
     240                 :          5 :     qRegisterMetaType<QgsProcessingOutputLayerDefinition>( "QgsProcessingOutputLayerDefinition" );
     241                 :          5 :     qRegisterMetaType<QgsUnitTypes::LayoutUnit>( "QgsUnitTypes::LayoutUnit" );
     242                 :          5 :     qRegisterMetaType<QgsFeatureId>( "QgsFeatureId" );
     243                 :          5 :     qRegisterMetaType<QgsFeatureIds>( "QgsFeatureIds" );
     244                 :          5 :     qRegisterMetaType<QgsProperty>( "QgsProperty" );
     245                 :          5 :     qRegisterMetaType<QgsFeatureStoreList>( "QgsFeatureStoreList" );
     246                 :          5 :     qRegisterMetaType<Qgis::MessageLevel>( "Qgis::MessageLevel" );
     247                 :          5 :     qRegisterMetaType<QgsReferencedRectangle>( "QgsReferencedRectangle" );
     248                 :          5 :     qRegisterMetaType<QgsReferencedPointXY>( "QgsReferencedPointXY" );
     249                 :          5 :     qRegisterMetaType<QgsReferencedGeometry>( "QgsReferencedGeometry" );
     250                 :          5 :     qRegisterMetaType<QgsLayoutRenderContext::Flags>( "QgsLayoutRenderContext::Flags" );
     251                 :          5 :     qRegisterMetaType<QgsStyle::StyleEntity>( "QgsStyle::StyleEntity" );
     252                 :          5 :     qRegisterMetaType<QgsCoordinateReferenceSystem>( "QgsCoordinateReferenceSystem" );
     253                 :          5 :     qRegisterMetaType<QgsAuthManager::MessageLevel>( "QgsAuthManager::MessageLevel" );
     254                 :          5 :     qRegisterMetaType<QgsNetworkRequestParameters>( "QgsNetworkRequestParameters" );
     255                 :          5 :     qRegisterMetaType<QgsNetworkReplyContent>( "QgsNetworkReplyContent" );
     256                 :          5 :     qRegisterMetaType<QgsGeometry>( "QgsGeometry" );
     257                 :          5 :     qRegisterMetaType<QgsDatumTransform::GridDetails>( "QgsDatumTransform::GridDetails" );
     258                 :          5 :     qRegisterMetaType<QgsDatumTransform::TransformDetails>( "QgsDatumTransform::TransformDetails" );
     259                 :          5 :     qRegisterMetaType<QgsNewsFeedParser::Entry>( "QgsNewsFeedParser::Entry" );
     260                 :          5 :     qRegisterMetaType<QgsRectangle>( "QgsRectangle" );
     261                 :          5 :     qRegisterMetaType<QgsLocatorResult>( "QgsLocatorResult" );
     262                 :          5 :     qRegisterMetaType<QgsProcessingModelChildParameterSource>( "QgsProcessingModelChildParameterSource" );
     263                 :          5 :     qRegisterMetaTypeStreamOperators<QgsProcessingModelChildParameterSource>( "QgsProcessingModelChildParameterSource" );
     264                 :          5 :     qRegisterMetaType<QgsRemappingSinkDefinition>( "QgsRemappingSinkDefinition" );
     265                 :          5 :     qRegisterMetaType<QgsProcessingModelChildDependency>( "QgsProcessingModelChildDependency" );
     266                 :          5 :     qRegisterMetaType<QgsTextFormat>( "QgsTextFormat" );
     267                 :          5 :     QMetaType::registerComparators<QgsProcessingModelChildDependency>();
     268                 :          5 :     QMetaType::registerEqualsComparator<QgsProcessingFeatureSourceDefinition>();
     269                 :          5 :     QMetaType::registerEqualsComparator<QgsProperty>();
     270                 :          5 :     QMetaType::registerEqualsComparator<QgsDateTimeRange>();
     271                 :          5 :     QMetaType::registerEqualsComparator<QgsDateRange>();
     272                 :          5 :     qRegisterMetaType<QPainter::CompositionMode>( "QPainter::CompositionMode" );
     273                 :          5 :     qRegisterMetaType<QgsDateTimeRange>( "QgsDateTimeRange" );
     274                 :          5 :   } );
     275                 :            : 
     276                 :          7 :   ( void ) resolvePkgPath();
     277                 :            : 
     278                 :          7 :   if ( ABISYM( mRunningFromBuildDir ) )
     279                 :            :   {
     280                 :            :     // we run from source directory - not installed to destination (specified prefix)
     281                 :          7 :     *sPrefixPath() = QString(); // set invalid path
     282                 :            : #if defined(_MSC_VER) && !defined(USING_NMAKE) && !defined(USING_NINJA)
     283                 :            :     setPluginPath( *sBuildOutputPath() + '/' + QString( QGIS_PLUGIN_SUBDIR ) + '/' + *sCfgIntDir() );
     284                 :            : #else
     285                 :         14 :     setPluginPath( *sBuildOutputPath() + '/' + QStringLiteral( QGIS_PLUGIN_SUBDIR ) );
     286                 :            : #endif
     287                 :         14 :     setPkgDataPath( *sBuildOutputPath() + QStringLiteral( "/data" ) ); // in buildDir/data - used for: doc, resources, svg
     288                 :          7 :     *sLibraryPath() = *sBuildOutputPath() + '/' + QGIS_LIB_SUBDIR + '/';
     289                 :            : #if defined(_MSC_VER) && !defined(USING_NMAKE) && !defined(USING_NINJA)
     290                 :            :     *sLibexecPath() = *sBuildOutputPath() + '/' + QGIS_LIBEXEC_SUBDIR + '/' + *sCfgIntDir() + '/';
     291                 :            : #else
     292                 :          7 :     *sLibexecPath() = *sBuildOutputPath() + '/' + QGIS_LIBEXEC_SUBDIR + '/';
     293                 :            : #endif
     294                 :            : #if defined( HAVE_QUICK )
     295                 :            :     *sQmlImportPath() = *sBuildOutputPath() + '/' + QGIS_QML_SUBDIR + '/';
     296                 :            : #endif
     297                 :          7 :   }
     298                 :            :   else
     299                 :            :   {
     300                 :          0 :     char *prefixPath = getenv( "QGIS_PREFIX_PATH" );
     301                 :          0 :     if ( !prefixPath )
     302                 :            :     {
     303                 :          0 :       if ( sPrefixPath()->isNull() )
     304                 :            :       {
     305                 :            : #if defined(Q_OS_MACX) || defined(Q_OS_WIN)
     306                 :            :         setPrefixPath( applicationDirPath(), true );
     307                 :            : #elif defined(ANDROID)
     308                 :            :         // this is "/data/data/org.qgis.qgis" in android
     309                 :            :         QDir myDir( QDir::homePath() );
     310                 :            :         myDir.cdUp();
     311                 :            :         QString myPrefix = myDir.absolutePath();
     312                 :            :         setPrefixPath( myPrefix, true );
     313                 :            : #else
     314                 :          0 :         QDir myDir( applicationDirPath() );
     315                 :            :         // Fix for server which is one level deeper in /usr/lib/cgi-bin
     316                 :          0 :         if ( applicationDirPath().contains( QStringLiteral( "cgi-bin" ) ) )
     317                 :            :         {
     318                 :          0 :           myDir.cdUp();
     319                 :          0 :         }
     320                 :          0 :         myDir.cdUp(); // Go from /usr/bin or /usr/lib (for server) to /usr
     321                 :          0 :         QString myPrefix = myDir.absolutePath();
     322                 :          0 :         setPrefixPath( myPrefix, true );
     323                 :            : #endif
     324                 :          0 :       }
     325                 :          0 :     }
     326                 :            :     else
     327                 :            :     {
     328                 :          0 :       setPrefixPath( prefixPath, true );
     329                 :            :     }
     330                 :            :   }
     331                 :            : 
     332                 :          7 :   *sConfigPath() = profileFolder + '/'; // make sure trailing slash is included
     333                 :         14 :   *sDefaultSvgPaths() << qgisSettingsDirPath() + QStringLiteral( "svg/" );
     334                 :            : 
     335                 :          7 :   *sAuthDbDirPath() = qgisSettingsDirPath();
     336                 :          7 :   if ( getenv( "QGIS_AUTH_DB_DIR_PATH" ) )
     337                 :            :   {
     338                 :          0 :     setAuthDatabaseDirPath( getenv( "QGIS_AUTH_DB_DIR_PATH" ) );
     339                 :          0 :   }
     340                 :            : 
     341                 :            :   // store system environment variables passed to application, before they are adjusted
     342                 :          7 :   QMap<QString, QString> systemEnvVarMap;
     343                 :         14 :   QString passfile( QStringLiteral( "QGIS_AUTH_PASSWORD_FILE" ) ); // QString, for comparison
     344                 :            : 
     345                 :          7 :   const auto systemEnvironment = QProcessEnvironment::systemEnvironment().toStringList();
     346                 :        275 :   for ( const QString &varStr : systemEnvironment )
     347                 :            :   {
     348                 :        268 :     int pos = varStr.indexOf( QLatin1Char( '=' ) );
     349                 :        268 :     if ( pos == -1 )
     350                 :          0 :       continue;
     351                 :        268 :     QString varStrName = varStr.left( pos );
     352                 :        268 :     QString varStrValue = varStr.mid( pos + 1 );
     353                 :        268 :     if ( varStrName != passfile )
     354                 :            :     {
     355                 :        268 :       systemEnvVarMap.insert( varStrName, varStrValue );
     356                 :        268 :     }
     357                 :        268 :   }
     358                 :          7 :   *sSystemEnvVars() = systemEnvVarMap;
     359                 :            : 
     360                 :            :   // append local user-writable folder as a proj search path
     361                 :          7 :   QStringList currentProjSearchPaths = QgsProjUtils::searchPaths();
     362                 :         14 :   currentProjSearchPaths.append( qgisSettingsDirPath() + QStringLiteral( "proj" ) );
     363                 :            : #ifdef Q_OS_MACX
     364                 :            :   // append bundled proj lib for MacOS
     365                 :            :   QString projLib( QDir::cleanPath( pkgDataPath().append( "/proj" ) ) );
     366                 :            :   if ( QFile::exists( projLib ) )
     367                 :            :   {
     368                 :            :     currentProjSearchPaths.append( projLib );
     369                 :            :   }
     370                 :            : #endif // Q_OS_MACX
     371                 :            : 
     372                 :          7 :   char **newPaths = new char *[currentProjSearchPaths.length()];
     373                 :         30 :   for ( int i = 0; i < currentProjSearchPaths.count(); ++i )
     374                 :            :   {
     375                 :         23 :     newPaths[i] = CPLStrdup( currentProjSearchPaths.at( i ).toUtf8().constData() );
     376                 :         23 :   }
     377                 :          7 :   proj_context_set_search_paths( nullptr, currentProjSearchPaths.count(), newPaths );
     378                 :         30 :   for ( int i = 0; i < currentProjSearchPaths.count(); ++i )
     379                 :            :   {
     380                 :         23 :     CPLFree( newPaths[i] );
     381                 :         23 :   }
     382                 :          7 :   delete [] newPaths;
     383                 :            : 
     384                 :            :   // allow Qt to search for Qt plugins (e.g. sqldrivers) in our plugin directory
     385                 :          7 :   QCoreApplication::addLibraryPath( pluginPath() );
     386                 :            : 
     387                 :            :   // set max. thread count to -1
     388                 :            :   // this should be read from QgsSettings but we don't know where they are at this point
     389                 :            :   // so we read actual value in main.cpp
     390                 :          7 :   ABISYM( sMaxThreads ) = -1;
     391                 :            : 
     392                 :            :   {
     393                 :          7 :     QgsScopedRuntimeProfile profile( tr( "Load color schemes" ) );
     394                 :          7 :     colorSchemeRegistry()->addDefaultSchemes();
     395                 :          7 :     colorSchemeRegistry()->initStyleScheme();
     396                 :          7 :   }
     397                 :            : 
     398                 :            :   {
     399                 :          7 :     QgsScopedRuntimeProfile profile( tr( "Load bookmarks" ) );
     400                 :          7 :     bookmarkManager()->initialize( QgsApplication::qgisSettingsDirPath() + "/bookmarks.xml" );
     401                 :          7 :   }
     402                 :            : 
     403                 :          7 :   if ( !members()->mStyleModel )
     404                 :          5 :     members()->mStyleModel = new QgsStyleModel( QgsStyle::defaultStyle() );
     405                 :            : 
     406                 :          7 :   ABISYM( mInitialized ) = true;
     407                 :          7 : }
     408                 :            : 
     409                 :          5 : QgsApplication::~QgsApplication()
     410                 :          5 : {
     411                 :          5 :   delete mDataItemProviderRegistry;
     412                 :          5 :   delete mApplicationMembers;
     413                 :          5 :   delete mQgisTranslator;
     414                 :          5 :   delete mQtTranslator;
     415                 :            : 
     416                 :            :   // we do this here as well as in exitQgis() -- it's safe to call as often as we want,
     417                 :            :   // and there's just a *chance* that someone hasn't properly called exitQgis prior to
     418                 :            :   // this destructor...
     419                 :          5 :   invalidateCaches();
     420                 :          5 : }
     421                 :            : 
     422                 :          8 : void QgsApplication::invalidateCaches()
     423                 :            : {
     424                 :            :   // invalidate coordinate cache while the PROJ context held by the thread-locale
     425                 :            :   // QgsProjContextStore object is still alive. Otherwise if this later object
     426                 :            :   // is destroyed before the static variables of the cache, we might use freed memory.
     427                 :          8 :   QgsCoordinateTransform::invalidateCache( true );
     428                 :          8 :   QgsCoordinateReferenceSystem::invalidateCache( true );
     429                 :          8 :   QgsEllipsoidUtils::invalidateCache( true );
     430                 :          8 : }
     431                 :            : 
     432                 :       2876 : QgsApplication *QgsApplication::instance()
     433                 :            : {
     434                 :       2876 :   return qobject_cast<QgsApplication *>( QCoreApplication::instance() );
     435                 :            : }
     436                 :            : 
     437                 :          0 : bool QgsApplication::event( QEvent *event )
     438                 :            : {
     439                 :          0 :   bool done = false;
     440                 :          0 :   if ( event->type() == QEvent::FileOpen )
     441                 :            :   {
     442                 :            :     // handle FileOpen event (double clicking a file icon in Mac OS X Finder)
     443                 :          0 :     if ( ABISYM( mFileOpenEventReceiver ) )
     444                 :            :     {
     445                 :            :       // Forward event to main window.
     446                 :          0 :       done = notify( ABISYM( mFileOpenEventReceiver ), event );
     447                 :          0 :     }
     448                 :            :     else
     449                 :            :     {
     450                 :            :       // Store filename because receiver has not registered yet.
     451                 :            :       // If QGIS has been launched by double clicking a file icon, FileOpen will be
     452                 :            :       // the first event; the main window is not yet ready to handle the event.
     453                 :          0 :       sFileOpenEventList()->append( static_cast<QFileOpenEvent *>( event )->file() );
     454                 :          0 :       done = true;
     455                 :            :     }
     456                 :          0 :   }
     457                 :            :   else
     458                 :            :   {
     459                 :            :     // pass other events to base class
     460                 :          0 :     done = QApplication::event( event );
     461                 :            :   }
     462                 :          0 :   return done;
     463                 :          0 : }
     464                 :            : 
     465                 :       1633 : bool QgsApplication::notify( QObject *receiver, QEvent *event )
     466                 :            : {
     467                 :       1633 :   bool done = false;
     468                 :            :   // Crashes  in customization (especially on Mac), if we're not in the main/UI thread, see #5597
     469                 :       1633 :   if ( thread() == receiver->thread() )
     470                 :       1624 :     emit preNotify( receiver, event, &done );
     471                 :            : 
     472                 :       1633 :   if ( done )
     473                 :          0 :     return true;
     474                 :            : 
     475                 :            :   // Send event to receiver and catch unhandled exceptions
     476                 :       1633 :   done = true;
     477                 :            :   try
     478                 :            :   {
     479                 :       1633 :     done = QApplication::notify( receiver, event );
     480                 :       1633 :   }
     481                 :            :   catch ( QgsException &e )
     482                 :            :   {
     483                 :          0 :     qCritical() << "Caught unhandled QgsException: " << e.what();
     484                 :          0 :     if ( qApp->thread() == QThread::currentThread() )
     485                 :          0 :       QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
     486                 :          0 :   }
     487                 :            :   catch ( std::exception &e )
     488                 :            :   {
     489                 :          0 :     qCritical() << "Caught unhandled std::exception: " << e.what();
     490                 :          0 :     if ( qApp->thread() == QThread::currentThread() )
     491                 :          0 :       QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
     492                 :          0 :   }
     493                 :            :   catch ( ... )
     494                 :            :   {
     495                 :          0 :     qCritical() << "Caught unhandled unknown exception";
     496                 :          0 :     if ( qApp->thread() == QThread::currentThread() )
     497                 :          0 :       QMessageBox::critical( activeWindow(), tr( "Exception" ), tr( "unknown exception" ) );
     498                 :          0 :   }
     499                 :            : 
     500                 :       1633 :   return done;
     501                 :       1633 : }
     502                 :            : 
     503                 :       1798 : QgsRuntimeProfiler *QgsApplication::profiler()
     504                 :            : {
     505                 :       1798 :   return QgsRuntimeProfiler::threadLocalInstance();
     506                 :            : }
     507                 :            : 
     508                 :          0 : void QgsApplication::setFileOpenEventReceiver( QObject *receiver )
     509                 :            : {
     510                 :            :   // Set receiver for FileOpen events
     511                 :          0 :   ABISYM( mFileOpenEventReceiver ) = receiver;
     512                 :            :   // Propagate any events collected before the receiver has registered.
     513                 :          0 :   if ( sFileOpenEventList()->count() > 0 )
     514                 :            :   {
     515                 :          0 :     const QStringList fileOpenEventList = *sFileOpenEventList();
     516                 :          0 :     for ( const QString &file : fileOpenEventList )
     517                 :            :     {
     518                 :          0 :       QFileOpenEvent foe( file );
     519                 :          0 :       QgsApplication::sendEvent( ABISYM( mFileOpenEventReceiver ), &foe );
     520                 :          0 :     }
     521                 :          0 :     sFileOpenEventList()->clear();
     522                 :          0 :   }
     523                 :          0 : }
     524                 :            : 
     525                 :          0 : void QgsApplication::setPrefixPath( const QString &prefixPath, bool useDefaultPaths )
     526                 :            : {
     527                 :          0 :   *sPrefixPath() = prefixPath;
     528                 :            : #if defined(Q_OS_WIN)
     529                 :            :   if ( sPrefixPath()->endsWith( "/bin" ) )
     530                 :            :   {
     531                 :            :     sPrefixPath()->chop( 4 );
     532                 :            :   }
     533                 :            : #endif
     534                 :          0 :   if ( useDefaultPaths && !ABISYM( mRunningFromBuildDir ) )
     535                 :            :   {
     536                 :          0 :     setPluginPath( *sPrefixPath() + '/' + QStringLiteral( QGIS_PLUGIN_SUBDIR ) );
     537                 :          0 :     setPkgDataPath( *sPrefixPath() + '/' + QStringLiteral( QGIS_DATA_SUBDIR ) );
     538                 :          0 :   }
     539                 :          0 :   *sLibraryPath() = *sPrefixPath() + '/' + QGIS_LIB_SUBDIR + '/';
     540                 :          0 :   *sLibexecPath() = *sPrefixPath() + '/' + QGIS_LIBEXEC_SUBDIR + '/';
     541                 :            : #if defined( HAVE_QUICK )
     542                 :            :   *sQmlImportPath() = *sPrefixPath() + '/' + QGIS_QML_SUBDIR + '/';
     543                 :            : #endif
     544                 :          0 : }
     545                 :            : 
     546                 :          7 : void QgsApplication::setPluginPath( const QString &pluginPath )
     547                 :            : {
     548                 :          7 :   *sPluginPath() = pluginPath;
     549                 :          7 : }
     550                 :            : 
     551                 :          7 : void QgsApplication::setPkgDataPath( const QString &pkgDataPath )
     552                 :            : {
     553                 :          7 :   *sPkgDataPath() = pkgDataPath;
     554                 :            : 
     555                 :         14 :   QString mySvgPath = pkgDataPath + QStringLiteral( "/svg/" );
     556                 :            : 
     557                 :            :   // avoid duplicate entries
     558                 :          7 :   if ( !sDefaultSvgPaths()->contains( mySvgPath ) )
     559                 :          5 :     *sDefaultSvgPaths() << mySvgPath;
     560                 :          7 : }
     561                 :            : 
     562                 :          0 : void QgsApplication::setDefaultSvgPaths( const QStringList &pathList )
     563                 :            : {
     564                 :          0 :   *sDefaultSvgPaths() = pathList;
     565                 :          0 : }
     566                 :            : 
     567                 :          0 : void QgsApplication::setAuthDatabaseDirPath( const QString &authDbDirPath )
     568                 :            : {
     569                 :          0 :   QFileInfo fi( authDbDirPath );
     570                 :          0 :   if ( fi.exists() && fi.isDir() && fi.isWritable() )
     571                 :            :   {
     572                 :          0 :     *sAuthDbDirPath() = fi.canonicalFilePath() + QDir::separator();
     573                 :          0 :   }
     574                 :          0 : }
     575                 :            : 
     576                 :          1 : QString QgsApplication::prefixPath()
     577                 :            : {
     578                 :            : #if 0
     579                 :            :   if ( ABISYM( mRunningFromBuildDir ) )
     580                 :            :   {
     581                 :            :     static bool sOnce = true;
     582                 :            :     if ( sOnce )
     583                 :            :     {
     584                 :            :       QgsMessageLogNotifyBlocker blockNotifications;
     585                 :            :       ( void ) blockNotifications;
     586                 :            :       qWarning( "!!! prefix path was requested, but it is not valid - we do not run from installed path !!!" );
     587                 :            :     }
     588                 :            :     sOnce = false;
     589                 :            :   }
     590                 :            : #endif
     591                 :            : 
     592                 :          1 :   return *sPrefixPath();
     593                 :            : }
     594                 :         14 : QString QgsApplication::pluginPath()
     595                 :            : {
     596                 :         14 :   return *sPluginPath();
     597                 :            : }
     598                 :            : 
     599                 :        103 : QString QgsApplication::pkgDataPath()
     600                 :            : {
     601                 :        103 :   if ( sPkgDataPath()->isNull() )
     602                 :         15 :     return resolvePkgPath();
     603                 :            :   else
     604                 :         88 :     return *sPkgDataPath();
     605                 :        103 : }
     606                 :            : 
     607                 :         21 : QString QgsApplication::defaultThemePath()
     608                 :            : {
     609                 :         42 :   return QStringLiteral( ":/images/themes/default/" );
     610                 :            : }
     611                 :         11 : QString QgsApplication::activeThemePath()
     612                 :            : {
     613                 :         11 :   QString usersThemes = userThemesFolder() + QDir::separator() + themeName() + QDir::separator() + "icons/";
     614                 :         11 :   QDir dir( usersThemes );
     615                 :         11 :   if ( dir.exists() )
     616                 :            :   {
     617                 :          0 :     return usersThemes;
     618                 :            :   }
     619                 :            :   else
     620                 :            :   {
     621                 :         11 :     QString defaultThemes = defaultThemesFolder() + QDir::separator() + themeName() + QDir::separator() + "icons/";
     622                 :         11 :     return defaultThemes;
     623                 :         11 :   }
     624                 :         11 : }
     625                 :            : 
     626                 :          0 : QString QgsApplication::appIconPath()
     627                 :            : {
     628                 :          0 :   return iconsPath() + QStringLiteral( "qgis-icon-60x60.png" );
     629                 :          0 : }
     630                 :            : 
     631                 :          0 : int QgsApplication::maxThreads()
     632                 :            : {
     633                 :          0 :   return ABISYM( sMaxThreads );
     634                 :            : }
     635                 :            : 
     636                 :          0 : QString QgsApplication::iconPath( const QString &iconFile )
     637                 :            : {
     638                 :            :   // try active theme
     639                 :          0 :   QString path = activeThemePath();
     640                 :          0 :   if ( QFile::exists( path + iconFile ) )
     641                 :          0 :     return path + iconFile;
     642                 :            : 
     643                 :            :   // use default theme
     644                 :          0 :   return defaultThemePath() + iconFile;
     645                 :          0 : }
     646                 :            : 
     647                 :         20 : QIcon QgsApplication::getThemeIcon( const QString &name )
     648                 :            : {
     649                 :         20 :   QgsApplication *app = instance();
     650                 :         20 :   if ( app && app->mIconCache.contains( name ) )
     651                 :         10 :     return app->mIconCache.value( name );
     652                 :            : 
     653                 :         10 :   QIcon icon;
     654                 :            : 
     655                 :         10 :   QString myPreferredPath = activeThemePath() + QDir::separator() + name;
     656                 :         10 :   QString myDefaultPath = defaultThemePath() + QDir::separator() + name;
     657                 :         10 :   if ( QFile::exists( myPreferredPath ) )
     658                 :            :   {
     659                 :          0 :     icon = QIcon( myPreferredPath );
     660                 :          0 :   }
     661                 :         10 :   else if ( QFile::exists( myDefaultPath ) )
     662                 :            :   {
     663                 :            :     //could still return an empty icon if it
     664                 :            :     //doesn't exist in the default theme either!
     665                 :         10 :     icon = QIcon( myDefaultPath );
     666                 :         10 :   }
     667                 :            :   else
     668                 :            :   {
     669                 :          0 :     icon = QIcon();
     670                 :            :   }
     671                 :            : 
     672                 :         10 :   if ( app )
     673                 :         10 :     app->mIconCache.insert( name, icon );
     674                 :         10 :   return icon;
     675                 :         20 : }
     676                 :            : 
     677                 :          0 : QCursor QgsApplication::getThemeCursor( Cursor cursor )
     678                 :            : {
     679                 :          0 :   QgsApplication *app = instance();
     680                 :          0 :   if ( app && app->mCursorCache.contains( cursor ) )
     681                 :          0 :     return app->mCursorCache.value( cursor );
     682                 :            : 
     683                 :            :   // All calculations are done on 32x32 icons
     684                 :            :   // Defaults to center, individual cursors may override
     685                 :          0 :   int activeX = 16;
     686                 :          0 :   int activeY = 16;
     687                 :            : 
     688                 :          0 :   QString name;
     689                 :          0 :   switch ( cursor )
     690                 :            :   {
     691                 :            :     case ZoomIn:
     692                 :          0 :       name = QStringLiteral( "mZoomIn.svg" );
     693                 :          0 :       activeX = 13;
     694                 :          0 :       activeY = 13;
     695                 :          0 :       break;
     696                 :            :     case ZoomOut:
     697                 :          0 :       name = QStringLiteral( "mZoomOut.svg" );
     698                 :          0 :       activeX = 13;
     699                 :          0 :       activeY = 13;
     700                 :          0 :       break;
     701                 :            :     case Identify:
     702                 :          0 :       activeX = 3;
     703                 :          0 :       activeY = 6;
     704                 :          0 :       name = QStringLiteral( "mIdentify.svg" );
     705                 :          0 :       break;
     706                 :            :     case CrossHair:
     707                 :          0 :       name = QStringLiteral( "mCrossHair.svg" );
     708                 :          0 :       break;
     709                 :            :     case CapturePoint:
     710                 :          0 :       name = QStringLiteral( "mCapturePoint.svg" );
     711                 :          0 :       break;
     712                 :            :     case Select:
     713                 :          0 :       name = QStringLiteral( "mSelect.svg" );
     714                 :          0 :       activeX = 6;
     715                 :          0 :       activeY = 6;
     716                 :          0 :       break;
     717                 :            :     case Sampler:
     718                 :          0 :       activeX = 5;
     719                 :          0 :       activeY = 5;
     720                 :          0 :       name = QStringLiteral( "mSampler.svg" );
     721                 :          0 :       break;
     722                 :            :       // No default
     723                 :            :   }
     724                 :            :   // It should never get here!
     725                 :            :   Q_ASSERT( ! name.isEmpty( ) );
     726                 :            : 
     727                 :          0 :   QIcon icon = getThemeIcon( QStringLiteral( "cursors" ) + QDir::separator() + name );
     728                 :          0 :   QCursor cursorIcon;
     729                 :            :   // Check if an icon exists for this cursor (the O.S. default cursor will be used if it does not)
     730                 :          0 :   if ( ! icon.isNull( ) )
     731                 :            :   {
     732                 :            :     // Apply scaling
     733                 :          0 :     float scale = Qgis::UI_SCALE_FACTOR * app->fontMetrics().height() / 32.0;
     734                 :          0 :     cursorIcon = QCursor( icon.pixmap( std::ceil( scale * 32 ), std::ceil( scale * 32 ) ), std::ceil( scale * activeX ), std::ceil( scale * activeY ) );
     735                 :          0 :   }
     736                 :          0 :   if ( app )
     737                 :          0 :     app->mCursorCache.insert( cursor, cursorIcon );
     738                 :          0 :   return cursorIcon;
     739                 :          0 : }
     740                 :            : 
     741                 :            : // TODO: add some caching mechanism ?
     742                 :          0 : QPixmap QgsApplication::getThemePixmap( const QString &name, const QColor &foreColor, const QColor &backColor, const int size )
     743                 :            : {
     744                 :          0 :   const QString preferredPath = activeThemePath() + QDir::separator() + name;
     745                 :          0 :   const QString defaultPath = defaultThemePath() + QDir::separator() + name;
     746                 :          0 :   const QString path = QFile::exists( preferredPath ) ? preferredPath : defaultPath;
     747                 :          0 :   if ( foreColor.isValid() || backColor.isValid() )
     748                 :            :   {
     749                 :          0 :     bool fitsInCache = false;
     750                 :          0 :     const QImage image = svgCache()->svgAsImage( path, size, backColor, foreColor, 1, 1, fitsInCache );
     751                 :          0 :     return QPixmap::fromImage( image );
     752                 :          0 :   }
     753                 :            : 
     754                 :          0 :   return QPixmap( path );
     755                 :          0 : }
     756                 :            : 
     757                 :          0 : void QgsApplication::setThemeName( const QString &themeName )
     758                 :            : {
     759                 :          0 :   *sThemeName() = themeName;
     760                 :          0 : }
     761                 :            : 
     762                 :         22 : QString QgsApplication::resolvePkgPath()
     763                 :            : {
     764                 :         22 :   static QString appPath;
     765                 :         22 :   if ( appPath.isNull() )
     766                 :            :   {
     767                 :          5 :     if ( QCoreApplication::instance() )
     768                 :            :     {
     769                 :          5 :       appPath = applicationDirPath();
     770                 :          5 :     }
     771                 :            :     else
     772                 :            :     {
     773                 :          0 :       qWarning( "Application path not initialized" );
     774                 :            :     }
     775                 :          5 :   }
     776                 :            : 
     777                 :         22 :   if ( !appPath.isNull() || getenv( "QGIS_PREFIX_PATH" ) )
     778                 :            :   {
     779                 :         22 :     QString prefix = getenv( "QGIS_PREFIX_PATH" ) ? getenv( "QGIS_PREFIX_PATH" ) : appPath;
     780                 :            : 
     781                 :            :     // check if QGIS is run from build directory (not the install directory)
     782                 :         22 :     QFile f;
     783                 :            :     // "/../../.." is for Mac bundled app in build directory
     784                 :         37 :     static const QStringList paths { QStringList() << QString() << QStringLiteral( "/.." ) << QStringLiteral( "/bin" ) << QStringLiteral( "/../../.." ) };
     785                 :         22 :     for ( const QString &path : paths )
     786                 :            :     {
     787                 :         22 :       f.setFileName( prefix + path + "/qgisbuildpath.txt" );
     788                 :         22 :       if ( f.exists() )
     789                 :         22 :         break;
     790                 :            :     }
     791                 :         22 :     if ( f.exists() && f.open( QIODevice::ReadOnly ) )
     792                 :            :     {
     793                 :         22 :       ABISYM( mRunningFromBuildDir ) = true;
     794                 :         22 :       *sBuildSourcePath() = f.readLine().trimmed();
     795                 :         22 :       *sBuildOutputPath() = f.readLine().trimmed();
     796                 :         22 :       QgsDebugMsgLevel( QStringLiteral( "Running from build directory!" ), 4 );
     797                 :         22 :       QgsDebugMsgLevel( QStringLiteral( "- source directory: %1" ).arg( sBuildSourcePath()->toUtf8().constData() ), 4 );
     798                 :         22 :       QgsDebugMsgLevel( QStringLiteral( "- output directory of the build: %1" ).arg( sBuildOutputPath()->toUtf8().constData() ), 4 );
     799                 :            : #if defined(_MSC_VER) && !defined(USING_NMAKE) && !defined(USING_NINJA)
     800                 :            :       *sCfgIntDir() = prefix.split( '/', QString::SkipEmptyParts ).last();
     801                 :            :       qDebug( "- cfg: %s", sCfgIntDir()->toUtf8().constData() );
     802                 :            : #endif
     803                 :         22 :     }
     804                 :         22 :   }
     805                 :            : 
     806                 :         22 :   QString prefixPath;
     807                 :         22 :   if ( getenv( "QGIS_PREFIX_PATH" ) )
     808                 :          0 :     prefixPath = getenv( "QGIS_PREFIX_PATH" );
     809                 :            :   else
     810                 :            :   {
     811                 :            : #if defined(ANDROID)
     812                 :            :     // this is "/data/data/org.qgis.qgis" in android
     813                 :            :     QDir dir( QDir::homePath() );
     814                 :            :     dir.cdUp();
     815                 :            :     prefixPath = dir.absolutePath();
     816                 :            : #else
     817                 :            : 
     818                 :            : #if defined(Q_OS_MACX)
     819                 :            :     prefixPath = appPath;
     820                 :            : #elif defined(Q_OS_WIN)
     821                 :            :     prefixPath = appPath;
     822                 :            :     if ( prefixPath.endsWith( "/bin" ) )
     823                 :            :       prefixPath.chop( 4 );
     824                 :            : #else
     825                 :         22 :     QDir dir( appPath );
     826                 :            :     // Fix for server which is one level deeper in /usr/lib/cgi-bin
     827                 :         44 :     if ( appPath.contains( QStringLiteral( "cgi-bin" ) ) )
     828                 :            :     {
     829                 :          0 :       dir.cdUp();
     830                 :          0 :     }
     831                 :         22 :     dir.cdUp(); // Go from /usr/bin or /usr/lib (for server) to /usr
     832                 :         22 :     prefixPath = dir.absolutePath();
     833                 :            : #endif
     834                 :            : #endif
     835                 :         22 :   }
     836                 :            : 
     837                 :         22 :   if ( ABISYM( mRunningFromBuildDir ) )
     838                 :         44 :     return *sBuildOutputPath() + QStringLiteral( "/data" );
     839                 :            :   else
     840                 :          0 :     return prefixPath + '/' + QStringLiteral( QGIS_DATA_SUBDIR );
     841                 :         22 : }
     842                 :            : 
     843                 :         23 : QString QgsApplication::themeName()
     844                 :            : {
     845                 :         23 :   return *sThemeName();
     846                 :            : }
     847                 :            : 
     848                 :          0 : void QgsApplication::setUITheme( const QString &themeName )
     849                 :            : {
     850                 :            :   // Loop all style sheets, find matching name, load it.
     851                 :          0 :   QHash<QString, QString> themes = QgsApplication::uiThemes();
     852                 :          0 :   if ( themeName == QLatin1String( "default" ) || !themes.contains( themeName ) )
     853                 :            :   {
     854                 :          0 :     setThemeName( QStringLiteral( "default" ) );
     855                 :          0 :     qApp->setStyleSheet( QString() );
     856                 :          0 :     return;
     857                 :            :   }
     858                 :            : 
     859                 :          0 :   QString path = themes.value( themeName );
     860                 :          0 :   QString stylesheetname = path + "/style.qss";
     861                 :            : 
     862                 :          0 :   QFile file( stylesheetname );
     863                 :          0 :   QFile variablesfile( path + "/variables.qss" );
     864                 :            : 
     865                 :          0 :   QFileInfo variableInfo( variablesfile );
     866                 :            : 
     867                 :          0 :   if ( !file.open( QIODevice::ReadOnly ) || ( variableInfo.exists() && !variablesfile.open( QIODevice::ReadOnly ) ) )
     868                 :            :   {
     869                 :          0 :     return;
     870                 :            :   }
     871                 :            : 
     872                 :          0 :   QString styledata = file.readAll();
     873                 :          0 :   styledata.replace( QLatin1String( "@theme_path" ), path );
     874                 :            : 
     875                 :          0 :   if ( variableInfo.exists() )
     876                 :            :   {
     877                 :          0 :     QTextStream in( &variablesfile );
     878                 :          0 :     while ( !in.atEnd() )
     879                 :            :     {
     880                 :          0 :       QString line = in.readLine();
     881                 :            :       // This is a variable
     882                 :          0 :       if ( line.startsWith( '@' ) )
     883                 :            :       {
     884                 :          0 :         int index = line.indexOf( ':' );
     885                 :          0 :         QString name = line.mid( 0, index );
     886                 :          0 :         QString value = line.mid( index + 1, line.length() );
     887                 :          0 :         styledata.replace( name, value );
     888                 :          0 :       }
     889                 :          0 :     }
     890                 :          0 :     variablesfile.close();
     891                 :          0 :   }
     892                 :          0 :   file.close();
     893                 :            : 
     894                 :          0 :   if ( Qgis::UI_SCALE_FACTOR != 1.0 )
     895                 :            :   {
     896                 :            :     // apply OS-specific UI scale factor to stylesheet's em values
     897                 :          0 :     int index = 0;
     898                 :          0 :     const static QRegularExpression regex( QStringLiteral( "(?<=[\\s:])([0-9\\.]+)(?=em)" ) );
     899                 :          0 :     QRegularExpressionMatch match = regex.match( styledata, index );
     900                 :          0 :     while ( match.hasMatch() )
     901                 :            :     {
     902                 :          0 :       index = match.capturedStart();
     903                 :          0 :       styledata.remove( index, match.captured( 0 ).length() );
     904                 :          0 :       QString number = QString::number( match.captured( 0 ).toDouble() * Qgis::UI_SCALE_FACTOR );
     905                 :          0 :       styledata.insert( index, number );
     906                 :          0 :       index += number.length();
     907                 :          0 :       match = regex.match( styledata, index );
     908                 :          0 :     }
     909                 :          0 :   }
     910                 :            : 
     911                 :          0 :   qApp->setStyleSheet( styledata );
     912                 :            : 
     913                 :          0 :   QFile palettefile( path + "/palette.txt" );
     914                 :          0 :   QFileInfo paletteInfo( palettefile );
     915                 :          0 :   if ( paletteInfo.exists() && palettefile.open( QIODevice::ReadOnly ) )
     916                 :            :   {
     917                 :          0 :     QPalette pal = qApp->palette();
     918                 :          0 :     QTextStream in( &palettefile );
     919                 :          0 :     while ( !in.atEnd() )
     920                 :            :     {
     921                 :          0 :       QString line = in.readLine();
     922                 :          0 :       QStringList parts = line.split( ':' );
     923                 :          0 :       if ( parts.count() == 2 )
     924                 :            :       {
     925                 :          0 :         int role = parts.at( 0 ).trimmed().toInt();
     926                 :          0 :         QColor color = QgsSymbolLayerUtils::decodeColor( parts.at( 1 ).trimmed() );
     927                 :          0 :         pal.setColor( static_cast< QPalette::ColorRole >( role ), color );
     928                 :          0 :       }
     929                 :          0 :     }
     930                 :          0 :     palettefile.close();
     931                 :          0 :     qApp->setPalette( pal );
     932                 :          0 :   }
     933                 :            : 
     934                 :          0 :   setThemeName( themeName );
     935                 :          0 : }
     936                 :            : 
     937                 :          0 : QHash<QString, QString> QgsApplication::uiThemes()
     938                 :            : {
     939                 :          0 :   QStringList paths = QStringList() << userThemesFolder() << defaultThemesFolder();
     940                 :          0 :   QHash<QString, QString> mapping;
     941                 :          0 :   mapping.insert( QStringLiteral( "default" ), QString() );
     942                 :          0 :   const auto constPaths = paths;
     943                 :          0 :   for ( const QString &path : constPaths )
     944                 :            :   {
     945                 :          0 :     QDir folder( path );
     946                 :          0 :     QFileInfoList styleFiles = folder.entryInfoList( QDir::Dirs | QDir::NoDotAndDotDot );
     947                 :          0 :     const auto constStyleFiles = styleFiles;
     948                 :          0 :     for ( const QFileInfo &info : constStyleFiles )
     949                 :            :     {
     950                 :          0 :       QFileInfo styleFile( info.absoluteFilePath() + "/style.qss" );
     951                 :          0 :       if ( !styleFile.exists() )
     952                 :          0 :         continue;
     953                 :            : 
     954                 :          0 :       QString name = info.baseName();
     955                 :          0 :       QString path = info.absoluteFilePath();
     956                 :          0 :       mapping.insert( name, path );
     957                 :          0 :     }
     958                 :          0 :   }
     959                 :          0 :   return mapping;
     960                 :          0 : }
     961                 :            : 
     962                 :          0 : QString QgsApplication::authorsFilePath()
     963                 :            : {
     964                 :          0 :   return pkgDataPath() + QStringLiteral( "/doc/AUTHORS" );
     965                 :          0 : }
     966                 :            : 
     967                 :          0 : QString QgsApplication::contributorsFilePath()
     968                 :            : {
     969                 :          0 :   return pkgDataPath() + QStringLiteral( "/doc/CONTRIBUTORS" );
     970                 :          0 : }
     971                 :          0 : QString QgsApplication::developersMapFilePath()
     972                 :            : {
     973                 :          0 :   return pkgDataPath() + QStringLiteral( "/doc/developersmap.html" );
     974                 :          0 : }
     975                 :            : 
     976                 :          0 : QString QgsApplication::sponsorsFilePath()
     977                 :            : {
     978                 :          0 :   return pkgDataPath() + QStringLiteral( "/doc/SPONSORS" );
     979                 :          0 : }
     980                 :            : 
     981                 :          0 : QString QgsApplication::donorsFilePath()
     982                 :            : {
     983                 :          0 :   return pkgDataPath() + QStringLiteral( "/doc/DONORS" );
     984                 :          0 : }
     985                 :            : 
     986                 :          0 : QString QgsApplication::translatorsFilePath()
     987                 :            : {
     988                 :          0 :   return pkgDataPath() + QStringLiteral( "/doc/TRANSLATORS" );
     989                 :          5 : }
     990                 :          5 : 
     991                 :          0 : QString QgsApplication::licenceFilePath()
     992                 :          5 : {
     993                 :          5 :   return pkgDataPath() + QStringLiteral( "/doc/LICENSE" );
     994                 :          0 : }
     995                 :            : 
     996                 :          5 : QString QgsApplication::i18nPath()
     997                 :          5 : {
     998                 :         10 :   if ( ABISYM( mRunningFromBuildDir ) )
     999                 :          5 :     return *sBuildOutputPath() + QStringLiteral( "/i18n/" );
    1000                 :          5 :   else
    1001                 :         15 :     return pkgDataPath() + QStringLiteral( "/i18n/" );
    1002                 :         10 : }
    1003                 :          5 : 
    1004                 :          5 : QString QgsApplication::metadataPath()
    1005                 :          5 : {
    1006                 :          5 :   return pkgDataPath() + QStringLiteral( "/resources/metadata-ISO/" );
    1007                 :          5 : }
    1008                 :          5 : 
    1009                 :          6 : QString QgsApplication::qgisMasterDatabaseFilePath()
    1010                 :          5 : {
    1011                 :          7 :   return pkgDataPath() + QStringLiteral( "/resources/qgis.db" );
    1012                 :          5 : }
    1013                 :          5 : 
    1014                 :        135 : QString QgsApplication::qgisSettingsDirPath()
    1015                 :          5 : {
    1016                 :        135 :   return *sConfigPath();
    1017                 :          5 : }
    1018                 :          5 : 
    1019                 :          6 : QString QgsApplication::qgisUserDatabaseFilePath()
    1020                 :          5 : {
    1021                 :          7 :   return qgisSettingsDirPath() + QStringLiteral( "qgis.db" );
    1022                 :          5 : }
    1023                 :          5 : 
    1024                 :          9 : QString QgsApplication::qgisAuthDatabaseFilePath()
    1025                 :          5 : {
    1026                 :         13 :   return *sAuthDbDirPath() + QStringLiteral( "qgis-auth.db" );
    1027                 :          5 : }
    1028                 :          5 : 
    1029                 :          5 : QString QgsApplication::splashPath()
    1030                 :          5 : {
    1031                 :          5 :   return QStringLiteral( ":/images/splash/" );
    1032                 :          5 : }
    1033                 :            : 
    1034                 :          0 : QString QgsApplication::iconsPath()
    1035                 :          5 : {
    1036                 :          0 :   return pkgDataPath() + QStringLiteral( "/images/icons/" );
    1037                 :          0 : }
    1038                 :            : 
    1039                 :          1 : QString QgsApplication::srsDatabaseFilePath()
    1040                 :            : {
    1041                 :          1 :   if ( ABISYM( mRunningFromBuildDir ) )
    1042                 :          5 :   {
    1043                 :          1 :     QString tempCopy = QDir::tempPath() + "/srs6.db";
    1044                 :            : 
    1045                 :          1 :     if ( !QFile( tempCopy ).exists() )
    1046                 :            :     {
    1047                 :          0 :       QFile f( buildSourcePath() + "/resources/srs6.db" );
    1048                 :          0 :       if ( !f.copy( tempCopy ) )
    1049                 :            :       {
    1050                 :          0 :         qFatal( "Could not create temporary copy" );
    1051                 :            :       }
    1052                 :          0 :     }
    1053                 :            : 
    1054                 :          1 :     return tempCopy;
    1055                 :          1 :   }
    1056                 :            :   else
    1057                 :            :   {
    1058                 :          0 :     return pkgDataPath() + QStringLiteral( "/resources/srs.db" );
    1059                 :            :   }
    1060                 :          1 : }
    1061                 :            : 
    1062                 :          0 : void QgsApplication::setSvgPaths( const QStringList &svgPaths )
    1063                 :            : {
    1064                 :          0 :   QgsSettings().setValue( QStringLiteral( "svg/searchPathsForSVG" ), svgPaths );
    1065                 :          0 :   members()->mSvgPathCacheValid = false;
    1066                 :          0 : }
    1067                 :            : 
    1068                 :         41 : QStringList QgsApplication::svgPaths()
    1069                 :            : {
    1070                 :         41 :   static QReadWriteLock lock;
    1071                 :            : 
    1072                 :         41 :   QgsReadWriteLocker locker( lock, QgsReadWriteLocker::Read );
    1073                 :            : 
    1074                 :         41 :   if ( members()->mSvgPathCacheValid )
    1075                 :            :   {
    1076                 :          0 :     return members()->mSvgPathCache;
    1077                 :            :   }
    1078                 :            :   else
    1079                 :            :   {
    1080                 :         41 :     locker.changeMode( QgsReadWriteLocker::Write );
    1081                 :            :     //local directories to search when looking for an SVG with a given basename
    1082                 :            :     //defined by user in options dialog
    1083                 :         41 :     QgsSettings settings;
    1084                 :         82 :     const QStringList pathList = settings.value( QStringLiteral( "svg/searchPathsForSVG" ) ).toStringList();
    1085                 :            : 
    1086                 :            :     // maintain user set order while stripping duplicates
    1087                 :         41 :     QStringList paths;
    1088                 :         41 :     for ( const QString &path : pathList )
    1089                 :            :     {
    1090                 :          0 :       if ( !paths.contains( path ) )
    1091                 :          0 :         paths.append( path );
    1092                 :            :     }
    1093                 :        124 :     for ( const QString &path : std::as_const( *sDefaultSvgPaths() ) )
    1094                 :            :     {
    1095                 :         83 :       if ( !paths.contains( path ) )
    1096                 :         82 :         paths.append( path );
    1097                 :            :     }
    1098                 :         41 :     members()->mSvgPathCache = paths;
    1099                 :            : 
    1100                 :         41 :     return paths;
    1101                 :         41 :   }
    1102                 :         41 : }
    1103                 :            : 
    1104                 :          0 : QStringList QgsApplication::layoutTemplatePaths()
    1105                 :            : {
    1106                 :            :   //local directories to search when looking for an template with a given basename
    1107                 :            :   //defined by user in options dialog
    1108                 :          0 :   QgsSettings settings;
    1109                 :          0 :   QStringList pathList = settings.value( QStringLiteral( "Layout/searchPathsForTemplates" ), QVariant(), QgsSettings::Core ).toStringList();
    1110                 :            : 
    1111                 :          0 :   return pathList;
    1112                 :          0 : }
    1113                 :            : 
    1114                 :          0 : QMap<QString, QString> QgsApplication::systemEnvVars()
    1115                 :            : {
    1116                 :          0 :   return *sSystemEnvVars();
    1117                 :            : }
    1118                 :            : 
    1119                 :          5 : QString QgsApplication::userStylePath()
    1120                 :            : {
    1121                 :         10 :   return qgisSettingsDirPath() + QStringLiteral( "symbology-style.db" );
    1122                 :          0 : }
    1123                 :            : 
    1124                 :          0 : QRegExp QgsApplication::shortNameRegExp()
    1125                 :            : {
    1126                 :          0 :   const thread_local QRegExp regexp( QStringLiteral( "^[A-Za-z][A-Za-z0-9\\._-]*" ) );
    1127                 :          0 :   return regexp;
    1128                 :          0 : }
    1129                 :            : 
    1130                 :          1 : QString QgsApplication::userLoginName()
    1131                 :            : {
    1132                 :          1 :   if ( !sUserName()->isEmpty() )
    1133                 :          0 :     return *sUserName();
    1134                 :            : 
    1135                 :            : #ifdef _MSC_VER
    1136                 :            :   TCHAR name [ UNLEN + 1 ];
    1137                 :            :   DWORD size = UNLEN + 1;
    1138                 :            : 
    1139                 :            :   if ( GetUserName( ( TCHAR * )name, &size ) )
    1140                 :            :   {
    1141                 :            :     *sUserName() = QString::fromLocal8Bit( name );
    1142                 :            :   }
    1143                 :            : 
    1144                 :            : #elif QT_CONFIG(process)
    1145                 :          1 :   QProcess process;
    1146                 :            : 
    1147                 :          2 :   process.start( QStringLiteral( "whoami" ), QStringList() );
    1148                 :          1 :   process.waitForFinished();
    1149                 :          1 :   *sUserName() = process.readAllStandardOutput().trimmed();
    1150                 :            : #endif
    1151                 :            : 
    1152                 :          1 :   if ( !sUserName()->isEmpty() )
    1153                 :          1 :     return *sUserName();
    1154                 :            : 
    1155                 :            :   //backup plan - use environment variables
    1156                 :          0 :   *sUserName() = qgetenv( "USER" );
    1157                 :          0 :   if ( !sUserName()->isEmpty() )
    1158                 :          0 :     return *sUserName();
    1159                 :            : 
    1160                 :            :   //last resort
    1161                 :          0 :   *sUserName() = qgetenv( "USERNAME" );
    1162                 :          0 :   return *sUserName();
    1163                 :          1 : }
    1164                 :            : 
    1165                 :          9 : QString QgsApplication::userFullName()
    1166                 :            : {
    1167                 :          9 :   if ( !sUserFullName()->isEmpty() )
    1168                 :          4 :     return *sUserFullName();
    1169                 :            : 
    1170                 :            : #ifdef _MSC_VER
    1171                 :            :   TCHAR name [ UNLEN + 1 ];
    1172                 :            :   DWORD size = UNLEN + 1;
    1173                 :            : 
    1174                 :            :   //note - this only works for accounts connected to domain
    1175                 :            :   if ( GetUserNameEx( NameDisplay, ( TCHAR * )name, &size ) )
    1176                 :            :   {
    1177                 :            :     *sUserFullName() = QString::fromLocal8Bit( name );
    1178                 :            :   }
    1179                 :            : 
    1180                 :            :   //fall back to login name
    1181                 :            :   if ( sUserFullName()->isEmpty() )
    1182                 :            :     *sUserFullName() = userLoginName();
    1183                 :            : #elif defined(Q_OS_ANDROID) || defined(__MINGW32__)
    1184                 :            :   *sUserFullName() = QStringLiteral( "Not available" );
    1185                 :            : #else
    1186                 :          5 :   struct passwd *p = getpwuid( getuid() );
    1187                 :            : 
    1188                 :          5 :   if ( p )
    1189                 :            :   {
    1190                 :          5 :     QString gecosName = QString( p->pw_gecos );
    1191                 :          5 :     *sUserFullName() = gecosName.left( gecosName.indexOf( ',', 0 ) );
    1192                 :          5 :   }
    1193                 :            : 
    1194                 :            : #endif
    1195                 :            : 
    1196                 :          5 :   return *sUserFullName();
    1197                 :          9 : }
    1198                 :            : 
    1199                 :          1 : QString QgsApplication::osName()
    1200                 :            : {
    1201                 :            : #if defined(Q_OS_ANDROID)
    1202                 :            :   return QLatin1String( "android" );
    1203                 :            : #elif defined(Q_OS_MAC)
    1204                 :            :   return QLatin1String( "osx" );
    1205                 :            : #elif defined(Q_OS_WIN)
    1206                 :            :   return QLatin1String( "windows" );
    1207                 :            : #elif defined(Q_OS_LINUX)
    1208                 :            :   return QStringLiteral( "linux" );
    1209                 :            : #elif defined(Q_OS_FREEBSD)
    1210                 :          2 :   return QStringLiteral( "freebsd" );
    1211                 :            : #elif defined(Q_OS_OPENBSD)
    1212                 :            :   return QStringLiteral( "openbsd" );
    1213                 :            : #elif defined(Q_OS_NETBSD)
    1214                 :            :   return QStringLiteral( "netbsd" );
    1215                 :            : #elif defined(Q_OS_UNIX)
    1216                 :            :   return QLatin1String( "unix" );
    1217                 :            : #else
    1218                 :            :   return QLatin1String( "unknown" );
    1219                 :            : #endif
    1220                 :            : }
    1221                 :            : 
    1222                 :          1 : QString QgsApplication::platform()
    1223                 :            : {
    1224                 :          1 :   return *sPlatformName();
    1225                 :            : }
    1226                 :            : 
    1227                 :          1 : QString QgsApplication::locale()
    1228                 :            : {
    1229                 :          1 :   QgsSettings settings;
    1230                 :          2 :   bool overrideLocale = settings.value( QStringLiteral( "locale/overrideFlag" ), false ).toBool();
    1231                 :          1 :   if ( overrideLocale )
    1232                 :            :   {
    1233                 :          0 :     QString locale = settings.value( QStringLiteral( "locale/userLocale" ), QString() ).toString();
    1234                 :            :     // don't differentiate en_US and en_GB
    1235                 :          0 :     if ( locale.startsWith( QLatin1String( "en" ), Qt::CaseInsensitive ) )
    1236                 :            :     {
    1237                 :          0 :       return locale.left( 2 );
    1238                 :            :     }
    1239                 :            : 
    1240                 :          0 :     return locale;
    1241                 :          0 :   }
    1242                 :            :   else
    1243                 :            :   {
    1244                 :          1 :     return QLocale().name().left( 2 );
    1245                 :            :   }
    1246                 :          1 : }
    1247                 :            : 
    1248                 :         11 : QString QgsApplication::userThemesFolder()
    1249                 :            : {
    1250                 :         22 :   return qgisSettingsDirPath() + QStringLiteral( "/themes" );
    1251                 :          0 : }
    1252                 :            : 
    1253                 :          0 : QString QgsApplication::defaultStylePath()
    1254                 :            : {
    1255                 :          0 :   return pkgDataPath() + QStringLiteral( "/resources/symbology-style.xml" );
    1256                 :          0 : }
    1257                 :            : 
    1258                 :         11 : QString QgsApplication::defaultThemesFolder()
    1259                 :            : {
    1260                 :         22 :   return pkgDataPath() + QStringLiteral( "/resources/themes" );
    1261                 :          0 : }
    1262                 :            : 
    1263                 :          0 : QString QgsApplication::serverResourcesPath()
    1264                 :            : {
    1265                 :          0 :   return pkgDataPath() + QStringLiteral( "/resources/server/" );
    1266                 :          0 : }
    1267                 :            : 
    1268                 :          0 : QString QgsApplication::libraryPath()
    1269                 :            : {
    1270                 :          0 :   return *sLibraryPath();
    1271                 :            : }
    1272                 :            : 
    1273                 :          0 : QString QgsApplication::libexecPath()
    1274                 :            : {
    1275                 :          0 :   return *sLibexecPath();
    1276                 :            : }
    1277                 :            : 
    1278                 :          0 : QString QgsApplication::qmlImportPath()
    1279                 :            : {
    1280                 :          0 :   return *sQmlImportPath();
    1281                 :            : }
    1282                 :            : 
    1283                 :        373 : QgsApplication::endian_t QgsApplication::endian()
    1284                 :            : {
    1285                 :        373 :   return ( htonl( 1 ) == 1 ) ? XDR : NDR;
    1286                 :            : }
    1287                 :            : 
    1288                 :          3 : void QgsApplication::initQgis()
    1289                 :            : {
    1290                 :          3 :   if ( !ABISYM( mInitialized ) && QgsApplication::instance() )
    1291                 :            :   {
    1292                 :          0 :     init( *sProfilePath() );
    1293                 :          0 :   }
    1294                 :            : 
    1295                 :            :   // set the provider plugin path (this creates provider registry)
    1296                 :          3 :   QgsProviderRegistry::instance( pluginPath() );
    1297                 :            : 
    1298                 :            :   // create data item provider registry
    1299                 :          3 :   ( void )QgsApplication::dataItemProviderRegistry();
    1300                 :            : 
    1301                 :            :   // create project instance if doesn't exist
    1302                 :          3 :   QgsProject::instance();
    1303                 :            : 
    1304                 :            :   // Initialize authentication manager and connect to database
    1305                 :          3 :   authManager()->init( pluginPath(), qgisAuthDatabaseFilePath() );
    1306                 :            : 
    1307                 :            :   // Make sure we have a NAM created on the main thread.
    1308                 :            :   // Note that this might call QgsApplication::authManager to
    1309                 :            :   // setup the proxy configuration that's why it needs to be
    1310                 :            :   // called after the QgsAuthManager instance has been created
    1311                 :          3 :   QgsNetworkAccessManager::instance();
    1312                 :            : 
    1313                 :          3 : }
    1314                 :            : 
    1315                 :          3 : QgsAuthManager *QgsApplication::authManager()
    1316                 :            : {
    1317                 :          3 :   if ( auto *lInstance = instance() )
    1318                 :            :   {
    1319                 :          3 :     if ( !lInstance->mAuthManager )
    1320                 :            :     {
    1321                 :          3 :       lInstance->mAuthManager = QgsAuthManager::instance();
    1322                 :          3 :     }
    1323                 :          3 :     return lInstance->mAuthManager;
    1324                 :            :   }
    1325                 :            :   else
    1326                 :            :   {
    1327                 :            :     // no QgsApplication instance
    1328                 :          0 :     if ( !sAuthManager )
    1329                 :          0 :       sAuthManager = QgsAuthManager::instance();
    1330                 :          0 :     return sAuthManager;
    1331                 :            :   }
    1332                 :          3 : }
    1333                 :            : 
    1334                 :            : 
    1335                 :          3 : void QgsApplication::exitQgis()
    1336                 :            : {
    1337                 :            :   // make sure all threads are done before exiting
    1338                 :          3 :   QThreadPool::globalInstance()->waitForDone();
    1339                 :            : 
    1340                 :            :   // don't create to delete
    1341                 :          3 :   if ( auto *lInstance = instance() )
    1342                 :          3 :     delete lInstance->mAuthManager;
    1343                 :            :   else
    1344                 :          0 :     delete sAuthManager;
    1345                 :            : 
    1346                 :            :   //Ensure that all remaining deleteLater QObjects are actually deleted before we exit.
    1347                 :            :   //This isn't strictly necessary (since we're exiting anyway) but doing so prevents a lot of
    1348                 :            :   //LeakSanitiser noise which hides real issues
    1349                 :          3 :   QgsApplication::sendPostedEvents( nullptr, QEvent::DeferredDelete );
    1350                 :            : 
    1351                 :            :   //delete all registered functions from expression engine (see above comment)
    1352                 :          3 :   QgsExpression::cleanRegisteredFunctions();
    1353                 :            : 
    1354                 :          3 :   delete QgsProject::instance();
    1355                 :            : 
    1356                 :            :   // avoid creating instance just to delete it!
    1357                 :          3 :   if ( QgsProviderRegistry::exists() )
    1358                 :          3 :     delete QgsProviderRegistry::instance();
    1359                 :            : 
    1360                 :          3 :   invalidateCaches();
    1361                 :            : 
    1362                 :          3 :   QgsStyle::cleanDefaultStyle();
    1363                 :            : 
    1364                 :            :   // tear-down GDAL/OGR
    1365                 :          3 :   OGRCleanupAll();
    1366                 :          3 :   GDALDestroyDriverManager();
    1367                 :          3 : }
    1368                 :            : 
    1369                 :          1 : QString QgsApplication::showSettings()
    1370                 :            : {
    1371                 :          1 :   QString myEnvironmentVar( getenv( "QGIS_PREFIX_PATH" ) );
    1372                 :          2 :   QString myState = tr( "Application state:\n"
    1373                 :            :                         "QGIS_PREFIX_PATH env var:\t\t%1\n"
    1374                 :            :                         "Prefix:\t\t%2\n"
    1375                 :            :                         "Plugin Path:\t\t%3\n"
    1376                 :            :                         "Package Data Path:\t%4\n"
    1377                 :            :                         "Active Theme Name:\t%5\n"
    1378                 :            :                         "Active Theme Path:\t%6\n"
    1379                 :            :                         "Default Theme Path:\t%7\n"
    1380                 :            :                         "SVG Search Paths:\t%8\n"
    1381                 :            :                         "User DB Path:\t%9\n"
    1382                 :            :                         "Auth DB Path:\t%10\n" )
    1383                 :          1 :                     .arg( myEnvironmentVar,
    1384                 :          1 :                           prefixPath(),
    1385                 :          1 :                           pluginPath(),
    1386                 :          1 :                           pkgDataPath(),
    1387                 :          1 :                           themeName(),
    1388                 :          1 :                           activeThemePath(),
    1389                 :          1 :                           defaultThemePath(),
    1390                 :          1 :                           svgPaths().join( tr( "\n\t\t", "match indentation of application state" ) ),
    1391                 :          1 :                           qgisMasterDatabaseFilePath() )
    1392                 :          1 :                     .arg( qgisAuthDatabaseFilePath() );
    1393                 :          1 :   return myState;
    1394                 :          1 : }
    1395                 :            : 
    1396                 :          0 : QString QgsApplication::reportStyleSheet( QgsApplication::StyleSheetType styleSheetType )
    1397                 :            : {
    1398                 :            :   //
    1399                 :            :   // Make the style sheet desktop preferences aware by using qapplication
    1400                 :            :   // palette as a basis for colors where appropriate
    1401                 :            :   //
    1402                 :            :   //  QColor myColor1 = palette().highlight().color();
    1403                 :          0 :   QColor myColor1( Qt::lightGray );
    1404                 :          0 :   QColor myColor2 = myColor1;
    1405                 :          0 :   myColor2 = myColor2.lighter( 110 ); //10% lighter
    1406                 :          0 :   QString myStyle;
    1407                 :          0 :   myStyle = QStringLiteral( ".overview{"
    1408                 :            :                             "  font: 1.82em;"
    1409                 :            :                             "  font-weight: bold;"
    1410                 :            :                             "}"
    1411                 :            :                             "body{"
    1412                 :            :                             "  background: white;"
    1413                 :            :                             "  color: black;"
    1414                 :            :                             "  font-family: 'Lato', 'Open Sans', 'Lucida Grande', 'Segoe UI', 'Arial', sans-serif;"
    1415                 :            :                             "  width: 100%;"
    1416                 :            :                             "}"
    1417                 :            :                             "h1{  background-color: #F6F6F6;"
    1418                 :            :                             "  color: #589632; " // from http://qgis.org/en/site/getinvolved/styleguide.html
    1419                 :            :                             "  font-size: x-large;  "
    1420                 :            :                             "  font-weight: normal;"
    1421                 :            :                             "  background: none;"
    1422                 :            :                             "  padding: 0.75em 0 0;"
    1423                 :            :                             "  margin: 0;"
    1424                 :            :                             "  line-height: 3em;"
    1425                 :            :                             "}"
    1426                 :            :                             "h2{  background-color: #F6F6F6;"
    1427                 :            :                             "  color: #589632; "  // from http://qgis.org/en/site/getinvolved/styleguide.html
    1428                 :            :                             "  font-size: medium;  "
    1429                 :            :                             "  font-weight: normal;"
    1430                 :            :                             "  background: none;"
    1431                 :            :                             "  padding: 0.75em 0 0;"
    1432                 :            :                             "  margin: 0;"
    1433                 :            :                             "  line-height: 1.1em;"
    1434                 :            :                             "}"
    1435                 :            :                             "h3{  background-color: #F6F6F6;"
    1436                 :            :                             "  color: #93b023;"  // from http://qgis.org/en/site/getinvolved/styleguide.html
    1437                 :            :                             "  font-weight: bold;"
    1438                 :            :                             "  font-size: large;"
    1439                 :            :                             "  text-align: left;"
    1440                 :            :                             "  border-bottom: 5px solid #DCEB5C;"
    1441                 :            :                             "}"
    1442                 :            :                             "h4{  background-color: #F6F6F6;"
    1443                 :            :                             "  color: #93b023;"  // from http://qgis.org/en/site/getinvolved/styleguide.html
    1444                 :            :                             "  font-weight: bold;"
    1445                 :            :                             "  font-size: medium;"
    1446                 :            :                             "  text-align: left;"
    1447                 :            :                             "}"
    1448                 :            :                             "h5{    background-color: #F6F6F6;"
    1449                 :            :                             "   color: #93b023;"  // from http://qgis.org/en/site/getinvolved/styleguide.html
    1450                 :            :                             "   font-weight: bold;"
    1451                 :            :                             "   font-size: small;"
    1452                 :            :                             "   text-align: left;"
    1453                 :            :                             "}"
    1454                 :            :                             "a{  color: #729FCF;"
    1455                 :            :                             "  font-family: arial,sans-serif;"
    1456                 :            :                             "}"
    1457                 :            :                             "label{  background-color: #FFFFCC;"
    1458                 :            :                             "  border: 1px solid black;"
    1459                 :            :                             "  margin: 1px;"
    1460                 :            :                             "  padding: 0px 3px; "
    1461                 :            :                             "  font-size: small;"
    1462                 :            :                             "}"
    1463                 :            :                             "th .strong {"
    1464                 :            :                             "  font-weight: bold;"
    1465                 :            :                             "}"
    1466                 :            :                             "hr {"
    1467                 :            :                             "  border: 0;"
    1468                 :            :                             "  height: 0;"
    1469                 :            :                             "  border-top: 1px solid black;"
    1470                 :            :                             "}"
    1471                 :            :                             ".list-view .highlight {"
    1472                 :            :                             "  text-align: left;"
    1473                 :            :                             "  border: 0px;"
    1474                 :            :                             "  width: 20%;"
    1475                 :            :                             "  padding-right: 15px;"
    1476                 :            :                             "  padding-left: 20px;"
    1477                 :            :                             "  font-weight: bold;"
    1478                 :            :                             "}"
    1479                 :            :                             ".tabular-view .odd-row {"
    1480                 :            :                             "  background-color: #f9f9f9;"
    1481                 :            :                             "}"
    1482                 :            :                             ".section {"
    1483                 :            :                             "  font-weight: bold;"
    1484                 :            :                             "  padding-top:25px;"
    1485                 :            :                             "}" );
    1486                 :            : 
    1487                 :            :   // We have some subtle differences between Qt based style and QWebKit style
    1488                 :          0 :   switch ( styleSheetType )
    1489                 :            :   {
    1490                 :            :     case StyleSheetType::Qt:
    1491                 :          0 :       myStyle += QStringLiteral(
    1492                 :            :                    ".tabular-view{ "
    1493                 :            :                    "  border-collapse: collapse;"
    1494                 :            :                    "  width: 95%;"
    1495                 :            :                    "}"
    1496                 :            :                    ".tabular-view th, .tabular-view td { "
    1497                 :            :                    "  border:1px solid black;"
    1498                 :            :                    "}" );
    1499                 :          0 :       break;
    1500                 :            : 
    1501                 :            :     case StyleSheetType::WebBrowser:
    1502                 :          0 :       myStyle += QStringLiteral(
    1503                 :            :                    "body { "
    1504                 :            :                    "   margin: auto;"
    1505                 :            :                    "   width: 97%;"
    1506                 :            :                    "}"
    1507                 :            :                    "table.tabular-view, table.list-view { "
    1508                 :            :                    "   border-collapse: collapse;"
    1509                 :            :                    "   table-layout:fixed;"
    1510                 :            :                    "   width: 100% !important;"
    1511                 :            :                    "   font-size: 90%;"
    1512                 :            :                    "}"
    1513                 :            :                    // Override
    1514                 :            :                    "h1 { "
    1515                 :            :                    "   line-height: inherit;"
    1516                 :            :                    "}"
    1517                 :            :                    "td, th {"
    1518                 :            :                    "   word-wrap: break-word; "
    1519                 :            :                    "   vertical-align: top;"
    1520                 :            :                    "}"
    1521                 :            :                    // Set first column width
    1522                 :            :                    ".list-view th:first-child, .list-view td:first-child {"
    1523                 :            :                    "   width: 20%;"
    1524                 :            :                    "}"
    1525                 :            :                    ".list-view.highlight { "
    1526                 :            :                    "   padding-left: inherit; "
    1527                 :            :                    "}"
    1528                 :            :                    // Set first column width for inner tables
    1529                 :            :                    ".tabular-view th:first-child, .tabular-view td:first-child { "
    1530                 :            :                    "   width: 20%; "
    1531                 :            :                    "}"
    1532                 :            :                    // Makes titles bg stand up
    1533                 :            :                    ".tabular-view th.strong { "
    1534                 :            :                    "   background-color: #eee; "
    1535                 :            :                    "}"
    1536                 :            :                    // Give some visual appearance to those ugly nested tables
    1537                 :            :                    ".tabular-view th, .tabular-view td { "
    1538                 :            :                    "   border: 1px solid #eee;"
    1539                 :            :                    "}"
    1540                 :            :                  );
    1541                 :          0 :       break;
    1542                 :            :   }
    1543                 :            : 
    1544                 :          0 :   return myStyle;
    1545                 :          0 : }
    1546                 :            : 
    1547                 :         67 : void QgsApplication::registerOgrDrivers()
    1548                 :            : {
    1549                 :         67 :   if ( 0 >= OGRGetDriverCount() )
    1550                 :            :   {
    1551                 :          0 :     OGRRegisterAll();
    1552                 :          0 :   }
    1553                 :         67 : }
    1554                 :            : 
    1555                 :          0 : QString QgsApplication::absolutePathToRelativePath( const QString &aPath, const QString &targetPath )
    1556                 :            : {
    1557                 :          0 :   QString aPathUrl = aPath;
    1558                 :          0 :   QString tPathUrl = targetPath;
    1559                 :            : #if defined( Q_OS_WIN )
    1560                 :            :   const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
    1561                 :            : 
    1562                 :            :   aPathUrl.replace( '\\', '/' );
    1563                 :            :   if ( aPathUrl.startsWith( "//" ) )
    1564                 :            :   {
    1565                 :            :     // keep UNC prefix
    1566                 :            :     aPathUrl = "\\\\" + aPathUrl.mid( 2 );
    1567                 :            :   }
    1568                 :            : 
    1569                 :            :   tPathUrl.replace( '\\', '/' );
    1570                 :            :   if ( tPathUrl.startsWith( "//" ) )
    1571                 :            :   {
    1572                 :            :     // keep UNC prefix
    1573                 :            :     tPathUrl = "\\\\" + tPathUrl.mid( 2 );
    1574                 :            :   }
    1575                 :            : #else
    1576                 :          0 :   const Qt::CaseSensitivity cs = Qt::CaseSensitive;
    1577                 :            : #endif
    1578                 :            : 
    1579                 :            : #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
    1580                 :            :   QStringList targetElems = tPathUrl.split( '/', QString::SkipEmptyParts );
    1581                 :            :   QStringList aPathElems = aPathUrl.split( '/', QString::SkipEmptyParts );
    1582                 :            : #else
    1583                 :          0 :   QStringList targetElems = tPathUrl.split( '/', Qt::SkipEmptyParts );
    1584                 :          0 :   QStringList aPathElems = aPathUrl.split( '/', Qt::SkipEmptyParts );
    1585                 :            : #endif
    1586                 :            : 
    1587                 :          0 :   targetElems.removeAll( QStringLiteral( "." ) );
    1588                 :          0 :   aPathElems.removeAll( QStringLiteral( "." ) );
    1589                 :            : 
    1590                 :            :   // remove common part
    1591                 :          0 :   int n = 0;
    1592                 :          0 :   while ( !aPathElems.isEmpty() &&
    1593                 :          0 :           !targetElems.isEmpty() &&
    1594                 :          0 :           aPathElems[0].compare( targetElems[0], cs ) == 0 )
    1595                 :            :   {
    1596                 :          0 :     aPathElems.removeFirst();
    1597                 :          0 :     targetElems.removeFirst();
    1598                 :          0 :     n++;
    1599                 :            :   }
    1600                 :            : 
    1601                 :          0 :   if ( n == 0 )
    1602                 :            :   {
    1603                 :            :     // no common parts; might not even be a file
    1604                 :          0 :     return aPathUrl;
    1605                 :            :   }
    1606                 :            : 
    1607                 :          0 :   if ( !targetElems.isEmpty() )
    1608                 :            :   {
    1609                 :            :     // go up to the common directory
    1610                 :          0 :     for ( int i = 0; i < targetElems.size(); i++ )
    1611                 :            :     {
    1612                 :          0 :       aPathElems.insert( 0, QStringLiteral( ".." ) );
    1613                 :          0 :     }
    1614                 :          0 :   }
    1615                 :            :   else
    1616                 :            :   {
    1617                 :            :     // let it start with . nevertheless,
    1618                 :            :     // so relative path always start with either ./ or ../
    1619                 :          0 :     aPathElems.insert( 0, QStringLiteral( "." ) );
    1620                 :            :   }
    1621                 :            : 
    1622                 :          0 :   return aPathElems.join( QLatin1Char( '/' ) );
    1623                 :          0 : }
    1624                 :            : 
    1625                 :          0 : QString QgsApplication::relativePathToAbsolutePath( const QString &rpath, const QString &targetPath )
    1626                 :            : {
    1627                 :            :   // relative path should always start with ./ or ../
    1628                 :          0 :   if ( !rpath.startsWith( QLatin1String( "./" ) ) && !rpath.startsWith( QLatin1String( "../" ) ) )
    1629                 :            :   {
    1630                 :          0 :     return rpath;
    1631                 :            :   }
    1632                 :            : 
    1633                 :          0 :   QString rPathUrl = rpath;
    1634                 :          0 :   QString targetPathUrl = targetPath;
    1635                 :            : 
    1636                 :            : #if defined(Q_OS_WIN)
    1637                 :            :   rPathUrl.replace( '\\', '/' );
    1638                 :            :   targetPathUrl.replace( '\\', '/' );
    1639                 :            : 
    1640                 :            :   bool uncPath = targetPathUrl.startsWith( "//" );
    1641                 :            : #endif
    1642                 :            : 
    1643                 :            : #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
    1644                 :            :   QStringList srcElems = rPathUrl.split( '/', QString::SkipEmptyParts );
    1645                 :            :   QStringList targetElems = targetPathUrl.split( '/', QString::SkipEmptyParts );
    1646                 :            : #else
    1647                 :          0 :   QStringList srcElems = rPathUrl.split( '/', Qt::SkipEmptyParts );
    1648                 :          0 :   QStringList targetElems = targetPathUrl.split( '/', Qt::SkipEmptyParts );
    1649                 :            : #endif
    1650                 :            : 
    1651                 :            : #if defined(Q_OS_WIN)
    1652                 :            :   if ( uncPath )
    1653                 :            :   {
    1654                 :            :     targetElems.insert( 0, "" );
    1655                 :            :     targetElems.insert( 0, "" );
    1656                 :            :   }
    1657                 :            : #endif
    1658                 :            : 
    1659                 :            :   // append source path elements
    1660                 :          0 :   targetElems << srcElems;
    1661                 :          0 :   targetElems.removeAll( QStringLiteral( "." ) );
    1662                 :            : 
    1663                 :            :   // resolve ..
    1664                 :            :   int pos;
    1665                 :          0 :   while ( ( pos = targetElems.indexOf( QLatin1String( ".." ) ) ) > 0 )
    1666                 :            :   {
    1667                 :            :     // remove preceding element and ..
    1668                 :          0 :     targetElems.removeAt( pos - 1 );
    1669                 :          0 :     targetElems.removeAt( pos - 1 );
    1670                 :            :   }
    1671                 :            : 
    1672                 :            : #if !defined(Q_OS_WIN)
    1673                 :            :   // make path absolute
    1674                 :          0 :   targetElems.prepend( QString() );
    1675                 :            : #endif
    1676                 :            : 
    1677                 :          0 :   return targetElems.join( QLatin1Char( '/' ) );
    1678                 :          0 : }
    1679                 :            : 
    1680                 :          0 : QString QgsApplication::buildSourcePath()
    1681                 :            : {
    1682                 :          0 :   return *sBuildSourcePath();
    1683                 :            : }
    1684                 :            : 
    1685                 :          0 : QString QgsApplication::buildOutputPath()
    1686                 :            : {
    1687                 :          0 :   return *sBuildOutputPath();
    1688                 :            : }
    1689                 :            : 
    1690                 :            : #if defined(_MSC_VER) && !defined(USING_NMAKE) && !defined(USING_NINJA)
    1691                 :            : QString QgsApplication::cfgIntDir()
    1692                 :            : {
    1693                 :            :   return *sCfgIntDir();
    1694                 :            : }
    1695                 :            : #endif
    1696                 :            : 
    1697                 :          0 : void QgsApplication::skipGdalDriver( const QString &driver )
    1698                 :            : {
    1699                 :          0 :   if ( sGdalSkipList()->contains( driver ) || driver.isEmpty() )
    1700                 :            :   {
    1701                 :          0 :     return;
    1702                 :            :   }
    1703                 :          0 :   *sGdalSkipList() << driver;
    1704                 :          0 :   applyGdalSkippedDrivers();
    1705                 :          0 : }
    1706                 :            : 
    1707                 :          0 : void QgsApplication::restoreGdalDriver( const QString &driver )
    1708                 :            : {
    1709                 :          0 :   if ( !sGdalSkipList()->contains( driver ) )
    1710                 :            :   {
    1711                 :          0 :     return;
    1712                 :            :   }
    1713                 :          0 :   int myPos = sGdalSkipList()->indexOf( driver );
    1714                 :          0 :   if ( myPos >= 0 )
    1715                 :            :   {
    1716                 :          0 :     sGdalSkipList()->removeAt( myPos );
    1717                 :          0 :   }
    1718                 :          0 :   applyGdalSkippedDrivers();
    1719                 :          0 : }
    1720                 :            : 
    1721                 :          0 : QStringList QgsApplication::skippedGdalDrivers()
    1722                 :            : {
    1723                 :          0 :   return *sGdalSkipList();
    1724                 :            : }
    1725                 :            : 
    1726                 :          0 : void QgsApplication::setSkippedGdalDrivers( const QStringList &skippedGdalDrivers,
    1727                 :            :     const QStringList &deferredSkippedGdalDrivers )
    1728                 :            : {
    1729                 :          0 :   *sGdalSkipList() = skippedGdalDrivers;
    1730                 :          0 :   *sDeferredSkippedGdalDrivers() = deferredSkippedGdalDrivers;
    1731                 :            : 
    1732                 :          0 :   QgsSettings settings;
    1733                 :          0 :   settings.setValue( QStringLiteral( "gdal/skipDrivers" ), skippedGdalDrivers.join( QLatin1Char( ',' ) ) );
    1734                 :            : 
    1735                 :          0 :   applyGdalSkippedDrivers();
    1736                 :          0 : }
    1737                 :            : 
    1738                 :          3 : void QgsApplication::registerGdalDriversFromSettings()
    1739                 :            : {
    1740                 :          3 :   QgsSettings settings;
    1741                 :          3 :   QString joinedList, delimiter;
    1742                 :          6 :   if ( settings.contains( QStringLiteral( "gdal/skipDrivers" ) ) )
    1743                 :            :   {
    1744                 :          0 :     joinedList = settings.value( QStringLiteral( "gdal/skipDrivers" ), QString() ).toString();
    1745                 :          0 :     delimiter = QStringLiteral( "," );
    1746                 :          0 :   }
    1747                 :            :   else
    1748                 :            :   {
    1749                 :          6 :     joinedList = settings.value( QStringLiteral( "gdal/skipList" ), QString() ).toString();
    1750                 :          6 :     delimiter = QStringLiteral( " " );
    1751                 :            :   }
    1752                 :          3 :   QStringList myList;
    1753                 :          3 :   if ( !joinedList.isEmpty() )
    1754                 :            :   {
    1755                 :          0 :     myList = joinedList.split( delimiter );
    1756                 :          0 :   }
    1757                 :          3 :   *sGdalSkipList() = myList;
    1758                 :          3 :   applyGdalSkippedDrivers();
    1759                 :          3 : }
    1760                 :            : 
    1761                 :          0 : QStringList QgsApplication::deferredSkippedGdalDrivers()
    1762                 :            : {
    1763                 :          0 :   return *sDeferredSkippedGdalDrivers();
    1764                 :            : }
    1765                 :            : 
    1766                 :          3 : void QgsApplication::applyGdalSkippedDrivers()
    1767                 :            : {
    1768                 :          3 :   sGdalSkipList()->removeDuplicates();
    1769                 :          3 :   QStringList realDisabledDriverList;
    1770                 :          3 :   for ( const auto &driverName : *sGdalSkipList() )
    1771                 :            :   {
    1772                 :          0 :     if ( !sDeferredSkippedGdalDrivers()->contains( driverName ) )
    1773                 :          0 :       realDisabledDriverList << driverName;
    1774                 :            :   }
    1775                 :          3 :   QString myDriverList = realDisabledDriverList.join( ',' );
    1776                 :          3 :   QgsDebugMsgLevel( QStringLiteral( "Gdal Skipped driver list set to:" ), 2 );
    1777                 :          3 :   QgsDebugMsgLevel( myDriverList, 2 );
    1778                 :          3 :   CPLSetConfigOption( "GDAL_SKIP", myDriverList.toUtf8() );
    1779                 :          3 :   GDALAllRegister(); //to update driver list and skip missing ones
    1780                 :          3 : }
    1781                 :            : 
    1782                 :          0 : bool QgsApplication::createThemeFolder()
    1783                 :            : {
    1784                 :          0 :   QString folder = userThemesFolder();
    1785                 :          0 :   QDir myDir( folder );
    1786                 :          0 :   if ( !myDir.exists() )
    1787                 :            :   {
    1788                 :          0 :     myDir.mkpath( folder );
    1789                 :          0 :   }
    1790                 :            : 
    1791                 :            :   return true;
    1792                 :          0 : }
    1793                 :            : 
    1794                 :          0 : void QgsApplication::copyPath( const QString &src, const QString &dst )
    1795                 :            : {
    1796                 :          0 :   QDir dir( src );
    1797                 :          0 :   if ( ! dir.exists() )
    1798                 :          0 :     return;
    1799                 :            : 
    1800                 :          0 :   const auto subDirectories = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
    1801                 :          0 :   for ( const QString &d : subDirectories )
    1802                 :            :   {
    1803                 :          0 :     QString dst_path = dst + QDir::separator() + d;
    1804                 :          0 :     dir.mkpath( dst_path );
    1805                 :          0 :     copyPath( src + QDir::separator() + d, dst_path );
    1806                 :          0 :   }
    1807                 :            : 
    1808                 :          0 :   const auto files = dir.entryList( QDir::Files );
    1809                 :          0 :   for ( const QString &f : files )
    1810                 :            :   {
    1811                 :          0 :     QFile::copy( src + QDir::separator() + f, dst + QDir::separator() + f );
    1812                 :            :   }
    1813                 :          0 : }
    1814                 :            : 
    1815                 :          1 : QVariantMap QgsApplication::customVariables()
    1816                 :            : {
    1817                 :            :   //read values from QgsSettings
    1818                 :          1 :   QgsSettings settings;
    1819                 :            : 
    1820                 :          1 :   QVariantMap variables;
    1821                 :            : 
    1822                 :            :   //check if settings contains any variables
    1823                 :          1 :   settings.beginGroup( "variables" );
    1824                 :          1 :   QStringList childKeys = settings.childKeys();
    1825                 :          1 :   for ( QStringList::const_iterator it = childKeys.constBegin(); it != childKeys.constEnd(); ++it )
    1826                 :            :   {
    1827                 :          0 :     QString name = *it;
    1828                 :          0 :     variables.insert( name, settings.value( name ) );
    1829                 :          0 :   }
    1830                 :            : 
    1831                 :          1 :   return variables;
    1832                 :          1 : }
    1833                 :            : 
    1834                 :          0 : void QgsApplication::setCustomVariables( const QVariantMap &variables )
    1835                 :            : {
    1836                 :          0 :   QgsSettings settings;
    1837                 :            : 
    1838                 :          0 :   QVariantMap::const_iterator it = variables.constBegin();
    1839                 :          0 :   settings.beginGroup( "variables" );
    1840                 :          0 :   settings.remove( "" );
    1841                 :          0 :   for ( ; it != variables.constEnd(); ++it )
    1842                 :            :   {
    1843                 :          0 :     settings.setValue( it.key(), it.value() );
    1844                 :          0 :   }
    1845                 :            : 
    1846                 :          0 :   emit instance()->customVariablesChanged();
    1847                 :          0 : }
    1848                 :            : 
    1849                 :          0 : void QgsApplication::setCustomVariable( const QString &name, const QVariant &value )
    1850                 :            : {
    1851                 :            :   // save variable to settings
    1852                 :          0 :   QgsSettings settings;
    1853                 :            : 
    1854                 :          0 :   settings.setValue( QStringLiteral( "variables/" ) + name, value );
    1855                 :            : 
    1856                 :          0 :   emit instance()->customVariablesChanged();
    1857                 :          0 : }
    1858                 :            : 
    1859                 :          0 : int QgsApplication::scaleIconSize( int standardSize, bool applyDevicePixelRatio )
    1860                 :            : {
    1861                 :          0 :   QFontMetrics fm( ( QFont() ) );
    1862                 :          0 :   const double scale = 1.1 * standardSize / 24;
    1863                 :          0 :   int scaledIconSize = static_cast< int >( std::floor( std::max( Qgis::UI_SCALE_FACTOR * fm.height() * scale, static_cast< double >( standardSize ) ) ) );
    1864                 :            : #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
    1865                 :            :   if ( applyDevicePixelRatio && QApplication::desktop() )
    1866                 :            :     scaledIconSize *= QApplication::desktop()->devicePixelRatio();
    1867                 :            : #else
    1868                 :          0 :   if ( applyDevicePixelRatio )
    1869                 :            :   {
    1870                 :          0 :     if ( QWidget *activeWindow = QApplication::activeWindow() )
    1871                 :          0 :       scaledIconSize *= ( activeWindow->screen() ? QApplication::activeWindow()->screen()->devicePixelRatio() : 1 );
    1872                 :          0 :   }
    1873                 :            : #endif
    1874                 :          0 :   return scaledIconSize;
    1875                 :          0 : }
    1876                 :            : 
    1877                 :         64 : int QgsApplication::maxConcurrentConnectionsPerPool() const
    1878                 :            : {
    1879                 :         64 :   return CONN_POOL_MAX_CONCURRENT_CONNS;
    1880                 :            : }
    1881                 :            : 
    1882                 :          0 : void QgsApplication::setTranslation( const QString &translation )
    1883                 :            : {
    1884                 :          0 :   *sTranslation() = translation;
    1885                 :          0 : }
    1886                 :            : 
    1887                 :          0 : void QgsApplication::collectTranslatableObjects( QgsTranslationContext *translationContext )
    1888                 :            : {
    1889                 :          0 :   emit requestForTranslatableObjects( translationContext );
    1890                 :          0 : }
    1891                 :            : 
    1892                 :          0 : QString QgsApplication::nullRepresentation()
    1893                 :            : {
    1894                 :          0 :   ApplicationMembers *appMembers = members();
    1895                 :          0 :   if ( appMembers->mNullRepresentation.isNull() )
    1896                 :            :   {
    1897                 :          0 :     appMembers->mNullRepresentation = QgsSettings().value( QStringLiteral( "qgis/nullValue" ), QStringLiteral( "NULL" ) ).toString();
    1898                 :          0 :   }
    1899                 :          0 :   return appMembers->mNullRepresentation;
    1900                 :          0 : }
    1901                 :            : 
    1902                 :          0 : void QgsApplication::setNullRepresentation( const QString &nullRepresentation )
    1903                 :            : {
    1904                 :          0 :   ApplicationMembers *appMembers = members();
    1905                 :          0 :   if ( !appMembers || appMembers->mNullRepresentation == nullRepresentation )
    1906                 :          0 :     return;
    1907                 :            : 
    1908                 :          0 :   appMembers->mNullRepresentation = nullRepresentation;
    1909                 :          0 :   QgsSettings().setValue( QStringLiteral( "qgis/nullValue" ), nullRepresentation );
    1910                 :            : 
    1911                 :          0 :   QgsApplication *app = instance();
    1912                 :          0 :   if ( app )
    1913                 :          0 :     emit app->nullRepresentationChanged();
    1914                 :          0 : }
    1915                 :            : 
    1916                 :          0 : QgsActionScopeRegistry *QgsApplication::actionScopeRegistry()
    1917                 :            : {
    1918                 :          0 :   return members()->mActionScopeRegistry;
    1919                 :            : }
    1920                 :            : 
    1921                 :          0 : bool QgsApplication::createDatabase( QString *errorMessage )
    1922                 :            : {
    1923                 :            :   // set a working directory up for gdal to write .aux.xml files into
    1924                 :            :   // for cases where the raster dir is read only to the user
    1925                 :            :   // if the env var is already set it will be used preferentially
    1926                 :          0 :   QString myPamPath = qgisSettingsDirPath() + QStringLiteral( "gdal_pam/" );
    1927                 :          0 :   QDir myDir( myPamPath );
    1928                 :          0 :   if ( !myDir.exists() )
    1929                 :            :   {
    1930                 :          0 :     myDir.mkpath( myPamPath ); //fail silently
    1931                 :          0 :   }
    1932                 :            : 
    1933                 :            : #if defined(Q_OS_WIN)
    1934                 :            :   CPLSetConfigOption( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8() );
    1935                 :            : #else
    1936                 :            :   //under other OS's we use an environment var so the user can
    1937                 :            :   //override the path if he likes
    1938                 :          0 :   int myChangeFlag = 0; //whether we want to force the env var to change
    1939                 :          0 :   setenv( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8(), myChangeFlag );
    1940                 :            : #endif
    1941                 :            : 
    1942                 :            :   // Check qgis.db and make private copy if necessary
    1943                 :          0 :   QFile qgisPrivateDbFile( QgsApplication::qgisUserDatabaseFilePath() );
    1944                 :            : 
    1945                 :            :   // first we look for ~/.qgis/qgis.db
    1946                 :          0 :   if ( !qgisPrivateDbFile.exists() )
    1947                 :            :   {
    1948                 :            :     // if it doesn't exist we copy it in from the global resources dir
    1949                 :          0 :     QString qgisMasterDbFileName = QgsApplication::qgisMasterDatabaseFilePath();
    1950                 :          0 :     QFile masterFile( qgisMasterDbFileName );
    1951                 :            : 
    1952                 :            :     // Must be sure there is destination directory ~/.qgis
    1953                 :          0 :     QDir().mkpath( QgsApplication::qgisSettingsDirPath() );
    1954                 :            : 
    1955                 :            :     //now copy the master file into the users .qgis dir
    1956                 :          0 :     bool isDbFileCopied = masterFile.copy( qgisPrivateDbFile.fileName() );
    1957                 :            : 
    1958                 :          0 :     if ( !isDbFileCopied )
    1959                 :            :     {
    1960                 :          0 :       if ( errorMessage )
    1961                 :            :       {
    1962                 :          0 :         *errorMessage = tr( "[ERROR] Can not make qgis.db private copy" );
    1963                 :          0 :       }
    1964                 :          0 :       return false;
    1965                 :            :     }
    1966                 :            : 
    1967                 :          0 :     QFile::Permissions perms = QFile( qgisPrivateDbFile.fileName() ).permissions();
    1968                 :          0 :     if ( !( perms & QFile::WriteOwner ) )
    1969                 :            :     {
    1970                 :          0 :       if ( !qgisPrivateDbFile.setPermissions( perms | QFile::WriteOwner ) )
    1971                 :            :       {
    1972                 :          0 :         if ( errorMessage )
    1973                 :            :         {
    1974                 :          0 :           *errorMessage = tr( "Can not make '%1' user writable" ).arg( qgisPrivateDbFile.fileName() );
    1975                 :          0 :         }
    1976                 :          0 :         return false;
    1977                 :            :       }
    1978                 :          0 :     }
    1979                 :          0 :   }
    1980                 :            :   else
    1981                 :            :   {
    1982                 :            :     // migrate if necessary
    1983                 :          0 :     sqlite3_database_unique_ptr database;
    1984                 :          0 :     if ( database.open( QgsApplication::qgisUserDatabaseFilePath() ) != SQLITE_OK )
    1985                 :            :     {
    1986                 :          0 :       if ( errorMessage )
    1987                 :            :       {
    1988                 :          0 :         *errorMessage = tr( "Could not open qgis.db" );
    1989                 :          0 :       }
    1990                 :          0 :       return false;
    1991                 :            :     }
    1992                 :            : 
    1993                 :          0 :     char *errmsg = nullptr;
    1994                 :          0 :     int res = sqlite3_exec( database.get(), "SELECT srs_id FROM tbl_srs LIMIT 0", nullptr, nullptr, &errmsg );
    1995                 :          0 :     if ( res != SQLITE_OK )
    1996                 :            :     {
    1997                 :          0 :       sqlite3_free( errmsg );
    1998                 :            : 
    1999                 :            :       // qgis.db is missing tbl_srs, create it
    2000                 :          0 :       if ( sqlite3_exec( database.get(),
    2001                 :            :                          "DROP INDEX IF EXISTS idx_srsauthid;"
    2002                 :            :                          "CREATE TABLE tbl_srs ("
    2003                 :            :                          "srs_id INTEGER PRIMARY KEY,"
    2004                 :            :                          "description text NOT NULL,"
    2005                 :            :                          "projection_acronym text NOT NULL,"
    2006                 :            :                          "ellipsoid_acronym NOT NULL,"
    2007                 :            :                          "parameters text NOT NULL,"
    2008                 :            :                          "srid integer,"
    2009                 :            :                          "auth_name varchar,"
    2010                 :            :                          "auth_id varchar,"
    2011                 :            :                          "is_geo integer NOT NULL,"
    2012                 :            :                          "deprecated boolean,"
    2013                 :            :                          "wkt text);"
    2014                 :          0 :                          "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);", nullptr, nullptr, &errmsg ) != SQLITE_OK )
    2015                 :            :       {
    2016                 :          0 :         if ( errorMessage )
    2017                 :            :         {
    2018                 :          0 :           *errorMessage = tr( "Creation of missing tbl_srs in the private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
    2019                 :          0 :         }
    2020                 :          0 :         sqlite3_free( errmsg );
    2021                 :          0 :         return false;
    2022                 :            :       }
    2023                 :          0 :     }
    2024                 :            :     else
    2025                 :            :     {
    2026                 :            :       // test if wkt column exists in database
    2027                 :          0 :       res = sqlite3_exec( database.get(), "SELECT wkt FROM tbl_srs LIMIT 0", nullptr, nullptr, &errmsg );
    2028                 :          0 :       if ( res != SQLITE_OK )
    2029                 :            :       {
    2030                 :            :         // need to add wkt column
    2031                 :          0 :         sqlite3_free( errmsg );
    2032                 :          0 :         if ( sqlite3_exec( database.get(),
    2033                 :            :                            "DROP INDEX IF EXISTS idx_srsauthid;"
    2034                 :            :                            "DROP TABLE IF EXISTS tbl_srs_bak;"
    2035                 :            :                            "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
    2036                 :            :                            "CREATE TABLE tbl_srs ("
    2037                 :            :                            "srs_id INTEGER PRIMARY KEY,"
    2038                 :            :                            "description text NOT NULL,"
    2039                 :            :                            "projection_acronym text NOT NULL,"
    2040                 :            :                            "ellipsoid_acronym NOT NULL,"
    2041                 :            :                            "parameters text NOT NULL,"
    2042                 :            :                            "srid integer,"
    2043                 :            :                            "auth_name varchar,"
    2044                 :            :                            "auth_id varchar,"
    2045                 :            :                            "is_geo integer NOT NULL,"
    2046                 :            :                            "deprecated boolean,"
    2047                 :            :                            "wkt text);"
    2048                 :            :                            "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
    2049                 :            :                            "INSERT INTO tbl_srs(srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,auth_name,auth_id,is_geo,deprecated) SELECT srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,'','',is_geo,0 FROM tbl_srs_bak;"
    2050                 :          0 :                            "DROP TABLE tbl_srs_bak", nullptr, nullptr, &errmsg ) != SQLITE_OK )
    2051                 :            :         {
    2052                 :          0 :           if ( errorMessage )
    2053                 :            :           {
    2054                 :          0 :             *errorMessage = tr( "Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
    2055                 :          0 :           }
    2056                 :          0 :           sqlite3_free( errmsg );
    2057                 :          0 :           return false;
    2058                 :            :         }
    2059                 :          0 :       }
    2060                 :            :     }
    2061                 :            : 
    2062                 :          0 :     res = sqlite3_exec( database.get(), "SELECT acronym FROM tbl_projection LIMIT 0", nullptr, nullptr, &errmsg );
    2063                 :          0 :     if ( res != SQLITE_OK )
    2064                 :            :     {
    2065                 :          0 :       sqlite3_free( errmsg );
    2066                 :            : 
    2067                 :            :       // qgis.db is missing tbl_projection, create it
    2068                 :          0 :       if ( sqlite3_exec( database.get(),
    2069                 :            :                          "CREATE TABLE tbl_projection ("
    2070                 :            :                          "acronym varchar(20) NOT NULL PRIMARY KEY,"
    2071                 :            :                          "name varchar(255) NOT NULL default '',"
    2072                 :            :                          "notes varchar(255) NOT NULL default '',"
    2073                 :            :                          "parameters varchar(255) NOT NULL default ''"
    2074                 :          0 :                          ")", nullptr, nullptr, &errmsg ) != SQLITE_OK )
    2075                 :            :       {
    2076                 :          0 :         if ( errorMessage )
    2077                 :            :         {
    2078                 :          0 :           *errorMessage = tr( "Creation of missing tbl_projection in the private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
    2079                 :          0 :         }
    2080                 :          0 :         sqlite3_free( errmsg );
    2081                 :          0 :         return false;
    2082                 :            :       }
    2083                 :          0 :     }
    2084                 :            : 
    2085                 :          0 :     res = sqlite3_exec( database.get(), "SELECT epsg FROM tbl_srs LIMIT 0", nullptr, nullptr, &errmsg );
    2086                 :          0 :     if ( res == SQLITE_OK )
    2087                 :            :     {
    2088                 :            :       // epsg column exists => need migration
    2089                 :          0 :       if ( sqlite3_exec( database.get(),
    2090                 :            :                          "DROP INDEX IF EXISTS idx_srsauthid;"
    2091                 :            :                          "DROP TABLE IF EXISTS tbl_srs_bak;"
    2092                 :            :                          "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
    2093                 :            :                          "CREATE TABLE tbl_srs ("
    2094                 :            :                          "srs_id INTEGER PRIMARY KEY,"
    2095                 :            :                          "description text NOT NULL,"
    2096                 :            :                          "projection_acronym text NOT NULL,"
    2097                 :            :                          "ellipsoid_acronym NOT NULL,"
    2098                 :            :                          "parameters text NOT NULL,"
    2099                 :            :                          "srid integer,"
    2100                 :            :                          "auth_name varchar,"
    2101                 :            :                          "auth_id varchar,"
    2102                 :            :                          "is_geo integer NOT NULL,"
    2103                 :            :                          "deprecated boolean,"
    2104                 :            :                          "wkt text);"
    2105                 :            :                          "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
    2106                 :            :                          "INSERT INTO tbl_srs(srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,auth_name,auth_id,is_geo,deprecated) SELECT srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,'','',is_geo,0 FROM tbl_srs_bak;"
    2107                 :          0 :                          "DROP TABLE tbl_srs_bak", nullptr, nullptr, &errmsg ) != SQLITE_OK )
    2108                 :            :       {
    2109                 :          0 :         if ( errorMessage )
    2110                 :            :         {
    2111                 :          0 :           *errorMessage = tr( "Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
    2112                 :          0 :         }
    2113                 :          0 :         sqlite3_free( errmsg );
    2114                 :          0 :         return false;
    2115                 :            :       }
    2116                 :          0 :     }
    2117                 :            :     else
    2118                 :            :     {
    2119                 :          0 :       sqlite3_free( errmsg );
    2120                 :            :     }
    2121                 :            : 
    2122                 :          0 :     if ( sqlite3_exec( database.get(), "DROP VIEW vw_srs", nullptr, nullptr, &errmsg ) != SQLITE_OK )
    2123                 :            :     {
    2124                 :          0 :       QgsDebugMsg( QStringLiteral( "vw_srs didn't exists in private qgis.db: %1" ).arg( errmsg ) );
    2125                 :          0 :     }
    2126                 :            : 
    2127                 :          0 :     if ( sqlite3_exec( database.get(),
    2128                 :            :                        "CREATE VIEW vw_srs AS"
    2129                 :            :                        " SELECT"
    2130                 :            :                        " a.description AS description"
    2131                 :            :                        ",a.srs_id AS srs_id"
    2132                 :            :                        ",a.is_geo AS is_geo"
    2133                 :            :                        ",coalesce(b.name,a.projection_acronym) AS name"
    2134                 :            :                        ",a.parameters AS parameters"
    2135                 :            :                        ",a.auth_name AS auth_name"
    2136                 :            :                        ",a.auth_id AS auth_id"
    2137                 :            :                        ",a.deprecated AS deprecated"
    2138                 :            :                        " FROM tbl_srs a"
    2139                 :            :                        " LEFT OUTER JOIN tbl_projection b ON a.projection_acronym=b.acronym"
    2140                 :          0 :                        " ORDER BY coalesce(b.name,a.projection_acronym),a.description", nullptr, nullptr, &errmsg ) != SQLITE_OK )
    2141                 :            :     {
    2142                 :          0 :       if ( errorMessage )
    2143                 :            :       {
    2144                 :          0 :         *errorMessage = tr( "Update of view in private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
    2145                 :          0 :       }
    2146                 :          0 :       sqlite3_free( errmsg );
    2147                 :          0 :       return false;
    2148                 :            :     }
    2149                 :          0 :   }
    2150                 :          0 :   return true;
    2151                 :          0 : }
    2152                 :            : 
    2153                 :          0 : void QgsApplication::setMaxThreads( int maxThreads )
    2154                 :            : {
    2155                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "maxThreads: %1" ).arg( maxThreads ), 2 );
    2156                 :            : 
    2157                 :            :   // make sure value is between 1 and #cores, if not set to -1 (use #cores)
    2158                 :            :   // 0 could be used to disable any parallel processing
    2159                 :          0 :   if ( maxThreads < 1 || maxThreads > QThread::idealThreadCount() )
    2160                 :          0 :     maxThreads = -1;
    2161                 :            : 
    2162                 :            :   // save value
    2163                 :          0 :   ABISYM( sMaxThreads ) = maxThreads;
    2164                 :            : 
    2165                 :            :   // if -1 use #cores
    2166                 :          0 :   if ( maxThreads == -1 )
    2167                 :          0 :     maxThreads = QThread::idealThreadCount();
    2168                 :            : 
    2169                 :            :   // set max thread count in QThreadPool
    2170                 :          0 :   QThreadPool::globalInstance()->setMaxThreadCount( maxThreads );
    2171                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ), 2 );
    2172                 :          0 : }
    2173                 :            : 
    2174                 :          0 : QgsTaskManager *QgsApplication::taskManager()
    2175                 :            : {
    2176                 :          0 :   return members()->mTaskManager;
    2177                 :            : }
    2178                 :            : 
    2179                 :         92 : QgsColorSchemeRegistry *QgsApplication::colorSchemeRegistry()
    2180                 :            : {
    2181                 :         92 :   return members()->mColorSchemeRegistry;
    2182                 :            : }
    2183                 :            : 
    2184                 :        490 : QgsPaintEffectRegistry *QgsApplication::paintEffectRegistry()
    2185                 :            : {
    2186                 :        490 :   return members()->mPaintEffectRegistry;
    2187                 :            : }
    2188                 :            : 
    2189                 :          0 : QgsRendererRegistry *QgsApplication::rendererRegistry()
    2190                 :            : {
    2191                 :          0 :   return members()->mRendererRegistry;
    2192                 :            : }
    2193                 :            : 
    2194                 :          0 : QgsRasterRendererRegistry *QgsApplication::rasterRendererRegistry()
    2195                 :            : {
    2196                 :          0 :   return members()->mRasterRendererRegistry;
    2197                 :            : }
    2198                 :            : 
    2199                 :          0 : QgsPointCloudRendererRegistry *QgsApplication::pointCloudRendererRegistry()
    2200                 :            : {
    2201                 :          0 :   return members()->mPointCloudRendererRegistry;
    2202                 :            : }
    2203                 :            : 
    2204                 :          3 : QgsDataItemProviderRegistry *QgsApplication::dataItemProviderRegistry()
    2205                 :            : {
    2206                 :          3 :   if ( auto *lInstance = instance() )
    2207                 :            :   {
    2208                 :          3 :     if ( !instance()->mDataItemProviderRegistry )
    2209                 :            :     {
    2210                 :          3 :       lInstance->mDataItemProviderRegistry = new QgsDataItemProviderRegistry();
    2211                 :          3 :     }
    2212                 :          3 :     return lInstance->mDataItemProviderRegistry;
    2213                 :            :   }
    2214                 :            :   else
    2215                 :            :   {
    2216                 :            :     // no QgsApplication instance
    2217                 :            :     static QgsDataItemProviderRegistry *sDataItemProviderRegistry = nullptr;
    2218                 :          0 :     if ( !sDataItemProviderRegistry )
    2219                 :          0 :       sDataItemProviderRegistry = new QgsDataItemProviderRegistry();
    2220                 :          0 :     return sDataItemProviderRegistry;
    2221                 :            :   }
    2222                 :          3 : }
    2223                 :            : 
    2224                 :          0 : QgsCoordinateReferenceSystemRegistry *QgsApplication::coordinateReferenceSystemRegistry()
    2225                 :            : {
    2226                 :          0 :   return members()->mCrsRegistry;
    2227                 :            : }
    2228                 :            : 
    2229                 :         85 : QgsSvgCache *QgsApplication::svgCache()
    2230                 :            : {
    2231                 :         85 :   return members()->mSvgCache;
    2232                 :            : }
    2233                 :            : 
    2234                 :          5 : QgsImageCache *QgsApplication::imageCache()
    2235                 :            : {
    2236                 :          5 :   return members()->mImageCache;
    2237                 :            : }
    2238                 :            : 
    2239                 :          0 : QgsSourceCache *QgsApplication::sourceCache()
    2240                 :            : {
    2241                 :          0 :   return members()->mSourceCache;
    2242                 :            : }
    2243                 :            : 
    2244                 :          0 : QgsNetworkContentFetcherRegistry *QgsApplication::networkContentFetcherRegistry()
    2245                 :            : {
    2246                 :          0 :   return members()->mNetworkContentFetcherRegistry;
    2247                 :            : }
    2248                 :            : 
    2249                 :          0 : QgsValidityCheckRegistry *QgsApplication::validityCheckRegistry()
    2250                 :            : {
    2251                 :          0 :   return members()->mValidityCheckRegistry;
    2252                 :            : }
    2253                 :            : 
    2254                 :       1980 : QgsSymbolLayerRegistry *QgsApplication::symbolLayerRegistry()
    2255                 :            : {
    2256                 :       1980 :   return members()->mSymbolLayerRegistry;
    2257                 :            : }
    2258                 :            : 
    2259                 :          0 : QgsCalloutRegistry *QgsApplication::calloutRegistry()
    2260                 :            : {
    2261                 :          0 :   return members()->mCalloutRegistry;
    2262                 :            : }
    2263                 :            : 
    2264                 :          0 : QgsLayoutItemRegistry *QgsApplication::layoutItemRegistry()
    2265                 :            : {
    2266                 :          0 :   return members()->mLayoutItemRegistry;
    2267                 :            : }
    2268                 :            : 
    2269                 :          0 : QgsAnnotationItemRegistry *QgsApplication::annotationItemRegistry()
    2270                 :            : {
    2271                 :          0 :   return members()->mAnnotationItemRegistry;
    2272                 :            : }
    2273                 :            : 
    2274                 :          0 : QgsGpsConnectionRegistry *QgsApplication::gpsConnectionRegistry()
    2275                 :            : {
    2276                 :          0 :   return members()->mGpsConnectionRegistry;
    2277                 :            : }
    2278                 :            : 
    2279                 :          0 : QgsPluginLayerRegistry *QgsApplication::pluginLayerRegistry()
    2280                 :            : {
    2281                 :          0 :   return members()->mPluginLayerRegistry;
    2282                 :            : }
    2283                 :            : 
    2284                 :          0 : QgsClassificationMethodRegistry *QgsApplication::classificationMethodRegistry()
    2285                 :            : {
    2286                 :          0 :   return members()->mClassificationMethodRegistry;
    2287                 :            : }
    2288                 :            : 
    2289                 :          7 : QgsBookmarkManager *QgsApplication::bookmarkManager()
    2290                 :            : {
    2291                 :          7 :   return members()->mBookmarkManager;
    2292                 :            : }
    2293                 :            : 
    2294                 :          0 : QgsTileDownloadManager *QgsApplication::tileDownloadManager()
    2295                 :            : {
    2296                 :          0 :   return members()->mTileDownloadManager;
    2297                 :            : }
    2298                 :            : 
    2299                 :          0 : QgsStyleModel *QgsApplication::defaultStyleModel()
    2300                 :            : {
    2301                 :          0 :   return members()->mStyleModel;
    2302                 :            : }
    2303                 :            : 
    2304                 :          3 : QgsMessageLog *QgsApplication::messageLog()
    2305                 :            : {
    2306                 :          3 :   return members()->mMessageLog;
    2307                 :            : }
    2308                 :            : 
    2309                 :          0 : QgsProcessingRegistry *QgsApplication::processingRegistry()
    2310                 :            : {
    2311                 :          0 :   return members()->mProcessingRegistry;
    2312                 :            : }
    2313                 :            : 
    2314                 :          0 : QgsConnectionRegistry *QgsApplication::connectionRegistry()
    2315                 :            : {
    2316                 :          0 :   return members()->mConnectionRegistry;
    2317                 :            : }
    2318                 :            : 
    2319                 :          0 : QgsPageSizeRegistry *QgsApplication::pageSizeRegistry()
    2320                 :            : {
    2321                 :          0 :   return members()->mPageSizeRegistry;
    2322                 :            : }
    2323                 :            : 
    2324                 :          0 : QgsAnnotationRegistry *QgsApplication::annotationRegistry()
    2325                 :            : {
    2326                 :          0 :   return members()->mAnnotationRegistry;
    2327                 :            : }
    2328                 :            : 
    2329                 :          0 : QgsNumericFormatRegistry *QgsApplication::numericFormatRegistry()
    2330                 :            : {
    2331                 :          0 :   return members()->mNumericFormatRegistry;
    2332                 :            : }
    2333                 :            : 
    2334                 :          0 : QgsFieldFormatterRegistry *QgsApplication::fieldFormatterRegistry()
    2335                 :            : {
    2336                 :          0 :   return members()->mFieldFormatterRegistry;
    2337                 :            : }
    2338                 :            : 
    2339                 :          0 : Qgs3DRendererRegistry *QgsApplication::renderer3DRegistry()
    2340                 :            : {
    2341                 :          0 :   return members()->m3DRendererRegistry;
    2342                 :            : }
    2343                 :            : 
    2344                 :          5 : Qgs3DSymbolRegistry *QgsApplication::symbol3DRegistry()
    2345                 :            : {
    2346                 :          5 :   return members()->m3DSymbolRegistry;
    2347                 :            : }
    2348                 :            : 
    2349                 :          0 : QgsScaleBarRendererRegistry *QgsApplication::scaleBarRendererRegistry()
    2350                 :            : {
    2351                 :          0 :   return members()->mScaleBarRendererRegistry;
    2352                 :            : }
    2353                 :            : 
    2354                 :          9 : QgsProjectStorageRegistry *QgsApplication::projectStorageRegistry()
    2355                 :            : {
    2356                 :          9 :   return members()->mProjectStorageRegistry;
    2357                 :            : }
    2358                 :            : 
    2359                 :          0 : QgsLocalizedDataPathRegistry *QgsApplication::localizedDataPathRegistry()
    2360                 :            : {
    2361                 :          0 :   return members()->mLocalizedDataPathRegistry;
    2362                 :            : }
    2363                 :            : 
    2364                 :          5 : QgsApplication::ApplicationMembers::ApplicationMembers()
    2365                 :            : {
    2366                 :            :   // don't use initializer lists or scoped pointers - as more objects are added here we
    2367                 :            :   // will need to be careful with the order of creation/destruction
    2368                 :          5 :   mLocalizedDataPathRegistry = new QgsLocalizedDataPathRegistry();
    2369                 :          5 :   mMessageLog = new QgsMessageLog();
    2370                 :          5 :   QgsRuntimeProfiler *profiler = QgsRuntimeProfiler::threadLocalInstance();
    2371                 :            : 
    2372                 :            :   {
    2373                 :          5 :     profiler->start( tr( "Setup coordinate reference system registry" ) );
    2374                 :          5 :     mCrsRegistry = new QgsCoordinateReferenceSystemRegistry();
    2375                 :          5 :     profiler->end();
    2376                 :            :   }
    2377                 :            :   {
    2378                 :          5 :     profiler->start( tr( "Create connection registry" ) );
    2379                 :          5 :     mConnectionRegistry = new QgsConnectionRegistry();
    2380                 :          5 :     profiler->end();
    2381                 :            :   }
    2382                 :            :   {
    2383                 :          5 :     profiler->start( tr( "Setup task manager" ) );
    2384                 :          5 :     mTaskManager = new QgsTaskManager();
    2385                 :          5 :     profiler->end();
    2386                 :            :   }
    2387                 :            :   {
    2388                 :          5 :     profiler->start( tr( "Setup action scope registry" ) );
    2389                 :          5 :     mActionScopeRegistry = new QgsActionScopeRegistry();
    2390                 :          5 :     profiler->end();
    2391                 :            :   }
    2392                 :            :   {
    2393                 :          5 :     profiler->start( tr( "Setup numeric formats" ) );
    2394                 :          5 :     mNumericFormatRegistry = new QgsNumericFormatRegistry();
    2395                 :          5 :     profiler->end();
    2396                 :            :   }
    2397                 :            :   {
    2398                 :          5 :     profiler->start( tr( "Setup field formats" ) );
    2399                 :          5 :     mFieldFormatterRegistry = new QgsFieldFormatterRegistry();
    2400                 :          5 :     profiler->end();
    2401                 :            :   }
    2402                 :            :   {
    2403                 :          5 :     profiler->start( tr( "Setup SVG cache" ) );
    2404                 :          5 :     mSvgCache = new QgsSvgCache();
    2405                 :          5 :     profiler->end();
    2406                 :            :   }
    2407                 :            :   {
    2408                 :          5 :     profiler->start( tr( "Setup image cache" ) );
    2409                 :          5 :     mImageCache = new QgsImageCache();
    2410                 :          5 :     profiler->end();
    2411                 :            :   }
    2412                 :            :   {
    2413                 :          5 :     profiler->start( tr( "Setup source cache" ) );
    2414                 :          5 :     mSourceCache = new QgsSourceCache();
    2415                 :          5 :     profiler->end();
    2416                 :            :   }
    2417                 :            :   {
    2418                 :          5 :     profiler->start( tr( "Setup color scheme registry" ) );
    2419                 :          5 :     mColorSchemeRegistry = new QgsColorSchemeRegistry();
    2420                 :          5 :     profiler->end();
    2421                 :            :   }
    2422                 :            :   {
    2423                 :          5 :     profiler->start( tr( "Setup paint effect" ) );
    2424                 :          5 :     mPaintEffectRegistry = new QgsPaintEffectRegistry();
    2425                 :          5 :     profiler->end();
    2426                 :            :   }
    2427                 :            :   {
    2428                 :          5 :     profiler->start( tr( "Setup symbol layer registry" ) );
    2429                 :          5 :     mSymbolLayerRegistry = new QgsSymbolLayerRegistry();
    2430                 :          5 :     profiler->end();
    2431                 :            :   }
    2432                 :            :   {
    2433                 :          5 :     profiler->start( tr( "Setup callout registry" ) );
    2434                 :          5 :     mCalloutRegistry = new QgsCalloutRegistry();
    2435                 :          5 :     profiler->end();
    2436                 :            :   }
    2437                 :            :   {
    2438                 :          5 :     profiler->start( tr( "Setup renderer registry" ) );
    2439                 :          5 :     mRendererRegistry = new QgsRendererRegistry();
    2440                 :          5 :     profiler->end();
    2441                 :            :   }
    2442                 :            :   {
    2443                 :          5 :     profiler->start( tr( "Setup raster renderer registry" ) );
    2444                 :          5 :     mRasterRendererRegistry = new QgsRasterRendererRegistry();
    2445                 :          5 :     profiler->end();
    2446                 :            :   }
    2447                 :            :   {
    2448                 :          5 :     profiler->start( tr( "Setup point cloud renderer registry" ) );
    2449                 :          5 :     mPointCloudRendererRegistry = new QgsPointCloudRendererRegistry();
    2450                 :          5 :     profiler->end();
    2451                 :            :   }
    2452                 :            :   {
    2453                 :          5 :     profiler->start( tr( "Setup GPS registry" ) );
    2454                 :          5 :     mGpsConnectionRegistry = new QgsGpsConnectionRegistry();
    2455                 :          5 :     profiler->end();
    2456                 :            :   }
    2457                 :            :   {
    2458                 :          5 :     profiler->start( tr( "Setup plugin layer registry" ) );
    2459                 :          5 :     mPluginLayerRegistry = new QgsPluginLayerRegistry();
    2460                 :          5 :     profiler->end();
    2461                 :            :   }
    2462                 :            :   {
    2463                 :          5 :     profiler->start( tr( "Setup Processing registry" ) );
    2464                 :          5 :     mProcessingRegistry = new QgsProcessingRegistry();
    2465                 :          5 :     profiler->end();
    2466                 :            :   }
    2467                 :          5 :   mPageSizeRegistry = new QgsPageSizeRegistry();
    2468                 :            :   {
    2469                 :          5 :     profiler->start( tr( "Setup layout item registry" ) );
    2470                 :          5 :     mLayoutItemRegistry = new QgsLayoutItemRegistry();
    2471                 :          5 :     mLayoutItemRegistry->populate();
    2472                 :          5 :     profiler->end();
    2473                 :            :   }
    2474                 :            :   {
    2475                 :          5 :     profiler->start( tr( "Setup annotation registry" ) );
    2476                 :          5 :     mAnnotationRegistry = new QgsAnnotationRegistry();
    2477                 :          5 :     profiler->end();
    2478                 :            :   }
    2479                 :            :   {
    2480                 :          5 :     profiler->start( tr( "Setup annotation item registry" ) );
    2481                 :          5 :     mAnnotationItemRegistry = new QgsAnnotationItemRegistry();
    2482                 :          5 :     mAnnotationItemRegistry->populate();
    2483                 :          5 :     profiler->end();
    2484                 :            :   }
    2485                 :            :   {
    2486                 :          5 :     profiler->start( tr( "Setup 3D symbol registry" ) );
    2487                 :          5 :     m3DSymbolRegistry = new Qgs3DSymbolRegistry();
    2488                 :          5 :     profiler->end();
    2489                 :            :   }
    2490                 :            :   {
    2491                 :          5 :     profiler->start( tr( "Setup 3D renderer registry" ) );
    2492                 :          5 :     m3DRendererRegistry = new Qgs3DRendererRegistry();
    2493                 :          5 :     profiler->end();
    2494                 :            :   }
    2495                 :            :   {
    2496                 :          5 :     profiler->start( tr( "Setup project storage registry" ) );
    2497                 :          5 :     mProjectStorageRegistry = new QgsProjectStorageRegistry();
    2498                 :          5 :     profiler->end();
    2499                 :            :   }
    2500                 :            :   {
    2501                 :          5 :     profiler->start( tr( "Setup network content cache" ) );
    2502                 :          5 :     mNetworkContentFetcherRegistry = new QgsNetworkContentFetcherRegistry();
    2503                 :          5 :     profiler->end();
    2504                 :            :   }
    2505                 :            :   {
    2506                 :          5 :     profiler->start( tr( "Setup layout check registry" ) );
    2507                 :          5 :     mValidityCheckRegistry = new QgsValidityCheckRegistry();
    2508                 :          5 :     profiler->end();
    2509                 :            :   }
    2510                 :            :   {
    2511                 :          5 :     profiler->start( tr( "Setup classification registry" ) );
    2512                 :          5 :     mClassificationMethodRegistry = new QgsClassificationMethodRegistry();
    2513                 :          5 :     profiler->end();
    2514                 :            :   }
    2515                 :            :   {
    2516                 :          5 :     profiler->start( tr( "Setup bookmark manager" ) );
    2517                 :          5 :     mBookmarkManager = new QgsBookmarkManager( nullptr );
    2518                 :          5 :     profiler->end();
    2519                 :            :   }
    2520                 :            :   {
    2521                 :          5 :     profiler->start( tr( "Setup tile download manager" ) );
    2522                 :          5 :     mTileDownloadManager = new QgsTileDownloadManager();
    2523                 :          5 :     profiler->end();
    2524                 :            :   }
    2525                 :            :   {
    2526                 :          5 :     profiler->start( tr( "Setup scalebar registry" ) );
    2527                 :          5 :     mScaleBarRendererRegistry = new QgsScaleBarRendererRegistry();
    2528                 :          5 :     profiler->end();
    2529                 :            :   }
    2530                 :          5 : }
    2531                 :            : 
    2532                 :          5 : QgsApplication::ApplicationMembers::~ApplicationMembers()
    2533                 :            : {
    2534                 :          5 :   delete mStyleModel;
    2535                 :          5 :   delete mTileDownloadManager;
    2536                 :          5 :   delete mScaleBarRendererRegistry;
    2537                 :          5 :   delete mValidityCheckRegistry;
    2538                 :          5 :   delete mActionScopeRegistry;
    2539                 :          5 :   delete m3DRendererRegistry;
    2540                 :          5 :   delete m3DSymbolRegistry;
    2541                 :          5 :   delete mAnnotationRegistry;
    2542                 :          5 :   delete mColorSchemeRegistry;
    2543                 :          5 :   delete mFieldFormatterRegistry;
    2544                 :          5 :   delete mGpsConnectionRegistry;
    2545                 :          5 :   delete mMessageLog;
    2546                 :          5 :   delete mPaintEffectRegistry;
    2547                 :          5 :   delete mPluginLayerRegistry;
    2548                 :          5 :   delete mProcessingRegistry;
    2549                 :          5 :   delete mProjectStorageRegistry;
    2550                 :          5 :   delete mPageSizeRegistry;
    2551                 :          5 :   delete mAnnotationItemRegistry;
    2552                 :          5 :   delete mLayoutItemRegistry;
    2553                 :          5 :   delete mPointCloudRendererRegistry;
    2554                 :          5 :   delete mRasterRendererRegistry;
    2555                 :          5 :   delete mRendererRegistry;
    2556                 :          5 :   delete mSvgCache;
    2557                 :          5 :   delete mImageCache;
    2558                 :          5 :   delete mSourceCache;
    2559                 :          5 :   delete mCalloutRegistry;
    2560                 :          5 :   delete mSymbolLayerRegistry;
    2561                 :          5 :   delete mTaskManager;
    2562                 :          5 :   delete mNetworkContentFetcherRegistry;
    2563                 :          5 :   delete mClassificationMethodRegistry;
    2564                 :          5 :   delete mNumericFormatRegistry;
    2565                 :          5 :   delete mBookmarkManager;
    2566                 :          5 :   delete mConnectionRegistry;
    2567                 :          5 :   delete mLocalizedDataPathRegistry;
    2568                 :          5 :   delete mCrsRegistry;
    2569                 :          5 : }
    2570                 :            : 
    2571                 :       2770 : QgsApplication::ApplicationMembers *QgsApplication::members()
    2572                 :            : {
    2573                 :       2770 :   if ( auto *lInstance = instance() )
    2574                 :            :   {
    2575                 :       2770 :     return lInstance->mApplicationMembers;
    2576                 :            :   }
    2577                 :            :   else
    2578                 :            :   {
    2579                 :            : #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
    2580                 :            :     static QMutex sMemberMutex( QMutex::Recursive );
    2581                 :            : #else
    2582                 :          0 :     static QRecursiveMutex sMemberMutex;
    2583                 :            : #endif
    2584                 :          0 :     QMutexLocker lock( &sMemberMutex );
    2585                 :          0 :     if ( !sApplicationMembers )
    2586                 :          0 :       sApplicationMembers = new ApplicationMembers();
    2587                 :          0 :     return sApplicationMembers;
    2588                 :          0 :   }
    2589                 :       2770 : }

Generated by: LCOV version 1.14