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