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