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