QGIS API Documentation  2.99.0-Master (cd0ba91)
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"
25 #include "qgsproviderregistry.h"
26 #include "qgsexpression.h"
27 #include "qgsactionscoperegistry.h"
28 #include "qgsruntimeprofiler.h"
29 #include "qgstaskmanager.h"
31 #include "qgssvgcache.h"
32 #include "qgscolorschemeregistry.h"
33 #include "qgspainteffectregistry.h"
35 #include "qgsrendererregistry.h"
36 #include "qgssymbollayerregistry.h"
37 #include "qgspluginlayerregistry.h"
38 #include "qgsmessagelog.h"
39 #include "qgsannotationregistry.h"
40 #include "qgssettings.h"
41 #include "qgsunittypes.h"
42 #include "qgsuserprofile.h"
43 #include "qgsuserprofilemanager.h"
44 #include "qgsreferencedgeometry.h"
45 #include "qgs3drendererregistry.h"
46 #include "qgslayoutcontext.h"
47 #include "qgssqliteutils.h"
48 
51 
53 
54 #include <QDir>
55 #include <QFile>
56 #include <QFileInfo>
57 #include <QFileOpenEvent>
58 #include <QMessageBox>
59 #include <QPalette>
60 #include <QProcess>
61 #include <QIcon>
62 #include <QPixmap>
63 #include <QThreadPool>
64 #include <QLocale>
65 
66 #ifndef Q_OS_WIN
67 #include <netinet/in.h>
68 #include <pwd.h>
69 #else
70 #include <winsock.h>
71 #include <windows.h>
72 #include <Lmcons.h>
73 #define SECURITY_WIN32
74 #include <Security.h>
75 #pragma comment( lib, "Secur32.lib" )
76 #endif
77 
78 #include "qgsconfig.h"
79 
80 #include <gdal.h>
81 #include <ogr_api.h>
82 #include <cpl_conv.h> // for setting gdal options
83 #include <sqlite3.h>
84 
85 QObject *ABISYM( QgsApplication::mFileOpenEventReceiver );
86 QStringList ABISYM( QgsApplication::mFileOpenEventList );
87 QString ABISYM( QgsApplication::mPrefixPath );
88 QString ABISYM( QgsApplication::mPluginPath );
89 QString ABISYM( QgsApplication::mPkgDataPath );
90 QString ABISYM( QgsApplication::mLibraryPath );
91 QString ABISYM( QgsApplication::mLibexecPath );
92 QString ABISYM( QgsApplication::mThemeName );
93 QString ABISYM( QgsApplication::mUIThemeName );
94 QStringList ABISYM( QgsApplication::mDefaultSvgPaths );
95 QMap<QString, QString> ABISYM( QgsApplication::mSystemEnvVars );
96 QString ABISYM( QgsApplication::mConfigPath );
97 bool ABISYM( QgsApplication::mRunningFromBuildDir ) = false;
98 QString ABISYM( QgsApplication::mBuildSourcePath );
99 #ifdef _MSC_VER
100 QString ABISYM( QgsApplication::mCfgIntDir );
101 #endif
102 QString ABISYM( QgsApplication::mBuildOutputPath );
103 QStringList ABISYM( QgsApplication::mGdalSkipList );
104 int ABISYM( QgsApplication::mMaxThreads );
105 QString ABISYM( QgsApplication::mAuthDbDirPath );
106 
107 QString QgsApplication::sUserName;
108 QString QgsApplication::sUserFullName;
109 QString QgsApplication::sPlatformName = QStringLiteral( "desktop" );
110 
111 const char *QgsApplication::QGIS_ORGANIZATION_NAME = "QGIS";
112 const char *QgsApplication::QGIS_ORGANIZATION_DOMAIN = "qgis.org";
113 const char *QgsApplication::QGIS_APPLICATION_NAME = "QGIS3";
114 
115 QgsApplication::ApplicationMembers *QgsApplication::sApplicationMembers = nullptr;
116 
117 QgsApplication::QgsApplication( int &argc, char **argv, bool GUIenabled, const QString &profileFolder, const QString &platformName )
118  : QApplication( argc, argv, GUIenabled )
119 {
120  sPlatformName = platformName;
121 
122  mApplicationMembers = new ApplicationMembers();
123 
124  init( profileFolder ); // init can also be called directly by e.g. unit tests that don't inherit QApplication.
125 }
126 
127 void QgsApplication::init( QString profileFolder )
128 {
129  if ( profileFolder.isEmpty() )
130  {
131  if ( getenv( "QGIS_CUSTOM_CONFIG_PATH" ) )
132  {
133  QString envProfileFolder = getenv( "QGIS_CUSTOM_CONFIG_PATH" );
134  profileFolder = envProfileFolder + QDir::separator() + "profiles";
135  }
136  else
137  {
138  profileFolder = QStandardPaths::standardLocations( QStandardPaths::AppDataLocation ).value( 0 );
139  }
140  // This will normally get here for custom scripts that use QgsApplication.
141  // This doesn't get this hit for QGIS Desktop because we setup the profile via main
142  QString rootProfileFolder = QgsUserProfileManager::resolveProfilesFolder( profileFolder );
143  QgsUserProfileManager manager( rootProfileFolder );
144  QgsUserProfile *profile = manager.getProfile();
145  profileFolder = profile->folder();
146  delete profile;
147  }
148 
149  qRegisterMetaType<QgsGeometry::Error>( "QgsGeometry::Error" );
150  qRegisterMetaType<QgsProcessingFeatureSourceDefinition>( "QgsProcessingFeatureSourceDefinition" );
151  qRegisterMetaType<QgsProcessingOutputLayerDefinition>( "QgsProcessingOutputLayerDefinition" );
152  qRegisterMetaType<QgsUnitTypes::LayoutUnit>( "QgsUnitTypes::LayoutUnit" );
153  qRegisterMetaType<QgsFeatureIds>( "QgsFeatureIds" );
154  qRegisterMetaType<QgsMessageLog::MessageLevel>( "QgsMessageLog::MessageLevel" );
155  qRegisterMetaType<QgsReferencedRectangle>( "QgsReferencedRectangle" );
156  qRegisterMetaType<QgsReferencedPointXY>( "QgsReferencedPointXY" );
157  qRegisterMetaType<QgsLayoutContext::Flags>( "QgsLayoutContext::Flags" );
158 
159  QString prefixPath( getenv( "QGIS_PREFIX_PATH" ) ? getenv( "QGIS_PREFIX_PATH" ) : applicationDirPath() );
160  // QgsDebugMsg( QString( "prefixPath(): %1" ).arg( prefixPath ) );
161 
162  // check if QGIS is run from build directory (not the install directory)
163  QFile f;
164  // "/../../.." is for Mac bundled app in build directory
165  Q_FOREACH ( const QString &path, QStringList() << "" << "/.." << "/bin" << "/../../.." )
166  {
167  f.setFileName( prefixPath + path + "/qgisbuildpath.txt" );
168  if ( f.exists() )
169  break;
170  }
171  if ( f.exists() && f.open( QIODevice::ReadOnly ) )
172  {
173  ABISYM( mRunningFromBuildDir ) = true;
174  ABISYM( mBuildSourcePath ) = f.readLine().trimmed();
175  ABISYM( mBuildOutputPath ) = f.readLine().trimmed();
176  QgsDebugMsgLevel( QStringLiteral( "Running from build directory!" ), 4 );
177  QgsDebugMsgLevel( QStringLiteral( "- source directory: %1" ).arg( ABISYM( mBuildSourcePath ).toUtf8().data() ), 4 );
178  QgsDebugMsgLevel( QStringLiteral( "- output directory of the build: %1" ).arg( ABISYM( mBuildOutputPath ).toUtf8().data() ), 4 );
179 #ifdef _MSC_VER
180  ABISYM( mCfgIntDir ) = prefixPath.split( '/', QString::SkipEmptyParts ).last();
181  qDebug( "- cfg: %s", ABISYM( mCfgIntDir ).toUtf8().data() );
182 #endif
183  }
184 
185  if ( ABISYM( mRunningFromBuildDir ) )
186  {
187  // we run from source directory - not installed to destination (specified prefix)
188  ABISYM( mPrefixPath ) = QString(); // set invalid path
189 #if defined(_MSC_VER) && !defined(USING_NMAKE) && !defined(USING_NINJA)
190  setPluginPath( ABISYM( mBuildOutputPath ) + '/' + QString( QGIS_PLUGIN_SUBDIR ) + '/' + ABISYM( mCfgIntDir ) );
191 #else
192  setPluginPath( ABISYM( mBuildOutputPath ) + '/' + QStringLiteral( QGIS_PLUGIN_SUBDIR ) );
193 #endif
194  setPkgDataPath( ABISYM( mBuildSourcePath ) ); // directly source path - used for: doc, resources, svg
195  ABISYM( mLibraryPath ) = ABISYM( mBuildOutputPath ) + '/' + QGIS_LIB_SUBDIR + '/';
196 #if defined(_MSC_VER) && !defined(USING_NMAKE) && !defined(USING_NINJA)
197  ABISYM( mLibexecPath ) = ABISYM( mBuildOutputPath ) + '/' + QGIS_LIBEXEC_SUBDIR + '/' + ABISYM( mCfgIntDir ) + '/';
198 #else
199  ABISYM( mLibexecPath ) = ABISYM( mBuildOutputPath ) + '/' + QGIS_LIBEXEC_SUBDIR + '/';
200 #endif
201  }
202  else
203  {
204  char *prefixPath = getenv( "QGIS_PREFIX_PATH" );
205  if ( !prefixPath )
206  {
207 #if defined(Q_OS_MACX) || defined(Q_OS_WIN)
208  setPrefixPath( applicationDirPath(), true );
209 #elif defined(ANDROID)
210  // this is "/data/data/org.qgis.qgis" in android
211  QDir myDir( QDir::homePath() );
212  myDir.cdUp();
213  QString myPrefix = myDir.absolutePath();
214  setPrefixPath( myPrefix, true );
215 #else
216  QDir myDir( applicationDirPath() );
217  myDir.cdUp();
218  QString myPrefix = myDir.absolutePath();
219  setPrefixPath( myPrefix, true );
220 #endif
221  }
222  else
223  {
224  setPrefixPath( prefixPath, true );
225  }
226  }
227 
228  ABISYM( mConfigPath ) = profileFolder + '/'; // make sure trailing slash is included
229  ABISYM( mDefaultSvgPaths ) << qgisSettingsDirPath() + QStringLiteral( "svg/" );
230 
231  ABISYM( mAuthDbDirPath ) = qgisSettingsDirPath();
232  if ( getenv( "QGIS_AUTH_DB_DIR_PATH" ) )
233  {
234  setAuthDatabaseDirPath( getenv( "QGIS_AUTH_DB_DIR_PATH" ) );
235  }
236 
237 
238  // store system environment variables passed to application, before they are adjusted
239  QMap<QString, QString> systemEnvVarMap;
240  QString passfile( QStringLiteral( "QGIS_AUTH_PASSWORD_FILE" ) ); // QString, for comparison
241  Q_FOREACH ( const QString &varStr, QProcess::systemEnvironment() )
242  {
243  int pos = varStr.indexOf( QLatin1Char( '=' ) );
244  if ( pos == -1 )
245  continue;
246  QString varStrName = varStr.left( pos );
247  QString varStrValue = varStr.mid( pos + 1 );
248  if ( varStrName != passfile )
249  {
250  systemEnvVarMap.insert( varStrName, varStrValue );
251  }
252  }
253  ABISYM( mSystemEnvVars ) = systemEnvVarMap;
254 
255  // allow Qt to search for Qt plugins (e.g. sqldrivers) in our plugin directory
256  QCoreApplication::addLibraryPath( pluginPath() );
257 
258  // set max. thread count to -1
259  // this should be read from QgsSettings but we don't know where they are at this point
260  // so we read actual value in main.cpp
261  ABISYM( mMaxThreads ) = -1;
262 }
263 
265 {
266  delete mDataItemProviderRegistry;
267  delete mApplicationMembers;
268 }
269 
271 {
272  return qobject_cast<QgsApplication *>( QCoreApplication::instance() );
273 }
274 
276 {
277  bool done = false;
278  if ( event->type() == QEvent::FileOpen )
279  {
280  // handle FileOpen event (double clicking a file icon in Mac OS X Finder)
281  if ( ABISYM( mFileOpenEventReceiver ) )
282  {
283  // Forward event to main window.
284  done = notify( ABISYM( mFileOpenEventReceiver ), event );
285  }
286  else
287  {
288  // Store filename because receiver has not registered yet.
289  // If QGIS has been launched by double clicking a file icon, FileOpen will be
290  // the first event; the main window is not yet ready to handle the event.
291  ABISYM( mFileOpenEventList ).append( static_cast<QFileOpenEvent *>( event )->file() );
292  done = true;
293  }
294  }
295  else
296  {
297  // pass other events to base class
298  done = QApplication::event( event );
299  }
300  return done;
301 }
302 
303 bool QgsApplication::notify( QObject *receiver, QEvent *event )
304 {
305  bool done = false;
306  // Crashes in customization (especially on Mac), if we're not in the main/UI thread, see #5597
307  if ( thread() == receiver->thread() )
308  emit preNotify( receiver, event, &done );
309 
310  if ( done )
311  return true;
312 
313  // Send event to receiver and catch unhandled exceptions
314  done = true;
315  try
316  {
317  done = QApplication::notify( receiver, event );
318  }
319  catch ( QgsException &e )
320  {
321  QgsDebugMsg( "Caught unhandled QgsException: " + e.what() );
322  if ( qApp->thread() == QThread::currentThread() )
323  QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
324  }
325  catch ( std::exception &e )
326  {
327  QgsDebugMsg( "Caught unhandled std::exception: " + QString::fromLatin1( e.what() ) );
328  if ( qApp->thread() == QThread::currentThread() )
329  QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
330  }
331  catch ( ... )
332  {
333  QgsDebugMsg( "Caught unhandled unknown exception" );
334  if ( qApp->thread() == QThread::currentThread() )
335  QMessageBox::critical( activeWindow(), tr( "Exception" ), tr( "unknown exception" ) );
336  }
337 
338  return done;
339 }
340 
342 {
343  return members()->mProfiler;
344 }
345 
347 {
348  // Set receiver for FileOpen events
349  ABISYM( mFileOpenEventReceiver ) = receiver;
350  // Propagate any events collected before the receiver has registered.
351  if ( ABISYM( mFileOpenEventList ).count() > 0 )
352  {
353  QStringListIterator i( ABISYM( mFileOpenEventList ) );
354  while ( i.hasNext() )
355  {
356  QFileOpenEvent foe( i.next() );
357  QgsApplication::sendEvent( ABISYM( mFileOpenEventReceiver ), &foe );
358  }
359  ABISYM( mFileOpenEventList ).clear();
360  }
361 }
362 
363 void QgsApplication::setPrefixPath( const QString &prefixPath, bool useDefaultPaths )
364 {
365  ABISYM( mPrefixPath ) = prefixPath;
366 #if defined(_MSC_VER)
367  if ( ABISYM( mPrefixPath ).endsWith( "/bin" ) )
368  {
369  ABISYM( mPrefixPath ).chop( 4 );
370  }
371 #endif
372  if ( useDefaultPaths && !ABISYM( mRunningFromBuildDir ) )
373  {
374  setPluginPath( ABISYM( mPrefixPath ) + '/' + QStringLiteral( QGIS_PLUGIN_SUBDIR ) );
375  setPkgDataPath( ABISYM( mPrefixPath ) + '/' + QStringLiteral( QGIS_DATA_SUBDIR ) );
376  }
377  ABISYM( mLibraryPath ) = ABISYM( mPrefixPath ) + '/' + QGIS_LIB_SUBDIR + '/';
378  ABISYM( mLibexecPath ) = ABISYM( mPrefixPath ) + '/' + QGIS_LIBEXEC_SUBDIR + '/';
379 }
380 
382 {
383  ABISYM( mPluginPath ) = pluginPath;
384 }
385 
387 {
388  ABISYM( mPkgDataPath ) = pkgDataPath;
389  QString mySvgPath = pkgDataPath + ( ABISYM( mRunningFromBuildDir ) ? "/images/svg/" : "/svg/" );
390  // avoid duplicate entries
391  if ( !ABISYM( mDefaultSvgPaths ).contains( mySvgPath ) )
392  ABISYM( mDefaultSvgPaths ) << mySvgPath;
393 }
394 
395 void QgsApplication::setDefaultSvgPaths( const QStringList &pathList )
396 {
397  ABISYM( mDefaultSvgPaths ) = pathList;
398 }
399 
400 void QgsApplication::setAuthDatabaseDirPath( const QString &authDbDirPath )
401 {
402  QFileInfo fi( authDbDirPath );
403  if ( fi.exists() && fi.isDir() && fi.isWritable() )
404  {
405  ABISYM( mAuthDbDirPath ) = fi.canonicalFilePath() + QDir::separator();
406  }
407 }
408 
410 {
411  if ( ABISYM( mRunningFromBuildDir ) )
412  {
413  static bool sOnce = true;
414  if ( sOnce )
415  qWarning( "!!! prefix path was requested, but it is not valid - we do not run from installed path !!!" );
416  sOnce = false;
417  }
418 
419  return ABISYM( mPrefixPath );
420 }
422 {
423  return ABISYM( mPluginPath );
424 }
426 {
427  return ABISYM( mPkgDataPath );
428 }
430 {
431  return QStringLiteral( ":/images/themes/default/" );
432 }
434 {
435  return userThemesFolder() + QDir::separator() + themeName() + QDir::separator() + "icons/";
436 }
437 
439 {
440  return iconsPath() + QStringLiteral( "qgis-icon-60x60.png" );
441 }
442 
443 QString QgsApplication::iconPath( const QString &iconFile )
444 {
445  // try active theme
446  QString path = activeThemePath();
447  if ( QFile::exists( path + iconFile ) )
448  return path + iconFile;
449 
450  // use default theme
451  return defaultThemePath() + iconFile;
452 }
453 
454 QIcon QgsApplication::getThemeIcon( const QString &name )
455 {
456  QgsApplication *app = instance();
457  if ( app && app->mIconCache.contains( name ) )
458  return app->mIconCache.value( name );
459 
460  QIcon icon;
461 
462  QString myPreferredPath = activeThemePath() + QDir::separator() + name;
463  QString myDefaultPath = defaultThemePath() + QDir::separator() + name;
464  if ( QFile::exists( myPreferredPath ) )
465  {
466  icon = QIcon( myPreferredPath );
467  }
468  else if ( QFile::exists( myDefaultPath ) )
469  {
470  //could still return an empty icon if it
471  //doesn't exist in the default theme either!
472  icon = QIcon( myDefaultPath );
473  }
474  else
475  {
476  icon = QIcon();
477  }
478 
479  if ( app )
480  app->mIconCache.insert( name, icon );
481  return icon;
482 }
483 
484 // TODO: add some caching mechanism ?
485 QPixmap QgsApplication::getThemePixmap( const QString &name )
486 {
487  QString myPreferredPath = activeThemePath() + QDir::separator() + name;
488  QString myDefaultPath = defaultThemePath() + QDir::separator() + name;
489  if ( QFile::exists( myPreferredPath ) )
490  {
491  return QPixmap( myPreferredPath );
492  }
493  else
494  {
495  //could still return an empty icon if it
496  //doesn't exist in the default theme either!
497  return QPixmap( myDefaultPath );
498  }
499 }
500 
502 {
503  ABISYM( mThemeName ) = themeName;
504 }
505 
507 {
508  return ABISYM( mThemeName );
509 }
510 
511 void QgsApplication::setUITheme( const QString &themeName )
512 {
513  // Loop all style sheets, find matching name, load it.
514  QHash<QString, QString> themes = QgsApplication::uiThemes();
515  if ( themeName == QStringLiteral( "default" ) || !themes.contains( themeName ) )
516  {
517  setThemeName( QStringLiteral( "default" ) );
518  qApp->setStyleSheet( QString() );
519  return;
520  }
521 
522  QString path = themes.value( themeName );
523  QString stylesheetname = path + "/style.qss";
524  QString autostylesheet = stylesheetname + ".auto";
525 
526  QFile file( stylesheetname );
527  QFile variablesfile( path + "/variables.qss" );
528  QFile fileout( autostylesheet );
529 
530  QFileInfo variableInfo( variablesfile );
531 
532  if ( variableInfo.exists() && variablesfile.open( QIODevice::ReadOnly ) )
533  {
534  if ( !file.open( QIODevice::ReadOnly ) || !fileout.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
535  {
536  return;
537  }
538 
539  QString styledata = file.readAll();
540  QTextStream in( &variablesfile );
541  while ( !in.atEnd() )
542  {
543  QString line = in.readLine();
544  // This is is a variable
545  if ( line.startsWith( '@' ) )
546  {
547  int index = line.indexOf( ':' );
548  QString name = line.mid( 0, index );
549  QString value = line.mid( index + 1, line.length() );
550  styledata.replace( name, value );
551  }
552  }
553  variablesfile.close();
554  QTextStream out( &fileout );
555  out << styledata;
556  fileout.close();
557  file.close();
558  stylesheetname = autostylesheet;
559  }
560 
561  QString styleSheet = QStringLiteral( "file:///" );
562  styleSheet.append( stylesheetname );
563  qApp->setStyleSheet( styleSheet );
564  setThemeName( themeName );
565 }
566 
567 QHash<QString, QString> QgsApplication::uiThemes()
568 {
569  QStringList paths = QStringList() << userThemesFolder();
570  QHash<QString, QString> mapping;
571  mapping.insert( QStringLiteral( "default" ), QLatin1String( "" ) );
572  Q_FOREACH ( const QString &path, paths )
573  {
574  QDir folder( path );
575  QFileInfoList styleFiles = folder.entryInfoList( QDir::Dirs | QDir::NoDotAndDotDot );
576  Q_FOREACH ( const QFileInfo &info, styleFiles )
577  {
578  QFileInfo styleFile( info.absoluteFilePath() + "/style.qss" );
579  if ( !styleFile.exists() )
580  continue;
581 
582  QString name = info.baseName();
583  QString path = info.absoluteFilePath();
584  mapping.insert( name, path );
585  }
586  }
587  return mapping;
588 }
589 
591 {
592  return ABISYM( mPkgDataPath ) + QStringLiteral( "/doc/AUTHORS" );
593 }
594 
596 {
597  return ABISYM( mPkgDataPath ) + QStringLiteral( "/doc/CONTRIBUTORS" );
598 }
600 {
601  return ABISYM( mPkgDataPath ) + QStringLiteral( "/doc/developersmap.html" );
602 }
603 
605 {
606  return ABISYM( mPkgDataPath ) + QStringLiteral( "/doc/SPONSORS" );
607 }
608 
610 {
611  return ABISYM( mPkgDataPath ) + QStringLiteral( "/doc/DONORS" );
612 }
613 
615 {
616  return ABISYM( mPkgDataPath ) + QStringLiteral( "/doc/TRANSLATORS" );
617 }
618 
620 {
621  return ABISYM( mPkgDataPath ) + QStringLiteral( "/doc/LICENSE" );
622 }
623 
625 {
626  if ( ABISYM( mRunningFromBuildDir ) )
627  return ABISYM( mBuildOutputPath ) + QStringLiteral( "/i18n" );
628  else
629  return ABISYM( mPkgDataPath ) + QStringLiteral( "/i18n/" );
630 }
631 
633 {
634  return ABISYM( mPkgDataPath ) + QStringLiteral( "/resources/metadata-ISO/" );
635 }
636 
638 {
639  return ABISYM( mPkgDataPath ) + QStringLiteral( "/resources/qgis.db" );
640 }
641 
643 {
644  return ABISYM( mConfigPath );
645 }
646 
648 {
649  return qgisSettingsDirPath() + QStringLiteral( "qgis.db" );
650 }
651 
653 {
654  return ABISYM( mAuthDbDirPath ) + QStringLiteral( "qgis-auth.db" );
655 }
656 
658 {
659  return QStringLiteral( ":/images/splash/" );
660 }
661 
663 {
664  return ABISYM( mPkgDataPath ) + QStringLiteral( "/images/icons/" );
665 }
666 
668 {
669  if ( ABISYM( mRunningFromBuildDir ) )
670  {
671  QString tempCopy = QDir::tempPath() + "/srs.db";
672 
673  if ( !QFile( tempCopy ).exists() )
674  {
675  QFile f( ABISYM( mPkgDataPath ) + "/resources/srs.db" );
676  if ( !f.copy( tempCopy ) )
677  {
678  qFatal( "Could not create temporary copy" );
679  }
680  }
681 
682  return tempCopy;
683  }
684  else
685  {
686  return ABISYM( mPkgDataPath ) + QStringLiteral( "/resources/srs.db" );
687  }
688 }
689 
691 {
692  //local directories to search when looking for an SVG with a given basename
693  //defined by user in options dialog
694  QgsSettings settings;
695  QStringList pathList = settings.value( QStringLiteral( "svg/searchPathsForSVG" ) ).toStringList();
696 
697  // maintain user set order while stripping duplicates
698  QStringList paths;
699  Q_FOREACH ( const QString &path, pathList )
700  {
701  if ( !paths.contains( path ) )
702  paths.append( path );
703  }
704  Q_FOREACH ( const QString &path, ABISYM( mDefaultSvgPaths ) )
705  {
706  if ( !paths.contains( path ) )
707  paths.append( path );
708  }
709 
710  return paths;
711 }
712 
714 {
715  //local directories to search when looking for an SVG with a given basename
716  //defined by user in options dialog
717  QgsSettings settings;
718  QStringList pathList = settings.value( QStringLiteral( "composer/searchPathsForTemplates" ) ).toStringList();
719 
720  return pathList;
721 }
722 
724 {
725  return qgisSettingsDirPath() + QStringLiteral( "symbology-style.db" );
726 }
727 
729 {
730  return QRegExp( "^[A-Za-z][A-Za-z0-9\\._-]*" );
731 }
732 
734 {
735  if ( !sUserName.isEmpty() )
736  return sUserName;
737 
738 #ifdef _MSC_VER
739  TCHAR name [ UNLEN + 1 ];
740  DWORD size = UNLEN + 1;
741 
742  if ( GetUserName( ( TCHAR * )name, &size ) )
743  {
744  sUserName = QString( name );
745  }
746 
747 #else
748  QProcess process;
749 
750  process.start( QStringLiteral( "whoami" ) );
751  process.waitForFinished();
752  sUserName = process.readAllStandardOutput().trimmed();
753 #endif
754 
755  if ( !sUserName.isEmpty() )
756  return sUserName;
757 
758  //backup plan - use environment variables
759  sUserName = qgetenv( "USER" );
760  if ( !sUserName.isEmpty() )
761  return sUserName;
762 
763  //last resort
764  sUserName = qgetenv( "USERNAME" );
765  return sUserName;
766 }
767 
769 {
770  if ( !sUserFullName.isEmpty() )
771  return sUserFullName;
772 
773 #ifdef _MSC_VER
774  TCHAR name [ UNLEN + 1 ];
775  DWORD size = UNLEN + 1;
776 
777  //note - this only works for accounts connected to domain
778  if ( GetUserNameEx( NameDisplay, ( TCHAR * )name, &size ) )
779  {
780  sUserFullName = QString( name );
781  }
782 
783  //fall back to login name
784  if ( sUserFullName.isEmpty() )
785  sUserFullName = userLoginName();
786 #elif defined(Q_OS_ANDROID)
787  sUserFullName = "Not available";
788 #else
789  struct passwd *p = getpwuid( getuid() );
790 
791  if ( p )
792  {
793  QString gecosName = QString( p->pw_gecos );
794  sUserFullName = gecosName.left( gecosName.indexOf( ',', 0 ) );
795  }
796 
797 #endif
798 
799  return sUserFullName;
800 }
801 
803 {
804 #if defined(Q_OS_ANDROID)
805  return QLatin1String( "android" );
806 #elif defined(Q_OS_MAC)
807  return QLatin1String( "osx" );
808 #elif defined(Q_OS_WIN)
809  return QLatin1String( "windows" );
810 #elif defined(Q_OS_LINUX)
811  return QStringLiteral( "linux" );
812 #else
813  return QLatin1String( "unknown" );
814 #endif
815 }
816 
818 {
819  return sPlatformName;
820 }
821 
823 {
824  QgsSettings settings;
825  bool overrideLocale = settings.value( QStringLiteral( "locale/overrideFlag" ), false ).toBool();
826  if ( overrideLocale )
827  {
828  return settings.value( QStringLiteral( "locale/userLocale" ), QString() ).toString();
829  }
830  else
831  {
832  return QLocale::system().name().left( 2 );
833  }
834 }
835 
837 {
838  return qgisSettingsDirPath() + QStringLiteral( "/themes" );
839 }
840 
842 {
843  return ABISYM( mPkgDataPath ) + QStringLiteral( "/resources/symbology-style.xml" );
844 }
845 
847 {
848  return ABISYM( mPkgDataPath ) + QStringLiteral( "/resources/themes" );
849 }
850 
852 {
853  return ABISYM( mPkgDataPath ) + QStringLiteral( "/resources/server/" );
854 }
855 
857 {
858  return ABISYM( mLibraryPath );
859 }
860 
862 {
863  return ABISYM( mLibexecPath );
864 }
865 
867 {
868  return ( htonl( 1 ) == 1 ) ? XDR : NDR;
869 }
870 
872 {
873  // set the provider plugin path (this creates provider registry)
875 
876  // create data item provider registry
878 
879  // create project instance if doesn't exist
881 
882  // Initialize authentication manager and connect to database
884 
885  // Make sure we have a NAM created on the main thread.
886  // Note that this might call QgsApplication::authManager to
887  // setup the proxy configuration that's why it needs to be
888  // called after the QgsAuthManager instance has been created
890 
891 }
892 
893 
895 {
896  if ( instance() )
897  {
898  if ( !instance()->mAuthManager )
899  {
900  instance()->mAuthManager = QgsAuthManager::instance();
901  }
902  return instance()->mAuthManager;
903  }
904  else
905  {
906  // no QgsApplication instance
907  static QgsAuthManager *sAuthManager = nullptr;
908  if ( !sAuthManager )
909  sAuthManager = QgsAuthManager::instance();
910  return sAuthManager;
911  }
912 }
913 
914 
916 {
918 
919  //Ensure that all remaining deleteLater QObjects are actually deleted before we exit.
920  //This isn't strictly necessary (since we're exiting anyway) but doing so prevents a lot of
921  //LeakSanitiser noise which hides real issues
922  QgsApplication::sendPostedEvents( nullptr, QEvent::DeferredDelete );
923 
924  //delete all registered functions from expression engine (see above comment)
925  QgsExpression::cleanRegisteredFunctions();
926 
927  delete QgsProject::instance();
928 
930 
931  // tear-down GDAL/OGR
932  OGRCleanupAll();
933  GDALDestroyDriverManager();
934 }
935 
937 {
938  QString myEnvironmentVar( getenv( "QGIS_PREFIX_PATH" ) );
939  QString myState = tr( "Application state:\n"
940  "QGIS_PREFIX_PATH env var:\t\t%1\n"
941  "Prefix:\t\t%2\n"
942  "Plugin Path:\t\t%3\n"
943  "Package Data Path:\t%4\n"
944  "Active Theme Name:\t%5\n"
945  "Active Theme Path:\t%6\n"
946  "Default Theme Path:\t%7\n"
947  "SVG Search Paths:\t%8\n"
948  "User DB Path:\t%9\n"
949  "Auth DB Path:\t%10\n" )
950  .arg( myEnvironmentVar,
951  prefixPath(),
952  pluginPath(),
953  pkgDataPath(),
954  themeName(),
955  activeThemePath(),
957  svgPaths().join( tr( "\n\t\t", "match indentation of application state" ) ),
959  .arg( qgisAuthDatabaseFilePath() );
960  return myState;
961 }
962 
964 {
965  //
966  // Make the style sheet desktop preferences aware by using qappliation
967  // palette as a basis for colors where appropriate
968  //
969 // QColor myColor1 = palette().highlight().color();
970  QColor myColor1( Qt::lightGray );
971  QColor myColor2 = myColor1;
972  myColor2 = myColor2.lighter( 110 ); //10% lighter
973  QString myStyle;
974  myStyle = "p.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
975  " stop: 0 " + myColor1.name() + ","
976  " stop: 0.1 " + myColor2.name() + ","
977  " stop: 0.5 " + myColor1.name() + ","
978  " stop: 0.9 " + myColor2.name() + ","
979  " stop: 1 " + myColor1.name() + ");"
980  " color: black;"
981  " padding-left: 4px;"
982  " padding-top: 20px;"
983  " padding-bottom: 8px;"
984  " border: 1px solid #6c6c6c;"
985  "}"
986  "p.subheaderglossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
987  " stop: 0 " + myColor1.name() + ","
988  " stop: 0.1 " + myColor2.name() + ","
989  " stop: 0.5 " + myColor1.name() + ","
990  " stop: 0.9 " + myColor2.name() + ","
991  " stop: 1 " + myColor1.name() + ");"
992  " font-weight: bold;"
993  " font-size: medium;"
994  " line-height: 1.1em;"
995  " width: 100%;"
996  " color: black;"
997  " padding-left: 4px;"
998  " padding-right: 4px;"
999  " padding-top: 20px;"
1000  " padding-bottom: 8px;"
1001  " border: 1px solid #6c6c6c;"
1002  "}"
1003  "th.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
1004  " stop: 0 " + myColor1.name() + ","
1005  " stop: 0.1 " + myColor2.name() + ","
1006  " stop: 0.5 " + myColor1.name() + ","
1007  " stop: 0.9 " + myColor2.name() + ","
1008  " stop: 1 " + myColor1.name() + ");"
1009  " color: black;"
1010  " border: 1px solid #6c6c6c;"
1011  "}"
1012  ".overview{"
1013  " font: 1.82em;"
1014  " font-weight: bold;"
1015  "}"
1016  "body{"
1017  " background: white;"
1018  " color: black;"
1019  " font-family: 'Lato', 'Ubuntu', 'Lucida Grande', 'Segoe UI', 'Arial', sans-serif;"
1020  " width: 100%;"
1021  "}"
1022  "h1{ background-color: #F6F6F6;"
1023  " color: #589632; " // from http://qgis.org/en/site/getinvolved/styleguide.html
1024  " font-size: x-large; "
1025  " font-weight: normal;"
1026  " background: none;"
1027  " padding: 0.75em 0 0;"
1028  " margin: 0;"
1029  " line-height: 3em;"
1030  "}"
1031  "h2{ background-color: #F6F6F6;"
1032  " color: #589632; " // from http://qgis.org/en/site/getinvolved/styleguide.html
1033  " font-size: medium; "
1034  " font-weight: normal;"
1035  " background: none;"
1036  " padding: 0.75em 0 0;"
1037  " margin: 0;"
1038  " line-height: 1.1em;"
1039  "}"
1040  "h3{ background-color: #F6F6F6;"
1041  " color: #93b023;" // from http://qgis.org/en/site/getinvolved/styleguide.html
1042  " font-weight: bold;"
1043  " font-size: large;"
1044  " text-align: right;"
1045  " border-bottom: 5px solid #DCEB5C;"
1046  "}"
1047  "h4{ background-color: #F6F6F6;"
1048  " color: #93b023;" // from http://qgis.org/en/site/getinvolved/styleguide.html
1049  " font-weight: bold;"
1050  " font-size: medium;"
1051  " text-align: right;"
1052  "}"
1053  "h5{ background-color: #F6F6F6;"
1054  " color: #93b023;" // from http://qgis.org/en/site/getinvolved/styleguide.html
1055  " font-weight: bold;"
1056  " font-size: small;"
1057  " text-align: right;"
1058  "}"
1059  "a{ color: #729FCF;"
1060  " font-family: arial,sans-serif;"
1061  " font-size: small;"
1062  "}"
1063  "label{ background-color: #FFFFCC;"
1064  " border: 1px solid black;"
1065  " margin: 1px;"
1066  " padding: 0px 3px; "
1067  " font-size: small;"
1068  "}"
1069  ".section {"
1070  " font-weight: bold;"
1071  " padding-top:25px;"
1072  "}"
1073  ".list-view .highlight {"
1074  " text-align: right;"
1075  " border: 0px;"
1076  " width: 20%;"
1077  " padding-right: 15px;"
1078  " padding-left: 20px;"
1079  " font-weight: bold;"
1080  "}"
1081  ".tabular-view{ "
1082  " border-collapse: collapse;"
1083  " width: 95%;"
1084  "}"
1085  ".tabular-view th, .tabular-view td { "
1086  " border:10px solid black;"
1087  "}"
1088  ".tabular-view .odd-row{"
1089  " background-color: #f9f9f9;"
1090  "}"
1091  "hr {"
1092  " border: 0;"
1093  " height: 0;"
1094  " border-top: 1px solid black;"
1095  "}";
1096  return myStyle;
1097 }
1098 
1100 {
1101  if ( 0 >= OGRGetDriverCount() )
1102  {
1103  OGRRegisterAll();
1104  }
1105 }
1106 
1107 QString QgsApplication::absolutePathToRelativePath( const QString &aPath, const QString &targetPath )
1108 {
1109  QString aPathUrl = aPath;
1110  QString tPathUrl = targetPath;
1111 #if defined( Q_OS_WIN )
1112  const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
1113 
1114  aPathUrl.replace( '\\', '/' );
1115  if ( aPathUrl.startsWith( "//" ) )
1116  {
1117  // keep UNC prefix
1118  aPathUrl = "\\\\" + aPathUrl.mid( 2 );
1119  }
1120 
1121  tPathUrl.replace( '\\', '/' );
1122  if ( tPathUrl.startsWith( "//" ) )
1123  {
1124  // keep UNC prefix
1125  tPathUrl = "\\\\" + tPathUrl.mid( 2 );
1126  }
1127 #else
1128  const Qt::CaseSensitivity cs = Qt::CaseSensitive;
1129 #endif
1130 
1131  QStringList targetElems = tPathUrl.split( '/', QString::SkipEmptyParts );
1132  QStringList aPathElems = aPathUrl.split( '/', QString::SkipEmptyParts );
1133 
1134  targetElems.removeAll( QStringLiteral( "." ) );
1135  aPathElems.removeAll( QStringLiteral( "." ) );
1136 
1137  // remove common part
1138  int n = 0;
1139  while ( !aPathElems.isEmpty() &&
1140  !targetElems.isEmpty() &&
1141  aPathElems[0].compare( targetElems[0], cs ) == 0 )
1142  {
1143  aPathElems.removeFirst();
1144  targetElems.removeFirst();
1145  n++;
1146  }
1147 
1148  if ( n == 0 )
1149  {
1150  // no common parts; might not even be a file
1151  return aPathUrl;
1152  }
1153 
1154  if ( !targetElems.isEmpty() )
1155  {
1156  // go up to the common directory
1157  for ( int i = 0; i < targetElems.size(); i++ )
1158  {
1159  aPathElems.insert( 0, QStringLiteral( ".." ) );
1160  }
1161  }
1162  else
1163  {
1164  // let it start with . nevertheless,
1165  // so relative path always start with either ./ or ../
1166  aPathElems.insert( 0, QStringLiteral( "." ) );
1167  }
1168 
1169  return aPathElems.join( QStringLiteral( "/" ) );
1170 }
1171 
1172 QString QgsApplication::relativePathToAbsolutePath( const QString &rpath, const QString &targetPath )
1173 {
1174  // relative path should always start with ./ or ../
1175  if ( !rpath.startsWith( QLatin1String( "./" ) ) && !rpath.startsWith( QLatin1String( "../" ) ) )
1176  {
1177  return rpath;
1178  }
1179 
1180  QString rPathUrl = rpath;
1181  QString targetPathUrl = targetPath;
1182 
1183 #if defined(Q_OS_WIN)
1184  rPathUrl.replace( '\\', '/' );
1185  targetPathUrl.replace( '\\', '/' );
1186 
1187  bool uncPath = targetPathUrl.startsWith( "//" );
1188 #endif
1189 
1190  QStringList srcElems = rPathUrl.split( '/', QString::SkipEmptyParts );
1191  QStringList targetElems = targetPathUrl.split( '/', QString::SkipEmptyParts );
1192 
1193 #if defined(Q_OS_WIN)
1194  if ( uncPath )
1195  {
1196  targetElems.insert( 0, "" );
1197  targetElems.insert( 0, "" );
1198  }
1199 #endif
1200 
1201  // append source path elements
1202  targetElems << srcElems;
1203  targetElems.removeAll( QStringLiteral( "." ) );
1204 
1205  // resolve ..
1206  int pos;
1207  while ( ( pos = targetElems.indexOf( QStringLiteral( ".." ) ) ) > 0 )
1208  {
1209  // remove preceding element and ..
1210  targetElems.removeAt( pos - 1 );
1211  targetElems.removeAt( pos - 1 );
1212  }
1213 
1214 #if !defined(Q_OS_WIN)
1215  // make path absolute
1216  targetElems.prepend( QLatin1String( "" ) );
1217 #endif
1218 
1219  return targetElems.join( QStringLiteral( "/" ) );
1220 }
1221 
1222 void QgsApplication::skipGdalDriver( const QString &driver )
1223 {
1224  if ( ABISYM( mGdalSkipList ).contains( driver ) || driver.isEmpty() )
1225  {
1226  return;
1227  }
1228  ABISYM( mGdalSkipList ) << driver;
1230 }
1231 
1232 void QgsApplication::restoreGdalDriver( const QString &driver )
1233 {
1234  if ( !ABISYM( mGdalSkipList ).contains( driver ) )
1235  {
1236  return;
1237  }
1238  int myPos = ABISYM( mGdalSkipList ).indexOf( driver );
1239  if ( myPos >= 0 )
1240  {
1241  ABISYM( mGdalSkipList ).removeAt( myPos );
1242  }
1244 }
1245 
1247 {
1248  ABISYM( mGdalSkipList ).removeDuplicates();
1249  QString myDriverList = ABISYM( mGdalSkipList ).join( QStringLiteral( " " ) );
1250  QgsDebugMsg( "Gdal Skipped driver list set to:" );
1251  QgsDebugMsg( myDriverList );
1252  CPLSetConfigOption( "GDAL_SKIP", myDriverList.toUtf8() );
1253  GDALAllRegister(); //to update driver list and skip missing ones
1254 }
1255 
1257 {
1258  QString folder = userThemesFolder();
1259  QDir myDir( folder );
1260  if ( !myDir.exists() )
1261  {
1262  myDir.mkpath( folder );
1263  }
1264 
1265  copyPath( defaultThemesFolder(), userThemesFolder() );
1266  return true;
1267 }
1268 
1269 void QgsApplication::copyPath( const QString &src, const QString &dst )
1270 {
1271  QDir dir( src );
1272  if ( ! dir.exists() )
1273  return;
1274 
1275  Q_FOREACH ( const QString &d, dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot ) )
1276  {
1277  QString dst_path = dst + QDir::separator() + d;
1278  dir.mkpath( dst_path );
1279  copyPath( src + QDir::separator() + d, dst_path );
1280  }
1281 
1282  Q_FOREACH ( const QString &f, dir.entryList( QDir::Files ) )
1283  {
1284  QFile::copy( src + QDir::separator() + f, dst + QDir::separator() + f );
1285  }
1286 }
1287 
1289 {
1290  //read values from QgsSettings
1291  QgsSettings settings;
1292 
1293  QVariantMap variables;
1294 
1295  //check if settings contains any variables
1296  if ( settings.contains( QStringLiteral( "/variables/values" ) ) )
1297  {
1298  QList< QVariant > customVariableVariants = settings.value( QStringLiteral( "variables/values" ) ).toList();
1299  QList< QVariant > customVariableNames = settings.value( QStringLiteral( "variables/names" ) ).toList();
1300  int variableIndex = 0;
1301  for ( QList< QVariant >::const_iterator it = customVariableVariants.constBegin();
1302  it != customVariableVariants.constEnd(); ++it )
1303  {
1304  if ( variableIndex >= customVariableNames.length() )
1305  {
1306  break;
1307  }
1308 
1309  QVariant value = ( *it );
1310  QString name = customVariableNames.at( variableIndex ).toString();
1311 
1312  variables.insert( name, value );
1313  variableIndex++;
1314  }
1315  }
1316 
1317  return variables;
1318 }
1319 
1320 void QgsApplication::setCustomVariables( const QVariantMap &variables )
1321 {
1322  QgsSettings settings;
1323 
1324  QList< QVariant > customVariableValues;
1325  QList< QVariant > customVariableNames;
1326 
1327  QVariantMap::const_iterator it = variables.constBegin();
1328  for ( ; it != variables.constEnd(); ++it )
1329  {
1330  customVariableNames << it.key();
1331  customVariableValues << it.value();
1332  }
1333 
1334  settings.setValue( QStringLiteral( "variables/names" ), customVariableNames );
1335  settings.setValue( QStringLiteral( "variables/values" ), customVariableValues );
1336 
1337  emit instance()->customVariablesChanged();
1338 }
1339 
1340 void QgsApplication::setCustomVariable( const QString &name, const QVariant &value )
1341 {
1342  // save variable to settings
1343  QgsSettings settings;
1344 
1345  QList< QVariant > customVariableVariants = settings.value( QStringLiteral( "variables/values" ) ).toList();
1346  QList< QVariant > customVariableNames = settings.value( QStringLiteral( "variables/names" ) ).toList();
1347 
1348  customVariableVariants << value;
1349  customVariableNames << name;
1350 
1351  settings.setValue( QStringLiteral( "variables/names" ), customVariableNames );
1352  settings.setValue( QStringLiteral( "variables/values" ), customVariableVariants );
1353 
1354  emit instance()->customVariablesChanged();
1355 }
1356 
1357 
1359 {
1360  ApplicationMembers *appMembers = members();
1361  if ( appMembers->mNullRepresentation.isNull() )
1362  {
1363  appMembers->mNullRepresentation = QgsSettings().value( QStringLiteral( "qgis/nullValue" ), QStringLiteral( "NULL" ) ).toString();
1364  }
1365  return appMembers->mNullRepresentation;
1366 }
1367 
1369 {
1370  ApplicationMembers *appMembers = members();
1371  if ( !appMembers || appMembers->mNullRepresentation == nullRepresentation )
1372  return;
1373 
1374  appMembers->mNullRepresentation = nullRepresentation;
1375  QgsSettings().setValue( QStringLiteral( "qgis/nullValue" ), nullRepresentation );
1376 
1377  QgsApplication *app = instance();
1378  if ( app )
1379  emit app->nullRepresentationChanged();
1380 }
1381 
1383 {
1384  return members()->mActionScopeRegistry;
1385 }
1386 
1387 bool QgsApplication::createDatabase( QString *errorMessage )
1388 {
1389  // set a working directory up for gdal to write .aux.xml files into
1390  // for cases where the raster dir is read only to the user
1391  // if the env var is already set it will be used preferentially
1392  QString myPamPath = qgisSettingsDirPath() + QStringLiteral( "gdal_pam/" );
1393  QDir myDir( myPamPath );
1394  if ( !myDir.exists() )
1395  {
1396  myDir.mkpath( myPamPath ); //fail silently
1397  }
1398 
1399 #if defined(Q_OS_WIN)
1400  CPLSetConfigOption( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8() );
1401 #else
1402  //under other OS's we use an environment var so the user can
1403  //override the path if he likes
1404  int myChangeFlag = 0; //whether we want to force the env var to change
1405  setenv( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8(), myChangeFlag );
1406 #endif
1407 
1408  // Check qgis.db and make private copy if necessary
1409  QFile qgisPrivateDbFile( QgsApplication::qgisUserDatabaseFilePath() );
1410 
1411  // first we look for ~/.qgis/qgis.db
1412  if ( !qgisPrivateDbFile.exists() )
1413  {
1414  // if it doesn't exist we copy it in from the global resources dir
1415  QString qgisMasterDbFileName = QgsApplication::qgisMasterDatabaseFilePath();
1416  QFile masterFile( qgisMasterDbFileName );
1417 
1418  // Must be sure there is destination directory ~/.qgis
1419  QDir().mkpath( QgsApplication::qgisSettingsDirPath() );
1420 
1421  //now copy the master file into the users .qgis dir
1422  bool isDbFileCopied = masterFile.copy( qgisPrivateDbFile.fileName() );
1423 
1424  if ( !isDbFileCopied )
1425  {
1426  if ( errorMessage )
1427  {
1428  *errorMessage = tr( "[ERROR] Can not make qgis.db private copy" );
1429  }
1430  return false;
1431  }
1432  }
1433  else
1434  {
1435  // migrate if necessary
1436  sqlite3_database_unique_ptr database;
1437  if ( database.open( QgsApplication::qgisUserDatabaseFilePath() ) != SQLITE_OK )
1438  {
1439  if ( errorMessage )
1440  {
1441  *errorMessage = tr( "Could not open qgis.db" );
1442  }
1443  return false;
1444  }
1445 
1446  char *errmsg = nullptr;
1447  int res = sqlite3_exec( database.get(), "SELECT epsg FROM tbl_srs LIMIT 0", nullptr, nullptr, &errmsg );
1448  if ( res == SQLITE_OK )
1449  {
1450  // epsg column exists => need migration
1451  if ( sqlite3_exec( database.get(),
1452  "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
1453  "CREATE TABLE tbl_srs ("
1454  "srs_id INTEGER PRIMARY KEY,"
1455  "description text NOT NULL,"
1456  "projection_acronym text NOT NULL,"
1457  "ellipsoid_acronym NOT NULL,"
1458  "parameters text NOT NULL,"
1459  "srid integer,"
1460  "auth_name varchar,"
1461  "auth_id varchar,"
1462  "is_geo integer NOT NULL,"
1463  "deprecated boolean);"
1464  "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
1465  "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;"
1466  "DROP TABLE tbl_srs_bak", nullptr, nullptr, &errmsg ) != SQLITE_OK
1467  )
1468  {
1469  if ( errorMessage )
1470  {
1471  *errorMessage = tr( "Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1472  }
1473  sqlite3_free( errmsg );
1474  return false;
1475  }
1476  }
1477  else
1478  {
1479  sqlite3_free( errmsg );
1480  }
1481 
1482  if ( sqlite3_exec( database.get(), "DROP VIEW vw_srs", nullptr, nullptr, &errmsg ) != SQLITE_OK )
1483  {
1484  QgsDebugMsg( QString( "vw_srs didn't exists in private qgis.db: %1" ).arg( errmsg ) );
1485  }
1486 
1487  if ( sqlite3_exec( database.get(),
1488  "CREATE VIEW vw_srs AS"
1489  " SELECT"
1490  " a.description AS description"
1491  ",a.srs_id AS srs_id"
1492  ",a.is_geo AS is_geo"
1493  ",coalesce(b.name,a.projection_acronym) AS name"
1494  ",a.parameters AS parameters"
1495  ",a.auth_name AS auth_name"
1496  ",a.auth_id AS auth_id"
1497  ",a.deprecated AS deprecated"
1498  " FROM tbl_srs a"
1499  " LEFT OUTER JOIN tbl_projection b ON a.projection_acronym=b.acronym"
1500  " ORDER BY coalesce(b.name,a.projection_acronym),a.description", nullptr, nullptr, &errmsg ) != SQLITE_OK
1501  )
1502  {
1503  if ( errorMessage )
1504  {
1505  *errorMessage = tr( "Update of view in private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1506  }
1507  sqlite3_free( errmsg );
1508  return false;
1509  }
1510  }
1511  return true;
1512 }
1513 
1515 {
1516  QgsDebugMsg( QString( "maxThreads: %1" ).arg( maxThreads ) );
1517 
1518  // make sure value is between 1 and #cores, if not set to -1 (use #cores)
1519  // 0 could be used to disable any parallel processing
1520  if ( maxThreads < 1 || maxThreads > QThread::idealThreadCount() )
1521  maxThreads = -1;
1522 
1523  // save value
1524  ABISYM( mMaxThreads ) = maxThreads;
1525 
1526  // if -1 use #cores
1527  if ( maxThreads == -1 )
1528  maxThreads = QThread::idealThreadCount();
1529 
1530  // set max thread count in QThreadPool
1531  QThreadPool::globalInstance()->setMaxThreadCount( maxThreads );
1532  QgsDebugMsg( QString( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
1533 }
1534 
1536 {
1537  return members()->mTaskManager;
1538 }
1539 
1541 {
1542  return members()->mColorSchemeRegistry;
1543 }
1544 
1546 {
1547  return members()->mPaintEffectRegistry;
1548 }
1549 
1551 {
1552  return members()->mRendererRegistry;
1553 }
1554 
1556 {
1557  return members()->mRasterRendererRegistry;
1558 }
1559 
1561 {
1562  if ( instance() )
1563  {
1564  if ( !instance()->mDataItemProviderRegistry )
1565  {
1566  instance()->mDataItemProviderRegistry = new QgsDataItemProviderRegistry();
1567  }
1568  return instance()->mDataItemProviderRegistry;
1569  }
1570  else
1571  {
1572  // no QgsApplication instance
1573  static QgsDataItemProviderRegistry *sDataItemProviderRegistry = nullptr;
1574  if ( !sDataItemProviderRegistry )
1575  sDataItemProviderRegistry = new QgsDataItemProviderRegistry();
1576  return sDataItemProviderRegistry;
1577  }
1578 }
1579 
1581 {
1582  return members()->mSvgCache;
1583 }
1584 
1586 {
1587  return members()->mSymbolLayerRegistry;
1588 }
1589 
1591 {
1592  return members()->mLayoutItemRegistry;
1593 }
1594 
1596 {
1597  return members()->mGpsConnectionRegistry;
1598 }
1599 
1601 {
1602  return members()->mPluginLayerRegistry;
1603 }
1604 
1606 {
1607  return members()->mMessageLog;
1608 }
1609 
1611 {
1612  return members()->mProcessingRegistry;
1613 }
1614 
1616 {
1617  return members()->mPageSizeRegistry;
1618 }
1619 
1620 QgsAnnotationRegistry *QgsApplication::annotationRegistry()
1621 {
1622  return members()->mAnnotationRegistry;
1623 }
1624 
1626 {
1627  return members()->mFieldFormatterRegistry;
1628 }
1629 
1631 {
1632  return members()->m3DRendererRegistry;
1633 }
1634 
1635 QgsApplication::ApplicationMembers::ApplicationMembers()
1636 {
1637  // don't use initializer lists or scoped pointers - as more objects are added here we
1638  // will need to be careful with the order of creation/destruction
1639  mMessageLog = new QgsMessageLog();
1640  mProfiler = new QgsRuntimeProfiler();
1641  mTaskManager = new QgsTaskManager();
1642  mActionScopeRegistry = new QgsActionScopeRegistry();
1643  mFieldFormatterRegistry = new QgsFieldFormatterRegistry();
1644  mSvgCache = new QgsSvgCache();
1645  mColorSchemeRegistry = new QgsColorSchemeRegistry();
1646  mColorSchemeRegistry->addDefaultSchemes();
1647  mPaintEffectRegistry = new QgsPaintEffectRegistry();
1648  mSymbolLayerRegistry = new QgsSymbolLayerRegistry();
1649  mRendererRegistry = new QgsRendererRegistry();
1650  mRasterRendererRegistry = new QgsRasterRendererRegistry();
1651  mGpsConnectionRegistry = new QgsGPSConnectionRegistry();
1652  mPluginLayerRegistry = new QgsPluginLayerRegistry();
1653  mProcessingRegistry = new QgsProcessingRegistry();
1654  mPageSizeRegistry = new QgsPageSizeRegistry();
1655  mLayoutItemRegistry = new QgsLayoutItemRegistry();
1656  mLayoutItemRegistry->populate();
1657  mAnnotationRegistry = new QgsAnnotationRegistry();
1658  m3DRendererRegistry = new Qgs3DRendererRegistry();
1659 }
1660 
1661 QgsApplication::ApplicationMembers::~ApplicationMembers()
1662 {
1663  delete mActionScopeRegistry;
1664  delete m3DRendererRegistry;
1665  delete mAnnotationRegistry;
1666  delete mColorSchemeRegistry;
1667  delete mFieldFormatterRegistry;
1668  delete mGpsConnectionRegistry;
1669  delete mMessageLog;
1670  delete mPaintEffectRegistry;
1671  delete mPluginLayerRegistry;
1672  delete mProcessingRegistry;
1673  delete mPageSizeRegistry;
1674  delete mLayoutItemRegistry;
1675  delete mProfiler;
1676  delete mRasterRendererRegistry;
1677  delete mRendererRegistry;
1678  delete mSvgCache;
1679  delete mSymbolLayerRegistry;
1680  delete mTaskManager;
1681 }
1682 
1683 QgsApplication::ApplicationMembers *QgsApplication::members()
1684 {
1685  if ( instance() )
1686  {
1687  return instance()->mApplicationMembers;
1688  }
1689  else
1690  {
1691  static QMutex sMemberMutex( QMutex::Recursive );
1692  QMutexLocker lock( &sMemberMutex );
1693  if ( !sApplicationMembers )
1694  sApplicationMembers = new ApplicationMembers();
1695  return sApplicationMembers;
1696  }
1697 }
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.
static Qgs3DRendererRegistry * renderer3DRegistry()
Returns registry of available 3D renderers.
static QString resolveProfilesFolder(const QString &basePath=QString())
Resolves the profiles folder for the given path.
static QgsAnnotationRegistry * annotationRegistry()
Returns the application&#39;s annotation registry, used for managing annotation types.
Extends QApplication to provide access to QGIS specific resources such as theme paths, database paths etc.
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Get the registry of available field formatters.
static QString userStylePath()
Returns the path to user&#39;s style.
Registry of color schemes.
static QgsAuthManager * instance()
Enforce singleton pattern.
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
static QString authorsFilePath()
Returns the path to the authors file.
static void setPrefixPath(const QString &prefixPath, bool useDefaultPaths=false)
Alters prefix path - used by 3rd party apps.
A registry of plugin layers types.
static QString qgisSettingsDirPath()
Returns the path to the settings directory in user&#39;s home dir.
static void setCustomVariables(const QVariantMap &customVariables)
Custom expression variables for this application.
static QString libraryPath()
Returns the path containing qgis_core, qgis_gui, qgispython (and other) libraries.
static QgsRuntimeProfiler * profiler()
Returns the application runtime profiler.
static QString defaultThemePath()
Returns the path to the default theme directory.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:55
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.
virtual bool event(QEvent *event) override
Watch for QFileOpenEvent.
bool contains(const QString &key, const QgsSettings::Section section=QgsSettings::NoSection) const
Returns true if there exists a setting called key; returns false otherwise.
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:37
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).
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:128
Registry of renderers.
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.
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.
static void setFileOpenEventReceiver(QObject *receiver)
Set the FileOpen event receiver.
static QString reportStyleSheet()
get a standard css style sheet for reports.
static int maxThreads()
Get maximum concurrent thread count.
static endian_t endian()
Returns whether this machine uses big or little endian.
static QPixmap getThemePixmap(const QString &name)
Helper to get a theme icon as a pixmap.
static QString userFullName()
Returns the user&#39;s operating system login account full display name.
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application&#39;s paint effect registry, used for managing paint effects. ...
static QString developersMapFilePath()
Returns the path to the developers map file.
static QString absolutePathToRelativePath(const QString &apath, const QString &targetPath)
Converts absolute path to path relative to target.
QString what() const
Definition: qgsexception.h:48
static QString defaultStylePath()
Returns the path to default style (works as a starting point).
static QgsTaskManager * taskManager()
Returns the application&#39;s task manager, used for managing application wide background task handling...
static QgsMessageLog * messageLog()
Returns the application&#39;s message log.
static void applyGdalSkippedDrivers()
Apply the skipped drivers list to gdal.
void setValue(const QString &key, const QVariant &value, const QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
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:38
Registry of available symbol layer classes.
static bool createThemeFolder()
Create the users theme folder.
static bool createDatabase(QString *errorMessage=nullptr)
initialize qgis.db
virtual ~QgsApplication()
static QString i18nPath()
Returns the path to the translation directory.
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.
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.
Task manager for managing a set of long-running QgsTask tasks.
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
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...
static QgsAuthManager * authManager()
Returns the application&#39;s authentication manager instance.
static QRegExp shortNameRegExp()
Returns the short name regular expression for line edit validator.
A class to register / unregister existing GPS connections such that the information is available to a...
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()
get application icon
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application&#39;s color scheme registry, used for managing color schemes. ...
static const char * QGIS_ORGANIZATION_DOMAIN
virtual 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.
static QgsNetworkAccessManager * instance()
returns a pointer to the single instance
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.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
QgsUserProfile * getProfile(const QString &defaultProfile="default", bool createNew=true, bool initSettings=true)
Return the profile from the given root profile location.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:383
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
static QStringList svgPaths()
Returns the paths to svg directories.
static QString sponsorsFilePath()
Returns the path to the sponsors file.
static QStringList composerTemplatePaths()
Returns the paths to composer template directories.
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
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:37
static void setMaxThreads(int maxThreads)
Set maximum concurrent thread count.
static QgsGPSConnectionRegistry * gpsConnectionRegistry()
Returns the application&#39;s GPS connection registry, used for managing GPS connections.
static void setUITheme(const QString &themeName)
Set the current UI theme used to style the interface.
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.