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