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