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