QGIS API Documentation 3.27.0-Master (1d7a28cfd2)
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"
20#include "qgsexception.h"
21#include "qgsgeometry.h"
24#include "qgslayout.h"
26#include "qgslogger.h"
27#include "qgsproject.h"
30#include "qgsnetworkreply.h"
31#include "qgsproviderregistry.h"
32#include "qgsexpression.h"
34#include "qgsruntimeprofiler.h"
35#include "qgstaskmanager.h"
39#include "qgssvgcache.h"
40#include "qgsimagecache.h"
41#include "qgssourcecache.h"
47#include "qgsrendererregistry.h"
51#include "qgssymbollayerutils.h"
52#include "qgscalloutsregistry.h"
55#include "qgsmessagelog.h"
57#include "qgssettings.h"
60#include "qgsunittypes.h"
61#include "qgsuserprofile.h"
65#include "qgs3dsymbolregistry.h"
67#include "qgssqliteutils.h"
68#include "qgsstyle.h"
69#include "qgsprojutils.h"
71#include "qgsnewsfeedparser.h"
72#include "qgsbookmarkmanager.h"
73#include "qgsstylemodel.h"
76#include "qgsmeshlayer.h"
77#include "qgsfeaturestore.h"
78#include "qgslocator.h"
79#include "qgsreadwritelocker.h"
81#include "qgsdbquerylog.h"
82#include "qgsfontmanager.h"
84#include "qgscolorrampimpl.h"
85#include "qgsinterval.h"
86
91
95
96#include <QDir>
97#include <QFile>
98#include <QFileInfo>
99#include <QFileOpenEvent>
100#include <QMessageBox>
101#include <QPalette>
102#include <QProcess>
103#include <QProcessEnvironment>
104#include <QIcon>
105#include <QPixmap>
106#include <QThreadPool>
107#include <QLocale>
108#include <QStyle>
109#include <QLibraryInfo>
110#include <QStandardPaths>
111#include <QRegularExpression>
112#include <QTextStream>
113#include <QScreen>
114#include <QAuthenticator>
115#include <QRecursiveMutex>
116
117#ifndef Q_OS_WIN
118#include <netinet/in.h>
119#include <pwd.h>
120#else
121#include <winsock.h>
122#include <windows.h>
123#include <lmcons.h>
124#define SECURITY_WIN32
125#include <security.h>
126#ifdef _MSC_VER
127#pragma comment( lib, "Secur32.lib" )
128#endif
129#endif
130
131#include "qgsconfig.h"
132
133#include <gdal.h>
134#include <ogr_api.h>
135#include <cpl_conv.h> // for setting gdal options
136#include <sqlite3.h>
137#include <mutex>
138
139#include <proj.h>
140
141#if defined(Q_OS_LINUX)
142#include <sys/sysinfo.h>
143#endif
144
145#define CONN_POOL_MAX_CONCURRENT_CONNS 4
146
147QObject *ABISYM( QgsApplication::mFileOpenEventReceiver ) = nullptr;
148bool ABISYM( QgsApplication::mInitialized ) = false;
149bool ABISYM( QgsApplication::mRunningFromBuildDir ) = false;
150const char *QgsApplication::QGIS_ORGANIZATION_NAME = "QGIS";
151const char *QgsApplication::QGIS_ORGANIZATION_DOMAIN = "qgis.org";
152const char *QgsApplication::QGIS_APPLICATION_NAME = "QGIS3";
153QgsApplication::ApplicationMembers *QgsApplication::sApplicationMembers = nullptr;
154QgsAuthManager *QgsApplication::sAuthManager = nullptr;
155int ABISYM( QgsApplication::sMaxThreads ) = -1;
156
157Q_GLOBAL_STATIC( QStringList, sFileOpenEventList )
158Q_GLOBAL_STATIC( QString, sPrefixPath )
159Q_GLOBAL_STATIC( QString, sPluginPath )
160Q_GLOBAL_STATIC( QString, sPkgDataPath )
161Q_GLOBAL_STATIC( QString, sLibraryPath )
162Q_GLOBAL_STATIC( QString, sLibexecPath )
163Q_GLOBAL_STATIC( QString, sQmlImportPath )
164Q_GLOBAL_STATIC( QString, sThemeName )
165Q_GLOBAL_STATIC( QString, sProfilePath )
166
167Q_GLOBAL_STATIC( QStringList, sDefaultSvgPaths )
168Q_GLOBAL_STATIC( QgsStringMap, sSystemEnvVars )
169Q_GLOBAL_STATIC( QString, sConfigPath )
170
171Q_GLOBAL_STATIC( QString, sBuildSourcePath )
172#if defined(_MSC_VER) && !defined(USING_NMAKE) && !defined(USING_NINJA)
173Q_GLOBAL_STATIC( QString, sCfgIntDir )
174#endif
175Q_GLOBAL_STATIC( QString, sBuildOutputPath )
176Q_GLOBAL_STATIC( QStringList, sGdalSkipList )
177Q_GLOBAL_STATIC( QStringList, sDeferredSkippedGdalDrivers )
178Q_GLOBAL_STATIC( QString, sAuthDbDirPath )
179
180Q_GLOBAL_STATIC( QString, sUserName )
181Q_GLOBAL_STATIC( QString, sUserFullName )
182Q_GLOBAL_STATIC_WITH_ARGS( QString, sPlatformName, ( "external" ) )
183Q_GLOBAL_STATIC( QString, sTranslation )
184
185Q_GLOBAL_STATIC( QTemporaryDir, sIconCacheDir )
186
187QgsApplication::QgsApplication( int &argc, char **argv, bool GUIenabled, const QString &profileFolder, const QString &platformName )
188 : QApplication( argc, argv, GUIenabled )
189{
190 *sPlatformName() = platformName;
191
192 if ( *sTranslation() != QLatin1String( "C" ) )
193 {
194 mQgisTranslator = new QTranslator();
195 if ( mQgisTranslator->load( QStringLiteral( "qgis_" ) + *sTranslation(), i18nPath() ) )
196 {
197 installTranslator( mQgisTranslator );
198 }
199 else
200 {
201 QgsDebugMsgLevel( QStringLiteral( "loading of qgis translation failed %1/qgis_%2" ).arg( i18nPath(), *sTranslation() ), 2 );
202 }
203
204 /* Translation file for Qt.
205 * The strings from the QMenuBar context section are used by Qt/Mac to shift
206 * the About, Preferences and Quit items to the Mac Application menu.
207 * These items must be translated identically in both qt_ and qgis_ files.
208 */
209 QString qtTranslationsPath = QLibraryInfo::location( QLibraryInfo::TranslationsPath );
210#ifdef __MINGW32__
211 QString prefix = QDir( QString( "%1/../" ).arg( QApplication::applicationDirPath() ) ).absolutePath();
212 qtTranslationsPath = prefix + qtTranslationsPath.mid( QLibraryInfo::location( QLibraryInfo::PrefixPath ).length() );
213#endif
214
215 mQtTranslator = new QTranslator();
216 if ( mQtTranslator->load( QStringLiteral( "qt_" ) + *sTranslation(), qtTranslationsPath ) )
217 {
218 installTranslator( mQtTranslator );
219 }
220 else
221 {
222 QgsDebugMsgLevel( QStringLiteral( "loading of qt translation failed %1/qt_%2" ).arg( qtTranslationsPath, *sTranslation() ), 2 );
223 }
224
225 mQtBaseTranslator = new QTranslator();
226 if ( mQtBaseTranslator->load( QStringLiteral( "qtbase_" ) + *sTranslation(), qtTranslationsPath ) )
227 {
228 installTranslator( mQtBaseTranslator );
229 }
230 else
231 {
232 QgsDebugMsgLevel( QStringLiteral( "loading of qtbase translation failed %1/qt_%2" ).arg( qtTranslationsPath, *sTranslation() ), 2 );
233 }
234 }
235
236 mApplicationMembers = new ApplicationMembers();
237
238 *sProfilePath() = profileFolder;
239
241}
242
243void QgsApplication::init( QString profileFolder )
244{
245 if ( profileFolder.isEmpty() )
246 {
247 if ( getenv( "QGIS_CUSTOM_CONFIG_PATH" ) )
248 {
249 profileFolder = getenv( "QGIS_CUSTOM_CONFIG_PATH" );
250 }
251 else
252 {
253 profileFolder = QStandardPaths::standardLocations( QStandardPaths::AppDataLocation ).value( 0 );
254 }
255 // This will normally get here for custom scripts that use QgsApplication.
256 // This doesn't get this hit for QGIS Desktop because we setup the profile via main
257 QString rootProfileFolder = QgsUserProfileManager::resolveProfilesFolder( profileFolder );
258 QgsUserProfileManager manager( rootProfileFolder );
259 QgsUserProfile *profile = manager.getProfile();
260 profileFolder = profile->folder();
261 delete profile;
262 }
263
264 *sProfilePath() = profileFolder;
265
266 static std::once_flag sMetaTypesRegistered;
267 std::call_once( sMetaTypesRegistered, []
268 {
269 qRegisterMetaType<QgsGeometry::Error>( "QgsGeometry::Error" );
270 qRegisterMetaType<QgsDatabaseQueryLogEntry>( "QgsDatabaseQueryLogEntry" );
271 qRegisterMetaType<QgsProcessingFeatureSourceDefinition>( "QgsProcessingFeatureSourceDefinition" );
272 qRegisterMetaType<QgsProcessingOutputLayerDefinition>( "QgsProcessingOutputLayerDefinition" );
273 qRegisterMetaType<QgsUnitTypes::LayoutUnit>( "QgsUnitTypes::LayoutUnit" );
274 qRegisterMetaType<QgsUnsetAttributeValue>( "QgsUnsetAttributeValue" );
275 qRegisterMetaType<QgsFeatureId>( "QgsFeatureId" );
276 qRegisterMetaType<QgsFields>( "QgsFields" );
277 qRegisterMetaType<QgsFeatureIds>( "QgsFeatureIds" );
278 qRegisterMetaType<QgsProperty>( "QgsProperty" );
279 qRegisterMetaType<QgsFeatureStoreList>( "QgsFeatureStoreList" );
280 qRegisterMetaType<Qgis::MessageLevel>( "Qgis::MessageLevel" );
281 qRegisterMetaType<Qgis::BrowserItemState>( "Qgis::BrowserItemState" );
282 qRegisterMetaType<QgsReferencedRectangle>( "QgsReferencedRectangle" );
283 qRegisterMetaType<QgsReferencedPointXY>( "QgsReferencedPointXY" );
284 qRegisterMetaType<QgsReferencedGeometry>( "QgsReferencedGeometry" );
285 qRegisterMetaType<QgsLayoutRenderContext::Flags>( "QgsLayoutRenderContext::Flags" );
286 qRegisterMetaType<QgsStyle::StyleEntity>( "QgsStyle::StyleEntity" );
287 qRegisterMetaType<QgsCoordinateReferenceSystem>( "QgsCoordinateReferenceSystem" );
288 qRegisterMetaType<QgsAuthManager::MessageLevel>( "QgsAuthManager::MessageLevel" );
289 qRegisterMetaType<QgsNetworkRequestParameters>( "QgsNetworkRequestParameters" );
290 qRegisterMetaType<QgsNetworkReplyContent>( "QgsNetworkReplyContent" );
291 qRegisterMetaType<QgsFeature>( "QgsFeature" );
292 qRegisterMetaType<QgsGeometry>( "QgsGeometry" );
293 qRegisterMetaType<QgsInterval>( "QgsInterval" );
294 qRegisterMetaType<QgsRectangle>( "QgsRectangle" );
295 qRegisterMetaType<QgsPointXY>( "QgsPointXY" );
296 qRegisterMetaType<QgsDatumTransform::GridDetails>( "QgsDatumTransform::GridDetails" );
297 qRegisterMetaType<QgsDatumTransform::TransformDetails>( "QgsDatumTransform::TransformDetails" );
298 qRegisterMetaType<QgsNewsFeedParser::Entry>( "QgsNewsFeedParser::Entry" );
299 qRegisterMetaType<QgsRectangle>( "QgsRectangle" );
300 qRegisterMetaType<QgsLocatorResult>( "QgsLocatorResult" );
301 qRegisterMetaType<QgsGradientColorRamp>( "QgsGradientColorRamp" );
302 qRegisterMetaType<QgsProcessingModelChildParameterSource>( "QgsProcessingModelChildParameterSource" );
303#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
304 // Qt6 documentation says these are not needed anymore (https://www.qt.io/blog/whats-new-in-qmetatype-qvariant) #spellok
305 // TODO: when tests can run against Qt6 builds, check for any regressions
306 qRegisterMetaTypeStreamOperators<QgsProcessingModelChildParameterSource>( "QgsProcessingModelChildParameterSource" );
307#endif
308 qRegisterMetaType<QgsRemappingSinkDefinition>( "QgsRemappingSinkDefinition" );
309 qRegisterMetaType<QgsProcessingModelChildDependency>( "QgsProcessingModelChildDependency" );
310 qRegisterMetaType<QgsTextFormat>( "QgsTextFormat" );
311#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
312 QMetaType::registerComparators<QgsProcessingModelChildDependency>();
313 QMetaType::registerEqualsComparator<QgsProcessingFeatureSourceDefinition>();
314 QMetaType::registerEqualsComparator<QgsProperty>();
315 QMetaType::registerEqualsComparator<QgsDateTimeRange>();
316 QMetaType::registerEqualsComparator<QgsDateRange>();
317 QMetaType::registerEqualsComparator<QgsUnsetAttributeValue>();
318#endif
319 qRegisterMetaType<QPainter::CompositionMode>( "QPainter::CompositionMode" );
320 qRegisterMetaType<QgsDateTimeRange>( "QgsDateTimeRange" );
321 qRegisterMetaType<QList<QgsMapLayer *>>( "QList<QgsMapLayer*>" );
322 qRegisterMetaType<QMap<QNetworkRequest::Attribute, QVariant>>( "QMap<QNetworkRequest::Attribute,QVariant>" );
323 qRegisterMetaType<QMap<QNetworkRequest::KnownHeaders, QVariant>>( "QMap<QNetworkRequest::KnownHeaders,QVariant>" );
324 qRegisterMetaType<QList<QNetworkReply::RawHeaderPair>>( "QList<QNetworkReply::RawHeaderPair>" );
325 qRegisterMetaType< QAuthenticator * >( "QAuthenticator*" );
326 } );
327
328 ( void ) resolvePkgPath();
329
330 if ( ABISYM( mRunningFromBuildDir ) )
331 {
332 // we run from source directory - not installed to destination (specified prefix)
333 *sPrefixPath() = QString(); // set invalid path
334#if defined(_MSC_VER) && !defined(USING_NMAKE) && !defined(USING_NINJA)
335 setPluginPath( *sBuildOutputPath() + '/' + QString( QGIS_PLUGIN_SUBDIR ) + '/' + *sCfgIntDir() );
336#else
337 setPluginPath( *sBuildOutputPath() + '/' + QStringLiteral( QGIS_PLUGIN_SUBDIR ) );
338#endif
339 setPkgDataPath( *sBuildOutputPath() + QStringLiteral( "/data" ) ); // in buildDir/data - used for: doc, resources, svg
340 *sLibraryPath() = *sBuildOutputPath() + '/' + QGIS_LIB_SUBDIR + '/';
341#if defined(_MSC_VER) && !defined(USING_NMAKE) && !defined(USING_NINJA)
342 *sLibexecPath() = *sBuildOutputPath() + '/' + QGIS_LIBEXEC_SUBDIR + '/' + *sCfgIntDir() + '/';
343#else
344 *sLibexecPath() = *sBuildOutputPath() + '/' + QGIS_LIBEXEC_SUBDIR + '/';
345#endif
346#if defined( HAVE_QUICK )
347 *sQmlImportPath() = *sBuildOutputPath() + '/' + QGIS_QML_SUBDIR + '/';
348#endif
349 }
350 else
351 {
352 char *prefixPath = getenv( "QGIS_PREFIX_PATH" );
353 if ( !prefixPath )
354 {
355 if ( sPrefixPath()->isNull() )
356 {
357#if defined(Q_OS_MACX) || defined(Q_OS_WIN)
358 setPrefixPath( applicationDirPath(), true );
359#elif defined(ANDROID)
360 // this is "/data/data/org.qgis.qgis" in android
361 QDir myDir( QDir::homePath() );
362 myDir.cdUp();
363 QString myPrefix = myDir.absolutePath();
364 setPrefixPath( myPrefix, true );
365#else
366 QDir myDir( applicationDirPath() );
367 // Fix for server which is one level deeper in /usr/lib/cgi-bin
368 if ( applicationDirPath().contains( QStringLiteral( "cgi-bin" ) ) )
369 {
370 myDir.cdUp();
371 }
372 myDir.cdUp(); // Go from /usr/bin or /usr/lib (for server) to /usr
373 QString myPrefix = myDir.absolutePath();
374 setPrefixPath( myPrefix, true );
375#endif
376 }
377 }
378 else
379 {
380 setPrefixPath( prefixPath, true );
381 }
382 }
383
384 *sConfigPath() = profileFolder + '/'; // make sure trailing slash is included
385 *sDefaultSvgPaths() << qgisSettingsDirPath() + QStringLiteral( "svg/" );
386
387 *sAuthDbDirPath() = qgisSettingsDirPath();
388 if ( getenv( "QGIS_AUTH_DB_DIR_PATH" ) )
389 {
390 setAuthDatabaseDirPath( getenv( "QGIS_AUTH_DB_DIR_PATH" ) );
391 }
392
393 // force use of OpenGL renderer for Qt3d.
394 qputenv( "QT3D_RENDERER", "opengl" );
395
396 // store system environment variables passed to application, before they are adjusted
397 QMap<QString, QString> systemEnvVarMap;
398 QString passfile( QStringLiteral( "QGIS_AUTH_PASSWORD_FILE" ) ); // QString, for comparison
399
400 const auto systemEnvironment = QProcessEnvironment::systemEnvironment().toStringList();
401 for ( const QString &varStr : systemEnvironment )
402 {
403 int pos = varStr.indexOf( QLatin1Char( '=' ) );
404 if ( pos == -1 )
405 continue;
406 QString varStrName = varStr.left( pos );
407 QString varStrValue = varStr.mid( pos + 1 );
408 if ( varStrName != passfile )
409 {
410 systemEnvVarMap.insert( varStrName, varStrValue );
411 }
412 }
413 *sSystemEnvVars() = systemEnvVarMap;
414
415 // append local user-writable folder as a proj search path
416 QStringList currentProjSearchPaths = QgsProjUtils::searchPaths();
417 currentProjSearchPaths.append( qgisSettingsDirPath() + QStringLiteral( "proj" ) );
418#ifdef Q_OS_MACX
419 // append bundled proj lib for MacOS
420 QString projLib( QDir::cleanPath( pkgDataPath().append( "/proj" ) ) );
421 if ( QFile::exists( projLib ) )
422 {
423 currentProjSearchPaths.append( projLib );
424 }
425#endif // Q_OS_MACX
426
427 char **newPaths = new char *[currentProjSearchPaths.length()];
428 for ( int i = 0; i < currentProjSearchPaths.count(); ++i )
429 {
430 newPaths[i] = CPLStrdup( currentProjSearchPaths.at( i ).toUtf8().constData() );
431 }
432 proj_context_set_search_paths( nullptr, currentProjSearchPaths.count(), newPaths );
433 for ( int i = 0; i < currentProjSearchPaths.count(); ++i )
434 {
435 CPLFree( newPaths[i] );
436 }
437 delete [] newPaths;
438
439 // allow Qt to search for Qt plugins (e.g. sqldrivers) in our plugin directory
440 QCoreApplication::addLibraryPath( pluginPath() );
441
442 {
443 QgsScopedRuntimeProfile profile( tr( "Load user fonts" ) );
445 }
446
447 // set max. thread count to -1
448 // this should be read from QgsSettings but we don't know where they are at this point
449 // so we read actual value in main.cpp
450 ABISYM( sMaxThreads ) = -1;
451
452 {
453 QgsScopedRuntimeProfile profile( tr( "Load color schemes" ) );
456 }
457
458 {
459 QgsScopedRuntimeProfile profile( tr( "Load bookmarks" ) );
461 }
462
463 // trigger creation of default style
464 QgsStyle *defaultStyle = QgsStyle::defaultStyle();
465 if ( !members()->mStyleModel )
466 members()->mStyleModel = new QgsStyleModel( defaultStyle );
467
468 ABISYM( mInitialized ) = true;
469}
470
472{
473 delete mDataItemProviderRegistry;
474 delete mApplicationMembers;
475 delete mQgisTranslator;
476 delete mQtTranslator;
477 delete mQtBaseTranslator;
478
479 // we do this here as well as in exitQgis() -- it's safe to call as often as we want,
480 // and there's just a *chance* that someone hasn't properly called exitQgis prior to
481 // this destructor...
482 invalidateCaches();
483}
484
485void QgsApplication::invalidateCaches()
486{
487 // invalidate coordinate cache while the PROJ context held by the thread-locale
488 // QgsProjContextStore object is still alive. Otherwise if this later object
489 // is destroyed before the static variables of the cache, we might use freed memory.
493}
494
496{
497 return qobject_cast<QgsApplication *>( QCoreApplication::instance() );
498}
499
500bool QgsApplication::event( QEvent *event )
501{
502 bool done = false;
503 if ( event->type() == QEvent::FileOpen )
504 {
505 // handle FileOpen event (double clicking a file icon in Mac OS X Finder)
506 if ( ABISYM( mFileOpenEventReceiver ) )
507 {
508 // Forward event to main window.
509 done = notify( ABISYM( mFileOpenEventReceiver ), event );
510 }
511 else
512 {
513 // Store filename because receiver has not registered yet.
514 // If QGIS has been launched by double clicking a file icon, FileOpen will be
515 // the first event; the main window is not yet ready to handle the event.
516 sFileOpenEventList()->append( static_cast<QFileOpenEvent *>( event )->file() );
517 done = true;
518 }
519 }
520 else
521 {
522 // pass other events to base class
523 done = QApplication::event( event );
524 }
525 return done;
526}
527
528bool QgsApplication::notify( QObject *receiver, QEvent *event )
529{
530 bool done = false;
531 // Crashes in customization (especially on Mac), if we're not in the main/UI thread, see #5597
532 if ( thread() == receiver->thread() )
533 emit preNotify( receiver, event, &done );
534
535 if ( done )
536 return true;
537
538 // Send event to receiver and catch unhandled exceptions
539 done = true;
540 try
541 {
542 done = QApplication::notify( receiver, event );
543 }
544 catch ( QgsException &e )
545 {
546 qCritical() << "Caught unhandled QgsException: " << e.what();
547 if ( qApp->thread() == QThread::currentThread() )
548 QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
549 }
550 catch ( std::exception &e )
551 {
552 qCritical() << "Caught unhandled std::exception: " << e.what();
553 if ( qApp->thread() == QThread::currentThread() )
554 QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
555 }
556 catch ( ... )
557 {
558 qCritical() << "Caught unhandled unknown exception";
559 if ( qApp->thread() == QThread::currentThread() )
560 QMessageBox::critical( activeWindow(), tr( "Exception" ), tr( "unknown exception" ) );
561 }
562
563 return done;
564}
565
567{
568 return QgsRuntimeProfiler::threadLocalInstance();
569}
570
572{
573 // Set receiver for FileOpen events
574 ABISYM( mFileOpenEventReceiver ) = receiver;
575 // Propagate any events collected before the receiver has registered.
576 if ( sFileOpenEventList()->count() > 0 )
577 {
578 const QStringList fileOpenEventList = *sFileOpenEventList();
579 for ( const QString &file : fileOpenEventList )
580 {
581 QFileOpenEvent foe( file );
582 QgsApplication::sendEvent( ABISYM( mFileOpenEventReceiver ), &foe );
583 }
584 sFileOpenEventList()->clear();
585 }
586}
587
588void QgsApplication::setPrefixPath( const QString &prefixPath, bool useDefaultPaths )
589{
590 *sPrefixPath() = prefixPath;
591#if defined(Q_OS_WIN)
592 if ( sPrefixPath()->endsWith( "/bin" ) )
593 {
594 sPrefixPath()->chop( 4 );
595 }
596#endif
597 if ( useDefaultPaths && !ABISYM( mRunningFromBuildDir ) )
598 {
599 setPluginPath( *sPrefixPath() + '/' + QStringLiteral( QGIS_PLUGIN_SUBDIR ) );
600 setPkgDataPath( *sPrefixPath() + '/' + QStringLiteral( QGIS_DATA_SUBDIR ) );
601 }
602 *sLibraryPath() = *sPrefixPath() + '/' + QGIS_LIB_SUBDIR + '/';
603 *sLibexecPath() = *sPrefixPath() + '/' + QGIS_LIBEXEC_SUBDIR + '/';
604#if defined( HAVE_QUICK )
605 *sQmlImportPath() = *sPrefixPath() + '/' + QGIS_QML_SUBDIR + '/';
606#endif
607}
608
609void QgsApplication::setPluginPath( const QString &pluginPath )
610{
611 *sPluginPath() = pluginPath;
612}
613
614void QgsApplication::setPkgDataPath( const QString &pkgDataPath )
615{
616 *sPkgDataPath() = pkgDataPath;
617
618 QString mySvgPath = pkgDataPath + QStringLiteral( "/svg/" );
619
620 // avoid duplicate entries
621 if ( !sDefaultSvgPaths()->contains( mySvgPath ) )
622 *sDefaultSvgPaths() << mySvgPath;
623}
624
625void QgsApplication::setDefaultSvgPaths( const QStringList &pathList )
626{
627 *sDefaultSvgPaths() = pathList;
628}
629
630void QgsApplication::setAuthDatabaseDirPath( const QString &authDbDirPath )
631{
632 QFileInfo fi( authDbDirPath );
633 if ( fi.exists() && fi.isDir() && fi.isWritable() )
634 {
635 *sAuthDbDirPath() = fi.canonicalFilePath() + QDir::separator();
636 }
637}
638
640{
641#if 0
642 if ( ABISYM( mRunningFromBuildDir ) )
643 {
644 static bool sOnce = true;
645 if ( sOnce )
646 {
647 QgsMessageLogNotifyBlocker blockNotifications;
648 ( void ) blockNotifications;
649 qWarning( "!!! prefix path was requested, but it is not valid - we do not run from installed path !!!" );
650 }
651 sOnce = false;
652 }
653#endif
654
655 return *sPrefixPath();
656}
658{
659 return *sPluginPath();
660}
661
663{
664 if ( sPkgDataPath()->isNull() )
665 return resolvePkgPath();
666 else
667 return *sPkgDataPath();
668}
669
671{
672 return QStringLiteral( ":/images/themes/default/" );
673}
675{
676 QString usersThemes = userThemesFolder() + QDir::separator() + themeName() + QDir::separator() + "icons/";
677 QDir dir( usersThemes );
678 if ( dir.exists() )
679 {
680 return usersThemes;
681 }
682 else
683 {
684 QString defaultThemes = defaultThemesFolder() + QDir::separator() + themeName() + QDir::separator() + "icons/";
685 return defaultThemes;
686 }
687}
688
690{
691 return iconsPath() + QStringLiteral( "qgis-icon-60x60.png" );
692}
693
695{
696 return ABISYM( sMaxThreads );
697}
698
699QString QgsApplication::iconPath( const QString &iconFile )
700{
701 // try active theme
702 QString path = activeThemePath();
703 if ( QFile::exists( path + iconFile ) )
704 return path + iconFile;
705
706 // use default theme
707 return defaultThemePath() + iconFile;
708}
709
710QIcon QgsApplication::getThemeIcon( const QString &name, const QColor &fillColor, const QColor &strokeColor )
711{
712 const QString cacheKey = ( name.startsWith( '/' ) ? name.mid( 1 ) : name )
713 + ( fillColor.isValid() ? QStringLiteral( "_%1" ).arg( fillColor.name( QColor::HexArgb ).mid( 1 ) ) : QString() )
714 + ( strokeColor.isValid() ? QStringLiteral( "_%1" ).arg( strokeColor.name( QColor::HexArgb ).mid( 1 ) ) : QString() );
715 QgsApplication *app = instance();
716 if ( app && app->mIconCache.contains( cacheKey ) )
717 return app->mIconCache.value( cacheKey );
718
719 QIcon icon;
720 const bool colorBased = fillColor.isValid() || strokeColor.isValid();
721
722 auto iconFromColoredSvg = [ = ]( const QString & path ) -> QIcon
723 {
724 // sizes are unused here!
725 const QByteArray svgContent = QgsApplication::svgCache()->svgContent( path, 16, fillColor, strokeColor, 1, 1 );
726
727 const QString iconPath = sIconCacheDir()->filePath( cacheKey + QStringLiteral( ".svg" ) );
728 QFile f( iconPath );
729 if ( f.open( QFile::WriteOnly | QFile::Truncate ) )
730 {
731 f.write( svgContent );
732 f.close();
733 }
734 else
735 {
736 QgsDebugMsg( QStringLiteral( "Could not create colorized icon svg at %1" ).arg( iconPath ) );
737 return QIcon();
738 }
739
740 return QIcon( f.fileName() );
741 };
742
743 QString preferredPath = activeThemePath() + QDir::separator() + name;
744 QString defaultPath = defaultThemePath() + QDir::separator() + name;
745 if ( QFile::exists( preferredPath ) )
746 {
747 if ( colorBased )
748 {
749 icon = iconFromColoredSvg( preferredPath );
750 }
751 else
752 {
753 icon = QIcon( preferredPath );
754 }
755 }
756 else if ( QFile::exists( defaultPath ) )
757 {
758 //could still return an empty icon if it
759 //doesn't exist in the default theme either!
760 if ( colorBased )
761 {
762 icon = iconFromColoredSvg( defaultPath );
763 }
764 else
765 {
766 icon = QIcon( defaultPath );
767 }
768 }
769 else
770 {
771 icon = QIcon();
772 }
773
774 if ( app )
775 app->mIconCache.insert( cacheKey, icon );
776 return icon;
777}
778
780{
781 QgsApplication *app = instance();
782 if ( app && app->mCursorCache.contains( cursor ) )
783 return app->mCursorCache.value( cursor );
784
785 // All calculations are done on 32x32 icons
786 // Defaults to center, individual cursors may override
787 int activeX = 16;
788 int activeY = 16;
789
790 QString name;
791 switch ( cursor )
792 {
793 case ZoomIn:
794 name = QStringLiteral( "mZoomIn.svg" );
795 activeX = 13;
796 activeY = 13;
797 break;
798 case ZoomOut:
799 name = QStringLiteral( "mZoomOut.svg" );
800 activeX = 13;
801 activeY = 13;
802 break;
803 case Identify:
804 activeX = 3;
805 activeY = 6;
806 name = QStringLiteral( "mIdentify.svg" );
807 break;
808 case CrossHair:
809 name = QStringLiteral( "mCrossHair.svg" );
810 break;
811 case CapturePoint:
812 name = QStringLiteral( "mCapturePoint.svg" );
813 break;
814 case Select:
815 name = QStringLiteral( "mSelect.svg" );
816 activeX = 6;
817 activeY = 6;
818 break;
819 case Sampler:
820 activeX = 5;
821 activeY = 5;
822 name = QStringLiteral( "mSampler.svg" );
823 break;
824 // No default
825 }
826 // It should never get here!
827 Q_ASSERT( ! name.isEmpty( ) );
828
829 QIcon icon = getThemeIcon( QStringLiteral( "cursors" ) + QDir::separator() + name );
830 QCursor cursorIcon;
831 // Check if an icon exists for this cursor (the O.S. default cursor will be used if it does not)
832 if ( ! icon.isNull( ) )
833 {
834 // Apply scaling
835 float scale = Qgis::UI_SCALE_FACTOR * QgsApplication::fontMetrics().height() / 32.0;
836 cursorIcon = QCursor( icon.pixmap( std::ceil( scale * 32 ), std::ceil( scale * 32 ) ), std::ceil( scale * activeX ), std::ceil( scale * activeY ) );
837 }
838 if ( app )
839 app->mCursorCache.insert( cursor, cursorIcon );
840 return cursorIcon;
841}
842
843// TODO: add some caching mechanism ?
844QPixmap QgsApplication::getThemePixmap( const QString &name, const QColor &foreColor, const QColor &backColor, const int size )
845{
846 const QString preferredPath = activeThemePath() + QDir::separator() + name;
847 const QString defaultPath = defaultThemePath() + QDir::separator() + name;
848 const QString path = QFile::exists( preferredPath ) ? preferredPath : defaultPath;
849 if ( foreColor.isValid() || backColor.isValid() )
850 {
851 bool fitsInCache = false;
852 const QImage image = svgCache()->svgAsImage( path, size, backColor, foreColor, 1, 1, fitsInCache );
853 return QPixmap::fromImage( image );
854 }
855
856 return QPixmap( path );
857}
858
859void QgsApplication::setThemeName( const QString &themeName )
860{
861 *sThemeName() = themeName;
862}
863
865{
866 static QString appPath;
867 if ( appPath.isNull() )
868 {
869 if ( QCoreApplication::instance() )
870 {
871 appPath = applicationDirPath();
872 }
873 else
874 {
875 qWarning( "Application path not initialized" );
876 }
877 }
878
879 if ( !appPath.isNull() || getenv( "QGIS_PREFIX_PATH" ) )
880 {
881 QString prefix = getenv( "QGIS_PREFIX_PATH" ) ? getenv( "QGIS_PREFIX_PATH" ) : appPath;
882
883 // check if QGIS is run from build directory (not the install directory)
884 QFile f;
885 // "/../../.." is for Mac bundled app in build directory
886 static const QStringList paths { QStringList() << QString() << QStringLiteral( "/.." ) << QStringLiteral( "/bin" ) << QStringLiteral( "/../../.." ) };
887 for ( const QString &path : paths )
888 {
889 f.setFileName( prefix + path + "/qgisbuildpath.txt" );
890 if ( f.exists() )
891 break;
892 }
893 if ( f.exists() && f.open( QIODevice::ReadOnly ) )
894 {
895 ABISYM( mRunningFromBuildDir ) = true;
896 *sBuildSourcePath() = f.readLine().trimmed();
897 *sBuildOutputPath() = f.readLine().trimmed();
898 QgsDebugMsgLevel( QStringLiteral( "Running from build directory!" ), 4 );
899 QgsDebugMsgLevel( QStringLiteral( "- source directory: %1" ).arg( sBuildSourcePath()->toUtf8().constData() ), 4 );
900 QgsDebugMsgLevel( QStringLiteral( "- output directory of the build: %1" ).arg( sBuildOutputPath()->toUtf8().constData() ), 4 );
901#if defined(_MSC_VER) && !defined(USING_NMAKE) && !defined(USING_NINJA)
902 *sCfgIntDir() = prefix.split( '/', QString::SkipEmptyParts ).last();
903 qDebug( "- cfg: %s", sCfgIntDir()->toUtf8().constData() );
904#endif
905 }
906 }
907
908 QString prefixPath;
909 if ( getenv( "QGIS_PREFIX_PATH" ) )
910 prefixPath = getenv( "QGIS_PREFIX_PATH" );
911 else
912 {
913#if defined(ANDROID)
914 // this is "/data/data/org.qgis.qgis" in android
915 QDir dir( QDir::homePath() );
916 dir.cdUp();
917 prefixPath = dir.absolutePath();
918#else
919
920#if defined(Q_OS_MACX)
921 prefixPath = appPath;
922#elif defined(Q_OS_WIN)
923 prefixPath = appPath;
924 if ( prefixPath.endsWith( "/bin" ) )
925 prefixPath.chop( 4 );
926#else
927 QDir dir( appPath );
928 // Fix for server which is one level deeper in /usr/lib/cgi-bin
929 if ( appPath.contains( QStringLiteral( "cgi-bin" ) ) )
930 {
931 dir.cdUp();
932 }
933 dir.cdUp(); // Go from /usr/bin or /usr/lib (for server) to /usr
934 prefixPath = dir.absolutePath();
935#endif
936#endif
937 }
938
939 if ( ABISYM( mRunningFromBuildDir ) )
940 return *sBuildOutputPath() + QStringLiteral( "/data" );
941 else
942 return prefixPath + '/' + QStringLiteral( QGIS_DATA_SUBDIR );
943}
944
946{
947 return *sThemeName();
948}
949
950void QgsApplication::setUITheme( const QString &themeName )
951{
952 // Loop all style sheets, find matching name, load it.
953 QHash<QString, QString> themes = QgsApplication::uiThemes();
954 if ( themeName == QLatin1String( "default" ) || !themes.contains( themeName ) )
955 {
956 setThemeName( QStringLiteral( "default" ) );
957 qApp->setStyleSheet( QString() );
958 return;
959 }
960
961 QString path = themes.value( themeName );
962 QString stylesheetname = path + "/style.qss";
963
964 QFile file( stylesheetname );
965 QFile variablesfile( path + "/variables.qss" );
966
967 QFileInfo variableInfo( variablesfile );
968
969 if ( !file.open( QIODevice::ReadOnly ) || ( variableInfo.exists() && !variablesfile.open( QIODevice::ReadOnly ) ) )
970 {
971 return;
972 }
973
974 QString styledata = file.readAll();
975 styledata.replace( QLatin1String( "@theme_path" ), path );
976
977 if ( variableInfo.exists() )
978 {
979 QTextStream in( &variablesfile );
980 while ( !in.atEnd() )
981 {
982 QString line = in.readLine();
983 // This is a variable
984 if ( line.startsWith( '@' ) )
985 {
986 int index = line.indexOf( ':' );
987 QString name = line.mid( 0, index );
988 QString value = line.mid( index + 1, line.length() );
989 styledata.replace( name, value );
990 }
991 }
992 variablesfile.close();
993 }
994 file.close();
995
996 if ( Qgis::UI_SCALE_FACTOR != 1.0 )
997 {
998 // apply OS-specific UI scale factor to stylesheet's em values
999 int index = 0;
1000 const static QRegularExpression regex( QStringLiteral( "(?<=[\\s:])([0-9\\.]+)(?=em)" ) );
1001 QRegularExpressionMatch match = regex.match( styledata, index );
1002 while ( match.hasMatch() )
1003 {
1004 index = match.capturedStart();
1005 styledata.remove( index, match.captured( 0 ).length() );
1006 QString number = QString::number( match.captured( 0 ).toDouble() * Qgis::UI_SCALE_FACTOR );
1007 styledata.insert( index, number );
1008 index += number.length();
1009 match = regex.match( styledata, index );
1010 }
1011 }
1012
1013 qApp->setStyleSheet( styledata );
1014
1015 QFile palettefile( path + "/palette.txt" );
1016 QFileInfo paletteInfo( palettefile );
1017 if ( paletteInfo.exists() && palettefile.open( QIODevice::ReadOnly ) )
1018 {
1019 QPalette pal = qApp->palette();
1020 QTextStream in( &palettefile );
1021 while ( !in.atEnd() )
1022 {
1023 QString line = in.readLine();
1024 QStringList parts = line.split( ':' );
1025 if ( parts.count() == 2 )
1026 {
1027 int role = parts.at( 0 ).trimmed().toInt();
1028 QColor color = QgsSymbolLayerUtils::decodeColor( parts.at( 1 ).trimmed() );
1029 pal.setColor( static_cast< QPalette::ColorRole >( role ), color );
1030 }
1031 }
1032 palettefile.close();
1033 qApp->setPalette( pal );
1034 }
1035
1037}
1038
1039QHash<QString, QString> QgsApplication::uiThemes()
1040{
1041 QStringList paths = QStringList() << userThemesFolder() << defaultThemesFolder();
1042 QHash<QString, QString> mapping;
1043 mapping.insert( QStringLiteral( "default" ), QString() );
1044 const auto constPaths = paths;
1045 for ( const QString &path : constPaths )
1046 {
1047 QDir folder( path );
1048 QFileInfoList styleFiles = folder.entryInfoList( QDir::Dirs | QDir::NoDotAndDotDot );
1049 const auto constStyleFiles = styleFiles;
1050 for ( const QFileInfo &info : constStyleFiles )
1051 {
1052 QFileInfo styleFile( info.absoluteFilePath() + "/style.qss" );
1053 if ( !styleFile.exists() )
1054 continue;
1055
1056 QString name = info.baseName();
1057 QString path = info.absoluteFilePath();
1058 mapping.insert( name, path );
1059 }
1060 }
1061 return mapping;
1062}
1063
1065{
1066 return pkgDataPath() + QStringLiteral( "/doc/AUTHORS" );
1067}
1068
1070{
1071 return pkgDataPath() + QStringLiteral( "/doc/CONTRIBUTORS" );
1072}
1074{
1075 return pkgDataPath() + QStringLiteral( "/doc/developersmap.html" );
1076}
1077
1079{
1080 return pkgDataPath() + QStringLiteral( "/doc/SPONSORS" );
1081}
1082
1084{
1085 return pkgDataPath() + QStringLiteral( "/doc/DONORS" );
1086}
1087
1089{
1090 return pkgDataPath() + QStringLiteral( "/doc/TRANSLATORS" );
1091}
1092
1094{
1095 return pkgDataPath() + QStringLiteral( "/doc/LICENSE" );
1096}
1097
1099{
1100 if ( ABISYM( mRunningFromBuildDir ) )
1101 return *sBuildOutputPath() + QStringLiteral( "/i18n/" );
1102 else
1103 return pkgDataPath() + QStringLiteral( "/i18n/" );
1104}
1105
1107{
1108 return pkgDataPath() + QStringLiteral( "/resources/metadata-ISO/" );
1109}
1110
1112{
1113 return pkgDataPath() + QStringLiteral( "/resources/qgis.db" );
1114}
1115
1117{
1118 return *sConfigPath();
1119}
1120
1122{
1123 return qgisSettingsDirPath() + QStringLiteral( "qgis.db" );
1124}
1125
1127{
1128 return *sAuthDbDirPath() + QStringLiteral( "qgis-auth.db" );
1129}
1130
1132{
1133 return QStringLiteral( ":/images/splash/" );
1134}
1135
1137{
1138 return pkgDataPath() + QStringLiteral( "/images/icons/" );
1139}
1140
1142{
1143 if ( ABISYM( mRunningFromBuildDir ) )
1144 {
1145 QString tempCopy = QDir::tempPath() + "/srs6.db";
1146
1147 if ( !QFile( tempCopy ).exists() )
1148 {
1149 QFile f( buildSourcePath() + "/resources/srs6.db" );
1150 if ( !f.copy( tempCopy ) )
1151 {
1152 qFatal( "Could not create temporary copy" );
1153 }
1154 }
1155
1156 return tempCopy;
1157 }
1158 else
1159 {
1160 return pkgDataPath() + QStringLiteral( "/resources/srs.db" );
1161 }
1162}
1163
1164void QgsApplication::setSvgPaths( const QStringList &svgPaths )
1165{
1167 members()->mSvgPathCacheValid = false;
1168}
1169
1171{
1172 static QReadWriteLock lock;
1173
1175
1176 if ( members()->mSvgPathCacheValid )
1177 {
1178 return members()->mSvgPathCache;
1179 }
1180 else
1181 {
1183 //local directories to search when looking for an SVG with a given basename
1184 //defined by user in options dialog
1185 const QStringList pathList = settingsSearchPathsForSVG.value();
1186
1187 // maintain user set order while stripping duplicates
1188 QStringList paths;
1189 for ( const QString &path : pathList )
1190 {
1191 if ( !paths.contains( path ) )
1192 paths.append( path );
1193 }
1194 for ( const QString &path : std::as_const( *sDefaultSvgPaths() ) )
1195 {
1196 if ( !paths.contains( path ) )
1197 paths.append( path );
1198 }
1199 members()->mSvgPathCache = paths;
1200
1201 return paths;
1202 }
1203}
1204
1206{
1207 //local directories to search when looking for an template with a given basename
1208 //defined by user in options dialog
1210}
1211
1212QMap<QString, QString> QgsApplication::systemEnvVars()
1213{
1214 return *sSystemEnvVars();
1215}
1216
1218{
1219 return qgisSettingsDirPath() + QStringLiteral( "symbology-style.db" );
1220}
1221
1223{
1224 const thread_local QRegularExpression regexp( QRegularExpression::anchoredPattern( QStringLiteral( "^[A-Za-z][A-Za-z0-9\\._-]*" ) ) );
1225 return regexp;
1226}
1227
1229{
1230 if ( !sUserName()->isEmpty() )
1231 return *sUserName();
1232
1233#ifdef _MSC_VER
1234 TCHAR name [ UNLEN + 1 ];
1235 DWORD size = UNLEN + 1;
1236
1237 if ( GetUserName( ( TCHAR * )name, &size ) )
1238 {
1239 *sUserName() = QString::fromLocal8Bit( name );
1240 }
1241
1242#elif QT_CONFIG(process)
1243 QProcess process;
1244
1245 process.start( QStringLiteral( "whoami" ), QStringList() );
1246 process.waitForFinished();
1247 *sUserName() = process.readAllStandardOutput().trimmed();
1248#endif
1249
1250 if ( !sUserName()->isEmpty() )
1251 return *sUserName();
1252
1253 //backup plan - use environment variables
1254 *sUserName() = qgetenv( "USER" );
1255 if ( !sUserName()->isEmpty() )
1256 return *sUserName();
1257
1258 //last resort
1259 *sUserName() = qgetenv( "USERNAME" );
1260 return *sUserName();
1261}
1262
1264{
1265 if ( !sUserFullName()->isEmpty() )
1266 return *sUserFullName();
1267
1268#ifdef _MSC_VER
1269 TCHAR name [ UNLEN + 1 ];
1270 DWORD size = UNLEN + 1;
1271
1272 //note - this only works for accounts connected to domain
1273 if ( GetUserNameEx( NameDisplay, ( TCHAR * )name, &size ) )
1274 {
1275 *sUserFullName() = QString::fromLocal8Bit( name );
1276 }
1277
1278 //fall back to login name
1279 if ( sUserFullName()->isEmpty() )
1280 *sUserFullName() = userLoginName();
1281#elif defined(Q_OS_ANDROID) || defined(__MINGW32__)
1282 *sUserFullName() = QStringLiteral( "Not available" );
1283#else
1284 struct passwd *p = getpwuid( getuid() );
1285
1286 if ( p )
1287 {
1288 QString gecosName = QString( p->pw_gecos );
1289 *sUserFullName() = gecosName.left( gecosName.indexOf( ',', 0 ) );
1290 }
1291
1292#endif
1293
1294 return *sUserFullName();
1295}
1296
1298{
1299#if defined(Q_OS_ANDROID)
1300 return QLatin1String( "android" );
1301#elif defined(Q_OS_MAC)
1302 return QLatin1String( "osx" );
1303#elif defined(Q_OS_WIN)
1304 return QLatin1String( "windows" );
1305#elif defined(Q_OS_LINUX)
1306 return QStringLiteral( "linux" );
1307#elif defined(Q_OS_FREEBSD)
1308 return QStringLiteral( "freebsd" );
1309#elif defined(Q_OS_OPENBSD)
1310 return QStringLiteral( "openbsd" );
1311#elif defined(Q_OS_NETBSD)
1312 return QStringLiteral( "netbsd" );
1313#elif defined(Q_OS_UNIX)
1314 return QLatin1String( "unix" );
1315#else
1316 return QLatin1String( "unknown" );
1317#endif
1318}
1319
1321{
1322#if defined(Q_OS_ANDROID)
1323 return -1;
1324#elif defined(Q_OS_MAC)
1325 return -1;
1326#elif defined(Q_OS_WIN)
1327 MEMORYSTATUSEX memoryStatus;
1328 ZeroMemory( &memoryStatus, sizeof( MEMORYSTATUSEX ) );
1329 memoryStatus.dwLength = sizeof( MEMORYSTATUSEX );
1330 if ( GlobalMemoryStatusEx( &memoryStatus ) )
1331 {
1332 return memoryStatus.ullTotalPhys / ( 1024 * 1024 );
1333 }
1334 else
1335 {
1336 return -1;
1337 }
1338#elif defined(Q_OS_LINUX)
1339 constexpr int megabyte = 1024 * 1024;
1340 struct sysinfo si;
1341 sysinfo( &si );
1342 return si.totalram / megabyte;
1343#elif defined(Q_OS_FREEBSD)
1344 return -1;
1345#elif defined(Q_OS_OPENBSD)
1346 return -1;
1347#elif defined(Q_OS_NETBSD)
1348 return -1;
1349#elif defined(Q_OS_UNIX)
1350 return -1;
1351#else
1352 return -1;
1353#endif
1354}
1355
1357{
1358 return *sPlatformName();
1359}
1360
1362{
1364 {
1366 // don't differentiate en_US and en_GB
1367 if ( locale.startsWith( QLatin1String( "en" ), Qt::CaseInsensitive ) )
1368 {
1369 return locale.left( 2 );
1370 }
1371
1372 return locale;
1373 }
1374 else
1375 {
1376 return QLocale().name().left( 2 );
1377 }
1378}
1379
1380void QgsApplication::setLocale( const QLocale &locale )
1381{
1382 QLocale::setDefault( locale );
1383 emit instance()->localeChanged();
1384}
1385
1387{
1388 return qgisSettingsDirPath() + QStringLiteral( "/themes" );
1389}
1390
1392{
1393 return pkgDataPath() + QStringLiteral( "/resources/symbology-style.xml" );
1394}
1395
1397{
1398 return pkgDataPath() + QStringLiteral( "/resources/themes" );
1399}
1400
1402{
1403 return pkgDataPath() + QStringLiteral( "/resources/server/" );
1404}
1405
1407{
1408 return *sLibraryPath();
1409}
1410
1412{
1413 return *sLibexecPath();
1414}
1415
1417{
1418 return *sQmlImportPath();
1419}
1420
1422{
1423 return ( htonl( 1 ) == 1 ) ? XDR : NDR;
1424}
1425
1427{
1428 if ( !ABISYM( mInitialized ) && QgsApplication::instance() )
1429 {
1430 init( *sProfilePath() );
1431 }
1432
1433 // set the provider plugin path (this creates provider registry)
1435
1436 // create data item provider registry
1438
1439 // create project instance if doesn't exist
1441
1442 // Initialize authentication manager and connect to database
1444
1445 // Make sure we have a NAM created on the main thread.
1446 // Note that this might call QgsApplication::authManager to
1447 // setup the proxy configuration that's why it needs to be
1448 // called after the QgsAuthManager instance has been created
1450
1451}
1452
1454{
1455 if ( auto *lInstance = instance() )
1456 {
1457 if ( !lInstance->mAuthManager )
1458 {
1459 lInstance->mAuthManager = QgsAuthManager::instance();
1460 }
1461 return lInstance->mAuthManager;
1462 }
1463 else
1464 {
1465 // no QgsApplication instance
1466 if ( !sAuthManager )
1467 sAuthManager = QgsAuthManager::instance();
1468 return sAuthManager;
1469 }
1470}
1471
1472
1474{
1475 // make sure all threads are done before exiting
1476 QThreadPool::globalInstance()->waitForDone();
1477
1478 // don't create to delete
1479 if ( auto *lInstance = instance() )
1480 delete lInstance->mAuthManager;
1481 else
1482 delete sAuthManager;
1483
1484 //Ensure that all remaining deleteLater QObjects are actually deleted before we exit.
1485 //This isn't strictly necessary (since we're exiting anyway) but doing so prevents a lot of
1486 //LeakSanitiser noise which hides real issues
1487 QgsApplication::sendPostedEvents( nullptr, QEvent::DeferredDelete );
1488
1489 //delete all registered functions from expression engine (see above comment)
1491
1492 delete QgsProject::instance();
1493
1494 // avoid creating instance just to delete it!
1495 if ( QgsProviderRegistry::exists() )
1497
1498 invalidateCaches();
1499
1501
1502 // tear-down GDAL/OGR
1503 OGRCleanupAll();
1504 GDALDestroyDriverManager();
1505}
1506
1508{
1509 QString myEnvironmentVar( getenv( "QGIS_PREFIX_PATH" ) );
1510 QString myState = tr( "Application state:\n"
1511 "QGIS_PREFIX_PATH env var:\t\t%1\n"
1512 "Prefix:\t\t%2\n"
1513 "Plugin Path:\t\t%3\n"
1514 "Package Data Path:\t%4\n"
1515 "Active Theme Name:\t%5\n"
1516 "Active Theme Path:\t%6\n"
1517 "Default Theme Path:\t%7\n"
1518 "SVG Search Paths:\t%8\n"
1519 "User DB Path:\t%9\n"
1520 "Auth DB Path:\t%10\n" )
1521 .arg( myEnvironmentVar,
1522 prefixPath(),
1523 pluginPath(),
1524 pkgDataPath(),
1525 themeName(),
1528 svgPaths().join( tr( "\n\t\t", "match indentation of application state" ) ),
1530 .arg( qgisAuthDatabaseFilePath() );
1531 return myState;
1532}
1533
1535{
1536 //
1537 // Make the style sheet desktop preferences aware by using qapplication
1538 // palette as a basis for colors where appropriate
1539 //
1540 // QColor myColor1 = palette().highlight().color();
1541 QColor myColor1( Qt::lightGray );
1542 QColor myColor2 = myColor1;
1543 myColor2 = myColor2.lighter( 110 ); //10% lighter
1544 QString myStyle;
1545 myStyle = QStringLiteral( ".overview{"
1546 " font: 1.82em;"
1547 " font-weight: bold;"
1548 "}"
1549 "body{"
1550 " background: white;"
1551 " color: black;"
1552 " font-family: 'Lato', 'Open Sans', 'Lucida Grande', 'Segoe UI', 'Arial', sans-serif;"
1553 " width: 100%;"
1554 "}"
1555 "h1{ background-color: #F6F6F6;"
1556 " color: #589632; " // from http://qgis.org/en/site/getinvolved/styleguide.html
1557 " font-size: x-large; "
1558 " font-weight: normal;"
1559 " background: none;"
1560 " padding: 0.75em 0 0;"
1561 " margin: 0;"
1562 " line-height: 3em;"
1563 "}"
1564 "h2{ background-color: #F6F6F6;"
1565 " color: #589632; " // from http://qgis.org/en/site/getinvolved/styleguide.html
1566 " font-size: medium; "
1567 " font-weight: normal;"
1568 " background: none;"
1569 " padding: 0.75em 0 0;"
1570 " margin: 0;"
1571 " line-height: 1.1em;"
1572 "}"
1573 "h3{ background-color: #F6F6F6;"
1574 " color: #93b023;" // from http://qgis.org/en/site/getinvolved/styleguide.html
1575 " font-weight: bold;"
1576 " font-size: large;"
1577 " text-align: left;"
1578 " border-bottom: 5px solid #DCEB5C;"
1579 "}"
1580 "h4{ background-color: #F6F6F6;"
1581 " color: #93b023;" // from http://qgis.org/en/site/getinvolved/styleguide.html
1582 " font-weight: bold;"
1583 " font-size: medium;"
1584 " text-align: left;"
1585 "}"
1586 "h5{ background-color: #F6F6F6;"
1587 " color: #93b023;" // from http://qgis.org/en/site/getinvolved/styleguide.html
1588 " font-weight: bold;"
1589 " font-size: small;"
1590 " text-align: left;"
1591 "}"
1592 "a{ color: #729FCF;"
1593 " font-family: arial,sans-serif;"
1594 "}"
1595 "label{ background-color: #FFFFCC;"
1596 " border: 1px solid black;"
1597 " margin: 1px;"
1598 " padding: 0px 3px; "
1599 " font-size: small;"
1600 "}"
1601 "th .strong {"
1602 " font-weight: bold;"
1603 "}"
1604 "hr {"
1605 " border: 0;"
1606 " height: 0;"
1607 " border-top: 1px solid black;"
1608 "}"
1609 ".list-view .highlight {"
1610 " text-align: left;"
1611 " border: 0px;"
1612 " width: 20%;"
1613 " padding-right: 15px;"
1614 " padding-left: 20px;"
1615 " font-weight: bold;"
1616 "}"
1617 ".tabular-view .odd-row {"
1618 " background-color: #f9f9f9;"
1619 "}"
1620 ".section {"
1621 " font-weight: bold;"
1622 " padding-top:25px;"
1623 "}" );
1624
1625 // We have some subtle differences between Qt based style and QWebKit style
1626 switch ( styleSheetType )
1627 {
1628 case StyleSheetType::Qt:
1629 myStyle += QStringLiteral(
1630 ".tabular-view{ "
1631 " border-collapse: collapse;"
1632 " width: 95%;"
1633 "}"
1634 ".tabular-view th, .tabular-view td { "
1635 " border:1px solid black;"
1636 "}" );
1637 break;
1638
1639 case StyleSheetType::WebBrowser:
1640 myStyle += QStringLiteral(
1641 "body { "
1642 " margin: auto;"
1643 " width: 97%;"
1644 "}"
1645 "table.tabular-view, table.list-view { "
1646 " border-collapse: collapse;"
1647 " table-layout:fixed;"
1648 " width: 100% !important;"
1649 " font-size: 90%;"
1650 "}"
1651 // Override
1652 "h1 { "
1653 " line-height: inherit;"
1654 "}"
1655 "td, th {"
1656 " word-wrap: break-word; "
1657 " vertical-align: top;"
1658 "}"
1659 // Set first column width
1660 ".list-view th:first-child, .list-view td:first-child {"
1661 " width: 20%;"
1662 "}"
1663 ".list-view.highlight { "
1664 " padding-left: inherit; "
1665 "}"
1666 // Set first column width for inner tables
1667 ".tabular-view th:first-child, .tabular-view td:first-child { "
1668 " width: 20%; "
1669 "}"
1670 // Makes titles bg stand up
1671 ".tabular-view th.strong { "
1672 " background-color: #eee; "
1673 "}"
1674 // Give some visual appearance to those ugly nested tables
1675 ".tabular-view th, .tabular-view td { "
1676 " border: 1px solid #eee;"
1677 "}"
1678 );
1679 break;
1680 }
1681
1682 return myStyle;
1683}
1684
1686{
1687 if ( 0 >= OGRGetDriverCount() )
1688 {
1689 OGRRegisterAll();
1690 }
1691}
1692
1693QString QgsApplication::absolutePathToRelativePath( const QString &aPath, const QString &targetPath )
1694{
1695 QString aPathUrl = aPath;
1696 QString tPathUrl = targetPath;
1697#if defined( Q_OS_WIN )
1698 const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
1699
1700 aPathUrl.replace( '\\', '/' );
1701 if ( aPathUrl.startsWith( "//" ) )
1702 {
1703 // keep UNC prefix
1704 aPathUrl = "\\\\" + aPathUrl.mid( 2 );
1705 }
1706
1707 tPathUrl.replace( '\\', '/' );
1708 if ( tPathUrl.startsWith( "//" ) )
1709 {
1710 // keep UNC prefix
1711 tPathUrl = "\\\\" + tPathUrl.mid( 2 );
1712 }
1713#else
1714 const Qt::CaseSensitivity cs = Qt::CaseSensitive;
1715#endif
1716
1717#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1718 QStringList targetElems = tPathUrl.split( '/', QString::SkipEmptyParts );
1719 QStringList aPathElems = aPathUrl.split( '/', QString::SkipEmptyParts );
1720#else
1721 QStringList targetElems = tPathUrl.split( '/', Qt::SkipEmptyParts );
1722 QStringList aPathElems = aPathUrl.split( '/', Qt::SkipEmptyParts );
1723#endif
1724
1725 targetElems.removeAll( QStringLiteral( "." ) );
1726 aPathElems.removeAll( QStringLiteral( "." ) );
1727
1728 // remove common part
1729 int n = 0;
1730 while ( !aPathElems.isEmpty() &&
1731 !targetElems.isEmpty() &&
1732 aPathElems[0].compare( targetElems[0], cs ) == 0 )
1733 {
1734 aPathElems.removeFirst();
1735 targetElems.removeFirst();
1736 n++;
1737 }
1738
1739 if ( n == 0 )
1740 {
1741 // no common parts; might not even be a file
1742 return aPathUrl;
1743 }
1744
1745 if ( !targetElems.isEmpty() )
1746 {
1747 // go up to the common directory
1748 for ( int i = 0; i < targetElems.size(); i++ )
1749 {
1750 aPathElems.insert( 0, QStringLiteral( ".." ) );
1751 }
1752 }
1753 else
1754 {
1755 // let it start with . nevertheless,
1756 // so relative path always start with either ./ or ../
1757 aPathElems.insert( 0, QStringLiteral( "." ) );
1758 }
1759
1760 return aPathElems.join( QLatin1Char( '/' ) );
1761}
1762
1763QString QgsApplication::relativePathToAbsolutePath( const QString &rpath, const QString &targetPath )
1764{
1765 // relative path should always start with ./ or ../
1766 if ( !rpath.startsWith( QLatin1String( "./" ) ) && !rpath.startsWith( QLatin1String( "../" ) ) )
1767 {
1768 return rpath;
1769 }
1770
1771 QString rPathUrl = rpath;
1772 QString targetPathUrl = targetPath;
1773
1774#if defined(Q_OS_WIN)
1775 rPathUrl.replace( '\\', '/' );
1776 targetPathUrl.replace( '\\', '/' );
1777
1778 bool uncPath = targetPathUrl.startsWith( "//" );
1779#endif
1780
1781#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1782 QStringList srcElems = rPathUrl.split( '/', QString::SkipEmptyParts );
1783 QStringList targetElems = targetPathUrl.split( '/', QString::SkipEmptyParts );
1784#else
1785 QStringList srcElems = rPathUrl.split( '/', Qt::SkipEmptyParts );
1786 QStringList targetElems = targetPathUrl.split( '/', Qt::SkipEmptyParts );
1787#endif
1788
1789#if defined(Q_OS_WIN)
1790 if ( uncPath )
1791 {
1792 targetElems.insert( 0, "" );
1793 targetElems.insert( 0, "" );
1794 }
1795#endif
1796
1797 // append source path elements
1798 targetElems << srcElems;
1799 targetElems.removeAll( QStringLiteral( "." ) );
1800
1801 // resolve ..
1802 int pos;
1803 while ( ( pos = targetElems.indexOf( QLatin1String( ".." ) ) ) > 0 )
1804 {
1805 // remove preceding element and ..
1806 targetElems.removeAt( pos - 1 );
1807 targetElems.removeAt( pos - 1 );
1808 }
1809
1810#if !defined(Q_OS_WIN)
1811 // make path absolute
1812 targetElems.prepend( QString() );
1813#endif
1814
1815 return targetElems.join( QLatin1Char( '/' ) );
1816}
1817
1819{
1820 return *sBuildSourcePath();
1821}
1822
1824{
1825 return *sBuildOutputPath();
1826}
1827
1828#if defined(_MSC_VER) && !defined(USING_NMAKE) && !defined(USING_NINJA)
1829QString QgsApplication::cfgIntDir()
1830{
1831 return *sCfgIntDir();
1832}
1833#endif
1834
1835void QgsApplication::skipGdalDriver( const QString &driver )
1836{
1837 if ( sGdalSkipList()->contains( driver ) || driver.isEmpty() )
1838 {
1839 return;
1840 }
1841 *sGdalSkipList() << driver;
1843}
1844
1845void QgsApplication::restoreGdalDriver( const QString &driver )
1846{
1847 if ( !sGdalSkipList()->contains( driver ) )
1848 {
1849 return;
1850 }
1851 int myPos = sGdalSkipList()->indexOf( driver );
1852 if ( myPos >= 0 )
1853 {
1854 sGdalSkipList()->removeAt( myPos );
1855 }
1857}
1858
1860{
1861 return *sGdalSkipList();
1862}
1863
1864void QgsApplication::setSkippedGdalDrivers( const QStringList &skippedGdalDrivers,
1865 const QStringList &deferredSkippedGdalDrivers )
1866{
1867 *sGdalSkipList() = skippedGdalDrivers;
1868 *sDeferredSkippedGdalDrivers() = deferredSkippedGdalDrivers;
1869
1870 QgsSettings settings;
1871 settings.setValue( QStringLiteral( "gdal/skipDrivers" ), skippedGdalDrivers.join( QLatin1Char( ',' ) ) );
1872
1874}
1875
1877{
1878 QgsSettings settings;
1879 QString joinedList, delimiter;
1880 if ( settings.contains( QStringLiteral( "gdal/skipDrivers" ) ) )
1881 {
1882 joinedList = settings.value( QStringLiteral( "gdal/skipDrivers" ), QString() ).toString();
1883 delimiter = QStringLiteral( "," );
1884 }
1885 else
1886 {
1887 joinedList = settings.value( QStringLiteral( "gdal/skipList" ), QString() ).toString();
1888 delimiter = QStringLiteral( " " );
1889 }
1890 QStringList myList;
1891 if ( !joinedList.isEmpty() )
1892 {
1893 myList = joinedList.split( delimiter );
1894 }
1895 *sGdalSkipList() = myList;
1897}
1898
1900{
1901 return *sDeferredSkippedGdalDrivers();
1902}
1903
1905{
1906 sGdalSkipList()->removeDuplicates();
1907 QStringList realDisabledDriverList;
1908 for ( const auto &driverName : *sGdalSkipList() )
1909 {
1910 if ( !sDeferredSkippedGdalDrivers()->contains( driverName ) )
1911 realDisabledDriverList << driverName;
1912 }
1913 QString myDriverList = realDisabledDriverList.join( ',' );
1914 QgsDebugMsgLevel( QStringLiteral( "Gdal Skipped driver list set to:" ), 2 );
1915 QgsDebugMsgLevel( myDriverList, 2 );
1916 CPLSetConfigOption( "GDAL_SKIP", myDriverList.toUtf8() );
1917 GDALAllRegister(); //to update driver list and skip missing ones
1918}
1919
1921{
1922 QString folder = userThemesFolder();
1923 QDir myDir( folder );
1924 if ( !myDir.exists() )
1925 {
1926 myDir.mkpath( folder );
1927 }
1928
1929 return true;
1930}
1931
1932void QgsApplication::copyPath( const QString &src, const QString &dst )
1933{
1934 QDir dir( src );
1935 if ( ! dir.exists() )
1936 return;
1937
1938 const auto subDirectories = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
1939 for ( const QString &d : subDirectories )
1940 {
1941 QString dst_path = dst + QDir::separator() + d;
1942 dir.mkpath( dst_path );
1943 copyPath( src + QDir::separator() + d, dst_path );
1944 }
1945
1946 const auto files = dir.entryList( QDir::Files );
1947 for ( const QString &f : files )
1948 {
1949 QFile::copy( src + QDir::separator() + f, dst + QDir::separator() + f );
1950 }
1951}
1952
1954{
1955 //read values from QgsSettings
1956 QgsSettings settings;
1957
1958 QVariantMap variables;
1959
1960 //check if settings contains any variables
1961 settings.beginGroup( "variables" );
1962 QStringList childKeys = settings.childKeys();
1963 for ( QStringList::const_iterator it = childKeys.constBegin(); it != childKeys.constEnd(); ++it )
1964 {
1965 QString name = *it;
1966 variables.insert( name, settings.value( name ) );
1967 }
1968
1969 return variables;
1970}
1971
1972void QgsApplication::setCustomVariables( const QVariantMap &variables )
1973{
1974 QgsSettings settings;
1975
1976 QVariantMap::const_iterator it = variables.constBegin();
1977 settings.beginGroup( "variables" );
1978 settings.remove( "" );
1979 for ( ; it != variables.constEnd(); ++it )
1980 {
1981 settings.setValue( it.key(), it.value() );
1982 }
1983
1985}
1986
1987void QgsApplication::setCustomVariable( const QString &name, const QVariant &value )
1988{
1989 // save variable to settings
1990 QgsSettings settings;
1991
1992 settings.setValue( QStringLiteral( "variables/" ) + name, value );
1993
1995}
1996
1997int QgsApplication::scaleIconSize( int standardSize, bool applyDevicePixelRatio )
1998{
1999 QFontMetrics fm( ( QFont() ) );
2000 const double scale = 1.1 * standardSize / 24;
2001 int scaledIconSize = static_cast< int >( std::floor( std::max( Qgis::UI_SCALE_FACTOR * fm.height() * scale, static_cast< double >( standardSize ) ) ) );
2002 if ( applyDevicePixelRatio )
2003 {
2004 if ( QWidget *activeWindow = QApplication::activeWindow() )
2005 scaledIconSize *= ( activeWindow->screen() ? QApplication::activeWindow()->screen()->devicePixelRatio() : 1 );
2006 }
2007 return scaledIconSize;
2008}
2009
2011{
2013}
2014
2015void QgsApplication::setTranslation( const QString &translation )
2016{
2017 *sTranslation() = translation;
2018}
2019
2021{
2022 return *sTranslation();
2023}
2024
2026{
2027 emit requestForTranslatableObjects( translationContext );
2028}
2029
2031{
2032 ApplicationMembers *appMembers = members();
2033 if ( appMembers->mNullRepresentation.isNull() )
2034 {
2035 appMembers->mNullRepresentation = QgsSettings().value( QStringLiteral( "qgis/nullValue" ), QStringLiteral( "NULL" ) ).toString();
2036 }
2037 return appMembers->mNullRepresentation;
2038}
2039
2040void QgsApplication::setNullRepresentation( const QString &nullRepresentation )
2041{
2042 ApplicationMembers *appMembers = members();
2043 if ( !appMembers || appMembers->mNullRepresentation == nullRepresentation )
2044 return;
2045
2046 appMembers->mNullRepresentation = nullRepresentation;
2047 QgsSettings().setValue( QStringLiteral( "qgis/nullValue" ), nullRepresentation );
2048
2049 QgsApplication *app = instance();
2050 if ( app )
2051 emit app->nullRepresentationChanged();
2052}
2053
2055{
2056 return members()->mActionScopeRegistry;
2057}
2058
2059bool QgsApplication::createDatabase( QString *errorMessage )
2060{
2061 // set a working directory up for gdal to write .aux.xml files into
2062 // for cases where the raster dir is read only to the user
2063 // if the env var is already set it will be used preferentially
2064 QString myPamPath = qgisSettingsDirPath() + QStringLiteral( "gdal_pam/" );
2065 QDir myDir( myPamPath );
2066 if ( !myDir.exists() )
2067 {
2068 myDir.mkpath( myPamPath ); //fail silently
2069 }
2070
2071#if defined(Q_OS_WIN)
2072 CPLSetConfigOption( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8() );
2073#else
2074 //under other OS's we use an environment var so the user can
2075 //override the path if he likes
2076 int myChangeFlag = 0; //whether we want to force the env var to change
2077 setenv( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8(), myChangeFlag );
2078#endif
2079
2080 // Check qgis.db and make private copy if necessary
2081 QFile qgisPrivateDbFile( QgsApplication::qgisUserDatabaseFilePath() );
2082
2083 // first we look for ~/.qgis/qgis.db
2084 if ( !qgisPrivateDbFile.exists() )
2085 {
2086 // if it doesn't exist we copy it in from the global resources dir
2087 QString qgisMasterDbFileName = QgsApplication::qgisMasterDatabaseFilePath();
2088 QFile masterFile( qgisMasterDbFileName );
2089
2090 // Must be sure there is destination directory ~/.qgis
2091 QDir().mkpath( QgsApplication::qgisSettingsDirPath() );
2092
2093 //now copy the master file into the users .qgis dir
2094 bool isDbFileCopied = masterFile.copy( qgisPrivateDbFile.fileName() );
2095
2096 if ( !isDbFileCopied )
2097 {
2098 if ( errorMessage )
2099 {
2100 *errorMessage = tr( "[ERROR] Can not make qgis.db private copy" );
2101 }
2102 return false;
2103 }
2104
2105 QFile::Permissions perms = QFile( qgisPrivateDbFile.fileName() ).permissions();
2106 if ( !( perms & QFile::WriteOwner ) )
2107 {
2108 if ( !qgisPrivateDbFile.setPermissions( perms | QFile::WriteOwner ) )
2109 {
2110 if ( errorMessage )
2111 {
2112 *errorMessage = tr( "Can not make '%1' user writable" ).arg( qgisPrivateDbFile.fileName() );
2113 }
2114 return false;
2115 }
2116 }
2117 }
2118 else
2119 {
2120 // migrate if necessary
2122 if ( database.open( QgsApplication::qgisUserDatabaseFilePath() ) != SQLITE_OK )
2123 {
2124 if ( errorMessage )
2125 {
2126 *errorMessage = tr( "Could not open qgis.db" );
2127 }
2128 return false;
2129 }
2130
2131 char *errmsg = nullptr;
2132 int res = sqlite3_exec( database.get(), "SELECT srs_id FROM tbl_srs LIMIT 0", nullptr, nullptr, &errmsg );
2133 if ( res != SQLITE_OK )
2134 {
2135 sqlite3_free( errmsg );
2136
2137 // qgis.db is missing tbl_srs, create it
2138 if ( sqlite3_exec( database.get(),
2139 "DROP INDEX IF EXISTS idx_srsauthid;"
2140 "CREATE TABLE tbl_srs ("
2141 "srs_id INTEGER PRIMARY KEY,"
2142 "description text NOT NULL,"
2143 "projection_acronym text NOT NULL,"
2144 "ellipsoid_acronym NOT NULL,"
2145 "parameters text NOT NULL,"
2146 "srid integer,"
2147 "auth_name varchar,"
2148 "auth_id varchar,"
2149 "is_geo integer NOT NULL,"
2150 "deprecated boolean,"
2151 "wkt text);"
2152 "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);", nullptr, nullptr, &errmsg ) != SQLITE_OK )
2153 {
2154 if ( errorMessage )
2155 {
2156 *errorMessage = tr( "Creation of missing tbl_srs in the private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
2157 }
2158 sqlite3_free( errmsg );
2159 return false;
2160 }
2161 }
2162 else
2163 {
2164 // test if wkt column exists in database
2165 res = sqlite3_exec( database.get(), "SELECT wkt FROM tbl_srs LIMIT 0", nullptr, nullptr, &errmsg );
2166 if ( res != SQLITE_OK )
2167 {
2168 // need to add wkt column
2169 sqlite3_free( errmsg );
2170 if ( sqlite3_exec( database.get(),
2171 "DROP INDEX IF EXISTS idx_srsauthid;"
2172 "DROP TABLE IF EXISTS tbl_srs_bak;"
2173 "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
2174 "CREATE TABLE tbl_srs ("
2175 "srs_id INTEGER PRIMARY KEY,"
2176 "description text NOT NULL,"
2177 "projection_acronym text NOT NULL,"
2178 "ellipsoid_acronym NOT NULL,"
2179 "parameters text NOT NULL,"
2180 "srid integer,"
2181 "auth_name varchar,"
2182 "auth_id varchar,"
2183 "is_geo integer NOT NULL,"
2184 "deprecated boolean,"
2185 "wkt text);"
2186 "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
2187 "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;"
2188 "DROP TABLE tbl_srs_bak", nullptr, nullptr, &errmsg ) != SQLITE_OK )
2189 {
2190 if ( errorMessage )
2191 {
2192 *errorMessage = tr( "Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
2193 }
2194 sqlite3_free( errmsg );
2195 return false;
2196 }
2197 }
2198 }
2199
2200 res = sqlite3_exec( database.get(), "SELECT acronym FROM tbl_projection LIMIT 0", nullptr, nullptr, &errmsg );
2201 if ( res != SQLITE_OK )
2202 {
2203 sqlite3_free( errmsg );
2204
2205 // qgis.db is missing tbl_projection, create it
2206 if ( sqlite3_exec( database.get(),
2207 "CREATE TABLE tbl_projection ("
2208 "acronym varchar(20) NOT NULL PRIMARY KEY,"
2209 "name varchar(255) NOT NULL default '',"
2210 "notes varchar(255) NOT NULL default '',"
2211 "parameters varchar(255) NOT NULL default ''"
2212 ")", nullptr, nullptr, &errmsg ) != SQLITE_OK )
2213 {
2214 if ( errorMessage )
2215 {
2216 *errorMessage = tr( "Creation of missing tbl_projection in the private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
2217 }
2218 sqlite3_free( errmsg );
2219 return false;
2220 }
2221 }
2222
2223 res = sqlite3_exec( database.get(), "SELECT epsg FROM tbl_srs LIMIT 0", nullptr, nullptr, &errmsg );
2224 if ( res == SQLITE_OK )
2225 {
2226 // epsg column exists => need migration
2227 if ( sqlite3_exec( database.get(),
2228 "DROP INDEX IF EXISTS idx_srsauthid;"
2229 "DROP TABLE IF EXISTS tbl_srs_bak;"
2230 "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
2231 "CREATE TABLE tbl_srs ("
2232 "srs_id INTEGER PRIMARY KEY,"
2233 "description text NOT NULL,"
2234 "projection_acronym text NOT NULL,"
2235 "ellipsoid_acronym NOT NULL,"
2236 "parameters text NOT NULL,"
2237 "srid integer,"
2238 "auth_name varchar,"
2239 "auth_id varchar,"
2240 "is_geo integer NOT NULL,"
2241 "deprecated boolean,"
2242 "wkt text);"
2243 "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
2244 "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;"
2245 "DROP TABLE tbl_srs_bak", nullptr, nullptr, &errmsg ) != SQLITE_OK )
2246 {
2247 if ( errorMessage )
2248 {
2249 *errorMessage = tr( "Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
2250 }
2251 sqlite3_free( errmsg );
2252 return false;
2253 }
2254 }
2255 else
2256 {
2257 sqlite3_free( errmsg );
2258 }
2259
2260 if ( sqlite3_exec( database.get(), "DROP VIEW vw_srs", nullptr, nullptr, &errmsg ) != SQLITE_OK )
2261 {
2262 QgsDebugMsg( QStringLiteral( "vw_srs didn't exists in private qgis.db: %1" ).arg( errmsg ) );
2263 }
2264
2265 if ( sqlite3_exec( database.get(),
2266 "CREATE VIEW vw_srs AS"
2267 " SELECT"
2268 " a.description AS description"
2269 ",a.srs_id AS srs_id"
2270 ",a.is_geo AS is_geo"
2271 ",coalesce(b.name,a.projection_acronym) AS name"
2272 ",a.parameters AS parameters"
2273 ",a.auth_name AS auth_name"
2274 ",a.auth_id AS auth_id"
2275 ",a.deprecated AS deprecated"
2276 " FROM tbl_srs a"
2277 " LEFT OUTER JOIN tbl_projection b ON a.projection_acronym=b.acronym"
2278 " ORDER BY coalesce(b.name,a.projection_acronym),a.description", nullptr, nullptr, &errmsg ) != SQLITE_OK )
2279 {
2280 if ( errorMessage )
2281 {
2282 *errorMessage = tr( "Update of view in private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
2283 }
2284 sqlite3_free( errmsg );
2285 return false;
2286 }
2287 }
2288 return true;
2289}
2290
2291void QgsApplication::setMaxThreads( int maxThreads )
2292{
2293 QgsDebugMsgLevel( QStringLiteral( "maxThreads: %1" ).arg( maxThreads ), 2 );
2294
2295 // make sure value is between 1 and #cores, if not set to -1 (use #cores)
2296 // 0 could be used to disable any parallel processing
2297 if ( maxThreads < 1 || maxThreads > QThread::idealThreadCount() )
2298 maxThreads = -1;
2299
2300 // save value
2301 ABISYM( sMaxThreads ) = maxThreads;
2302
2303 // if -1 use #cores
2304 if ( maxThreads == -1 )
2305 maxThreads = QThread::idealThreadCount();
2306
2307 // set max thread count in QThreadPool
2308 QThreadPool::globalInstance()->setMaxThreadCount( maxThreads );
2309 QgsDebugMsgLevel( QStringLiteral( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ), 2 );
2310}
2311
2313{
2314 return members()->mTaskManager;
2315}
2316
2318{
2319 return members()->mSettingsRegistryCore;
2320}
2321
2323{
2324 return members()->mColorSchemeRegistry;
2325}
2326
2328{
2329 return members()->mPaintEffectRegistry;
2330}
2331
2333{
2334 return members()->mRendererRegistry;
2335}
2336
2338{
2339 return members()->mRasterRendererRegistry;
2340}
2341
2343{
2344 return members()->mPointCloudRendererRegistry;
2345}
2346
2348{
2349 if ( auto *lInstance = instance() )
2350 {
2351 if ( !instance()->mDataItemProviderRegistry )
2352 {
2353 lInstance->mDataItemProviderRegistry = new QgsDataItemProviderRegistry();
2354 }
2355 return lInstance->mDataItemProviderRegistry;
2356 }
2357 else
2358 {
2359 // no QgsApplication instance
2360 static QgsDataItemProviderRegistry *sDataItemProviderRegistry = nullptr;
2361 if ( !sDataItemProviderRegistry )
2362 sDataItemProviderRegistry = new QgsDataItemProviderRegistry();
2363 return sDataItemProviderRegistry;
2364 }
2365}
2366
2368{
2369 return members()->mCrsRegistry;
2370}
2371
2373{
2374 return members()->mSvgCache;
2375}
2376
2378{
2379 return members()->mImageCache;
2380}
2381
2383{
2384 return members()->mSourceCache;
2385}
2386
2388{
2389 return members()->mNetworkContentFetcherRegistry;
2390}
2391
2393{
2394 return members()->mValidityCheckRegistry;
2395}
2396
2398{
2399 return members()->mSymbolLayerRegistry;
2400}
2401
2403{
2404 return members()->mCalloutRegistry;
2405}
2406
2408{
2409 return members()->mLayoutItemRegistry;
2410}
2411
2413{
2414 return members()->mAnnotationItemRegistry;
2415}
2416
2418{
2419 return members()->mGpsConnectionRegistry;
2420}
2421
2423{
2424 return members()->mGpsBabelFormatRegistry;
2425}
2426
2428{
2429 return members()->mPluginLayerRegistry;
2430}
2431
2433{
2434 return members()->mClassificationMethodRegistry;
2435}
2436
2438{
2439 return members()->mBookmarkManager;
2440}
2441
2443{
2444 return members()->mTileDownloadManager;
2445}
2446
2448{
2449 return members()->mRecentStyleHandler;
2450}
2451
2453{
2454 return members()->mQueryLogger;
2455}
2456
2458{
2459 return members()->mStyleModel;
2460}
2461
2463{
2464 return members()->mFontManager;
2465}
2466
2468{
2469 return members()->mMessageLog;
2470}
2471
2473{
2474 return members()->mProcessingRegistry;
2475}
2476
2478{
2479 return members()->mConnectionRegistry;
2480}
2481
2483{
2484 return members()->mLayerMetadataProviderRegistry;
2485}
2486
2488{
2489 return members()->mPageSizeRegistry;
2490}
2491
2493{
2494 return members()->mAnnotationRegistry;
2495}
2496
2498{
2499 return members()->mNumericFormatRegistry;
2500}
2501
2503{
2504 return members()->mFieldFormatterRegistry;
2505}
2506
2508{
2509 return members()->m3DRendererRegistry;
2510}
2511
2513{
2514 return members()->m3DSymbolRegistry;
2515}
2516
2518{
2519 return members()->mScaleBarRendererRegistry;
2520}
2521
2523{
2524 return members()->mProjectStorageRegistry;
2525}
2526
2528{
2529 return members()->mExternalStorageRegistry;
2530}
2531
2533{
2534 return members()->mLocalizedDataPathRegistry;
2535}
2536
2537QgsApplication::ApplicationMembers::ApplicationMembers()
2538{
2539 // don't use initializer lists or scoped pointers - as more objects are added here we
2540 // will need to be careful with the order of creation/destruction
2541 mSettingsRegistryCore = new QgsSettingsRegistryCore();
2542 mLocalizedDataPathRegistry = new QgsLocalizedDataPathRegistry();
2543 mMessageLog = new QgsMessageLog();
2544 QgsRuntimeProfiler *profiler = QgsRuntimeProfiler::threadLocalInstance();
2545
2546 {
2547 profiler->start( tr( "Create query logger" ) );
2548 mQueryLogger = new QgsDatabaseQueryLog();
2549 profiler->end();
2550 }
2551 {
2552 profiler->start( tr( "Setup coordinate reference system registry" ) );
2553 mCrsRegistry = new QgsCoordinateReferenceSystemRegistry();
2554 profiler->end();
2555 }
2556 {
2557 profiler->start( tr( "Create connection registry" ) );
2558 mConnectionRegistry = new QgsConnectionRegistry();
2559 profiler->end();
2560 }
2561 {
2562 profiler->start( tr( "Create project storage registry" ) );
2563 mProjectStorageRegistry = new QgsProjectStorageRegistry();
2564 profiler->end();
2565 }
2566 {
2567 profiler->start( tr( "Create metadata provider registry" ) );
2568 mLayerMetadataProviderRegistry = new QgsLayerMetadataProviderRegistry();
2569 profiler->end();
2570 }
2571 {
2572 profiler->start( tr( "Create font manager" ) );
2573 mFontManager = new QgsFontManager();
2574 profiler->end();
2575 }
2576 {
2577 profiler->start( tr( "Setup task manager" ) );
2578 mTaskManager = new QgsTaskManager();
2579 profiler->end();
2580 }
2581 {
2582 profiler->start( tr( "Setup action scope registry" ) );
2583 mActionScopeRegistry = new QgsActionScopeRegistry();
2584 profiler->end();
2585 }
2586 {
2587 profiler->start( tr( "Setup numeric formats" ) );
2588 mNumericFormatRegistry = new QgsNumericFormatRegistry();
2589 profiler->end();
2590 }
2591 {
2592 profiler->start( tr( "Setup field formats" ) );
2593 mFieldFormatterRegistry = new QgsFieldFormatterRegistry();
2594 profiler->end();
2595 }
2596 {
2597 profiler->start( tr( "Setup SVG cache" ) );
2598 mSvgCache = new QgsSvgCache();
2599 profiler->end();
2600 }
2601 {
2602 profiler->start( tr( "Setup image cache" ) );
2603 mImageCache = new QgsImageCache();
2604 profiler->end();
2605 }
2606 {
2607 profiler->start( tr( "Setup source cache" ) );
2608 mSourceCache = new QgsSourceCache();
2609 profiler->end();
2610 }
2611 {
2612 profiler->start( tr( "Setup color scheme registry" ) );
2613 mColorSchemeRegistry = new QgsColorSchemeRegistry();
2614 profiler->end();
2615 }
2616 {
2617 profiler->start( tr( "Setup paint effect" ) );
2618 mPaintEffectRegistry = new QgsPaintEffectRegistry();
2619 profiler->end();
2620 }
2621 {
2622 profiler->start( tr( "Setup symbol layer registry" ) );
2623 mSymbolLayerRegistry = new QgsSymbolLayerRegistry();
2624 profiler->end();
2625 }
2626 {
2627 profiler->start( tr( "Recent style handler" ) );
2628 mRecentStyleHandler = new QgsRecentStyleHandler();
2629 profiler->end();
2630 }
2631 {
2632 profiler->start( tr( "Setup callout registry" ) );
2633 mCalloutRegistry = new QgsCalloutRegistry();
2634 profiler->end();
2635 }
2636 {
2637 profiler->start( tr( "Setup renderer registry" ) );
2638 mRendererRegistry = new QgsRendererRegistry();
2639 profiler->end();
2640 }
2641 {
2642 profiler->start( tr( "Setup raster renderer registry" ) );
2643 mRasterRendererRegistry = new QgsRasterRendererRegistry();
2644 profiler->end();
2645 }
2646 {
2647 profiler->start( tr( "Setup point cloud renderer registry" ) );
2648 mPointCloudRendererRegistry = new QgsPointCloudRendererRegistry();
2649 profiler->end();
2650 }
2651 {
2652 profiler->start( tr( "Setup GPS registry" ) );
2653 mGpsConnectionRegistry = new QgsGpsConnectionRegistry();
2654 profiler->end();
2655 }
2656 {
2657 profiler->start( tr( "Setup GPSBabel format registry" ) );
2658 mGpsBabelFormatRegistry = new QgsBabelFormatRegistry();
2659 profiler->end();
2660 }
2661 {
2662 profiler->start( tr( "Setup plugin layer registry" ) );
2663 mPluginLayerRegistry = new QgsPluginLayerRegistry();
2664 profiler->end();
2665 }
2666 {
2667 profiler->start( tr( "Setup Processing registry" ) );
2668 mProcessingRegistry = new QgsProcessingRegistry();
2669 profiler->end();
2670 }
2671 mPageSizeRegistry = new QgsPageSizeRegistry();
2672 {
2673 profiler->start( tr( "Setup layout item registry" ) );
2674 mLayoutItemRegistry = new QgsLayoutItemRegistry();
2675 mLayoutItemRegistry->populate();
2676 profiler->end();
2677 }
2678 {
2679 profiler->start( tr( "Setup annotation registry" ) );
2680 mAnnotationRegistry = new QgsAnnotationRegistry();
2681 profiler->end();
2682 }
2683 {
2684 profiler->start( tr( "Setup annotation item registry" ) );
2685 mAnnotationItemRegistry = new QgsAnnotationItemRegistry();
2686 mAnnotationItemRegistry->populate();
2687 profiler->end();
2688 }
2689 {
2690 profiler->start( tr( "Setup 3D symbol registry" ) );
2691 m3DSymbolRegistry = new Qgs3DSymbolRegistry();
2692 profiler->end();
2693 }
2694 {
2695 profiler->start( tr( "Setup 3D renderer registry" ) );
2696 m3DRendererRegistry = new Qgs3DRendererRegistry();
2697 profiler->end();
2698 }
2699 {
2700 profiler->start( tr( "Setup project storage registry" ) );
2701 mProjectStorageRegistry = new QgsProjectStorageRegistry();
2702 profiler->end();
2703 }
2704 {
2705 profiler->start( tr( "Setup layer metadata provider registry" ) );
2706 mLayerMetadataProviderRegistry = new QgsLayerMetadataProviderRegistry();
2707 profiler->end();
2708 }
2709 {
2710 profiler->start( tr( "Setup external storage registry" ) );
2711 mExternalStorageRegistry = new QgsExternalStorageRegistry();
2712 profiler->end();
2713 }
2714 {
2715 profiler->start( tr( "Setup network content cache" ) );
2716 mNetworkContentFetcherRegistry = new QgsNetworkContentFetcherRegistry();
2717 profiler->end();
2718 }
2719 {
2720 profiler->start( tr( "Setup layout check registry" ) );
2721 mValidityCheckRegistry = new QgsValidityCheckRegistry();
2722 profiler->end();
2723 }
2724 {
2725 profiler->start( tr( "Setup classification registry" ) );
2726 mClassificationMethodRegistry = new QgsClassificationMethodRegistry();
2727 profiler->end();
2728 }
2729 {
2730 profiler->start( tr( "Setup bookmark manager" ) );
2731 mBookmarkManager = new QgsBookmarkManager( nullptr );
2732 profiler->end();
2733 }
2734 {
2735 profiler->start( tr( "Setup tile download manager" ) );
2736 mTileDownloadManager = new QgsTileDownloadManager();
2737 profiler->end();
2738 }
2739 {
2740 profiler->start( tr( "Setup scalebar registry" ) );
2741 mScaleBarRendererRegistry = new QgsScaleBarRendererRegistry();
2742 profiler->end();
2743 }
2744}
2745
2746QgsApplication::ApplicationMembers::~ApplicationMembers()
2747{
2748 delete mStyleModel;
2749 delete mTileDownloadManager;
2750 delete mScaleBarRendererRegistry;
2751 delete mValidityCheckRegistry;
2752 delete mActionScopeRegistry;
2753 delete m3DRendererRegistry;
2754 delete m3DSymbolRegistry;
2755 delete mAnnotationRegistry;
2756 delete mColorSchemeRegistry;
2757 delete mFieldFormatterRegistry;
2758 delete mGpsConnectionRegistry;
2759 delete mGpsBabelFormatRegistry;
2760 delete mMessageLog;
2761 delete mPaintEffectRegistry;
2762 delete mPluginLayerRegistry;
2763 delete mProcessingRegistry;
2764 delete mPageSizeRegistry;
2765 delete mAnnotationItemRegistry;
2766 delete mLayoutItemRegistry;
2767 delete mPointCloudRendererRegistry;
2768 delete mRasterRendererRegistry;
2769 delete mRendererRegistry;
2770 delete mSvgCache;
2771 delete mImageCache;
2772 delete mSourceCache;
2773 delete mCalloutRegistry;
2774 delete mRecentStyleHandler;
2775 delete mSymbolLayerRegistry;
2776 delete mExternalStorageRegistry;
2777 delete mTaskManager;
2778 delete mNetworkContentFetcherRegistry;
2779 delete mClassificationMethodRegistry;
2780 delete mNumericFormatRegistry;
2781 delete mBookmarkManager;
2782 delete mConnectionRegistry;
2783 delete mProjectStorageRegistry;
2784 delete mLayerMetadataProviderRegistry;
2785 delete mFontManager;
2786 delete mLocalizedDataPathRegistry;
2787 delete mCrsRegistry;
2788 delete mQueryLogger;
2789 delete mSettingsRegistryCore;
2790}
2791
2792QgsApplication::ApplicationMembers *QgsApplication::members()
2793{
2794 if ( auto *lInstance = instance() )
2795 {
2796 return lInstance->mApplicationMembers;
2797 }
2798 else
2799 {
2800 static QRecursiveMutex sMemberMutex;
2801 QMutexLocker lock( &sMemberMutex );
2802 if ( !sApplicationMembers )
2803 sApplicationMembers = new ApplicationMembers();
2804 return sApplicationMembers;
2805 }
2806}
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:2284
Keeps track of available 3D renderers.
Registry of available 3D symbol classes.
The action scope registry is an application wide registry that contains a list of available action sc...
Registry of available annotation item types.
Extends QApplication to provide access to QGIS specific resources such as theme paths,...
static QString resolvePkgPath()
Calculate the application pkg path.
static int scaleIconSize(int standardSize, bool applyDevicePixelRatio=false)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
static void restoreGdalDriver(const QString &driver)
Sets the GDAL_SKIP environment variable to exclude the specified driver and then calls GDALDriverMana...
static void setCustomVariables(const QVariantMap &customVariables)
Custom expression variables for this application.
QString translation() const
Returns the current application translation locale code.
static QString i18nPath()
Returns the path to the translation directory.
static QgsAnnotationItemRegistry * annotationItemRegistry()
Returns the application's annotation item registry, used for annotation item types.
static QString osName()
Returns a string name of the operating system QGIS is running on.
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
static QString sponsorsFilePath()
Returns the path to the sponsors file.
static QgsRecentStyleHandler * recentStyleHandler()
Returns the handler for recently used style items.
endian_t
Constants for endian-ness.
static QString qgisMasterDatabaseFilePath()
Returns the path to the master qgis.db file.
static void skipGdalDriver(const QString &driver)
Sets the GDAL_SKIP environment variable to include the specified driver and then calls GDALDriverMana...
static QString defaultThemePath()
Returns the path to the default theme directory.
static QgsPageSizeRegistry * pageSizeRegistry()
Returns the application's page size registry, used for managing layout page sizes.
static QgsValidityCheckRegistry * validityCheckRegistry()
Returns the application's validity check registry, used for managing validity checks.
static QgsDataItemProviderRegistry * dataItemProviderRegistry()
Returns the application's data item provider registry, which keeps a list of data item providers that...
static QString userStylePath()
Returns the path to user's style.
static QString platform()
Returns the QGIS platform name, e.g., "desktop", "server", "qgis_process" or "external" (for external...
static QgsProcessingRegistry * processingRegistry()
Returns the application's processing registry, used for managing processing providers,...
static QgsLayerMetadataProviderRegistry * layerMetadataProviderRegistry()
Returns registry of available layer metadata provider implementations.
static QgsConnectionRegistry * connectionRegistry()
Returns the application's connection registry, used for managing saved data provider connections.
static void exitQgis()
deletes provider registry and map layer registry
static void setPluginPath(const QString &pluginPath)
Alters plugin path - used by 3rd party apps.
static QPixmap getThemePixmap(const QString &name, const QColor &foreColor=QColor(), const QColor &backColor=QColor(), int size=16)
Helper to get a theme icon as a pixmap.
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
static QVariantMap customVariables()
Custom expression variables for this application.
static QgsPointCloudRendererRegistry * pointCloudRendererRegistry()
Returns the application's point cloud renderer registry, used for managing point cloud layer 2D rende...
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application's paint effect registry, used for managing paint effects.
static QString pluginPath()
Returns the path to the application plugin directory.
static void setUITheme(const QString &themeName)
Set the current UI theme used to style the interface.
static bool createDatabase(QString *errorMessage=nullptr)
initialize qgis.db
static QCursor getThemeCursor(Cursor cursor)
Helper to get a theme cursor.
static int systemMemorySizeMb()
Returns the size of the system memory (RAM) in megabytes.
static void setLocale(const QLocale &locale)
Sets the QGIS locale - used mainly by 3rd party apps and tests.
static void init(QString profileFolder=QString())
This method initializes paths etc for QGIS.
static void setThemeName(const QString &themeName)
Set the active theme to the specified theme.
void customVariablesChanged()
Emitted whenever a custom global variable changes.
static QString buildSourcePath()
Returns path to the source directory. Valid only when running from build directory.
static QString buildOutputPath()
Returns path to the build output directory. Valid only when running from build directory.
bool notify(QObject *receiver, QEvent *event) override
Catch exceptions when sending event to receiver.
static int maxThreads()
Gets maximum concurrent thread count.
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
static QString reportStyleSheet(QgsApplication::StyleSheetType styleSheetType=QgsApplication::StyleSheetType::Qt)
Returns a css style sheet for reports, the styleSheetType argument determines what type of stylesheet...
static QString pkgDataPath()
Returns the common root path of all application data directories.
static QgsScaleBarRendererRegistry * scaleBarRendererRegistry()
Gets the registry of available scalebar renderers.
static QgsLayoutItemRegistry * layoutItemRegistry()
Returns the application's layout item registry, used for layout item types.
static void setFileOpenEventReceiver(QObject *receiver)
Sets the FileOpen event receiver.
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application's symbol layer registry, used for managing symbol layers.
static QgsRasterRendererRegistry * rasterRendererRegistry()
Returns the application's raster renderer registry, used for managing raster layer renderers.
static void applyGdalSkippedDrivers()
Apply the skipped drivers list to gdal.
static void setMaxThreads(int maxThreads)
Set maximum concurrent thread count.
static QgsNumericFormatRegistry * numericFormatRegistry()
Gets the registry of available numeric formats.
static QgsNetworkContentFetcherRegistry * networkContentFetcherRegistry()
Returns the application's network content registry used for fetching temporary files during QGIS sess...
static QgsProjectStorageRegistry * projectStorageRegistry()
Returns registry of available project storage implementations.
static QString licenceFilePath()
Returns the path to the licence file.
static QString libexecPath()
Returns the path with utility executables (help viewer, crssync, ...)
static QStringList skippedGdalDrivers()
Returns the list of gdal drivers that should be skipped (based on GDAL_SKIP environment variable)
StyleSheetType
The StyleSheetType enum represents the stylesheet type that a widget supports.
static QString translatorsFilePath()
Returns the path to the sponsors file.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static void setNullRepresentation(const QString &nullRepresentation)
This string is used to represent the value NULL throughout QGIS.
static QgsGpsConnectionRegistry * gpsConnectionRegistry()
Returns the application's GPS connection registry, used for managing GPS connections.
static QString locale()
Returns the QGIS locale.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
static QStringList svgPaths()
Returns the paths to svg directories.
static void initQgis()
loads providers
static QString showSettings()
Convenience function to get a summary of the paths used in this application instance useful for debug...
bool event(QEvent *event) override
Watch for QFileOpenEvent.
static void setPkgDataPath(const QString &pkgDataPath)
Alters pkg data path - used by 3rd party apps.
static QString absolutePathToRelativePath(const QString &apath, const QString &targetPath)
Converts absolute path to path relative to target.
static QgsRuntimeProfiler * profiler()
Returns the application runtime profiler.
~QgsApplication() override
static QgsLocalizedDataPathRegistry * localizedDataPathRegistry()
Returns the registry of data repositories These are used as paths for basemaps, logos,...
static const char * QGIS_APPLICATION_NAME
static QgsTileDownloadManager * tileDownloadManager()
Returns the application's tile download manager, used for download of map tiles when rendering.
static const char * QGIS_ORGANIZATION_DOMAIN
static QMap< QString, QString > systemEnvVars()
Returns the system environment variables passed to application.
static void setAuthDatabaseDirPath(const QString &authDbDirPath)
Alters authentication data base directory path - used by 3rd party apps.
static QString prefixPath()
Returns the path to the application prefix directory.
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
static QgsFontManager * fontManager()
Returns the application font manager, which manages available fonts and font installation for the QGI...
static QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
static QgsDatabaseQueryLog * databaseQueryLog()
Returns the database query log.
static QgsMessageLog * messageLog()
Returns the application's message log.
void preNotify(QObject *receiver, QEvent *event, bool *done)
static bool createThemeFolder()
Create the users theme folder.
static QString metadataPath()
Returns the path to the metadata directory.
void localeChanged()
Emitted when project locale has been changed.
static QgsActionScopeRegistry * actionScopeRegistry()
Returns the action scope registry.
static QgsCoordinateReferenceSystemRegistry * coordinateReferenceSystemRegistry()
Returns the application's coordinate reference system (CRS) registry, which handles known CRS definit...
static const QgsSettingsEntryBool settingsLocaleOverrideFlag
Settings entry locale override flag.
static const char * QGIS_ORGANIZATION_NAME
static QString contributorsFilePath()
Returns the path to the contributors file.
static const QgsSettingsEntryStringList settingsSearchPathsForSVG
Settings entry search path for SVG.
void collectTranslatableObjects(QgsTranslationContext *translationContext)
Emits the signal to collect all the strings of .qgs to be included in ts file.
static QgsSourceCache * sourceCache()
Returns the application's source cache, used for caching embedded and remote source strings as local ...
static QRegularExpression shortNameRegularExpression()
Returns the short name regular expression for line edit validator.
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
static QgsAnnotationRegistry * annotationRegistry()
Returns the application's annotation registry, used for managing annotation types.
static QgsPluginLayerRegistry * pluginLayerRegistry()
Returns the application's plugin layer registry, used for managing plugin layer types.
static QgsClassificationMethodRegistry * classificationMethodRegistry()
Returns the application's classification methods registry, used in graduated renderer.
static QStringList deferredSkippedGdalDrivers()
Returns the list of gdal drivers that have been disabled in the current session, and thus,...
static QString defaultStylePath()
Returns the path to default style (works as a starting point).
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
static QString qmlImportPath()
Returns the path where QML components are installed for QGIS Quick library.
Cursor
The Cursor enum defines constants for QGIS custom cursors.
@ ZoomOut
Zoom out.
@ CrossHair
Precisely identify a point on the canvas.
@ Identify
Identify: obtain information about the object.
@ Select
Select a rectangle.
@ CapturePoint
Select and capture a point or a feature.
@ Sampler
Color/Value picker.
@ ZoomIn
Zoom in.
static QString qgisAuthDatabaseFilePath()
Returns the path to the user authentication database file: qgis-auth.db.
static QString authorsFilePath()
Returns the path to the authors file.
static QgsBookmarkManager * bookmarkManager()
Returns the application's bookmark manager, used for storing installation-wide bookmarks.
static QString qgisUserDatabaseFilePath()
Returns the path to the user qgis.db file.
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
static QString activeThemePath()
Returns the path to the currently active theme directory.
static QString defaultThemesFolder()
Returns the path to default themes folder from install (works as a starting point).
static void setSkippedGdalDrivers(const QStringList &skippedGdalDrivers, const QStringList &deferredSkippedGdalDrivers)
Sets the list of gdal drivers that should be disabled (skippedGdalDrivers), but excludes for now the ...
static QgsRendererRegistry * rendererRegistry()
Returns the application's renderer registry, used for managing vector layer renderers.
static void setTranslation(const QString &translation)
Set translation locale code.
static QgsCalloutRegistry * calloutRegistry()
Returns the application's callout registry, used for managing callout types.
static void setPrefixPath(const QString &prefixPath, bool useDefaultPaths=false)
Alters prefix path - used by 3rd party apps.
static QgsStyleModel * defaultStyleModel()
Returns a shared QgsStyleModel containing the default style library (see QgsStyle::defaultStyle()).
static QString relativePathToAbsolutePath(const QString &rpath, const QString &targetPath)
Converts path relative to target to an absolute path.
static void setSvgPaths(const QStringList &svgPaths)
Sets the paths to svg directories and invalidates the svg path list cache.
static QString developersMapFilePath()
Returns the path to the developers map file.
static QgsBabelFormatRegistry * gpsBabelFormatRegistry()
Returns the application's GPSBabel format registry, used for managing GPSBabel formats.
static endian_t endian()
Returns whether this machine uses big or little endian.
int maxConcurrentConnectionsPerPool() const
The maximum number of concurrent connections per connections pool.
static void setCustomVariable(const QString &name, const QVariant &value)
Set a single custom expression variable.
void requestForTranslatableObjects(QgsTranslationContext *translationContext)
Emitted when project strings which require translation are being collected for inclusion in a ....
static QString iconsPath()
Returns the path to the icons image directory.
static Qgs3DSymbolRegistry * symbol3DRegistry()
Returns registry of available 3D symbols.
static QgsExternalStorageRegistry * externalStorageRegistry()
Returns registry of available external storage implementations.
static QHash< QString, QString > uiThemes()
All themes found in ~/.qgis3/themes folder.
static QString splashPath()
Returns the path to the splash screen image directory.
static QString donorsFilePath()
Returns the path to the donors file.
static QString themeName()
Set the active theme to the specified theme.
void nullRepresentationChanged()
This string is used to represent the value NULL throughout QGIS.
static QString srsDatabaseFilePath()
Returns the path to the srs.db file.
static QString userThemesFolder()
Returns the path to user's themes folder.
static void registerGdalDriversFromSettings()
Register gdal drivers, excluding the ones mentioned in "gdal/skipList" setting.
static Qgs3DRendererRegistry * renderer3DRegistry()
Returns registry of available 3D renderers.
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
static void setDefaultSvgPaths(const QStringList &pathList)
Alters default svg paths - used by 3rd party apps.
static QString libraryPath()
Returns the path containing qgis_core, qgis_gui, qgispython (and other) libraries.
static QStringList layoutTemplatePaths()
Returns the paths to layout template directories.
static QString userFullName()
Returns the user's operating system login account full display name.
static QgsSettingsRegistryCore * settingsRegistryCore()
Returns the application's settings registry, used for managing application settings.
static QString serverResourcesPath()
Returns the path to the server resources directory.
static QString appIconPath()
Gets application icon.
static QString userLoginName()
Returns the user's operating system login account name.
static const QgsSettingsEntryString settingsLocaleUserLocale
Settings entry locale user locale.
Singleton offering an interface to manage the authentication configuration database and to utilize co...
bool init(const QString &pluginPath=QString(), const QString &authDatabasePath=QString())
init initialize QCA, prioritize qca-ossl plugin and optionally set up the authentication database
static QgsAuthManager * instance()
Enforce singleton pattern.
A registry for QgsAbstractBabelFormat GPSBabel formats.
Manages storage of a set of bookmarks.
void initialize(const QString &filePath)
Initializes the bookmark manager.
Registry of available callout classes.
This class manages all known classification methods.
Registry of color schemes.
void addDefaultSchemes()
Adds all default color schemes to this color scheme.
void initStyleScheme()
Initializes the default random style color scheme for the user.
A registry for saved data provider connections, allowing retrieval of saved connections by name and p...
A registry for known coordinate reference system (CRS) definitions, including any user-defined CRSes.
static void invalidateCache(bool disableCache=false)
Clears the internal cache used to initialize QgsCoordinateReferenceSystem objects.
static void invalidateCache(bool disableCache=false)
Clears the internal cache used to initialize QgsCoordinateTransform objects.
This class keeps a list of data item providers that may add items to the browser tree.
Handles logging of database queries.
static void applyLocaleChange()
Adjusts the date time formats according to locale.
static void invalidateCache(bool disableCache=false)
Clears the internal cache used.
Defines a QGIS exception class.
Definition: qgsexception.h:35
QString what() const
Definition: qgsexception.h:48
static void cleanRegisteredFunctions()
Deletes all registered functions whose ownership have been transferred to the expression engine.
Registry of external storage backends used by QgsExternalResourceWidget.
The QgsFieldFormatterRegistry manages registered classes of QgsFieldFormatter.
Manages available fonts and font installation for a QGIS instance.
void installUserFonts()
Installs user fonts from the profile/fonts directory as application fonts.
A class to register / unregister existing GPS connections such that the information is available to a...
A cache for images derived from raster files.
Registry of layer metadata provider backends.
Registry of available layout item types.
static const QgsSettingsEntryStringList settingsSearchPathForTemplates
Settings entry search path for templates.
Definition: qgslayout.h:663
A registry class to hold localized data paths which can be used for basemaps, logos,...
Temporarily blocks the application QgsMessageLog (see QgsApplication::messageLog()) from emitting the...
Interface for logging messages from QGIS in GUI independent way.
Definition: qgsmessagelog.h:40
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
Registry for temporary fetched files.
The QgsNumericFormatRegistry manages registered classes of QgsNumericFormat.
A registry for known page sizes.
Registry of available paint effects.
A registry of plugin layers types.
Registry of 2D renderers for point clouds.
Registry for various processing components, including providers, algorithms and various parameters an...
static QStringList searchPaths()
Returns the current list of Proj file search paths.
Registry of storage backends that QgsProject may use.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Registry for raster renderers.
The QgsReadWriteLocker class is a convenience class that simplifies locking and unlocking QReadWriteL...
@ Write
Lock for write.
@ Read
Lock for read.
void changeMode(Mode mode)
Change the mode of the lock to mode.
Handles and tracks style items recently used in the QGIS GUI.
Registry of renderers.
Provides a method of recording run time profiles of operations, allowing easy recording of their over...
void end(const QString &group="startup")
End the current profile event.
void start(const QString &name, const QString &group="startup")
Start a profile event with the given name.
The QgsScaleBarRendererRegistry manages registered scalebar renderers.
Scoped object for logging of the runtime for a single operation or group of operations.
bool setValue(const T &value, const QString &dynamicKeyPart=QString()) const
Set settings value.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
QgsSettingsRegistryCore is used for settings introspection and collects all QgsSettingsEntry instance...
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
bool contains(const QString &key, QgsSettings::Section section=QgsSettings::NoSection) const
Returns true if there exists a setting called key; returns false otherwise.
void beginGroup(const QString &prefix, QgsSettings::Section section=QgsSettings::NoSection)
Appends prefix to the current group.
Definition: qgssettings.cpp:90
QStringList childKeys() const
Returns a list of all top-level keys that can be read using the QSettings object.
void remove(const QString &key, QgsSettings::Section section=QgsSettings::NoSection)
Removes the setting key and any sub-settings of key in a section.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
A cache for source strings that returns a local file path containing the source content.
A QAbstractItemModel subclass for showing symbol and color ramp entities contained within a QgsStyle ...
static void cleanDefaultStyle()
Deletes the default style. Only to be used by QgsApplication::exitQgis()
Definition: qgsstyle.cpp:176
static QgsStyle * defaultStyle()
Returns default application-wide style.
Definition: qgsstyle.cpp:145
A cache for images / pictures derived from SVG files.
Definition: qgssvgcache.h:123
QImage svgAsImage(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > &parameters=QMap< QString, QString >())
Returns an SVG drawing as a QImage.
QByteArray svgContent(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > &parameters=QMap< QString, QString >(), bool *isMissingImage=nullptr)
Gets the SVG content corresponding to the given path.
Registry of available symbol layer classes.
static QColor decodeColor(const QString &str)
Task manager for managing a set of long-running QgsTask tasks.
Tile download manager handles downloads of map tiles for the purpose of map rendering.
Used for the collecting of strings from projects for translation and creation of ts files.
User profile manager is used to manager list, and manage user profiles on the users machine.
QgsUserProfile * getProfile(const QString &defaultProfile="default", bool createNew=true, bool initSettings=true)
Returns the profile from the given root profile location.
static QString resolveProfilesFolder(const QString &basePath=QString())
Resolves the profiles folder for the given path.
User profile contains information about the user profile folders on the machine.
const QString folder() const
The base folder for the user profile.
This class keeps a list of QgsAbstractValidityCheck checks which can be used when performing validity...
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
int open(const QString &path)
Opens the database at the specified file path.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:3002
QObject * ABISYM(QgsApplication::mFileOpenEventReceiver)
#define CONN_POOL_MAX_CONCURRENT_CONNS
Q_GLOBAL_STATIC_WITH_ARGS(PalPropertyList, palHiddenProperties,({ QgsPalLayerSettings::PositionX, QgsPalLayerSettings::PositionY, QgsPalLayerSettings::Show, QgsPalLayerSettings::LabelRotation, QgsPalLayerSettings::Family, QgsPalLayerSettings::FontStyle, QgsPalLayerSettings::Size, QgsPalLayerSettings::Bold, QgsPalLayerSettings::Italic, QgsPalLayerSettings::Underline, QgsPalLayerSettings::Color, QgsPalLayerSettings::Strikeout, QgsPalLayerSettings::MultiLineAlignment, QgsPalLayerSettings::BufferSize, QgsPalLayerSettings::BufferDraw, QgsPalLayerSettings::BufferColor, QgsPalLayerSettings::LabelDistance, QgsPalLayerSettings::Hali, QgsPalLayerSettings::Vali, QgsPalLayerSettings::ScaleVisibility, QgsPalLayerSettings::MinScale, QgsPalLayerSettings::MaxScale, QgsPalLayerSettings::AlwaysShow, QgsPalLayerSettings::CalloutDraw, QgsPalLayerSettings::LabelAllParts })) QgsAuxiliaryLayer
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38