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