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