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