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