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