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