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