Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qcoreapplication.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2021 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
8
9#ifndef QT_NO_QOBJECT
11#include "qcoreevent.h"
12#include "qcoreevent_p.h"
13#include "qeventloop.h"
14#endif
15#include "qmetaobject.h"
16#include <private/qproperty_p.h>
17#include <qdatastream.h>
18#include <qdebug.h>
19#include <qdir.h>
20#include <qfile.h>
21#include <qfileinfo.h>
22#include <private/qfilesystementry_p.h>
23#include <qmutex.h>
24#include <private/qloggingregistry_p.h>
25#include <qscopeguard.h>
26#include <qstandardpaths.h>
27#ifndef QT_NO_QOBJECT
28#include <qthread.h>
29#include <qthreadstorage.h>
30#if QT_CONFIG(future)
31#include <QtCore/qpromise.h>
32#endif
33#include <private/qthread_p.h>
34#if QT_CONFIG(thread)
35#include <qthreadpool.h>
36#include <private/qthreadpool_p.h>
37#endif
38#endif
39#include <qlibraryinfo.h>
40#include <qpointer.h>
41#include <qvarlengtharray.h>
42#include <private/qfactoryloader_p.h>
43#include <private/qfunctions_p.h>
44#include <private/qlocale_p.h>
45#include <private/qlocking_p.h>
46#include <private/qhooks_p.h>
47#include <private/qnativeinterface_p.h>
48
49#ifdef Q_OS_WASM
50#include <private/qstdweb_p.h>
51#endif
52
53#if QT_CONFIG(permissions)
54#include <private/qpermissions_p.h>
55#endif
56
57#ifndef QT_NO_QOBJECT
58#if defined(Q_OS_UNIX)
59# if defined(Q_OS_DARWIN)
60# include "qeventdispatcher_cf_p.h"
61# else
62# if !defined(QT_NO_GLIB)
63# include "qeventdispatcher_glib_p.h"
64# endif
65# endif
66# if !defined(Q_OS_WASM)
67# include "qeventdispatcher_unix_p.h"
68# endif
69#endif
70#ifdef Q_OS_WIN
71#include "qeventdispatcher_win_p.h"
72#endif
73#endif // QT_NO_QOBJECT
74
75#if defined(Q_OS_ANDROID)
76#include <QtCore/qjniobject.h>
77#endif
78
79#if defined(Q_OS_HARMONY) && !defined(QT_BOOTSTRAPPED)
80#include <QtCore/private/qcore_ohos_p.h>
81#include <QtCore/private/qnapi_p.h>
82#include <QtCore/private/qohosmemoizingjsthreadfetcher_p.h>
83#endif
84
85#ifdef Q_OS_DARWIN
86# include "qcore_mac_p.h"
87#endif
88
89#include <stdlib.h>
90
91#ifdef Q_OS_UNIX
92# include <locale.h>
93# ifndef Q_OS_INTEGRITY
94# include <langinfo.h>
95# endif
96# include <unistd.h>
97# include <sys/types.h>
98
99# include "qcore_unix_p.h"
100#endif
101
102#if __has_include(<sys/auxv.h>) // Linux and FreeBSD
103# include <sys/auxv.h>
104#endif
105
106#ifdef Q_OS_VXWORKS
107# include <taskLib.h>
108#endif
109
110#ifdef Q_OS_WASM
111#include <emscripten/val.h>
112#endif
113
114#ifdef QT_BOOTSTRAPPED
115#include <private/qtrace_p.h>
116#else
117#include <qtcore_tracepoints_p.h>
118#endif
119
120#include <algorithm>
121#include <memory>
122#include <string>
123
124#ifdef Q_OS_WIN
125# include <qt_windows.h>
126#endif
127
128QT_BEGIN_NAMESPACE
129
130using namespace Qt::StringLiterals;
131
133 "#include <qcoreevent.h>"
134);
135Q_TRACE_METADATA(qtcore, "ENUM { AUTO, RANGE User ... MaxUser } QEvent::Type;");
136Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_entry, QObject *receiver, QEvent *event, QEvent::Type type);
139Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_event_posted, QObject *receiver, QEvent *event, QEvent::Type type);
140Q_TRACE_POINT(qtcore, QCoreApplication_sendEvent, QObject *receiver, QEvent *event, QEvent::Type type);
141Q_TRACE_POINT(qtcore, QCoreApplication_sendSpontaneousEvent, QObject *receiver, QEvent *event, QEvent::Type type);
142Q_TRACE_POINT(qtcore, QCoreApplication_notify_entry, QObject *receiver, QEvent *event, QEvent::Type type);
143Q_TRACE_POINT(qtcore, QCoreApplication_notify_exit, bool consumed, bool filtered);
144
145#if (defined(Q_OS_WIN) || defined(Q_OS_DARWIN)) && !defined(QT_BOOTSTRAPPED)
146extern QString qAppFileName();
147#endif
148
149Q_CONSTINIT bool QCoreApplicationPrivate::setuidAllowed = false;
150
151#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
152# warning "Audit remaining direct usages of this variable for memory ordering semantics"
153Q_CONSTINIT QBasicAtomicPointer<QCoreApplication> QCoreApplication::self = nullptr;
154#else
155Q_CONSTINIT QCoreApplication *QCoreApplication::self = nullptr;
156Q_CONSTINIT static QBasicAtomicPointer<QCoreApplication> g_self = nullptr;
157# undef qApp
158# define qApp g_self.loadRelaxed()
159
160/*!
161 \internal
162
163 This function is a Qt 6 thread-safe (no data races) version of:
164 \code
165 QCoreApplication::instance() != nullptr
166 \endcode
167
168 We may remove it in Qt 7.0 because the above will be thread-safe.
169*/
170bool QCoreApplication::instanceExists() noexcept
171{
172 return qApp != nullptr;
173}
174#endif
175
176#if !defined(Q_OS_WIN) || defined(QT_BOOTSTRAPPED)
177#ifdef Q_OS_DARWIN
178QString QCoreApplicationPrivate::infoDictionaryStringProperty(const QString &propertyName)
179{
180 QString bundleName;
181 QCFString cfPropertyName = propertyName.toCFString();
182 CFTypeRef string = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(),
183 cfPropertyName);
184 if (string)
185 bundleName = QString::fromCFString(static_cast<CFStringRef>(string));
186 return bundleName;
187}
188#endif
189QString QCoreApplicationPrivate::appName() const
190{
191 QString applicationName;
192#ifdef Q_OS_DARWIN
193 applicationName = infoDictionaryStringProperty(QStringLiteral("CFBundleName"));
194#endif
195 if (applicationName.isEmpty() && argv[0]) {
196 char *p = strrchr(argv[0], '/');
197 applicationName = QString::fromLocal8Bit(p ? p + 1 : argv[0]);
198 }
199
200 return applicationName;
201}
202
203#if defined(Q_OS_HARMONY) && !defined(QT_BOOTSTRAPPED)
204static QOhosMemoizingJsThreadFetcher<QString> bundleVersionNameFetcher(
205 [](QOhosJsState &jsState) -> std::optional<QString> {
206 const auto flag = jsState.eval<QNapi::Number>(
207 "@ohos.bundle.bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION");
208 return QString::fromStdString(
209 jsState.eval<QNapi::String>(
210 "@ohos.bundle.bundleManager.getBundleInfoForSelfSync(*).versionName",
211 {flag}));
212 },
213 "BundleInfo.versionName");
214#endif
215
216QString QCoreApplicationPrivate::appVersion() const
217{
218 QString applicationVersion;
219#if defined(Q_OS_DARWIN)
220 applicationVersion = infoDictionaryStringProperty(QStringLiteral("CFBundleVersion"));
221#elif defined(Q_OS_ANDROID) && !defined(QT_BOOTSTRAPPED)
222 QJniObject context(QNativeInterface::QAndroidApplication::context());
223 if (context.isValid()) {
224 QJniObject pm = context.callObjectMethod(
225 "getPackageManager", "()Landroid/content/pm/PackageManager;");
226 QJniObject pn = context.callObjectMethod<jstring>("getPackageName");
227 if (pm.isValid() && pn.isValid()) {
228 QJniObject packageInfo = pm.callObjectMethod(
229 "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;",
230 pn.object(), 0);
231 if (packageInfo.isValid()) {
232 QJniObject versionName = packageInfo.getObjectField(
233 "versionName", "Ljava/lang/String;");
234 if (versionName.isValid())
235 return versionName.toString();
236 }
237 }
238 }
239#elif defined(Q_OS_HARMONY) && !defined(QT_BOOTSTRAPPED)
240 applicationVersion = bundleVersionNameFetcher.optValue().value_or(QString());
241#endif
242 return applicationVersion;
243}
244#endif // !Q_OS_WIN || QT_BOOTSTRAPPED
245
246bool QCoreApplicationPrivate::checkInstance(const char *function)
247{
248 bool b = (qApp != nullptr);
249 if (!b)
250 qWarning("QApplication::%s: Please instantiate the QApplication object first", function);
251 return b;
252}
253
254#if QT_CONFIG(commandlineparser)
255void QCoreApplicationPrivate::addQtOptions(QList<QCommandLineOption> *options)
256{
257 options->append(QCommandLineOption(QStringLiteral("qmljsdebugger"),
258 QStringLiteral("Activates the QML/JS debugger with a specified port. The value must be of format port:1234[,block]. \"block\" makes the application wait for a connection."),
259 QStringLiteral("value")));
260}
261#endif
262
263void QCoreApplicationPrivate::processCommandLineArguments()
264{
265 int j = argc ? 1 : 0;
266 for (int i = 1; i < argc; ++i) {
267 if (!argv[i])
268 continue;
269 if (*argv[i] != '-') {
270 argv[j++] = argv[i];
271 continue;
272 }
273 const char *arg = argv[i];
274 if (arg[1] == '-') // startsWith("--")
275 ++arg;
276 if (strncmp(arg, "-qmljsdebugger=", 15) == 0) {
277 qmljs_debug_arguments = QString::fromLocal8Bit(arg + 15);
278 } else if (strcmp(arg, "-qmljsdebugger") == 0 && i < argc - 1) {
279 ++i;
280 qmljs_debug_arguments = QString::fromLocal8Bit(argv[i]);
281 } else {
282 argv[j++] = argv[i];
283 }
284 }
285
286 if (j < argc) {
287 argv[j] = nullptr;
288 argc = j;
289 }
290}
291
292// Support for introspection
293
294extern "C" void
295#ifdef QT_SHARED
297#endif
301
305Q_GLOBAL_STATIC(QVFuncList, postRList)
306Q_CONSTINIT static QBasicMutex globalRoutinesMutex;
307Q_CONSTINIT static bool preRoutinesCalled = false;
308
309/*!
310 \internal
311
312 Adds a global routine that will be called from the QCoreApplication
313 constructor. The public API is Q_COREAPP_STARTUP_FUNCTION.
314*/
316{
317 QStartUpFuncList *list = preRList();
318 if (!list)
319 return;
320
321 if (preRoutinesCalled) {
322 Q_ASSERT(qApp);
323 p();
324 }
325
326 // Due to C++11 parallel dynamic initialization, this can be called
327 // from multiple threads.
328 const auto locker = qt_scoped_lock(globalRoutinesMutex);
329 list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines
330}
331
333{
334 QVFuncList *list = postRList();
335 if (!list)
336 return;
337 const auto locker = qt_scoped_lock(globalRoutinesMutex);
338 list->prepend(p);
339}
340
342{
343 QVFuncList *list = postRList();
344 if (!list)
345 return;
346 const auto locker = qt_scoped_lock(globalRoutinesMutex);
347 list->removeAll(p);
348}
349
351{
352 // After will be allowed invoke QtStartUpFunction when calling qAddPreRoutine
353 preRoutinesCalled = true;
354
355 if (!preRList.exists())
356 return;
357
358 const QStartUpFuncList list = [] {
359 const auto locker = qt_scoped_lock(globalRoutinesMutex);
360 // Unlike qt_call_post_routines, we don't empty the list, because
361 // Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
362 // the function to be executed every time QCoreApplication is created.
363 return *preRList;
364 }();
365
366 for (QtStartUpFunction f : list)
367 f();
368}
369
370void Q_CORE_EXPORT qt_call_post_routines()
371{
372 if (!postRList.exists())
373 return;
374
375 forever {
376 QVFuncList list;
377 {
378 // extract the current list and make the stored list empty
379 const auto locker = qt_scoped_lock(globalRoutinesMutex);
380 qSwap(*postRList, list);
381 }
382
383 if (list.isEmpty())
384 break;
385 for (QtCleanUpFunction f : std::as_const(list))
386 f();
387 }
388}
389
390
391#ifndef QT_NO_QOBJECT
392
393// app starting up if false
394Q_CONSTINIT bool QCoreApplicationPrivate::is_app_running = false;
395 // app closing down if true
396Q_CONSTINIT bool QCoreApplicationPrivate::is_app_closing = false;
397
399{
400 const QPostEventList &l = QThreadData::current()->postEventList;
401 return l.size() - l.startOffset;
402}
403
404Q_CONSTINIT QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = nullptr;
405
406#endif // QT_NO_QOBJECT
407
408Q_CONSTINIT uint QCoreApplicationPrivate::attribs =
409 (1 << Qt::AA_SynthesizeMouseForUnhandledTouchEvents) |
410 (1 << Qt::AA_SynthesizeMouseForUnhandledTabletEvents);
411
413{
415 applicationNameSet = false;
416 applicationVersionSet = false;
417 }
418
420 QString application; // application name, initially from argv[0], can then be modified.
422 bool applicationNameSet; // true if setApplicationName was called
423 bool applicationVersionSet; // true if setApplicationVersion was called
424
425#if QT_CONFIG(library)
426 // QList does not have isNull()
427 bool libPathsInitialized() const noexcept
428 { return !app_libpaths.data_ptr().isNull(); }
429 bool libPathsManuallySet() const noexcept
430 { return !manual_libpaths.data_ptr().isNull(); }
433 QRecursiveMutex libraryPathMutex; // protects this block
434#endif
435
436};
437
438Q_GLOBAL_STATIC(QCoreApplicationData, coreappdata)
439
440#ifndef QT_NO_QOBJECT
441Q_CONSTINIT static bool quitLockEnabled = true;
442#endif
443
444#if defined(Q_OS_WIN)
445// Check whether the command line arguments passed to QCoreApplication
446// match those passed into main(), to see if the user has modified them
447// before passing them on to us. We do this by comparing to the global
448// __argv/__argc (MS extension). Deep comparison is required since
449// argv/argc is rebuilt by our WinMain entrypoint.
450static inline bool isArgvModified(int argc, char **argv)
451{
452 if (__argc != argc || !__argv /* wmain() */)
453 return true;
454 if (__argv == argv)
455 return false;
456 for (int a = 0; a < argc; ++a) {
457 if (argv[a] != __argv[a] && strcmp(argv[a], __argv[a]))
458 return true;
459 }
460 return false;
461}
462
463static inline bool contains(int argc, char **argv, const char *needle)
464{
465 for (int a = 0; a < argc; ++a) {
466 if (!strcmp(argv[a], needle))
467 return true;
468 }
469 return false;
470}
471#endif // Q_OS_WIN
472
473QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv)
474 : argc(aargc), argv(aargv)
475{
476 static const char *const empty = "";
477 if (argc == 0 || argv == nullptr) {
478 argc = 0;
479 argv = const_cast<char **>(&empty);
480 }
481#if defined(Q_OS_WIN)
482 if (!isArgvModified(argc, argv)) {
483 origArgc = argc;
484 origArgv = q20::make_unique_for_overwrite<char *[]>(argc);
485 std::copy(argv, argv + argc, origArgv.get());
486 }
487#endif // Q_OS_WIN
488
489#ifndef QT_NO_QOBJECT
490 QCoreApplicationPrivate::is_app_closing = false;
491
492# if defined(Q_OS_UNIX)
493 if (Q_UNLIKELY(!setuidAllowed && (geteuid() != getuid())))
494 qFatal("FATAL: The application binary appears to be running setuid, this is a security hole.");
495# endif // Q_OS_UNIX
496
497 QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread!
498 if (cur != theMainThread.loadAcquire())
499 qWarning("WARNING: QApplication was not created in the main() thread.");
500#endif
501}
502
503QCoreApplicationPrivate::~QCoreApplicationPrivate()
504{
505#ifndef QT_NO_QOBJECT
506 cleanupThreadData();
507#endif
508#if defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED)
509 cleanupDebuggingConsole();
510#endif
511}
512
513#ifndef QT_NO_QOBJECT
514
515void QCoreApplicationPrivate::cleanupThreadData()
516{
517 auto thisThreadData = threadData.loadRelaxed();
518
519 if (thisThreadData && !threadData_clean) {
520#if QT_CONFIG(thread)
521 QThreadStoragePrivate::finish(&thisThreadData->tls);
522#endif
523
524 // need to clear the state of the mainData, just in case a new QCoreApplication comes along.
525 thisThreadData->clearEvents();
526 thisThreadData->quitNow = false;
527 threadData_clean = true;
528 }
529}
530
531void QCoreApplicationPrivate::createEventDispatcher()
532{
533 Q_Q(QCoreApplication);
534 QThreadData *data = QThreadData::current();
535 Q_ASSERT(!data->hasEventDispatcher());
536 eventDispatcher = data->createEventDispatcher();
537 eventDispatcher->setParent(q);
538}
539
540void QCoreApplicationPrivate::eventDispatcherReady()
541{
542}
543
544Q_CONSTINIT QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
545Q_CONSTINIT QBasicAtomicPointer<void> QCoreApplicationPrivate::theMainThreadId = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
546QThread *QCoreApplicationPrivate::mainThread()
547{
548 Q_ASSERT(theMainThread.loadRelaxed() != nullptr);
549 return theMainThread.loadRelaxed();
550}
551
552#endif // QT_NO_QOBJECT
553
554QString qAppName()
555{
556 if (!QCoreApplicationPrivate::checkInstance("qAppName"))
557 return QString();
558 return QCoreApplication::instance()->d_func()->appName();
559}
560
561void QCoreApplicationPrivate::initLocale()
562{
563#if defined(QT_BOOTSTRAPPED)
564 // Don't try to control bootstrap library locale or encoding.
565#elif defined(Q_OS_UNIX)
566 Q_CONSTINIT static bool qt_locale_initialized = false;
567 if (qt_locale_initialized)
568 return;
569 qt_locale_initialized = true;
570
571 // By default the portable "C"/POSIX locale is selected and active.
572 // Apply the locale from the environment, via setlocale(), which will
573 // read LC_ALL, LC_<category>, and LANG, in order (for each category).
574 setlocale(LC_ALL, "");
575
576 // Next, let's ensure that LC_CTYPE is UTF-8, since QStringConverter's
577 // QLocal8Bit hard-codes this, and we need to be consistent.
578# if defined(Q_OS_INTEGRITY)
579 setlocale(LC_CTYPE, "UTF-8");
580# elif defined(Q_OS_QNX)
581 // QNX has no nl_langinfo, so we can't check.
582 // FIXME: Shouldn't we still setlocale("UTF-8")?
583# elif defined(Q_OS_ANDROID) && __ANDROID_API__ < __ANDROID_API_O__
584 // Android 6 still lacks nl_langinfo(), so we can't check.
585 // FIXME: Shouldn't we still setlocale("UTF-8")?
586# elif defined(Q_OS_VXWORKS)
587 // VxWorks has no nl_langinfo, so we can't check.
588# else
589 // std::string's SSO usually saves this the need to allocate:
590 const std::string oldEncoding = nl_langinfo(CODESET);
591 if (!Q_LIKELY(qstricmp(oldEncoding.data(), "UTF-8") == 0
592 || qstricmp(oldEncoding.data(), "utf8") == 0)) {
593 const QByteArray oldLocale = setlocale(LC_ALL, nullptr);
594 QByteArray newLocale;
595 bool warnOnOverride = true;
596# if defined(Q_OS_DARWIN)
597 // Don't warn unless the char encoding has been changed from the
598 // default "C" encoding, or the user touched any of the locale
599 // environment variables to force the "C" char encoding.
600 warnOnOverride = qstrcmp(setlocale(LC_CTYPE, nullptr), "C") != 0
601 || getenv("LC_ALL") || getenv("LC_CTYPE") || getenv("LANG");
602
603 // No need to try language or region specific CTYPEs, as they
604 // all point back to the same generic UTF-8 CTYPE.
605 newLocale = setlocale(LC_CTYPE, "UTF-8");
606# else
607 newLocale = setlocale(LC_CTYPE, nullptr);
608 if (qsizetype dot = newLocale.indexOf('.'); dot != -1)
609 newLocale.truncate(dot); // remove encoding, if any
610 if (qsizetype at = newLocale.indexOf('@'); at != -1)
611 newLocale.truncate(at); // remove variant, as the old de_DE@euro
612 newLocale += ".UTF-8";
613 newLocale = setlocale(LC_CTYPE, newLocale);
614
615 // If that locale doesn't exist, try some fallbacks:
616 if (newLocale.isEmpty())
617 newLocale = setlocale(LC_CTYPE, "C.UTF-8");
618 if (newLocale.isEmpty())
619 newLocale = setlocale(LC_CTYPE, "C.utf8");
620# endif
621
622 if (newLocale.isEmpty()) {
623 // Failed to set a UTF-8 locale.
624 qWarning("Detected locale \"%s\" with character encoding \"%s\", which is not UTF-8.\n"
625 "Qt depends on a UTF-8 locale, but has failed to switch to one.\n"
626 "If this causes problems, reconfigure your locale. See the locale(1) manual\n"
627 "for more information.", oldLocale.constData(), oldEncoding.data());
628 } else if (warnOnOverride) {
629 // Let the user know we over-rode their configuration.
630 qWarning("Detected locale \"%s\" with character encoding \"%s\", which is not UTF-8.\n"
631 "Qt depends on a UTF-8 locale, and has switched to \"%s\" instead.\n"
632 "If this causes problems, reconfigure your locale. See the locale(1) manual\n"
633 "for more information.",
634 oldLocale.constData(), oldEncoding.data(), newLocale.constData());
635 }
636 }
637# endif // Platform choice
638#endif // Unix
639}
640
641
642/*!
643 \class QCoreApplication
644 \inmodule QtCore
645 \brief The QCoreApplication class provides an event loop for Qt
646 applications without UI.
647
648 This class is used by non-GUI applications to provide their event
649 loop. For non-GUI application that uses Qt, there should be exactly
650 one QCoreApplication object. For GUI applications, see
651 QGuiApplication. For applications that use the Qt Widgets module,
652 see QApplication.
653
654 QCoreApplication contains the main event loop, where all events
655 from the operating system (e.g., timer and network events) and
656 other sources are processed and dispatched. It also handles the
657 application's initialization and finalization, as well as
658 system-wide and application-wide settings.
659
660 \section1 The Event Loop and Event Handling
661
662 The event loop is started with a call to exec(). Long-running
663 operations can call processEvents() to keep the application
664 responsive.
665
666 In general, we recommend that you create a QCoreApplication,
667 QGuiApplication or a QApplication object in your \c main()
668 function as early as possible. exec() will not return until
669 the event loop exits; e.g., when quit() is called.
670
671 Several static convenience functions are also provided. The
672 QCoreApplication object is available from instance(). Events can
673 be sent with sendEvent() or posted to an event queue with postEvent().
674 Pending events can be removed with removePostedEvents() or dispatched
675 with sendPostedEvents().
676
677 The class provides a quit() slot and an aboutToQuit() signal.
678
679 \section1 Application and Library Paths
680
681 An application has an applicationDirPath() and an
682 applicationFilePath(). Library paths (see QLibrary) can be retrieved
683 with libraryPaths() and manipulated by setLibraryPaths(), addLibraryPath(),
684 and removeLibraryPath().
685
686 \section1 Internationalization and Translations
687
688 Translation files can be added or removed
689 using installTranslator() and removeTranslator(). Application
690 strings can be translated using translate(). The QObject::tr()
691 function is implemented in terms of translate().
692
693 \section1 Accessing Command Line Arguments
694
695 The command line arguments which are passed to QCoreApplication's
696 constructor should be accessed using the arguments() function.
697
698 \note QCoreApplication removes option \c -qmljsdebugger="...". It parses the
699 argument of \c qmljsdebugger, and then removes this option plus its argument.
700
701 For more advanced command line option handling, create a QCommandLineParser.
702
703 \section1 Locale Settings
704
705 On Unix/Linux Qt is configured to use the system locale settings by
706 default. This can cause a conflict when using POSIX functions, for
707 instance, when converting between data types such as floats and
708 strings, since the notation may differ between locales. To get
709 around this problem, call the POSIX function \c{setlocale(LC_NUMERIC,"C")}
710 right after initializing QApplication, QGuiApplication or QCoreApplication
711 to reset the locale that is used for number formatting to "C"-locale.
712
713 \sa QGuiApplication, QAbstractEventDispatcher, QEventLoop,
714 {Producer and Consumer using Semaphores},
715 {Producer and Consumer using Wait Conditions}
716*/
717
718/*!
719 \fn static QCoreApplication *QCoreApplication::instance()
720
721 Returns a pointer to the application's QCoreApplication (or
722 QGuiApplication/QApplication) instance.
723
724 If no instance has been allocated, \nullptr is returned.
725
726 \b{Data race notice}: this function should not be used to test for the
727 existence of the QCoreApplication instance from auxiliary threads, unless
728 the caller code is compiled as C++20.
729*/
730
731/*!
732 \internal
733 */
734QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
735#ifdef QT_NO_QOBJECT
736 : d_ptr(&p)
737#else
738 : QObject(p, nullptr)
739#endif
740{
741 d_func()->q_ptr = this;
742 // note: it is the subclasses' job to call
743 // QCoreApplicationPrivate::eventDispatcher->startingUp();
744}
745
746/*!
747 Constructs a Qt core application. Core applications are applications without
748 a graphical user interface. Such applications are used at the console or as
749 server processes.
750
751 The \a argc and \a argv arguments are processed by the application,
752 and made available in a more convenient form by the arguments()
753 function.
754
755 \warning The data referred to by \a argc and \a argv must stay valid
756 for the entire lifetime of the QCoreApplication object. In addition,
757 \a argc must be greater than zero and \a argv must contain at least
758 one valid character string.
759*/
760QCoreApplication::QCoreApplication(int &argc, char **argv
761#ifndef Q_QDOC
762 , int
763#endif
764 )
765#ifdef QT_NO_QOBJECT
766 : d_ptr(new QCoreApplicationPrivate(argc, argv))
767#else
768 : QObject(*new QCoreApplicationPrivate(argc, argv))
769#endif
770{
771 d_func()->q_ptr = this;
772 d_func()->init();
773#ifndef QT_NO_QOBJECT
774 QCoreApplicationPrivate::eventDispatcher->startingUp();
775#endif
776}
777
778/*!
779 \enum QCoreApplication::anonymous
780 \internal
781
782 \value ApplicationFlags QT_VERSION
783*/
784
785void Q_TRACE_INSTRUMENT(qtcore) QCoreApplicationPrivate::init()
786{
787 Q_TRACE_SCOPE(QCoreApplicationPrivate_init);
788
789#if defined(Q_OS_MACOS)
790 QMacAutoReleasePool pool;
791#endif
792
793 Q_Q(QCoreApplication);
794
795#if defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED)
796 initDebuggingConsole();
797#endif
798
799 initLocale();
800
801 Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object");
802#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
803# ifdef __cpp_lib_atomic_ref
804 std::atomic_ref(QCoreApplication::self).store(q, std::memory_order_relaxed);
805# else
806 QCoreApplication::self = q;
807# endif
808 g_self.storeRelaxed(q);
809#else
810 QCoreApplication::self.storeRelaxed(q);
811#endif
812
813#if QT_CONFIG(thread)
814#ifdef Q_OS_WASM
815 emscripten::val hardwareConcurrency = emscripten::val::global("navigator")["hardwareConcurrency"];
816 if (hardwareConcurrency.isUndefined())
817 QThreadPrivate::idealThreadCount = 2;
818 else
819 QThreadPrivate::idealThreadCount = hardwareConcurrency.as<int>();
820#endif
821#endif
822
823 // Store app name/version (so they're still available after QCoreApplication is destroyed)
824 if (!coreappdata()->applicationNameSet)
825 coreappdata()->application = appName();
826
827 if (!coreappdata()->applicationVersionSet)
828 coreappdata()->applicationVersion = appVersion();
829
830#if (defined(Q_OS_ANDROID) || defined(Q_OS_HARMONY)) && !defined(QT_BOOTSTRAPPED)
831 // We've deferred initializing the logging registry due to not being
832 // able to guarantee that logging happened on the same thread as the
833 // Qt main thread, but now that the Qt main thread is set up, we can
834 // enable categorized logging.
835 QLoggingRegistry::instance()->initializeRules();
836#endif
837
838#if QT_CONFIG(library)
839 // Reset the lib paths, so that they will be recomputed, taking the availability of argv[0]
840 // into account. If necessary, recompute right away and replay the manual changes on top of the
841 // new lib paths.
842 if (coreappdata->libPathsInitialized()) {
843 const QStringList appPaths = std::exchange(coreappdata->app_libpaths, {});
844 Q_ASSERT(!coreappdata->libPathsInitialized());
845
846 if (coreappdata->libPathsManuallySet()) {
847 const QStringList manualPaths = std::exchange(coreappdata->manual_libpaths, {});
848 Q_ASSERT(!coreappdata->libPathsManuallySet());
849
850 // Replay the delta. As paths can only be prepended to the front or removed from
851 // anywhere in the list, we can just linearly scan the lists and find the items that
852 // have been removed. Once the original list is exhausted we know all the remaining
853 // items have been added.
854 QStringList newPaths(q->libraryPaths());
855 for (qsizetype i = manualPaths.size(), j = appPaths.size(); i > 0 || j > 0; qt_noop()) {
856 if (--j < 0) {
857 newPaths.prepend(manualPaths[--i]);
858 } else if (--i < 0) {
859 newPaths.removeAll(appPaths[j]);
860 } else if (manualPaths[i] != appPaths[j]) {
861 newPaths.removeAll(appPaths[j]);
862 ++i; // try again with next item.
863 }
864 }
865 coreappdata->manual_libpaths.swap(newPaths);
866 }
867 }
868#endif
869
870#ifndef QT_NO_QOBJECT
871 // use the event dispatcher created by the app programmer (if any)
872 Q_ASSERT(!eventDispatcher);
873 auto thisThreadData = threadData.loadRelaxed();
874 eventDispatcher = thisThreadData->eventDispatcher.loadRelaxed();
875
876 // otherwise we create one
877 if (!eventDispatcher)
878 createEventDispatcher();
879 Q_ASSERT(eventDispatcher);
880
881 if (!eventDispatcher->parent()) {
882 eventDispatcher->moveToThread(thisThreadData->thread.loadAcquire());
883 eventDispatcher->setParent(q);
884 }
885
886 thisThreadData->eventDispatcher = eventDispatcher;
887 eventDispatcherReady();
888#endif
889
890 processCommandLineArguments();
891
892 qt_call_pre_routines();
893 QT_MANGLE_NAMESPACE(qt_startup_hook)();
894#ifndef QT_BOOTSTRAPPED
895 QtPrivate::initBindingStatusThreadId();
896 if (Q_UNLIKELY(qtHookData[QHooks::Startup]))
897 reinterpret_cast<QHooks::StartupCallback>(qtHookData[QHooks::Startup])();
898#endif
899
900#ifndef QT_NO_QOBJECT
901 is_app_running = true; // No longer starting up.
902#endif
903}
904
905/*!
906 Destroys the QCoreApplication object.
907*/
908QCoreApplication::~QCoreApplication()
909{
910 preRoutinesCalled = false;
911
912 qt_call_post_routines();
913
914#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
915# ifdef __cpp_lib_atomic_ref
916 std::atomic_ref(self).store(nullptr, std::memory_order_relaxed);
917# else
918 self = nullptr;
919# endif
920 g_self.storeRelaxed(nullptr);
921#else
922 self.storeRelaxed(nullptr);
923#endif
924
925#ifndef QT_NO_QOBJECT
926 QCoreApplicationPrivate::is_app_closing = true;
927 QCoreApplicationPrivate::is_app_running = false;
928#endif
929
930#if QT_CONFIG(thread)
931 // Synchronize and stop the global thread pool threads.
932 QThreadPool *globalThreadPool = nullptr;
933 QT_TRY {
934 globalThreadPool = QThreadPool::globalInstance();
935 } QT_CATCH (...) {
936 // swallow the exception, since destructors shouldn't throw
937 }
938 if (globalThreadPool) {
939 globalThreadPool->waitForDone();
940 delete globalThreadPool;
941 }
942#endif
943
944#ifndef QT_NO_QOBJECT
945 d_func()->threadData.loadRelaxed()->eventDispatcher = nullptr;
946 if (QCoreApplicationPrivate::eventDispatcher)
947 QCoreApplicationPrivate::eventDispatcher->closingDown();
948 QCoreApplicationPrivate::eventDispatcher = nullptr;
949#endif
950
951#if QT_CONFIG(library)
952 if (coreappdata.exists()) {
953 // neither .clear(), .resize(), nor = {} will make isNull() == true
954 coreappdata->app_libpaths = QStringList();
955 coreappdata->manual_libpaths = QStringList();
956 Q_ASSERT(!coreappdata->libPathsManuallySet());
957 Q_ASSERT(!coreappdata->libPathsInitialized());
958 }
959#endif
960}
961
962/*!
963 \since 5.3
964
965 Allows the application to run setuid on UNIX platforms if \a allow
966 is true.
967
968 If \a allow is false (the default) and Qt detects the application is
969 running with an effective user id different than the real user id,
970 the application will be aborted when a QCoreApplication instance is
971 created.
972
973 Qt is not an appropriate solution for setuid programs due to its
974 large attack surface. However some applications may be required
975 to run in this manner for historical reasons. This flag will
976 prevent Qt from aborting the application when this is detected,
977 and must be set before a QCoreApplication instance is created.
978
979 \note It is strongly recommended not to enable this option since
980 it introduces security risks. If this application does enable the flag and
981 starts child processes, it should drop the privileges as early as possible
982 by calling \c{setuid(2)} for itself, or at the latest by using the
983 QProcess::UnixProcessParameters::ResetIds flag.
984*/
985void QCoreApplication::setSetuidAllowed(bool allow)
986{
987 QCoreApplicationPrivate::setuidAllowed = allow;
988}
989
990/*!
991 \since 5.3
992
993 Returns true if the application is allowed to run setuid on UNIX
994 platforms.
995
996 \sa QCoreApplication::setSetuidAllowed()
997*/
998bool QCoreApplication::isSetuidAllowed()
999{
1000 return QCoreApplicationPrivate::setuidAllowed;
1001}
1002
1003/*!
1004 Sets the attribute \a attribute if \a on is true;
1005 otherwise clears the attribute.
1006
1007 \note Some application attributes must be set \b before creating a
1008 QCoreApplication instance. Refer to the Qt::ApplicationAttribute
1009 documentation for more information.
1010
1011 \sa testAttribute()
1012*/
1013void QCoreApplication::setAttribute(Qt::ApplicationAttribute attribute, bool on)
1014{
1015 // Since we bit-shift these values, we can't go higher than 32 on 32 bit operating systems
1016 // without changing the storage type of QCoreApplicationPrivate::attribs to quint64.
1017 static_assert(Qt::AA_AttributeCount <= sizeof(QCoreApplicationPrivate::attribs) * CHAR_BIT);
1018
1019 if (on)
1020 QCoreApplicationPrivate::attribs |= 1 << attribute;
1021 else
1022 QCoreApplicationPrivate::attribs &= ~(1 << attribute);
1023#if defined(QT_NO_QOBJECT)
1024 if (Q_UNLIKELY(qApp)) {
1025#else
1026 if (Q_UNLIKELY(QCoreApplicationPrivate::is_app_running)) {
1027#endif
1028 switch (attribute) {
1029 case Qt::AA_PluginApplication:
1030 case Qt::AA_UseDesktopOpenGL:
1031 case Qt::AA_UseOpenGLES:
1032 case Qt::AA_UseSoftwareOpenGL:
1033#ifdef QT_BOOTSTRAPPED
1034 qWarning("Attribute %d must be set before QCoreApplication is created.",
1035 attribute);
1036#else
1037 qWarning("Attribute Qt::%s must be set before QCoreApplication is created.",
1038 QMetaEnum::fromType<Qt::ApplicationAttribute>().valueToKey(attribute));
1039#endif
1040 break;
1041 default:
1042 break;
1043 }
1044 }
1045}
1046
1047/*!
1048 Returns \c true if attribute \a attribute is set;
1049 otherwise returns \c false.
1050
1051 \sa setAttribute()
1052 */
1053bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute)
1054{
1055 return QCoreApplicationPrivate::testAttribute(attribute);
1056}
1057
1058#ifndef QT_NO_QOBJECT
1059
1060/*!
1061 \property QCoreApplication::quitLockEnabled
1062
1063 \brief Whether the use of the QEventLoopLocker feature can cause the
1064 application to quit.
1065
1066 When this property is \c true the release of the last remaining
1067 QEventLoopLocker operating on the application will attempt to
1068 quit the application.
1069
1070 Note that attempting a quit may not necessarily result in the
1071 application quitting, for example if there still are open windows,
1072 or the QEvent::Quit event is ignored.
1073
1074 The default is \c true.
1075
1076 \sa QEventLoopLocker
1077*/
1078
1079bool QCoreApplication::isQuitLockEnabled()
1080{
1081 return quitLockEnabled;
1082}
1083
1084static bool doNotify(QObject *, QEvent *);
1085
1086void QCoreApplication::setQuitLockEnabled(bool enabled)
1087{
1088 quitLockEnabled = enabled;
1089}
1090
1091/*!
1092 \internal
1093 \since 5.6
1094
1095 This function is here to make it possible for Qt extensions to
1096 hook into event notification without subclassing QApplication.
1097*/
1098bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
1099{
1100 // Qt enforces the rule that events can only be sent to objects in
1101 // the current thread, so receiver->d_func()->threadData is
1102 // equivalent to QThreadData::current(), just without the function
1103 // call overhead.
1104 QObjectPrivate *d = receiver->d_func();
1105 QThreadData *threadData = d->threadData.loadAcquire();
1106 bool selfRequired = threadData->requiresCoreApplication;
1107 if (selfRequired && !qApp)
1108 return false;
1109
1110 // Make it possible for Qt Script to hook into events even
1111 // though QApplication is subclassed...
1112 bool result = false;
1113 void *cbdata[] = { receiver, event, &result };
1114 if (QInternal::activateCallbacks(QInternal::EventNotifyCallback, cbdata)) {
1115 return result;
1116 }
1117
1118 QScopedScopeLevelCounter scopeLevelCounter(threadData);
1119 if (!selfRequired)
1120 return doNotify(receiver, event);
1121
1122#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
1123 if (!QThread::isMainThread())
1124 return false;
1125#endif
1126 return qApp->notify(receiver, event);
1127}
1128
1129/*!
1130 \internal
1131 \since 5.10
1132
1133 Forwards the \a event to the \a receiver, using the spontaneous
1134 state of the \a originatingEvent if specified.
1135*/
1136bool QCoreApplication::forwardEvent(QObject *receiver, QEvent *event, QEvent *originatingEvent)
1137{
1138 if (event && originatingEvent)
1139 event->m_spont = originatingEvent->m_spont;
1140
1141 return notifyInternal2(receiver, event);
1142}
1143
1144/*!
1145 Sends \a event to \a receiver: \a {receiver}->event(\a event).
1146 Returns the value that is returned from the receiver's event
1147 handler. Note that this function is called for all events sent to
1148 any object in any thread.
1149
1150 For certain types of events (e.g. mouse and key events),
1151 the event will be propagated to the receiver's parent and so on up to
1152 the top-level object if the receiver is not interested in the event
1153 (i.e., it returns \c false).
1154
1155 There are five different ways that events can be processed;
1156 reimplementing this virtual function is just one of them. All five
1157 approaches are listed below:
1158 \list 1
1159 \li Reimplementing \l {QWidget::}{paintEvent()}, \l {QWidget::}{mousePressEvent()} and so
1160 on. This is the most common, easiest, and least powerful way.
1161
1162 \li Reimplementing this function. This is very powerful, providing
1163 complete control; but only one subclass can be active at a time.
1164
1165 \li Installing an event filter on QCoreApplication::instance(). Such
1166 an event filter is able to process all events for all widgets, so
1167 it's just as powerful as reimplementing notify(); furthermore, it's
1168 possible to have more than one application-global event filter.
1169 Global event filters even see mouse events for
1170 \l{QWidget::isEnabled()}{disabled widgets}. Note that application
1171 event filters are only called for objects that live in the main
1172 thread.
1173
1174 \li Reimplementing QObject::event() (as QWidget does). If you do
1175 this you get Tab key presses, and you get to see the events before
1176 any widget-specific event filters.
1177
1178 \li Installing an event filter on the object. Such an event filter gets all
1179 the events, including Tab and Shift+Tab key press events, as long as they
1180 do not change the focus widget.
1181 \endlist
1182
1183 \b{Future direction:} This function will not be called for objects that live
1184 outside the main thread in Qt 7. Applications that need that functionality
1185 should find other solutions for their event inspection needs in the meantime.
1186 The change may be extended to the main thread, causing this function to be
1187 deprecated.
1188
1189 \warning If you override this function, you must ensure all threads that
1190 process events stop doing so before your application object begins
1191 destruction. This includes threads started by other libraries that you may be
1192 using, but does not apply to Qt's own threads.
1193
1194 \sa QObject::event(), installNativeEventFilter()
1195*/
1196
1197bool QCoreApplication::notify(QObject *receiver, QEvent *event)
1198{
1199 Q_ASSERT(receiver);
1200 Q_ASSERT(event);
1201
1202#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
1203 Q_ASSERT(receiver->d_func()->threadData.loadAcquire()->thread.loadRelaxed()
1204 == QCoreApplicationPrivate::mainThread());
1205#endif
1206
1207 // no events are delivered after ~QCoreApplication() has started
1208 if (QCoreApplicationPrivate::is_app_closing)
1209 return true;
1210 return doNotify(receiver, event);
1211}
1212
1213static bool doNotify(QObject *receiver, QEvent *event)
1214{
1215 Q_ASSERT(event);
1216
1217 // ### Qt 7: turn into an assert
1218 if (receiver == nullptr) { // serious error
1219 qWarning("QCoreApplication::notify: Unexpected null receiver");
1220 return true;
1221 }
1222
1223 QCoreApplicationPrivate::checkReceiverThread(receiver, "QCoreApplication::notify");
1224
1225 return receiver->isWidgetType() ? false : QCoreApplicationPrivate::notify_helper(receiver, event);
1226}
1227
1228bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
1229{
1230 // We can't access the application event filters outside of the main thread (race conditions)
1231 Q_ASSERT(QThread::isMainThread());
1232
1233 if (extraData) {
1234 // application event filters are only called for objects in the GUI thread
1235 for (qsizetype i = 0; i < extraData->eventFilters.size(); ++i) {
1236 QObject *obj = extraData->eventFilters.at(i);
1237 if (!obj)
1238 continue;
1239 if (obj->d_func()->threadData.loadRelaxed() != threadData.loadRelaxed()) {
1240 qWarning("QCoreApplication: Application event filter cannot be in a different thread.");
1241 continue;
1242 }
1243 if (obj->eventFilter(receiver, event))
1244 return true;
1245 }
1246 }
1247 return false;
1248}
1249
1250bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, QEvent *event)
1251{
1252 if (receiver != qApp && receiver->d_func()->extraData) {
1253 for (qsizetype i = 0; i < receiver->d_func()->extraData->eventFilters.size(); ++i) {
1254 QObject *obj = receiver->d_func()->extraData->eventFilters.at(i);
1255 if (!obj)
1256 continue;
1257 if (obj->d_func()->threadData.loadRelaxed() != receiver->d_func()->threadData.loadRelaxed()) {
1258 qWarning("QCoreApplication: Object event filter cannot be in a different thread.");
1259 continue;
1260 }
1261 if (obj->eventFilter(receiver, event))
1262 return true;
1263 }
1264 }
1265 return false;
1266}
1267
1268/*!
1269 \internal
1270
1271 Helper function called by QCoreApplicationPrivate::notify() and qapplication.cpp
1272 */
1273bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
1274{
1275 // Note: when adjusting the tracepoints in here
1276 // consider adjusting QApplicationPrivate::notify_helper too.
1277 Q_TRACE(QCoreApplication_notify_entry, receiver, event, event->type());
1278 bool consumed = false;
1279 bool filtered = false;
1280 Q_TRACE_EXIT(QCoreApplication_notify_exit, consumed, filtered);
1281
1282 // send to all application event filters (only does anything in the main thread)
1283 if (QThread::isMainThread()
1284 && QCoreApplication::self
1285 && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
1286 filtered = true;
1287 return filtered;
1288 }
1289 // send to all receiver event filters
1290 if (sendThroughObjectEventFilters(receiver, event)) {
1291 filtered = true;
1292 return filtered;
1293 }
1294
1295 // deliver the event
1296 consumed = receiver->event(event);
1297 return consumed;
1298}
1299
1300/*!
1301 Returns \c true if an application object has not been created yet;
1302 otherwise returns \c false.
1303
1304 \sa closingDown()
1305*/
1306
1307bool QCoreApplication::startingUp()
1308{
1309 return !QCoreApplicationPrivate::is_app_running;
1310}
1311
1312/*!
1313 Returns \c true if the application objects are being destroyed;
1314 otherwise returns \c false.
1315
1316 \sa startingUp()
1317*/
1318
1319bool QCoreApplication::closingDown()
1320{
1321 return QCoreApplicationPrivate::is_app_closing;
1322}
1323
1324
1325/*!
1326 Processes some pending events for the calling thread according to
1327 the specified \a flags.
1328
1329 Use of this function is discouraged. Instead, prefer to move long
1330 operations out of the GUI thread into an auxiliary one and to completely
1331 avoid nested event loop processing. If event processing is really
1332 necessary, consider using \l QEventLoop instead.
1333
1334 In the event that you are running a local loop which calls this function
1335 continuously, without an event loop, the
1336 \l{QEvent::DeferredDelete}{DeferredDelete} events will
1337 not be processed. This can affect the behaviour of widgets,
1338 e.g. QToolTip, that rely on \l{QEvent::DeferredDelete}{DeferredDelete}
1339 events to function properly. An alternative would be to call
1340 \l{QCoreApplication::sendPostedEvents()}{sendPostedEvents()} from
1341 within that local loop.
1342
1343 Calling this function processes events only for the calling thread,
1344 and returns after all available events have been processed. Available
1345 events are events queued before the function call. This means that
1346 events that are posted while the function runs will be queued until
1347 a later round of event processing.
1348
1349 \threadsafe
1350
1351 \sa exec(), QTimer, QChronoTimer, QEventLoop::processEvents(),
1352 sendPostedEvents()
1353*/
1354void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
1355{
1356 QThreadData *data = QThreadData::current();
1357 if (!data->hasEventDispatcher())
1358 return;
1359 data->eventDispatcher.loadRelaxed()->processEvents(flags);
1360}
1361
1362/*!
1363 \overload
1364
1365 Processes pending events for the calling thread for \a ms
1366 milliseconds or until there are no more events to process,
1367 whichever is shorter.
1368
1369 This is equivalent to calling:
1370 \code
1371 QCoreApplication::processEvents(flags, QDeadlineTimer(ms));
1372 \endcode
1373*/
1374void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int ms)
1375{
1376 QCoreApplication::processEvents(flags, QDeadlineTimer(ms));
1377}
1378
1379/*!
1380 \since 6.7
1381 \overload
1382
1383 Processes pending events for the calling thread untile \a deadline has expired,
1384 or until there are no more events to process, whichever happens first.
1385
1386 Use of this function is discouraged. Instead, prefer to move long
1387 operations out of the GUI thread into an auxiliary one and to completely
1388 avoid nested event loop processing. If event processing is really
1389 necessary, consider using \l QEventLoop instead.
1390
1391 Calling this function processes events only for the calling thread.
1392
1393 \note Unlike the \l{QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)}{processEvents()}
1394 overload, this function also processes events that are posted while the function runs.
1395
1396 \note All events that were queued before the timeout will be processed,
1397 however long it takes.
1398
1399 \threadsafe
1400
1401 \sa exec(), QTimer, QChronoTimer, QEventLoop::processEvents()
1402*/
1403void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, QDeadlineTimer deadline)
1404{
1405 // ### TODO: consider splitting this method into a public and a private
1406 // one, so that a user-invoked processEvents can be detected
1407 // and handled properly.
1408 QThreadData *data = QThreadData::current();
1409 if (!data->hasEventDispatcher())
1410 return;
1411
1412 while (data->eventDispatcher.loadRelaxed()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
1413 if (deadline.hasExpired())
1414 break;
1415 }
1416}
1417
1418/*****************************************************************************
1419 Main event loop wrappers
1420 *****************************************************************************/
1421
1422/*!
1423 Enters the main event loop and waits until exit() is called. Returns
1424 the value that was passed to exit() (which is 0 if exit() is called via
1425 quit()).
1426
1427 It is necessary to call this function to start event handling. The
1428 main event loop receives events from the window system and
1429 dispatches these to the application widgets.
1430
1431 To make your application perform idle processing (by executing a special
1432 function whenever there are no pending events), use a QChronoTimer
1433 with 0ns timeout. More advanced idle processing schemes can be achieved
1434 using processEvents().
1435
1436 We recommend that you connect clean-up code to the
1437 \l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in
1438 your application's \c{main()} function because on some platforms the
1439 exec() call may not return. For example, on Windows
1440 when the user logs off, the system terminates the process after Qt
1441 closes all top-level windows. Hence, there is no guarantee that the
1442 application will have time to exit its event loop and execute code at
1443 the end of the \c{main()} function after the exec()
1444 call.
1445
1446 \sa quit(), exit(), processEvents(), QApplication::exec()
1447*/
1448int QCoreApplication::exec()
1449{
1450 if (!QCoreApplicationPrivate::checkInstance("exec"))
1451 return -1;
1452
1453 QThreadData *threadData = self->d_func()->threadData.loadAcquire();
1454 if (threadData != QThreadData::current()) {
1455 qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
1456 return -1;
1457 }
1458 if (!threadData->eventLoops.isEmpty()) {
1459 qWarning("QCoreApplication::exec: The event loop is already running");
1460 return -1;
1461 }
1462
1463 threadData->quitNow = false;
1464 QEventLoop eventLoop;
1465 self->d_func()->in_exec = true;
1466 self->d_func()->aboutToQuitEmitted = false;
1467 int returnCode = eventLoop.exec(QEventLoop::ApplicationExec);
1468 threadData->quitNow = false;
1469
1470 if (self)
1471 self->d_func()->execCleanup();
1472
1473 return returnCode;
1474}
1475
1476
1477// Cleanup after eventLoop is done executing in QCoreApplication::exec().
1478// This is for use cases in which QCoreApplication is instantiated by a
1479// library and not by an application executable, for example, Active X
1480// servers.
1481
1482void QCoreApplicationPrivate::execCleanup()
1483{
1484 threadData.loadRelaxed()->quitNow = false;
1485 in_exec = false;
1486 QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
1487}
1488
1489
1490/*!
1491 Tells the application to exit with a return code.
1492
1493 After this function has been called, the application leaves the
1494 main event loop and returns from the call to exec(). The exec()
1495 function returns \a returnCode. If the event loop is not running,
1496 this function does nothing.
1497
1498 By convention, a \a returnCode of 0 means success, and any non-zero
1499 value indicates an error.
1500
1501 It's good practice to always connect signals to this slot using a
1502 \l{Qt::}{QueuedConnection}. If a signal connected (non-queued) to this slot
1503 is emitted before control enters the main event loop (such as before
1504 "int main" calls \l{QCoreApplication::}{exec()}), the slot has no effect
1505 and the application never exits. Using a queued connection ensures that the
1506 slot will not be invoked until after control enters the main event loop.
1507
1508 Note that unlike the C library function of the same name, this
1509 function \e does return to the caller -- it is event processing that
1510 stops.
1511
1512 Note also that this function is not thread-safe. It should be called only
1513 from the main thread (the thread that the QCoreApplication object is
1514 processing events on). To ask the application to exit from another thread,
1515 either use QCoreApplication::quit() or instead call this function from the
1516 main thread with QMetaMethod::invokeMethod().
1517
1518 \sa quit(), exec()
1519*/
1520void QCoreApplication::exit(int returnCode)
1521{
1522 if (!self)
1523 return;
1524
1525#ifdef Q_OS_WASM
1526 if (!qstdweb::haveAsyncify())
1527 qFatal("Terminating since we don't have asyncify");
1528#endif
1529 QCoreApplicationPrivate *d = self->d_func();
1530 if (!d->aboutToQuitEmitted) {
1531 emit self->aboutToQuit(QCoreApplication::QPrivateSignal());
1532 d->aboutToQuitEmitted = true;
1533 }
1534 QThreadData *data = d->threadData.loadRelaxed();
1535 data->quitNow = true;
1536 for (qsizetype i = 0; i < data->eventLoops.size(); ++i) {
1537 QEventLoop *eventLoop = data->eventLoops.at(i);
1538 eventLoop->exit(returnCode);
1539 }
1540}
1541
1542/*****************************************************************************
1543 QCoreApplication management of posted events
1544 *****************************************************************************/
1545
1546#ifndef QT_NO_QOBJECT
1547/*!
1548 \fn bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
1549
1550 Sends event \a event directly to receiver \a receiver, using the
1551 notify() function. Returns the value that was returned from the
1552 event handler.
1553
1554 The event is \e not deleted when the event has been sent. The normal
1555 approach is to create the event on the stack, for example:
1556
1557 \snippet code/src_corelib_kernel_qcoreapplication.cpp 0
1558
1559 \sa postEvent(), notify()
1560*/
1561bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
1562{
1563 Q_ASSERT_X(receiver, "QCoreApplication::sendEvent", "Unexpected null receiver");
1564 Q_ASSERT_X(event, "QCoreApplication::sendEvent", "Unexpected null event");
1565
1566 Q_TRACE(QCoreApplication_sendEvent, receiver, event, event->type());
1567
1568 event->m_spont = false;
1569 return notifyInternal2(receiver, event);
1570}
1571
1572/*!
1573 \internal
1574*/
1575bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
1576{
1577 Q_ASSERT_X(receiver, "QCoreApplication::sendSpontaneousEvent", "Unexpected null receiver");
1578 Q_ASSERT_X(event, "QCoreApplication::sendSpontaneousEvent", "Unexpected null event");
1579
1580 Q_TRACE(QCoreApplication_sendSpontaneousEvent, receiver, event, event->type());
1581
1582 event->m_spont = true;
1583 return notifyInternal2(receiver, event);
1584}
1585
1586#endif // QT_NO_QOBJECT
1587
1588QCoreApplicationPrivate::QPostEventListLocker QCoreApplicationPrivate::lockThreadPostEventList(QObject *object)
1589{
1590 QPostEventListLocker locker;
1591
1592 if (!object) {
1593 locker.threadData = QThreadData::current();
1594 locker.locker = qt_unique_lock(locker.threadData->postEventList.mutex);
1595 return locker;
1596 }
1597
1598 auto &threadData = QObjectPrivate::get(object)->threadData;
1599
1600 // if object has moved to another thread, follow it
1601 for (;;) {
1602 // synchronizes with the storeRelease in QObject::moveToThread
1603 locker.threadData = threadData.loadAcquire();
1604 if (!locker.threadData) {
1605 // destruction in progress
1606 return locker;
1607 }
1608
1609 auto temporaryLocker = qt_unique_lock(locker.threadData->postEventList.mutex);
1610 if (locker.threadData == threadData.loadAcquire()) {
1611 locker.locker = std::move(temporaryLocker);
1612 break;
1613 }
1614 }
1615
1616 Q_ASSERT(locker.threadData);
1617 return locker;
1618}
1619
1620/*!
1621 \since 4.3
1622
1623 Adds the event \a event, with the object \a receiver as the
1624 receiver of the event, to an event queue and returns immediately.
1625
1626 The event must be allocated on the heap since the post event queue
1627 will take ownership of the event and delete it once it has been
1628 posted. It is \e {not safe} to access the event after
1629 it has been posted.
1630
1631 When control returns to the main event loop, all events that are
1632 stored in the queue will be sent using the notify() function.
1633
1634 Events are sorted in descending \a priority order, i.e. events
1635 with a high \a priority are queued before events with a lower \a
1636 priority. The \a priority can be any integer value, i.e. between
1637 INT_MAX and INT_MIN, inclusive; see Qt::EventPriority for more
1638 details. Events with equal \a priority will be processed in the
1639 order posted.
1640
1641 \note QObject::deleteLater() schedules the object for deferred
1642 deletion, which is typically handled by the receiver's event
1643 loop. If no event loop is running in the thread, the deletion
1644 will be performed when the thread finishes. A common and safe
1645 pattern is to connect the thread's finished() signal to the
1646 object's deleteLater() slot:
1647
1648 \code
1649 QObject::connect(thread, &QThread::finished, worker, &QObject::deleteLater);
1650 \endcode
1651
1652 \threadsafe
1653
1654 \sa sendEvent(), notify(), sendPostedEvents(), Qt::EventPriority
1655*/
1656void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
1657{
1658 Q_ASSERT_X(event, "QCoreApplication::postEvent", "Unexpected null event");
1659
1660 Q_TRACE_SCOPE(QCoreApplication_postEvent, receiver, event, event->type());
1661
1662 // ### Qt 7: turn into an assert
1663 if (receiver == nullptr) {
1664 qWarning("QCoreApplication::postEvent: Unexpected null receiver");
1665 delete event;
1666 return;
1667 }
1668
1669 auto locker = QCoreApplicationPrivate::lockThreadPostEventList(receiver);
1670 if (!locker.threadData) {
1671 // posting during destruction? just delete the event to prevent a leak
1672 delete event;
1673 return;
1674 }
1675
1676 QThreadData *data = locker.threadData;
1677
1678 QT_WARNING_PUSH
1679 QT_WARNING_DISABLE_DEPRECATED // compressEvent()
1680 // if this is one of the compressible events, do compression
1681 if (receiver->d_func()->postedEvents.loadAcquire()
1682 && self && self->compressEvent(event, receiver, &data->postEventList)) {
1683 Q_TRACE(QCoreApplication_postEvent_event_compressed, receiver, event);
1684 return;
1685 }
1686 QT_WARNING_POP
1687
1688 // delete the event on exceptions to protect against memory leaks till the event is
1689 // properly owned in the postEventList
1690 std::unique_ptr<QEvent> eventDeleter(event);
1691 Q_TRACE(QCoreApplication_postEvent_event_posted, receiver, event, event->type());
1692 data->postEventList.addEvent(QPostEvent(receiver, event, priority));
1693 Q_UNUSED(eventDeleter.release());
1694 event->m_posted = true;
1695 receiver->d_func()->postedEvents.fetchAndAddRelease(1);
1696 data->canWait = false;
1697 locker.unlock();
1698
1699 QAbstractEventDispatcher* dispatcher = data->eventDispatcher.loadAcquire();
1700 if (dispatcher)
1701 dispatcher->wakeUp();
1702}
1703
1704/*!
1705 \internal
1706 Returns \c true if \a event was compressed away (possibly deleted) and should not be added to the list.
1707*/
1708#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
1709bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
1710{
1711 return d_func()->compressEvent(event, receiver, postedEvents);
1712}
1713#endif
1714
1715bool QCoreApplicationPrivate::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
1716{
1717 Q_ASSERT(event);
1718 Q_ASSERT(receiver);
1719 Q_ASSERT(postedEvents);
1720
1721 // compress posted timers to this object.
1722 if (event->type() == QEvent::Timer) {
1723 const int timerId = static_cast<QTimerEvent *>(event)->timerId();
1724 auto it = postedEvents->cbegin();
1725 const auto end = postedEvents->cend();
1726 while (it != end) {
1727 if (it->event && it->event->type() == QEvent::Timer && it->receiver == receiver) {
1728 if (static_cast<QTimerEvent *>(it->event)->timerId() == timerId) {
1729 delete event;
1730 return true;
1731 }
1732 }
1733 ++it;
1734 }
1735 return false;
1736 }
1737
1738 if (event->type() == QEvent::Quit) {
1739 for (const QPostEvent &cur : std::as_const(*postedEvents)) {
1740 if (cur.receiver != receiver
1741 || cur.event == nullptr
1742 || cur.event->type() != event->type())
1743 continue;
1744 // found an event for this receiver
1745 delete event;
1746 return true;
1747 }
1748 }
1749
1750 return false;
1751}
1752
1753/*!
1754 Immediately dispatches all events which have been previously queued
1755 with QCoreApplication::postEvent() and which are for the object \a
1756 receiver and have the event type \a event_type.
1757
1758 Events from the window system are \e not dispatched by this
1759 function, but by processEvents().
1760
1761 If \a receiver is \nullptr, the events of \a event_type are sent for
1762 all objects. If \a event_type is 0, all the events are sent for
1763 \a receiver.
1764
1765 \note This method must be called from the thread in which its QObject
1766 parameter, \a receiver, lives.
1767
1768 \sa postEvent()
1769*/
1770void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type)
1771{
1772 // ### TODO: consider splitting this method into a public and a private
1773 // one, so that a user-invoked sendPostedEvents can be detected
1774 // and handled properly.
1775 QThreadData *data = QThreadData::current();
1776
1777 QCoreApplicationPrivate::sendPostedEvents(receiver, event_type, data);
1778}
1779
1780void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type,
1781 QThreadData *data)
1782{
1783 if (event_type == -1) {
1784 // we were called by an obsolete event dispatcher.
1785 event_type = 0;
1786 }
1787
1788 if (receiver && receiver->d_func()->threadData.loadRelaxed() != data) {
1789 qWarning("QCoreApplication::sendPostedEvents: Cannot send "
1790 "posted events for objects in another thread");
1791 return;
1792 }
1793
1794 ++data->postEventList.recursion;
1795
1796 auto locker = qt_unique_lock(data->postEventList.mutex);
1797
1798 // by default, we assume that the event dispatcher can go to sleep after
1799 // processing all events. if any new events are posted while we send
1800 // events, canWait will be set to false.
1801 data->canWait = (data->postEventList.size() == 0);
1802
1803 if (data->postEventList.size() == 0
1804 || (receiver && !receiver->d_func()->postedEvents.loadAcquire())) {
1805 --data->postEventList.recursion;
1806 return;
1807 }
1808
1809 data->canWait = true;
1810
1811 // okay. here is the tricky loop. be careful about optimizing
1812 // this, it looks the way it does for good reasons.
1813 qsizetype startOffset = data->postEventList.startOffset;
1814 qsizetype &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset;
1815 data->postEventList.insertionOffset = data->postEventList.size();
1816
1817 // Exception-safe cleaning up without the need for a try/catch block
1818 struct CleanUp {
1819 Q_DISABLE_COPY_MOVE(CleanUp)
1820
1821 QObject *receiver;
1822 int event_type;
1823 QThreadData *data;
1824 bool exceptionCaught;
1825
1826 inline CleanUp(QObject *receiver, int event_type, QThreadData *data) :
1827 receiver(receiver), event_type(event_type), data(data), exceptionCaught(true)
1828 {}
1829 inline ~CleanUp()
1830 {
1831 if (exceptionCaught) {
1832 // since we were interrupted, we need another pass to make sure we clean everything up
1833 data->canWait = false;
1834 }
1835
1836 --data->postEventList.recursion;
1837 if (!data->postEventList.recursion && !data->canWait && data->hasEventDispatcher())
1838 data->eventDispatcher.loadRelaxed()->wakeUp();
1839
1840 // clear the global list, i.e. remove everything that was
1841 // delivered.
1842 if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
1843 const QPostEventList::iterator it = data->postEventList.begin();
1844 data->postEventList.erase(it, it + data->postEventList.startOffset);
1845 data->postEventList.insertionOffset -= data->postEventList.startOffset;
1846 Q_ASSERT(data->postEventList.insertionOffset >= 0);
1847 data->postEventList.startOffset = 0;
1848 }
1849 }
1850 };
1851 CleanUp cleanup(receiver, event_type, data);
1852
1853 while (i < data->postEventList.size()) {
1854 // avoid live-lock
1855 if (i >= data->postEventList.insertionOffset)
1856 break;
1857
1858 const QPostEvent &pe = data->postEventList.at(i);
1859 ++i;
1860
1861 if (!pe.event)
1862 continue;
1863 if ((receiver && receiver != pe.receiver) || (event_type && event_type != pe.event->type())) {
1864 data->canWait = false;
1865 continue;
1866 }
1867
1868 if (pe.event->type() == QEvent::DeferredDelete) {
1869 // DeferredDelete events are sent either
1870 // 1) when the event loop that posted the event has returned; or
1871 // 2) if explicitly requested (with QEvent::DeferredDelete) for
1872 // events posted by the current event loop; or
1873 // 3) if the event was posted before the outermost event loop.
1874
1875 const int eventLoopLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->loopLevel();
1876 const int eventScopeLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->scopeLevel();
1877
1878 const bool postedBeforeOutermostLoop = eventLoopLevel == 0;
1879 const bool allowDeferredDelete =
1880 (eventLoopLevel + eventScopeLevel > data->loopLevel + data->scopeLevel
1881 || (postedBeforeOutermostLoop && data->loopLevel > 0)
1882 || (event_type == QEvent::DeferredDelete
1883 && eventLoopLevel + eventScopeLevel == data->loopLevel + data->scopeLevel));
1884 if (!allowDeferredDelete) {
1885 // cannot send deferred delete
1886 if (!event_type && !receiver) {
1887 // we must copy it first; we want to re-post the event
1888 // with the event pointer intact, but we can't delay
1889 // nulling the event ptr until after re-posting, as
1890 // addEvent may invalidate pe.
1891 QPostEvent pe_copy = pe;
1892
1893 // null out the event so if sendPostedEvents recurses, it
1894 // will ignore this one, as it's been re-posted.
1895 const_cast<QPostEvent &>(pe).event = nullptr;
1896
1897 // re-post the copied event so it isn't lost
1898 data->postEventList.addEvent(pe_copy);
1899 }
1900 continue;
1901 }
1902 }
1903
1904 // first, we diddle the event so that we can deliver
1905 // it, and that no one will try to touch it later.
1906 pe.event->m_posted = false;
1907 QEvent *e = pe.event;
1908 QObject * r = pe.receiver;
1909
1910 [[maybe_unused]]
1911 const auto previous = r->d_func()->postedEvents.fetchAndSubAcquire(1);
1912 Q_ASSERT(previous > 0);
1913
1914 // next, update the data structure so that we're ready
1915 // for the next event.
1916 const_cast<QPostEvent &>(pe).event = nullptr;
1917
1918 locker.unlock();
1919 const auto relocker = qScopeGuard([&locker] { locker.lock(); });
1920
1921 const std::unique_ptr<QEvent> event_deleter(e); // will delete the event (with the mutex unlocked)
1922
1923 // after all that work, it's time to deliver the event.
1924 QCoreApplication::sendEvent(r, e);
1925
1926 // careful when adding anything below this point - the
1927 // sendEvent() call might invalidate any invariants this
1928 // function depends on.
1929 }
1930
1931 cleanup.exceptionCaught = false;
1932}
1933
1934/*!
1935 \since 4.3
1936
1937 Removes all events of the given \a eventType that were posted
1938 using postEvent() for \a receiver.
1939
1940 The events are \e not dispatched, instead they are removed from
1941 the queue. You should never need to call this function. If you do
1942 call it, be aware that killing events may cause \a receiver to
1943 break one or more invariants.
1944
1945 If \a receiver is \nullptr, the events of \a eventType are removed
1946 for all objects. If \a eventType is 0, all the events are removed
1947 for \a receiver. You should never call this function with \a
1948 eventType of 0.
1949
1950 \threadsafe
1951*/
1952
1953void QCoreApplication::removePostedEvents(QObject *receiver, int eventType)
1954{
1955 auto locker = QCoreApplicationPrivate::lockThreadPostEventList(receiver);
1956 QThreadData *data = locker.threadData;
1957
1958 // the QObject destructor calls this function directly. this can
1959 // happen while the event loop is in the middle of posting events,
1960 // and when we get here, we may not have any more posted events
1961 // for this object.
1962 if (receiver && !receiver->d_func()->postedEvents.loadAcquire())
1963 return;
1964
1965 //we will collect all the posted events for the QObject
1966 //and we'll delete after the mutex was unlocked
1967 QVarLengthArray<QEvent*> events;
1968 qsizetype n = data->postEventList.size();
1969 qsizetype j = 0;
1970
1971 for (qsizetype i = 0; i < n; ++i) {
1972 const QPostEvent &pe = data->postEventList.at(i);
1973
1974 if ((!receiver || pe.receiver == receiver)
1975 && (pe.event && (eventType == 0 || pe.event->type() == eventType))) {
1976 pe.receiver->d_func()->postedEvents.fetchAndSubAcquire(1);
1977 pe.event->m_posted = false;
1978 events.append(pe.event);
1979 const_cast<QPostEvent &>(pe).event = nullptr;
1980 } else if (!data->postEventList.recursion) {
1981 if (i != j)
1982 qSwap(data->postEventList[i], data->postEventList[j]);
1983 ++j;
1984 }
1985 }
1986
1987#ifdef QT_DEBUG
1988 if (receiver && eventType == 0) {
1989 Q_ASSERT(!receiver->d_func()->postedEvents.loadRelaxed());
1990 }
1991#endif
1992
1993 if (!data->postEventList.recursion) {
1994 // truncate list
1995 data->postEventList.erase(data->postEventList.begin() + j, data->postEventList.end());
1996 }
1997
1998 locker.unlock();
1999 qDeleteAll(events);
2000}
2001
2002/*!
2003 Removes \a event from the queue of posted events, and emits a
2004 warning message if appropriate.
2005
2006 \warning This function can be \e really slow. Avoid using it, if
2007 possible.
2008
2009 \threadsafe
2010 \internal
2011*/
2012
2013void QCoreApplicationPrivate::removePostedEvent(QEvent * event)
2014{
2015 if (!event || !event->m_posted)
2016 return;
2017
2018 QThreadData *data = QThreadData::current();
2019
2020 const auto locker = qt_scoped_lock(data->postEventList.mutex);
2021
2022 if (data->postEventList.size() == 0) {
2023#if defined(QT_DEBUG)
2024 qDebug("QCoreApplication::removePostedEvent: Internal error: %p %d is posted",
2025 (void*)event, event->type());
2026 return;
2027#endif
2028 }
2029
2030 for (const QPostEvent &pe : std::as_const(data->postEventList)) {
2031 if (pe.event == event) {
2032#ifndef QT_NO_DEBUG
2033 qWarning("QCoreApplication::removePostedEvent: Event of type %d deleted while posted to %s %s",
2034 event->type(),
2035 pe.receiver->metaObject()->className(),
2036 pe.receiver->objectName().toLocal8Bit().data());
2037#endif
2038 pe.receiver->d_func()->postedEvents.fetchAndSubAcquire(1);
2039 pe.event->m_posted = false;
2040 delete pe.event;
2041 const_cast<QPostEvent &>(pe).event = nullptr;
2042 return;
2043 }
2044 }
2045}
2046
2047/*!\reimp
2048
2049*/
2050bool QCoreApplication::event(QEvent *e)
2051{
2052 if (e->type() == QEvent::Quit) {
2053 exit(0);
2054 return true;
2055 }
2056 return QObject::event(e);
2057}
2058
2059void QCoreApplicationPrivate::ref()
2060{
2061 quitLockRef.ref();
2062}
2063
2064void QCoreApplicationPrivate::deref()
2065{
2066 quitLockRef.deref();
2067
2068 if (quitLockEnabled && canQuitAutomatically())
2069 quitAutomatically();
2070}
2071
2072bool QCoreApplicationPrivate::canQuitAutomatically()
2073{
2074 if (!in_exec)
2075 return false;
2076
2077 // The automatic quit functionality is triggered by
2078 // both QEventLoopLocker and maybeLastWindowClosed.
2079 // In either case, we don't want to quit if there
2080 // are active QEventLoopLockers, even if quitLockEnabled
2081 // is not enabled, as the property signals whether to
2082 // trigger the automatic quit, not whether to block it.
2083 if (quitLockRef.loadRelaxed())
2084 return false;
2085
2086 return true;
2087}
2088
2089void QCoreApplicationPrivate::quitAutomatically()
2090{
2091 Q_Q(QCoreApplication);
2092
2093 // Explicit requests by the user to quit() is plumbed via the platform
2094 // if possible, and delivers the quit event synchronously. For automatic
2095 // quits we implicitly support cancelling the quit by showing another
2096 // window, which currently relies on removing any posted quit events
2097 // from the event queue. As a result, we can't use the normal quit()
2098 // code path, and need to post manually.
2099 QCoreApplication::postEvent(q, new QEvent(QEvent::Quit));
2100}
2101
2102/*!
2103 \threadsafe
2104
2105 Asks the application to quit.
2106
2107 The request may be ignored if the application prevents the quit,
2108 for example if one of its windows can't be closed. The application
2109 can affect this by handling the QEvent::Quit event on the application
2110 level, or QEvent::Close events for the individual windows.
2111
2112 If the quit is not interrupted the application will exit with return
2113 code 0 (success).
2114
2115 To exit the application without a chance of being interrupted, call
2116 exit() directly. Note that method is not thread-safe.
2117
2118 It's good practice to always connect signals to this slot using a
2119 \l{Qt::}{QueuedConnection}. If a signal connected (non-queued) to this slot
2120 is emitted before control enters the main event loop (such as before
2121 "int main" calls \l{QCoreApplication::}{exec()}), the slot has no effect
2122 and the application never exits. Using a queued connection ensures that the
2123 slot will not be invoked until after control enters the main event loop.
2124
2125 Example:
2126
2127 \snippet code/src_corelib_kernel_qcoreapplication.cpp 1
2128
2129 \b{Thread-safety note}: this function may be called from any thread to
2130 thread-safely cause the currently-running main application loop to exit.
2131 However, thread-safety is not guaranteed if the QCoreApplication object is
2132 being destroyed at the same time.
2133
2134 \sa exit(), aboutToQuit()
2135*/
2136void QCoreApplication::quit()
2137{
2138 if (!self)
2139 return;
2140
2141 if (!self->d_func()->in_exec)
2142 return;
2143
2144 self->d_func()->quit();
2145}
2146
2147void QCoreApplicationPrivate::quit()
2148{
2149 Q_Q(QCoreApplication);
2150
2151 if (QThread::isMainThread()) {
2152 QEvent quitEvent(QEvent::Quit);
2153 QCoreApplication::sendEvent(q, &quitEvent);
2154 } else {
2155 QCoreApplication::postEvent(q, new QEvent(QEvent::Quit));
2156 }
2157}
2158
2159/*!
2160 \fn void QCoreApplication::aboutToQuit()
2161
2162 This signal is emitted when the application is about to quit the
2163 main event loop, e.g. when the event loop level drops to zero.
2164 This may happen either after a call to quit() from inside the
2165 application or when the user shuts down the entire desktop session.
2166
2167 The signal is particularly useful if your application has to do some
2168 last-second cleanup. Note that no user interaction is possible in
2169 this state.
2170
2171 \note At this point the main event loop is still running, but will
2172 not process further events on return except QEvent::DeferredDelete
2173 events for objects deleted via deleteLater(). If event processing is
2174 needed, use a nested event loop or call QCoreApplication::processEvents()
2175 manually.
2176
2177 \sa quit()
2178*/
2179
2180#endif // QT_NO_QOBJECT
2181
2182#ifndef QT_NO_TRANSLATION
2183/*!
2184 Adds the translation file \a translationFile to the list of
2185 translation files to be used for translations.
2186
2187 Multiple translation files can be installed. Translations are
2188 searched for in the reverse order in which they were installed,
2189 so the most recently installed translation file is searched first
2190 and the first translation file installed is searched last.
2191 The search stops as soon as a translation containing a matching
2192 string is found.
2193
2194 Installing or removing a QTranslator, or changing an installed QTranslator
2195 generates a \l{QEvent::LanguageChange}{LanguageChange} event for the
2196 QCoreApplication instance. A QApplication instance will propagate the event
2197 to all toplevel widgets, where a reimplementation of changeEvent can
2198 re-translate the user interface by passing user-visible strings via the
2199 tr() function to the respective property setters. User-interface classes
2200 generated by \QD provide a \c retranslateUi() function that can be
2201 called.
2202
2203 The function returns \c true on success and \c false on failure.
2204
2205 \note QCoreApplication does \e not take ownership of \a translationFile.
2206 It is the responsibility of the application to ensure that, if the
2207 function returned \c true, the \a translationFile object is alive until
2208 either \l removeTranslator() is called for it, or the application exits.
2209
2210 \sa removeTranslator(), translate(), QTranslator::load(),
2211 {Writing Source Code for Translation#Prepare for Dynamic Language Changes}{Prepare for Dynamic Language Changes}
2212*/
2213
2214bool QCoreApplication::installTranslator(QTranslator *translationFile)
2215{
2216 if (!translationFile)
2217 return false;
2218
2219 if (!QCoreApplicationPrivate::checkInstance("installTranslator"))
2220 return false;
2221
2222 QCoreApplicationPrivate *d = self->d_func();
2223 {
2224 QWriteLocker locker(&d->translateMutex);
2225 d->translators.prepend(translationFile);
2226 }
2227
2228 if (translationFile->isEmpty())
2229 return true;
2230
2231#ifndef QT_NO_QOBJECT
2232 QEvent ev(QEvent::LanguageChange);
2233 QCoreApplication::sendEvent(self, &ev);
2234#endif
2235
2236 return true;
2237}
2238
2239/*!
2240 Removes the translation file \a translationFile from the list of
2241 translation files used by this application. (It does not delete the
2242 translation file from the file system.)
2243
2244 The function returns \c true on success and false on failure.
2245
2246 \sa installTranslator(), translate(), QObject::tr()
2247*/
2248
2249bool QCoreApplication::removeTranslator(QTranslator *translationFile)
2250{
2251 if (!translationFile)
2252 return false;
2253 if (!QCoreApplicationPrivate::checkInstance("removeTranslator"))
2254 return false;
2255 QCoreApplicationPrivate *d = self->d_func();
2256 QWriteLocker locker(&d->translateMutex);
2257 if (d->translators.removeAll(translationFile)) {
2258#ifndef QT_NO_QOBJECT
2259 locker.unlock();
2260 if (!self->closingDown()) {
2261 QEvent ev(QEvent::LanguageChange);
2262 QCoreApplication::sendEvent(self, &ev);
2263 }
2264#endif
2265 return true;
2266 }
2267 return false;
2268}
2269
2270static void replacePercentN(QString *result, int n)
2271{
2272 if (n >= 0) {
2273 qsizetype percentPos = 0;
2274 qsizetype len = 0;
2275 while ((percentPos = result->indexOf(u'%', percentPos + len)) != -1) {
2276 len = 1;
2277 if (percentPos + len == result->size())
2278 break;
2279 QString fmt;
2280 if (result->at(percentPos + len) == u'L') {
2281 ++len;
2282 if (percentPos + len == result->size())
2283 break;
2284 fmt = "%L1"_L1;
2285 } else {
2286 fmt = "%1"_L1;
2287 }
2288 if (result->at(percentPos + len) == u'n') {
2289 fmt = fmt.arg(n);
2290 ++len;
2291 result->replace(percentPos, len, fmt);
2292 len = fmt.size();
2293 }
2294 }
2295 }
2296}
2297
2298/*!
2299 \threadsafe
2300
2301 Returns the translation text for \a sourceText, by querying the
2302 installed translation files. The translation files are searched
2303 from the most recently installed file back to the first
2304 installed file.
2305
2306 QObject::tr() provides this functionality more conveniently.
2307
2308 \a context is typically a class name (e.g., "MyDialog") and \a
2309 sourceText is either English text or a short identifying text.
2310
2311 \a disambiguation is an identifying string, for when the same \a
2312 sourceText is used in different roles within the same context. By
2313 default, it is \nullptr.
2314
2315 See the \l QTranslator and \l QObject::tr() documentation for
2316 more information about contexts, disambiguations and comments.
2317
2318 \a n is used in conjunction with \c %n to support plural forms.
2319 See QObject::tr() for details.
2320
2321 If none of the translation files contain a translation for \a
2322 sourceText in \a context, this function returns a QString
2323 equivalent of \a sourceText.
2324
2325 This function is not virtual. You can use alternative translation
2326 techniques by subclassing \l QTranslator.
2327
2328 \sa QObject::tr(), installTranslator(), removeTranslator(),
2329 {Internationalization and Translations}
2330*/
2331QString QCoreApplication::translate(const char *context, const char *sourceText,
2332 const char *disambiguation, int n)
2333{
2334 QString result;
2335
2336 if (!sourceText)
2337 return result;
2338
2339 if (self) {
2340 QCoreApplicationPrivate *d = self->d_func();
2341 QReadLocker locker(&d->translateMutex);
2342 if (!d->translators.isEmpty()) {
2343 QList<QTranslator*>::ConstIterator it;
2344 QTranslator *translationFile;
2345 for (it = d->translators.constBegin(); it != d->translators.constEnd(); ++it) {
2346 translationFile = *it;
2347 result = translationFile->translate(context, sourceText, disambiguation, n);
2348 if (!result.isNull())
2349 break;
2350 }
2351 }
2352 }
2353
2354 if (result.isNull())
2355 result = QString::fromUtf8(sourceText);
2356
2357 replacePercentN(&result, n);
2358 return result;
2359}
2360
2361// Declared in qglobal.h
2362QString qtTrId(const char *id, int n)
2363{
2364 return QCoreApplication::translate(nullptr, id, nullptr, n);
2365}
2366
2367bool QCoreApplicationPrivate::isTranslatorInstalled(QTranslator *translator)
2368{
2369 if (!QCoreApplication::self)
2370 return false;
2371 QCoreApplicationPrivate *d = QCoreApplication::self->d_func();
2372 QReadLocker locker(&d->translateMutex);
2373 return d->translators.contains(translator);
2374}
2375
2376#else
2377
2378QString QCoreApplication::translate(const char *context, const char *sourceText,
2379 const char *disambiguation, int n)
2380{
2381 Q_UNUSED(context);
2382 Q_UNUSED(disambiguation);
2383 QString ret = QString::fromUtf8(sourceText);
2384 if (n >= 0)
2385 ret.replace("%n"_L1, QString::number(n));
2386 return ret;
2387}
2388
2389#endif //QT_NO_TRANSLATION
2390
2391#ifndef QT_BOOTSTRAPPED
2392/*!
2393 Returns the directory that contains the application executable.
2394
2395 For example, if you have installed Qt in the \c{C:\Qt}
2396 directory, and you run the \c{regexp} example, this function will
2397 return "C:/Qt/examples/tools/regexp".
2398
2399 On \macos and iOS this will point to the directory actually containing
2400 the executable, which may be inside an application bundle (if the
2401 application is bundled).
2402
2403 On Android this will point to the directory actually containing the
2404 executable, which may be inside the application APK (if it was built
2405 with uncompressed libraries support).
2406
2407 \warning On Linux, this function will try to get the path from the
2408 \c {/proc} file system. If that fails, it assumes that \c
2409 {argv[0]} contains the absolute file name of the executable. The
2410 function also assumes that the current directory has not been
2411 changed by the application.
2412
2413 \sa applicationFilePath()
2414*/
2415QString QCoreApplication::applicationDirPath()
2416{
2417 if (!self) {
2418 qWarning("QCoreApplication::applicationDirPath: Please instantiate the QApplication object first");
2419 return QString();
2420 }
2421
2422 QFileSystemEntry appFilePath(applicationFilePath(), QFileSystemEntry::FromInternalPath{});
2423 return appFilePath.isEmpty() ? QString() : appFilePath.path();
2424}
2425
2426#if !defined(Q_OS_WIN) && !defined(Q_OS_DARWIN)
2427// qcoreapplication_win.cpp or qcoreapplication_mac.cpp for those
2428static QString qAppFileName()
2429{
2430# if defined(Q_OS_ANDROID) || defined(Q_OS_HARMONY)
2431 // the actual process on Android is the Java VM, so this doesn't help us
2432 return QString();
2433# elif defined(Q_OS_LINUX)
2434 // this includes the Embedded Android builds
2435 return QFile::decodeName(qt_readlink("/proc/self/exe"));
2436# elif defined(AT_EXECPATH)
2437 // seen on FreeBSD, but I suppose the other BSDs could adopt this API
2438 char execfn[PATH_MAX];
2439 if (elf_aux_info(AT_EXECPATH, execfn, sizeof(execfn)) != 0)
2440 execfn[0] = '\0';
2441
2442 qsizetype len = qstrlen(execfn);
2443 return QFile::decodeName(QByteArray::fromRawData(execfn, len));
2444# else
2445 // other OS or something
2446 return QString();
2447# endif
2448}
2449#endif // !Q_OS_WIN && !Q_OS_DARWIN
2450
2451/*!
2452 Returns the file path of the application executable.
2453
2454 For example, if you have installed Qt in the \c{/usr/local/qt}
2455 directory, and you run the \c{regexp} example, this function will
2456 return "/usr/local/qt/examples/tools/regexp/regexp".
2457
2458 \warning On Linux, this function will try to get the path from the
2459 \c {/proc} file system. If that fails, it assumes that \c
2460 {argv[0]} contains the absolute file name of the executable. The
2461 function also assumes that the current directory has not been
2462 changed by the application.
2463
2464 \sa applicationDirPath()
2465*/
2466QString QCoreApplication::applicationFilePath()
2467{
2468 if (!self) {
2469 qWarning("QCoreApplication::applicationFilePath: Please instantiate the QApplication object first");
2470 return QString();
2471 }
2472
2473 QCoreApplicationPrivate *d = self->d_func();
2474
2475 if (d->argc) {
2476 static QByteArray procName = QByteArray(d->argv[0]);
2477 if (procName != QByteArrayView(d->argv[0])) {
2478 // clear the cache if the procname changes, so we reprocess it.
2479 d->cachedApplicationFilePath = QString();
2480 procName.assign(d->argv[0]);
2481 }
2482 }
2483
2484 if (!d->cachedApplicationFilePath.isNull())
2485 return d->cachedApplicationFilePath;
2486
2487 QString absPath = qAppFileName();
2488 if (Q_LIKELY(!absPath.isEmpty())) { // Darwin, FreeBSD, Linux, Windows
2489 // the OS has canonicalized for us
2490 return d->cachedApplicationFilePath = std::move(absPath);
2491 }
2492
2493 if (const QStringList args = arguments(); !args.isEmpty()) {
2494 const QString &argv0 = args[0];
2495
2496 if (!argv0.isEmpty() && argv0.at(0) == u'/') {
2497 /*
2498 If argv0 starts with a slash, it is already an absolute
2499 file path.
2500 */
2501 absPath = argv0;
2502 } else if (argv0.contains(u'/')) {
2503 /*
2504 If argv0 contains one or more slashes, it is a file path
2505 relative to the current directory.
2506 */
2507 absPath = QDir::current().absoluteFilePath(argv0);
2508 } else {
2509 /*
2510 Otherwise, the file path has to be determined using the
2511 PATH environment variable.
2512 */
2513 absPath = QStandardPaths::findExecutable(argv0);
2514 }
2515 }
2516
2517 absPath = QFileInfo(absPath).canonicalFilePath();
2518 if (!absPath.isEmpty()) {
2519 return d->cachedApplicationFilePath = std::move(absPath);
2520 }
2521 return QString();
2522}
2523#endif // !QT_BOOTSTRAPPED
2524
2525/*!
2526 \since 4.4
2527
2528 Returns the current process ID for the application.
2529*/
2530qint64 QCoreApplication::applicationPid() noexcept
2531{
2532#if defined(Q_OS_WIN)
2533 return GetCurrentProcessId();
2534#elif defined(Q_OS_VXWORKS)
2535 return (pid_t) taskIdCurrent;
2536#else
2537 return getpid();
2538#endif
2539}
2540
2541#ifdef Q_OS_WIN
2542static QStringList winCmdArgs()
2543{
2544 // On Windows, it is possible to pass Unicode arguments on
2545 // the command line, but we don't implement any of the wide
2546 // entry-points (wmain/wWinMain), so get the arguments from
2547 // the Windows API instead of using argv. Note that we only
2548 // do this when argv were not modified by the user in main().
2549 QStringList result;
2550 int size;
2551 if (wchar_t **argv = CommandLineToArgvW(GetCommandLine(), &size)) {
2552 result.reserve(size);
2553 wchar_t **argvEnd = argv + size;
2554 for (wchar_t **a = argv; a < argvEnd; ++a)
2555 result.append(QString::fromWCharArray(*a));
2556 LocalFree(argv);
2557 }
2558 return result;
2559}
2560#endif // Q_OS_WIN
2561
2562/*!
2563 \since 4.1
2564
2565 Returns the list of command-line arguments.
2566
2567 Usually arguments().at(0) is the program name, arguments().at(1)
2568 is the first argument, and arguments().last() is the last
2569 argument. See the note below about Windows.
2570
2571 Calling this function is slow - you should store the result in a variable
2572 when parsing the command line.
2573
2574 \warning On Unix, this list is built from the argc and argv parameters passed
2575 to the constructor in the main() function. The string-data in argv is
2576 interpreted using QString::fromLocal8Bit(); hence it is not possible to
2577 pass, for example, Japanese command line arguments on a system that runs in a
2578 Latin1 locale. Most modern Unix systems do not have this limitation, as they are
2579 Unicode-based.
2580
2581 On Windows, the list is built from the argc and argv parameters only if
2582 modified argv/argc parameters are passed to the constructor. In that case,
2583 encoding problems might occur.
2584
2585 Otherwise, the arguments() are constructed from the return value of
2586 \l{https://docs.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-getcommandlinea}{GetCommandLine()}.
2587 As a result of this, the string given by arguments().at(0)
2588 might not be the exact program used to start the application
2589 on Windows.
2590
2591 \sa applicationFilePath(), QCommandLineParser
2592*/
2593
2594QStringList QCoreApplication::arguments()
2595{
2596 QStringList list;
2597
2598 if (!self) {
2599 qWarning("QCoreApplication::arguments: Please instantiate the QApplication object first");
2600 return list;
2601 }
2602
2603 const QCoreApplicationPrivate *d = self->d_func();
2604
2605 const int argc = d->argc;
2606 char ** const argv = d->argv;
2607 list.reserve(argc);
2608
2609#if defined(Q_OS_WIN)
2610 const bool argsModifiedByUser = d->origArgv == nullptr;
2611 if (!argsModifiedByUser) {
2612 QStringList commandLineArguments = winCmdArgs();
2613
2614 // Even if the user didn't modify argv before passing them
2615 // on to QCoreApplication, derived QApplications might have.
2616 // If that's the case argc will differ from origArgc.
2617 if (argc != d->origArgc) {
2618 // Note: On MingGW the arguments from GetCommandLine are
2619 // not wildcard expanded (if wildcard expansion is enabled),
2620 // as opposed to the arguments in argv. This means we can't
2621 // compare commandLineArguments to argv/origArgc, but
2622 // must remove elements by value, based on whether they
2623 // were filtered out from argc.
2624 for (int i = 0; i < d->origArgc; ++i) {
2625 if (!contains(argc, argv, d->origArgv[i]))
2626 commandLineArguments.removeAll(QString::fromLocal8Bit(d->origArgv[i]));
2627 }
2628 }
2629
2630 return commandLineArguments;
2631 } // Fall back to rebuilding from argv/argc when a modified argv was passed.
2632#endif // defined(Q_OS_WIN)
2633
2634 for (int a = 0; a < argc; ++a)
2635 list << QString::fromLocal8Bit(argv[a]);
2636
2637 return list;
2638}
2639
2640/*!
2641 \property QCoreApplication::organizationName
2642 \brief the name of the organization that wrote this application
2643
2644 The value is used by the QSettings class when it is constructed
2645 using the default constructor. This saves having to repeat this
2646 information each time a QSettings object is created.
2647
2648 On Mac, QSettings uses \l {QCoreApplication::}{organizationDomain()} as the organization
2649 if it's not an empty string; otherwise it uses
2650 organizationName(). On all other platforms, QSettings uses
2651 organizationName() as the organization.
2652
2653 \sa organizationDomain, applicationName
2654*/
2655
2656/*!
2657 \fn void QCoreApplication::organizationNameChanged()
2658 \internal
2659
2660 While not useful from C++ due to how organizationName is normally set once on
2661 startup, this is still needed for QML so that bindings are reevaluated after
2662 that initial change.
2663*/
2664void QCoreApplication::setOrganizationName(const QString &orgName)
2665{
2666 if (coreappdata()->orgName == orgName)
2667 return;
2668 coreappdata()->orgName = orgName;
2669#ifndef QT_NO_QOBJECT
2670 if (QCoreApplication::self)
2671 emit QCoreApplication::self->organizationNameChanged();
2672#endif
2673}
2674
2675QString QCoreApplication::organizationName()
2676{
2677 return coreappdata()->orgName;
2678}
2679
2680/*!
2681 \property QCoreApplication::organizationDomain
2682 \brief the Internet domain of the organization that wrote this application
2683
2684 The value is used by the QSettings class when it is constructed
2685 using the default constructor. This saves having to repeat this
2686 information each time a QSettings object is created.
2687
2688 On Mac, QSettings uses organizationDomain() as the organization
2689 if it's not an empty string; otherwise it uses organizationName().
2690 On all other platforms, QSettings uses organizationName() as the
2691 organization.
2692
2693 \sa organizationName, applicationName, applicationVersion
2694*/
2695/*!
2696 \fn void QCoreApplication::organizationDomainChanged()
2697 \internal
2698
2699 Primarily for QML, see organizationNameChanged.
2700*/
2701void QCoreApplication::setOrganizationDomain(const QString &orgDomain)
2702{
2703 if (coreappdata()->orgDomain == orgDomain)
2704 return;
2705 coreappdata()->orgDomain = orgDomain;
2706#ifndef QT_NO_QOBJECT
2707 if (QCoreApplication::self)
2708 emit QCoreApplication::self->organizationDomainChanged();
2709#endif
2710}
2711
2712QString QCoreApplication::organizationDomain()
2713{
2714 return coreappdata()->orgDomain;
2715}
2716
2717/*!
2718 \property QCoreApplication::applicationName
2719 \brief the name of this application
2720
2721 The application name is used in various Qt classes and modules,
2722 most prominently in \l{QSettings} when it is constructed using the default constructor.
2723 Other uses are in formatted logging output (see \l{qSetMessagePattern()}),
2724 in output by \l{QCommandLineParser}, in \l{QTemporaryDir} and \l{QTemporaryFile}
2725 default paths, and in some file locations of \l{QStandardPaths}.
2726 \l{Qt D-Bus}, \l{Accessibility}, and the XCB platform integration make use
2727 of the application name, too.
2728
2729 If not set, the application name defaults to the executable name.
2730
2731 \sa organizationName, organizationDomain, applicationVersion, applicationFilePath()
2732*/
2733/*!
2734 \fn void QCoreApplication::applicationNameChanged()
2735 \internal
2736
2737 Primarily for QML, see organizationNameChanged.
2738*/
2739void QCoreApplication::setApplicationName(const QString &application)
2740{
2741 coreappdata()->applicationNameSet = !application.isEmpty();
2742 QString newAppName = application;
2743 if (newAppName.isEmpty() && QCoreApplication::self)
2744 newAppName = QCoreApplication::self->d_func()->appName();
2745 if (coreappdata()->application == newAppName)
2746 return;
2747 coreappdata()->application = newAppName;
2748#ifndef QT_NO_QOBJECT
2749 if (QCoreApplication::self)
2750 emit QCoreApplication::self->applicationNameChanged();
2751#endif
2752}
2753
2754QString QCoreApplication::applicationName()
2755{
2756 return coreappdata() ? coreappdata()->application : QString();
2757}
2758
2759/*!
2760 \property QCoreApplication::applicationVersion
2761 \since 4.4
2762 \brief the version of this application
2763
2764 If not set, the application version defaults to a platform-specific value
2765 determined from the main application executable or package (since Qt 5.9):
2766
2767 \table
2768 \header
2769 \li Platform
2770 \li Source
2771 \row
2772 \li Windows (classic desktop)
2773 \li PRODUCTVERSION parameter of the VERSIONINFO resource
2774 \row
2775 \li macOS, iOS, tvOS, watchOS
2776 \li CFBundleVersion property of the information property list
2777 \row
2778 \li Android
2779 \li android:versionName property of the AndroidManifest.xml manifest element
2780 \row
2781 \li HarmonyOS
2782 \li versionName field of the app.json5 configuration file
2783 \endtable
2784
2785 On other platforms, the default is the empty string.
2786
2787 \sa applicationName, organizationName, organizationDomain
2788*/
2789/*!
2790 \fn void QCoreApplication::applicationVersionChanged()
2791 \internal
2792
2793 Primarily for QML, see organizationNameChanged.
2794*/
2795void QCoreApplication::setApplicationVersion(const QString &version)
2796{
2797 coreappdata()->applicationVersionSet = !version.isEmpty();
2798 QString newVersion = version;
2799 if (newVersion.isEmpty() && QCoreApplication::self)
2800 newVersion = QCoreApplication::self->d_func()->appVersion();
2801 if (coreappdata()->applicationVersion == newVersion)
2802 return;
2803 coreappdata()->applicationVersion = newVersion;
2804#ifndef QT_NO_QOBJECT
2805 if (QCoreApplication::self)
2806 emit QCoreApplication::self->applicationVersionChanged();
2807#endif
2808}
2809
2810QString QCoreApplication::applicationVersion()
2811{
2812 return coreappdata() ? coreappdata()->applicationVersion : QString();
2813}
2814
2815#if QT_CONFIG(permissions) || defined(Q_QDOC)
2816
2817/*!
2818 Checks the status of the given \a permission
2819
2820 If the result is Qt::PermissionStatus::Undetermined then permission should be
2821 requested via requestPermission() to determine the user's intent.
2822
2823 \since 6.5
2824 \sa requestPermission(), {Application Permissions}
2825*/
2826Qt::PermissionStatus QCoreApplication::checkPermission(const QPermission &permission)
2827{
2828 return QPermissions::Private::checkPermission(permission);
2829}
2830
2831/*!
2832 \fn template <typename Functor> void QCoreApplication::requestPermission(
2833 const QPermission &permission, Functor &&functor)
2834
2835 Requests the given \a permission.
2836
2837 \include permissions.qdocinc requestPermission-functor
2838
2839 The \a functor can be a free-standing or static member function:
2840
2841 \code
2842 qApp->requestPermission(QCameraPermission{}, &permissionUpdated);
2843 \endcode
2844
2845 or a lambda:
2846
2847 \code
2848 qApp->requestPermission(QCameraPermission{}, [](const QPermission &permission) {
2849 });
2850 \endcode
2851
2852 \include permissions.qdocinc requestPermission-postamble
2853
2854 \since 6.5
2855 \sa checkPermission(), {Application Permissions}
2856*/
2857
2858/*!
2859 \fn template<typename Functor> void QCoreApplication::requestPermission(
2860 const QPermission &permission, const QObject *context,
2861 Functor functor)
2862
2863 Requests the given \a permission, in the context of \a context.
2864
2865 \include permissions.qdocinc requestPermission-functor
2866
2867 The \a functor can be a free-standing or static member function:
2868
2869 \code
2870 qApp->requestPermission(QCameraPermission{}, context, &permissionUpdated);
2871 \endcode
2872
2873 a lambda:
2874
2875 \code
2876 qApp->requestPermission(QCameraPermission{}, context, [](const QPermission &permission) {
2877 });
2878 \endcode
2879
2880 or a slot in the \a context object:
2881
2882 \code
2883 qApp->requestPermission(QCameraPermission{}, this, &CamerWidget::permissionUpdated);
2884 \endcode
2885
2886 The \a functor will be called in the thread of the \a context object. If
2887 \a context is destroyed before the request completes, the \a functor will
2888 not be called.
2889
2890 \include permissions.qdocinc requestPermission-postamble
2891
2892 \since 6.5
2893 \overload
2894 \sa checkPermission(), {Application Permissions}
2895*/
2896
2897/*!
2898 \internal
2899
2900 Called by the various requestPermission overloads to perform the request.
2901
2902 Calls the functor encapsulated in the \a slotObjRaw in the given \a context
2903 (which may be \c nullptr).
2904*/
2905void QCoreApplication::requestPermissionImpl(const QPermission &requestedPermission,
2906 QtPrivate::QSlotObjectBase *slotObjRaw, const QObject *context)
2907{
2908 QtPrivate::SlotObjUniquePtr slotObj{slotObjRaw}; // adopts
2909 Q_ASSERT(slotObj);
2910
2911 if (!QThread::isMainThread()) {
2912 qCWarning(lcPermissions, "Permissions can only be requested from the GUI (main) thread");
2913 return;
2914 }
2915
2916 class PermissionReceiver : public QObject
2917 {
2918 public:
2919 explicit PermissionReceiver(QtPrivate::SlotObjUniquePtr &&slotObject, const QObject *context)
2920 : slotObject(std::move(slotObject)), context(context ? context : this)
2921 {
2922 Q_ASSERT(this->context);
2923 moveToThread(this->context->thread());
2924 }
2925
2926 void finalizePermissionRequest(const QPermission &permission)
2927 {
2928 Q_ASSERT(slotObject);
2929 // only execute if context object is still alive
2930 if (context) {
2931 void *args[] = { nullptr, const_cast<QPermission *>(&permission) };
2932 slotObject->call(const_cast<QObject *>(context.data()), args);
2933 }
2934 }
2935
2936 private:
2937 QtPrivate::SlotObjUniquePtr slotObject;
2938 QPointer<const QObject> context;
2939 };
2940
2941 // ### use unique_ptr once PermissionCallback is a move_only function
2942 auto receiver = std::make_shared<PermissionReceiver>(std::move(slotObj), context);
2943
2944 QPermissions::Private::requestPermission(requestedPermission,
2945 [=, receiver = std::move(receiver)](Qt::PermissionStatus status) mutable {
2946 if (status == Qt::PermissionStatus::Undetermined) {
2947 Q_ASSERT_X(false, "QPermission",
2948 "Internal error: requestPermission() should never return Undetermined");
2949 status = Qt::PermissionStatus::Denied;
2950 }
2951
2952 if (QCoreApplication::self) {
2953 QPermission permission = requestedPermission;
2954 permission.m_status = status;
2955 auto receiverObject = receiver.get();
2956 QMetaObject::invokeMethod(receiverObject,
2957 [receiver = std::move(receiver), permission] {
2958 receiver->finalizePermissionRequest(permission);
2959 }, Qt::QueuedConnection);
2960 }
2961 });
2962}
2963
2964#endif // QT_CONFIG(permissions)
2965
2966#if QT_CONFIG(library)
2967static QStringList libraryPathsLocked();
2968
2969/*!
2970 Returns a list of paths that the application will search when
2971 dynamically loading libraries.
2972
2973 The return value of this function may change when a QCoreApplication
2974 is created. It is not recommended to call it before creating a
2975 QCoreApplication. The directory of the application executable (\b not
2976 the working directory) is part of the list if it is known. In order
2977 to make it known a QCoreApplication has to be constructed as it will
2978 use \c {argv[0]} to find it.
2979
2980 Qt provides default library paths, but they can also be set using
2981 a \l{Using qt.conf}{qt.conf} file. Paths specified in this file
2982 will override default values. Note that if the qt.conf file is in
2983 the directory of the application executable, it may not be found
2984 until a QCoreApplication is created. If it is not found when calling
2985 this function, the default library paths will be used.
2986
2987 The list will include the installation directories for plugins if
2988 they exist (the default installation directory for plugins is \c
2989 INSTALL/plugins, where \c INSTALL is the directory where Qt was
2990 installed). The colon separated entries of the \c QT_PLUGIN_PATH
2991 environment variable are always added. The plugin installation
2992 directory (and its existence) may change when the directory of
2993 the application executable becomes known.
2994
2995 \warning This function does not currently include QLibraryInfo::LibrariesPath
2996 in its default paths, and QLibrary does not currently use this function to look
2997 up non-absolute library paths.
2998
2999 \sa setLibraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary,
3000 {How to Create Qt Plugins}
3001*/
3002QStringList QCoreApplication::libraryPaths()
3003{
3004 QMutexLocker locker(&coreappdata->libraryPathMutex);
3005 return libraryPathsLocked();
3006}
3007
3008/*!
3009 \internal
3010*/
3011static QStringList libraryPathsLocked()
3012{
3013 QCoreApplicationData *d = coreappdata;
3014 if (d->libPathsManuallySet())
3015 return d->manual_libpaths;
3016
3017 QStringList *app_libpaths = &d->app_libpaths;
3018 if (!d->libPathsInitialized()) {
3019
3020 auto setPathsFromEnv = [&](QString libPathEnv) {
3021 if (!libPathEnv.isEmpty()) {
3022 QStringList paths = libPathEnv.split(QDir::listSeparator(), Qt::SkipEmptyParts);
3023 for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) {
3024 QString canonicalPath = QDir(*it).canonicalPath();
3025 if (!canonicalPath.isEmpty()
3026 && !app_libpaths->contains(canonicalPath)) {
3027 app_libpaths->append(canonicalPath);
3028 }
3029 }
3030 }
3031 };
3032 setPathsFromEnv(qEnvironmentVariable("QT_PLUGIN_PATH"));
3033
3034 const auto pluginPaths = QLibraryInfo::paths(QLibraryInfo::PluginsPath);
3035 for (auto path : pluginPaths) {
3036 if (QFile::exists(path)) {
3037 // Make sure we convert from backslashes to slashes.
3038 path = QDir(path).canonicalPath();
3039 if (!app_libpaths->contains(path))
3040 app_libpaths->append(path);
3041 }
3042 }
3043
3044 // If QCoreApplication is not yet instantiated,
3045 // make sure we add the application path when we construct the QCoreApplication
3046 if (qApp) {
3047 QString app_location = QCoreApplication::applicationFilePath();
3048 app_location.truncate(app_location.lastIndexOf(u'/'));
3049 app_location = QDir(app_location).canonicalPath();
3050 if (QFile::exists(app_location) && !app_libpaths->contains(app_location))
3051 app_libpaths->append(app_location);
3052 }
3053 if (app_libpaths->isEmpty())
3054 app_libpaths->reserve(1); // detach from null
3055 Q_ASSERT(d->libPathsInitialized());
3056 }
3057 return *app_libpaths;
3058}
3059
3060
3061
3062/*!
3063
3064 Sets the list of directories to search when loading plugins with
3065 QLibrary to \a paths. All existing paths will be deleted and the
3066 path list will consist of the paths given in \a paths and the path
3067 to the application.
3068
3069 The library paths are reset to the default when an instance of
3070 QCoreApplication is destructed.
3071
3072 \warning QLibrary does not currently use the given paths to look
3073 up non-absolute library paths.
3074
3075 \sa libraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary
3076 */
3077void QCoreApplication::setLibraryPaths(const QStringList &paths)
3078{
3079 QCoreApplicationData *d = coreappdata;
3080 QMutexLocker locker(&d->libraryPathMutex);
3081
3082 // setLibraryPaths() is considered a "remove everything and then add some new ones" operation.
3083 // When the application is constructed it should still amend the paths. So we keep the originals
3084 // around, and even create them if they don't exist, yet.
3085 if (!d->libPathsInitialized())
3086 libraryPathsLocked();
3087
3088 d->manual_libpaths = paths;
3089 if (d->manual_libpaths.isEmpty())
3090 d->manual_libpaths.reserve(1); // detach from null
3091 Q_ASSERT(d->libPathsManuallySet());
3092
3093 locker.unlock();
3094 QFactoryLoader::refreshAll();
3095}
3096
3097/*!
3098 Prepends \a path to the beginning of the library path list, ensuring that
3099 it is searched for libraries first. If \a path is empty or already in the
3100 path list, the path list is not changed.
3101
3102 The default path list consists of one or two entries. The first is the
3103 installation directory for plugins, which is \c INSTALL/plugins, where \c
3104 INSTALL is the directory where Qt was installed. The second is the
3105 application's own directory (\b not the current directory), but only after
3106 the QCoreApplication object is instantiated.
3107
3108 The library paths are reset to the default when an instance of
3109 QCoreApplication is destructed.
3110
3111 \warning QLibrary does not currently use the given path to look
3112 up non-absolute library paths.
3113
3114 \sa removeLibraryPath(), libraryPaths(), setLibraryPaths()
3115 */
3116void QCoreApplication::addLibraryPath(const QString &path)
3117{
3118 if (path.isEmpty())
3119 return;
3120
3121 QString canonicalPath = QDir(path).canonicalPath();
3122 if (canonicalPath.isEmpty())
3123 return;
3124
3125 QCoreApplicationData *d = coreappdata;
3126 QMutexLocker locker(&d->libraryPathMutex);
3127
3128 QStringList *libpaths = &d->manual_libpaths;
3129 if (d->libPathsManuallySet()) {
3130 if (d->manual_libpaths.contains(canonicalPath))
3131 return;
3132 } else {
3133 // make sure that library paths are initialized
3134 libraryPathsLocked();
3135 QStringList *app_libpaths = &d->app_libpaths;
3136 if (app_libpaths->contains(canonicalPath))
3137 return;
3138
3139 *libpaths = *app_libpaths;
3140 }
3141
3142 libpaths->prepend(canonicalPath);
3143 Q_ASSERT(d->libPathsManuallySet());
3144 locker.unlock();
3145 QFactoryLoader::refreshAll();
3146}
3147
3148/*!
3149 Removes \a path from the library path list. If \a path is empty or not
3150 in the path list, the list is not changed.
3151
3152 The library paths are reset to the default when an instance of
3153 QCoreApplication is destructed.
3154
3155 \warning QLibrary does not currently use libraryPaths()
3156 to look up non-absolute library paths.
3157
3158 \sa addLibraryPath(), libraryPaths(), setLibraryPaths()
3159*/
3160void QCoreApplication::removeLibraryPath(const QString &path)
3161{
3162 if (path.isEmpty())
3163 return;
3164
3165 QString canonicalPath = QDir(path).canonicalPath();
3166 if (canonicalPath.isEmpty())
3167 return;
3168
3169 QCoreApplicationData *d = coreappdata;
3170 QMutexLocker locker(&d->libraryPathMutex);
3171
3172 QStringList *libpaths = &d->manual_libpaths;
3173 if (d->libPathsManuallySet()) {
3174 if (libpaths->removeAll(canonicalPath) == 0)
3175 return;
3176 } else {
3177 // make sure that library paths is initialized
3178 libraryPathsLocked();
3179 QStringList *app_libpaths = &d->app_libpaths;
3180 if (!app_libpaths->contains(canonicalPath))
3181 return;
3182
3183 *libpaths = *app_libpaths;
3184 libpaths->removeAll(canonicalPath);
3185 Q_ASSERT(d->libPathsManuallySet());
3186 }
3187
3188 locker.unlock();
3189 QFactoryLoader::refreshAll();
3190}
3191
3192#endif // QT_CONFIG(library)
3193
3194#ifndef QT_NO_QOBJECT
3195
3196/*!
3197 Installs an event filter \a filterObj for all native events
3198 received by the application in the main thread.
3199
3200 The event filter \a filterObj receives events via its \l {QAbstractNativeEventFilter::}{nativeEventFilter()}
3201 function, which is called for all native events received in the main thread.
3202
3203 The QAbstractNativeEventFilter::nativeEventFilter() function should
3204 return true if the event should be filtered, i.e. stopped. It should
3205 return false to allow normal Qt processing to continue: the native
3206 event can then be translated into a QEvent and handled by the standard
3207 Qt \l{QEvent} {event} filtering, e.g. QObject::installEventFilter().
3208
3209 If multiple event filters are installed, the filter that was
3210 installed last is activated first.
3211
3212 \note The filter function set here receives native messages,
3213 i.e. MSG or XCB event structs.
3214
3215 \note Native event filters will be disabled in the application when the
3216 Qt::AA_PluginApplication attribute is set.
3217
3218 For maximum portability, you should always try to use QEvent
3219 and QObject::installEventFilter() whenever possible.
3220
3221 \sa QObject::installEventFilter()
3222
3223 \since 5.0
3224*/
3225void QCoreApplication::installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
3226{
3227 if (QCoreApplication::testAttribute(Qt::AA_PluginApplication)) {
3228 qWarning("Native event filters are not applied when the Qt::AA_PluginApplication attribute is set");
3229 return;
3230 }
3231
3232 QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(QCoreApplicationPrivate::theMainThread.loadAcquire());
3233 if (!filterObj || !eventDispatcher)
3234 return;
3235 eventDispatcher->installNativeEventFilter(filterObj);
3236}
3237
3238/*!
3239 Removes an event \a filterObject from this object. The
3240 request is ignored if such an event filter has not been installed.
3241
3242 All event filters for this object are automatically removed when
3243 this object is destroyed.
3244
3245 It is always safe to remove an event filter, even during event
3246 filter activation (i.e. from the nativeEventFilter() function).
3247
3248 \sa installNativeEventFilter()
3249 \since 5.0
3250*/
3251void QCoreApplication::removeNativeEventFilter(QAbstractNativeEventFilter *filterObject)
3252{
3253 QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(QCoreApplicationPrivate::theMainThread.loadAcquire());
3254 if (!filterObject || !eventDispatcher)
3255 return;
3256 eventDispatcher->removeNativeEventFilter(filterObject);
3257}
3258
3259/*!
3260 Returns a pointer to the event dispatcher object for the main thread. If no
3261 event dispatcher exists for the thread, this function returns \nullptr.
3262*/
3263QAbstractEventDispatcher *QCoreApplication::eventDispatcher()
3264{
3265 if (QCoreApplicationPrivate::theMainThread.loadAcquire())
3266 return QCoreApplicationPrivate::theMainThread.loadRelaxed()->eventDispatcher();
3267 return nullptr;
3268}
3269
3270/*!
3271 Sets the event dispatcher for the main thread to \a eventDispatcher. This
3272 is only possible as long as there is no event dispatcher installed yet. That
3273 is, before QCoreApplication has been instantiated. This method takes
3274 ownership of the object.
3275*/
3276void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
3277{
3278 QThread *mainThread = QCoreApplicationPrivate::theMainThread.loadAcquire();
3279 if (!mainThread)
3280 mainThread = QThread::currentThread(); // will also setup theMainThread
3281 mainThread->setEventDispatcher(eventDispatcher);
3282}
3283
3284#endif // QT_NO_QOBJECT
3285
3286/*!
3287 \macro Q_COREAPP_STARTUP_FUNCTION(QtStartUpFunction ptr)
3288 \since 5.1
3289 \relates QCoreApplication
3290 \reentrant
3291
3292 Adds a global function that will be called from the QCoreApplication
3293 constructor. This macro is normally used to initialize libraries
3294 for program-wide functionality, without requiring the application to
3295 call into the library for initialization.
3296
3297 The function specified by \a ptr should take no arguments and should
3298 return nothing. For example:
3299
3300 \snippet code/src_corelib_kernel_qcoreapplication.cpp 3
3301
3302 Note that the startup function will run at the end of the QCoreApplication constructor,
3303 before any GUI initialization. If GUI code is required in the function,
3304 use a timer (or a queued invocation) to perform the initialization later on,
3305 from the event loop.
3306
3307 If QCoreApplication is deleted and another QCoreApplication is created,
3308 the startup function will be invoked again.
3309
3310 \note This macro is not suitable for use in library code that is then
3311 statically linked into an application since the function may not be called
3312 at all due to being eliminated by the linker.
3313*/
3314
3315/*!
3316 \fn void qAddPostRoutine(QtCleanUpFunction ptr)
3317 \threadsafe
3318 \relates QCoreApplication
3319
3320 Adds a global routine that will be called from the QCoreApplication
3321 destructor. This function is normally used to add cleanup routines
3322 for program-wide functionality.
3323
3324 The cleanup routines are called in the reverse order of their addition.
3325
3326 The function specified by \a ptr should take no arguments and should
3327 return nothing. For example:
3328
3329 \snippet code/src_corelib_kernel_qcoreapplication.cpp 4
3330
3331 Note that for an application- or module-wide cleanup, qAddPostRoutine()
3332 is often not suitable. For example, if the program is split into dynamically
3333 loaded modules, the relevant module may be unloaded long before the
3334 QCoreApplication destructor is called. In such cases, if using qAddPostRoutine()
3335 is still desirable, qRemovePostRoutine() can be used to prevent a routine
3336 from being called by the QCoreApplication destructor. For example, if that
3337 routine was called before the module was unloaded.
3338
3339 For modules and libraries, using a reference-counted
3340 initialization manager or Qt's parent-child deletion mechanism may
3341 be better. Here is an example of a private class that uses the
3342 parent-child mechanism to call a cleanup function at the right
3343 time:
3344
3345 \snippet code/src_corelib_kernel_qcoreapplication.cpp 5
3346
3347 By selecting the right parent object, this can often be made to
3348 clean up the module's data at the right moment.
3349
3350 \note This function has been thread-safe since Qt 5.10.
3351
3352 \sa qRemovePostRoutine()
3353*/
3354
3355/*!
3356 \fn void qRemovePostRoutine(QtCleanUpFunction ptr)
3357 \threadsafe
3358 \relates QCoreApplication
3359 \since 5.3
3360
3361 Removes the cleanup routine specified by \a ptr from the list of
3362 routines called by the QCoreApplication destructor. The routine
3363 must have been previously added to the list by a call to
3364 qAddPostRoutine(), otherwise this function has no effect.
3365
3366 \note This function has been thread-safe since Qt 5.10.
3367
3368 \sa qAddPostRoutine()
3369*/
3370
3371/*!
3372 \macro Q_DECLARE_TR_FUNCTIONS(context)
3373 \relates QCoreApplication
3374
3375 The Q_DECLARE_TR_FUNCTIONS() macro declares and implements the
3376 translation function \c tr() with this signature:
3377
3378 \snippet code/src_corelib_kernel_qcoreapplication.cpp 6
3379
3380 This macro is useful if you want to use QObject::tr() in classes
3381 that don't inherit from QObject.
3382
3383 Q_DECLARE_TR_FUNCTIONS() must appear at the very top of the
3384 class definition (before the first \c{public:} or \c{protected:}).
3385 For example:
3386
3387 \snippet code/src_corelib_kernel_qcoreapplication.cpp 7
3388
3389 The \a context parameter is normally the class name, but it can
3390 be any text.
3391
3392 \sa Q_OBJECT, QObject::tr()
3393*/
3394
3395void *QCoreApplication::resolveInterface(const char *name, int revision) const
3396{
3397#if defined(Q_OS_ANDROID)
3398 // The QAndroidApplication is wrongly using static methods for
3399 // its native interface (QTBUG-128796). Until we fix that we at
3400 // least want the preferred way of resolving a native interface
3401 // to work, so provide a minimal subclass of the interface.
3402 using namespace QNativeInterface;
3403 struct AndroidApplication : public QAndroidApplication {};
3404 static AndroidApplication androidApplication;
3405 QT_NATIVE_INTERFACE_RETURN_IF(QAndroidApplication, &androidApplication);
3406#endif
3407 Q_UNUSED(name); Q_UNUSED(revision);
3408 return nullptr;
3409}
3410
3411QT_END_NAMESPACE
3412
3413#ifndef QT_NO_QOBJECT
3414#include "moc_qcoreapplication.cpp"
3415#endif
\inmodule QtCore
#define __has_include(x)
QString qAppName()
Q_TRACE_POINT(qtcore, QCoreApplication_notify_exit, bool consumed, bool filtered)
void QT_MANGLE_NAMESPACE qt_startup_hook()
static QString qAppFileName()
QList< QtStartUpFunction > QStartUpFuncList
Q_TRACE_METADATA(qtcore, "ENUM { AUTO, RANGE User ... MaxUser } QEvent::Type;")
QString qtTrId(const char *id, int n)
Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_exit)
static void qt_call_pre_routines()
qsizetype qGlobalPostedEventsCount()
static Q_CONSTINIT bool preRoutinesCalled
QList< QtCleanUpFunction > QVFuncList
static void replacePercentN(QString *result, int n)
Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_event_compressed, QObject *receiver, QEvent *event)
Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_entry, QObject *receiver, QEvent *event, QEvent::Type type)
Q_TRACE_PREFIX(qtcore, "#include <qcoreevent.h>")
Q_CORE_EXPORT void qAddPostRoutine(QtCleanUpFunction)
void(* QtCleanUpFunction)()
void(* QtStartUpFunction)()
Q_CORE_EXPORT void qAddPreRoutine(QtStartUpFunction)
Q_CORE_EXPORT void qRemovePostRoutine(QtCleanUpFunction)
#define qApp
Q_GLOBAL_STATIC(QReadWriteLock, g_updateMutex)