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