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