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