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