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