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