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