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