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