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