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