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