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

source code of qtbase/src/corelib/kernel/qcoreapplication.cpp