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
2347bool QCoreApplicationPrivate::isTranslatorInstalled(QTranslator *translator)
2348{
2349 if (!QCoreApplication::self)
2350 return false;
2351 QCoreApplicationPrivate *d = QCoreApplication::self->d_func();
2352 QReadLocker locker(&d->translateMutex);
2353 return d->translators.contains(translator);
2354}
2355
2356#else
2357
2358QString QCoreApplication::translate(const char *context, const char *sourceText,
2359 const char *disambiguation, int n)
2360{
2361 Q_UNUSED(context);
2362 Q_UNUSED(disambiguation);
2363 QString ret = QString::fromUtf8(sourceText);
2364 if (n >= 0)
2365 ret.replace("%n"_L1, QString::number(n));
2366 return ret;
2367}
2368
2369#endif //QT_NO_TRANSLATION
2370
2371#ifndef QT_BOOTSTRAPPED
2372/*!
2373 Returns the directory that contains the application executable.
2374
2375 For example, if you have installed Qt in the \c{C:\Qt}
2376 directory, and you run the \c{regexp} example, this function will
2377 return "C:/Qt/examples/tools/regexp".
2378
2379 On \macos and iOS this will point to the directory actually containing
2380 the executable, which may be inside an application bundle (if the
2381 application is bundled).
2382
2383 On Android this will point to the directory actually containing the
2384 executable, which may be inside the application APK (if it was built
2385 with uncompressed libraries support).
2386
2387 \warning On Linux, this function will try to get the path from the
2388 \c {/proc} file system. If that fails, it assumes that \c
2389 {argv[0]} contains the absolute file name of the executable. The
2390 function also assumes that the current directory has not been
2391 changed by the application.
2392
2393 \sa applicationFilePath()
2394*/
2395QString QCoreApplication::applicationDirPath()
2396{
2397 if (!self) {
2398 qWarning("QCoreApplication::applicationDirPath: Please instantiate the QApplication object first");
2399 return QString();
2400 }
2401
2402 QFileSystemEntry appFilePath(applicationFilePath(), QFileSystemEntry::FromInternalPath{});
2403 return appFilePath.isEmpty() ? QString() : appFilePath.path();
2404}
2405
2406#if !defined(Q_OS_WIN) && !defined(Q_OS_DARWIN)
2407// qcoreapplication_win.cpp or qcoreapplication_mac.cpp for those
2408static QString qAppFileName()
2409{
2410# if defined(Q_OS_ANDROID)
2411 // the actual process on Android is the Java VM, so this doesn't help us
2412 return QString();
2413# elif defined(Q_OS_LINUX)
2414 // this includes the Embedded Android builds
2415 return QFile::decodeName(qt_readlink("/proc/self/exe"));
2416# elif defined(AT_EXECPATH)
2417 // seen on FreeBSD, but I suppose the other BSDs could adopt this API
2418 char execfn[PATH_MAX];
2419 if (elf_aux_info(AT_EXECPATH, execfn, sizeof(execfn)) != 0)
2420 execfn[0] = '\0';
2421
2422 qsizetype len = qstrlen(execfn);
2423 return QFile::decodeName(QByteArray::fromRawData(execfn, len));
2424# else
2425 // other OS or something
2426 return QString();
2427#endif
2428}
2429#endif // !Q_OS_WIN && !Q_OS_DARWIN
2430
2431/*!
2432 Returns the file path of the application executable.
2433
2434 For example, if you have installed Qt in the \c{/usr/local/qt}
2435 directory, and you run the \c{regexp} example, this function will
2436 return "/usr/local/qt/examples/tools/regexp/regexp".
2437
2438 \warning On Linux, this function will try to get the path from the
2439 \c {/proc} file system. If that fails, it assumes that \c
2440 {argv[0]} contains the absolute file name of the executable. The
2441 function also assumes that the current directory has not been
2442 changed by the application.
2443
2444 \sa applicationDirPath()
2445*/
2446QString QCoreApplication::applicationFilePath()
2447{
2448 if (!self) {
2449 qWarning("QCoreApplication::applicationFilePath: Please instantiate the QApplication object first");
2450 return QString();
2451 }
2452
2453 QCoreApplicationPrivate *d = self->d_func();
2454
2455 if (d->argc) {
2456 static QByteArray procName = QByteArray(d->argv[0]);
2457 if (procName != QByteArrayView(d->argv[0])) {
2458 // clear the cache if the procname changes, so we reprocess it.
2459 d->cachedApplicationFilePath = QString();
2460 procName.assign(d->argv[0]);
2461 }
2462 }
2463
2464 if (!d->cachedApplicationFilePath.isNull())
2465 return d->cachedApplicationFilePath;
2466
2467 QString absPath = qAppFileName();
2468 if (Q_LIKELY(!absPath.isEmpty())) { // Darwin, FreeBSD, Linux, Windows
2469 // the OS has canonicalized for us
2470 return d->cachedApplicationFilePath = std::move(absPath);
2471 }
2472
2473 if (const QStringList args = arguments(); !args.isEmpty()) {
2474 const QString &argv0 = args[0];
2475
2476 if (!argv0.isEmpty() && argv0.at(0) == u'/') {
2477 /*
2478 If argv0 starts with a slash, it is already an absolute
2479 file path.
2480 */
2481 absPath = argv0;
2482 } else if (argv0.contains(u'/')) {
2483 /*
2484 If argv0 contains one or more slashes, it is a file path
2485 relative to the current directory.
2486 */
2487 absPath = QDir::current().absoluteFilePath(argv0);
2488 } else {
2489 /*
2490 Otherwise, the file path has to be determined using the
2491 PATH environment variable.
2492 */
2493 absPath = QStandardPaths::findExecutable(argv0);
2494 }
2495 }
2496
2497 absPath = QFileInfo(absPath).canonicalFilePath();
2498 if (!absPath.isEmpty()) {
2499 return d->cachedApplicationFilePath = std::move(absPath);
2500 }
2501 return QString();
2502}
2503#endif // !QT_BOOTSTRAPPED
2504
2505/*!
2506 \since 4.4
2507
2508 Returns the current process ID for the application.
2509*/
2510qint64 QCoreApplication::applicationPid() noexcept
2511{
2512#if defined(Q_OS_WIN)
2513 return GetCurrentProcessId();
2514#elif defined(Q_OS_VXWORKS)
2515 return (pid_t) taskIdCurrent;
2516#else
2517 return getpid();
2518#endif
2519}
2520
2521#ifdef Q_OS_WIN
2522static QStringList winCmdArgs()
2523{
2524 // On Windows, it is possible to pass Unicode arguments on
2525 // the command line, but we don't implement any of the wide
2526 // entry-points (wmain/wWinMain), so get the arguments from
2527 // the Windows API instead of using argv. Note that we only
2528 // do this when argv were not modified by the user in main().
2529 QStringList result;
2530 int size;
2531 if (wchar_t **argv = CommandLineToArgvW(GetCommandLine(), &size)) {
2532 result.reserve(size);
2533 wchar_t **argvEnd = argv + size;
2534 for (wchar_t **a = argv; a < argvEnd; ++a)
2535 result.append(QString::fromWCharArray(*a));
2536 LocalFree(argv);
2537 }
2538 return result;
2539}
2540#endif // Q_OS_WIN
2541
2542/*!
2543 \since 4.1
2544
2545 Returns the list of command-line arguments.
2546
2547 Usually arguments().at(0) is the program name, arguments().at(1)
2548 is the first argument, and arguments().last() is the last
2549 argument. See the note below about Windows.
2550
2551 Calling this function is slow - you should store the result in a variable
2552 when parsing the command line.
2553
2554 \warning On Unix, this list is built from the argc and argv parameters passed
2555 to the constructor in the main() function. The string-data in argv is
2556 interpreted using QString::fromLocal8Bit(); hence it is not possible to
2557 pass, for example, Japanese command line arguments on a system that runs in a
2558 Latin1 locale. Most modern Unix systems do not have this limitation, as they are
2559 Unicode-based.
2560
2561 On Windows, the list is built from the argc and argv parameters only if
2562 modified argv/argc parameters are passed to the constructor. In that case,
2563 encoding problems might occur.
2564
2565 Otherwise, the arguments() are constructed from the return value of
2566 \l{https://docs.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-getcommandlinea}{GetCommandLine()}.
2567 As a result of this, the string given by arguments().at(0)
2568 might not be the exact program used to start the application
2569 on Windows.
2570
2571 \sa applicationFilePath(), QCommandLineParser
2572*/
2573
2574QStringList QCoreApplication::arguments()
2575{
2576 QStringList list;
2577
2578 if (!self) {
2579 qWarning("QCoreApplication::arguments: Please instantiate the QApplication object first");
2580 return list;
2581 }
2582
2583 const QCoreApplicationPrivate *d = self->d_func();
2584
2585 const int argc = d->argc;
2586 char ** const argv = d->argv;
2587 list.reserve(argc);
2588
2589#if defined(Q_OS_WIN)
2590 const bool argsModifiedByUser = d->origArgv == nullptr;
2591 if (!argsModifiedByUser) {
2592 QStringList commandLineArguments = winCmdArgs();
2593
2594 // Even if the user didn't modify argv before passing them
2595 // on to QCoreApplication, derived QApplications might have.
2596 // If that's the case argc will differ from origArgc.
2597 if (argc != d->origArgc) {
2598 // Note: On MingGW the arguments from GetCommandLine are
2599 // not wildcard expanded (if wildcard expansion is enabled),
2600 // as opposed to the arguments in argv. This means we can't
2601 // compare commandLineArguments to argv/origArgc, but
2602 // must remove elements by value, based on whether they
2603 // were filtered out from argc.
2604 for (int i = 0; i < d->origArgc; ++i) {
2605 if (!contains(argc, argv, d->origArgv[i]))
2606 commandLineArguments.removeAll(QString::fromLocal8Bit(d->origArgv[i]));
2607 }
2608 }
2609
2610 return commandLineArguments;
2611 } // Fall back to rebuilding from argv/argc when a modified argv was passed.
2612#endif // defined(Q_OS_WIN)
2613
2614 for (int a = 0; a < argc; ++a)
2615 list << QString::fromLocal8Bit(argv[a]);
2616
2617 return list;
2618}
2619
2620/*!
2621 \property QCoreApplication::organizationName
2622 \brief the name of the organization that wrote this application
2623
2624 The value is used by the QSettings class when it is constructed
2625 using the default constructor. This saves having to repeat this
2626 information each time a QSettings object is created.
2627
2628 On Mac, QSettings uses \l {QCoreApplication::}{organizationDomain()} as the organization
2629 if it's not an empty string; otherwise it uses
2630 organizationName(). On all other platforms, QSettings uses
2631 organizationName() as the organization.
2632
2633 \sa organizationDomain, applicationName
2634*/
2635
2636/*!
2637 \fn void QCoreApplication::organizationNameChanged()
2638 \internal
2639
2640 While not useful from C++ due to how organizationName is normally set once on
2641 startup, this is still needed for QML so that bindings are reevaluated after
2642 that initial change.
2643*/
2644void QCoreApplication::setOrganizationName(const QString &orgName)
2645{
2646 if (coreappdata()->orgName == orgName)
2647 return;
2648 coreappdata()->orgName = orgName;
2649#ifndef QT_NO_QOBJECT
2650 if (QCoreApplication::self)
2651 emit QCoreApplication::self->organizationNameChanged();
2652#endif
2653}
2654
2655QString QCoreApplication::organizationName()
2656{
2657 return coreappdata()->orgName;
2658}
2659
2660/*!
2661 \property QCoreApplication::organizationDomain
2662 \brief the Internet domain of the organization that wrote this application
2663
2664 The value is used by the QSettings class when it is constructed
2665 using the default constructor. This saves having to repeat this
2666 information each time a QSettings object is created.
2667
2668 On Mac, QSettings uses organizationDomain() as the organization
2669 if it's not an empty string; otherwise it uses organizationName().
2670 On all other platforms, QSettings uses organizationName() as the
2671 organization.
2672
2673 \sa organizationName, applicationName, applicationVersion
2674*/
2675/*!
2676 \fn void QCoreApplication::organizationDomainChanged()
2677 \internal
2678
2679 Primarily for QML, see organizationNameChanged.
2680*/
2681void QCoreApplication::setOrganizationDomain(const QString &orgDomain)
2682{
2683 if (coreappdata()->orgDomain == orgDomain)
2684 return;
2685 coreappdata()->orgDomain = orgDomain;
2686#ifndef QT_NO_QOBJECT
2687 if (QCoreApplication::self)
2688 emit QCoreApplication::self->organizationDomainChanged();
2689#endif
2690}
2691
2692QString QCoreApplication::organizationDomain()
2693{
2694 return coreappdata()->orgDomain;
2695}
2696
2697/*!
2698 \property QCoreApplication::applicationName
2699 \brief the name of this application
2700
2701 The application name is used in various Qt classes and modules,
2702 most prominently in \l{QSettings} when it is constructed using the default constructor.
2703 Other uses are in formatted logging output (see \l{qSetMessagePattern()}),
2704 in output by \l{QCommandLineParser}, in \l{QTemporaryDir} and \l{QTemporaryFile}
2705 default paths, and in some file locations of \l{QStandardPaths}.
2706 \l{Qt D-Bus}, \l{Accessibility}, and the XCB platform integration make use
2707 of the application name, too.
2708
2709 If not set, the application name defaults to the executable name.
2710
2711 \sa organizationName, organizationDomain, applicationVersion, applicationFilePath()
2712*/
2713/*!
2714 \fn void QCoreApplication::applicationNameChanged()
2715 \internal
2716
2717 Primarily for QML, see organizationNameChanged.
2718*/
2719void QCoreApplication::setApplicationName(const QString &application)
2720{
2721 coreappdata()->applicationNameSet = !application.isEmpty();
2722 QString newAppName = application;
2723 if (newAppName.isEmpty() && QCoreApplication::self)
2724 newAppName = QCoreApplication::self->d_func()->appName();
2725 if (coreappdata()->application == newAppName)
2726 return;
2727 coreappdata()->application = newAppName;
2728#ifndef QT_NO_QOBJECT
2729 if (QCoreApplication::self)
2730 emit QCoreApplication::self->applicationNameChanged();
2731#endif
2732}
2733
2734QString QCoreApplication::applicationName()
2735{
2736 return coreappdata() ? coreappdata()->application : QString();
2737}
2738
2739/*!
2740 \property QCoreApplication::applicationVersion
2741 \since 4.4
2742 \brief the version of this application
2743
2744 If not set, the application version defaults to a platform-specific value
2745 determined from the main application executable or package (since Qt 5.9):
2746
2747 \table
2748 \header
2749 \li Platform
2750 \li Source
2751 \row
2752 \li Windows (classic desktop)
2753 \li PRODUCTVERSION parameter of the VERSIONINFO resource
2754 \row
2755 \li macOS, iOS, tvOS, watchOS
2756 \li CFBundleVersion property of the information property list
2757 \row
2758 \li Android
2759 \li android:versionName property of the AndroidManifest.xml manifest element
2760 \endtable
2761
2762 On other platforms, the default is the empty string.
2763
2764 \sa applicationName, organizationName, organizationDomain
2765*/
2766/*!
2767 \fn void QCoreApplication::applicationVersionChanged()
2768 \internal
2769
2770 Primarily for QML, see organizationNameChanged.
2771*/
2772void QCoreApplication::setApplicationVersion(const QString &version)
2773{
2774 coreappdata()->applicationVersionSet = !version.isEmpty();
2775 QString newVersion = version;
2776 if (newVersion.isEmpty() && QCoreApplication::self)
2777 newVersion = QCoreApplication::self->d_func()->appVersion();
2778 if (coreappdata()->applicationVersion == newVersion)
2779 return;
2780 coreappdata()->applicationVersion = newVersion;
2781#ifndef QT_NO_QOBJECT
2782 if (QCoreApplication::self)
2783 emit QCoreApplication::self->applicationVersionChanged();
2784#endif
2785}
2786
2787QString QCoreApplication::applicationVersion()
2788{
2789 return coreappdata() ? coreappdata()->applicationVersion : QString();
2790}
2791
2792#if QT_CONFIG(permissions) || defined(Q_QDOC)
2793
2794/*!
2795 Checks the status of the given \a permission
2796
2797 If the result is Qt::PermissionStatus::Undetermined then permission should be
2798 requested via requestPermission() to determine the user's intent.
2799
2800 \since 6.5
2801 \sa requestPermission(), {Application Permissions}
2802*/
2803Qt::PermissionStatus QCoreApplication::checkPermission(const QPermission &permission)
2804{
2805 return QPermissions::Private::checkPermission(permission);
2806}
2807
2808/*!
2809 \fn template <typename Functor> void QCoreApplication::requestPermission(
2810 const QPermission &permission, Functor &&functor)
2811
2812 Requests the given \a permission.
2813
2814 \include permissions.qdocinc requestPermission-functor
2815
2816 The \a functor can be a free-standing or static member function:
2817
2818 \code
2819 qApp->requestPermission(QCameraPermission{}, &permissionUpdated);
2820 \endcode
2821
2822 or a lambda:
2823
2824 \code
2825 qApp->requestPermission(QCameraPermission{}, [](const QPermission &permission) {
2826 });
2827 \endcode
2828
2829 \include permissions.qdocinc requestPermission-postamble
2830
2831 \since 6.5
2832 \sa checkPermission(), {Application Permissions}
2833*/
2834
2835/*!
2836 \fn template<typename Functor> void QCoreApplication::requestPermission(
2837 const QPermission &permission, const QObject *context,
2838 Functor functor)
2839
2840 Requests the given \a permission, in the context of \a context.
2841
2842 \include permissions.qdocinc requestPermission-functor
2843
2844 The \a functor can be a free-standing or static member function:
2845
2846 \code
2847 qApp->requestPermission(QCameraPermission{}, context, &permissionUpdated);
2848 \endcode
2849
2850 a lambda:
2851
2852 \code
2853 qApp->requestPermission(QCameraPermission{}, context, [](const QPermission &permission) {
2854 });
2855 \endcode
2856
2857 or a slot in the \a context object:
2858
2859 \code
2860 qApp->requestPermission(QCameraPermission{}, this, &CamerWidget::permissionUpdated);
2861 \endcode
2862
2863 The \a functor will be called in the thread of the \a context object. If
2864 \a context is destroyed before the request completes, the \a functor will
2865 not be called.
2866
2867 \include permissions.qdocinc requestPermission-postamble
2868
2869 \since 6.5
2870 \overload
2871 \sa checkPermission(), {Application Permissions}
2872*/
2873
2874/*!
2875 \internal
2876
2877 Called by the various requestPermission overloads to perform the request.
2878
2879 Calls the functor encapsulated in the \a slotObjRaw in the given \a context
2880 (which may be \c nullptr).
2881*/
2882void QCoreApplication::requestPermissionImpl(const QPermission &requestedPermission,
2883 QtPrivate::QSlotObjectBase *slotObjRaw, const QObject *context)
2884{
2885 QtPrivate::SlotObjUniquePtr slotObj{slotObjRaw}; // adopts
2886 Q_ASSERT(slotObj);
2887
2888 if (!QThread::isMainThread()) {
2889 qCWarning(lcPermissions, "Permissions can only be requested from the GUI (main) thread");
2890 return;
2891 }
2892
2893 class PermissionReceiver : public QObject
2894 {
2895 public:
2896 explicit PermissionReceiver(QtPrivate::SlotObjUniquePtr &&slotObject, const QObject *context)
2897 : slotObject(std::move(slotObject)), context(context ? context : this)
2898 {
2899 Q_ASSERT(this->context);
2900 moveToThread(this->context->thread());
2901 }
2902
2903 void finalizePermissionRequest(const QPermission &permission)
2904 {
2905 Q_ASSERT(slotObject);
2906 // only execute if context object is still alive
2907 if (context) {
2908 void *args[] = { nullptr, const_cast<QPermission *>(&permission) };
2909 slotObject->call(const_cast<QObject *>(context.data()), args);
2910 }
2911 }
2912
2913 private:
2914 QtPrivate::SlotObjUniquePtr slotObject;
2915 QPointer<const QObject> context;
2916 };
2917
2918 // ### use unique_ptr once PermissionCallback is a move_only function
2919 auto receiver = std::make_shared<PermissionReceiver>(std::move(slotObj), context);
2920
2921 QPermissions::Private::requestPermission(requestedPermission,
2922 [=, receiver = std::move(receiver)](Qt::PermissionStatus status) mutable {
2923 if (status == Qt::PermissionStatus::Undetermined) {
2924 Q_ASSERT_X(false, "QPermission",
2925 "Internal error: requestPermission() should never return Undetermined");
2926 status = Qt::PermissionStatus::Denied;
2927 }
2928
2929 if (QCoreApplication::self) {
2930 QPermission permission = requestedPermission;
2931 permission.m_status = status;
2932 auto receiverObject = receiver.get();
2933 QMetaObject::invokeMethod(receiverObject,
2934 [receiver = std::move(receiver), permission] {
2935 receiver->finalizePermissionRequest(permission);
2936 }, Qt::QueuedConnection);
2937 }
2938 });
2939}
2940
2941#endif // QT_CONFIG(permissions)
2942
2943#if QT_CONFIG(library)
2944static QStringList libraryPathsLocked();
2945
2946/*!
2947 Returns a list of paths that the application will search when
2948 dynamically loading libraries.
2949
2950 The return value of this function may change when a QCoreApplication
2951 is created. It is not recommended to call it before creating a
2952 QCoreApplication. The directory of the application executable (\b not
2953 the working directory) is part of the list if it is known. In order
2954 to make it known a QCoreApplication has to be constructed as it will
2955 use \c {argv[0]} to find it.
2956
2957 Qt provides default library paths, but they can also be set using
2958 a \l{Using qt.conf}{qt.conf} file. Paths specified in this file
2959 will override default values. Note that if the qt.conf file is in
2960 the directory of the application executable, it may not be found
2961 until a QCoreApplication is created. If it is not found when calling
2962 this function, the default library paths will be used.
2963
2964 The list will include the installation directory for plugins if
2965 it exists (the default installation directory for plugins is \c
2966 INSTALL/plugins, where \c INSTALL is the directory where Qt was
2967 installed). The colon separated entries of the \c QT_PLUGIN_PATH
2968 environment variable are always added. The plugin installation
2969 directory (and its existence) may change when the directory of
2970 the application executable becomes known.
2971
2972 \sa setLibraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary,
2973 {How to Create Qt Plugins}
2974*/
2975QStringList QCoreApplication::libraryPaths()
2976{
2977 QMutexLocker locker(&coreappdata->libraryPathMutex);
2978 return libraryPathsLocked();
2979}
2980
2981/*!
2982 \internal
2983*/
2984static QStringList libraryPathsLocked()
2985{
2986 QCoreApplicationData *d = coreappdata;
2987 if (d->libPathsManuallySet())
2988 return d->manual_libpaths;
2989
2990 QStringList *app_libpaths = &d->app_libpaths;
2991 if (!d->libPathsInitialized()) {
2992
2993 auto setPathsFromEnv = [&](QString libPathEnv) {
2994 if (!libPathEnv.isEmpty()) {
2995 QStringList paths = libPathEnv.split(QDir::listSeparator(), Qt::SkipEmptyParts);
2996 for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) {
2997 QString canonicalPath = QDir(*it).canonicalPath();
2998 if (!canonicalPath.isEmpty()
2999 && !app_libpaths->contains(canonicalPath)) {
3000 app_libpaths->append(canonicalPath);
3001 }
3002 }
3003 }
3004 };
3005 setPathsFromEnv(qEnvironmentVariable("QT_PLUGIN_PATH"));
3006#ifdef Q_OS_DARWIN
3007 // Check the main bundle's PlugIns directory as this is a standard location for Apple OSes.
3008 // Note that the QLibraryInfo::PluginsPath below will coincidentally be the same as this value
3009 // but with a different casing, so it can't be relied upon when the underlying filesystem
3010 // is case sensitive (and this is always the case on newer OSes like iOS).
3011 if (CFBundleRef bundleRef = CFBundleGetMainBundle()) {
3012 if (QCFType<CFURLRef> urlRef = CFBundleCopyBuiltInPlugInsURL(bundleRef)) {
3013 if (QCFType<CFURLRef> absoluteUrlRef = CFURLCopyAbsoluteURL(urlRef)) {
3014 if (QCFString path = CFURLCopyFileSystemPath(absoluteUrlRef, kCFURLPOSIXPathStyle)) {
3015 if (QFile::exists(path)) {
3016 path = QDir(path).canonicalPath();
3017 if (!app_libpaths->contains(path))
3018 app_libpaths->append(path);
3019 }
3020 }
3021 }
3022 }
3023 }
3024#endif // Q_OS_DARWIN
3025
3026 QString installPathPlugins = QLibraryInfo::path(QLibraryInfo::PluginsPath);
3027 if (QFile::exists(installPathPlugins)) {
3028 // Make sure we convert from backslashes to slashes.
3029 installPathPlugins = QDir(installPathPlugins).canonicalPath();
3030 if (!app_libpaths->contains(installPathPlugins))
3031 app_libpaths->append(installPathPlugins);
3032 }
3033
3034 // If QCoreApplication is not yet instantiated,
3035 // make sure we add the application path when we construct the QCoreApplication
3036 if (qApp) {
3037 QString app_location = QCoreApplication::applicationFilePath();
3038 app_location.truncate(app_location.lastIndexOf(u'/'));
3039 app_location = QDir(app_location).canonicalPath();
3040 if (QFile::exists(app_location) && !app_libpaths->contains(app_location))
3041 app_libpaths->append(app_location);
3042 }
3043 if (app_libpaths->isEmpty())
3044 app_libpaths->reserve(1); // detach from null
3045 Q_ASSERT(d->libPathsInitialized());
3046 }
3047 return *app_libpaths;
3048}
3049
3050
3051
3052/*!
3053
3054 Sets the list of directories to search when loading plugins with
3055 QLibrary to \a paths. All existing paths will be deleted and the
3056 path list will consist of the paths given in \a paths and the path
3057 to the application.
3058
3059 The library paths are reset to the default when an instance of
3060 QCoreApplication is destructed.
3061
3062 \sa libraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary
3063 */
3064void QCoreApplication::setLibraryPaths(const QStringList &paths)
3065{
3066 QCoreApplicationData *d = coreappdata;
3067 QMutexLocker locker(&d->libraryPathMutex);
3068
3069 // setLibraryPaths() is considered a "remove everything and then add some new ones" operation.
3070 // When the application is constructed it should still amend the paths. So we keep the originals
3071 // around, and even create them if they don't exist, yet.
3072 if (!d->libPathsInitialized())
3073 libraryPathsLocked();
3074
3075 d->manual_libpaths = paths;
3076 if (d->manual_libpaths.isEmpty())
3077 d->manual_libpaths.reserve(1); // detach from null
3078 Q_ASSERT(d->libPathsManuallySet());
3079
3080 locker.unlock();
3081 QFactoryLoader::refreshAll();
3082}
3083
3084/*!
3085 Prepends \a path to the beginning of the library path list, ensuring that
3086 it is searched for libraries first. If \a path is empty or already in the
3087 path list, the path list is not changed.
3088
3089 The default path list consists of one or two entries. The first is the
3090 installation directory for plugins, which is \c INSTALL/plugins, where \c
3091 INSTALL is the directory where Qt was installed. The second is the
3092 application's own directory (\b not the current directory), but only after
3093 the QCoreApplication object is instantiated.
3094
3095 The library paths are reset to the default when an instance of
3096 QCoreApplication is destructed.
3097
3098 \sa removeLibraryPath(), libraryPaths(), setLibraryPaths()
3099 */
3100void QCoreApplication::addLibraryPath(const QString &path)
3101{
3102 if (path.isEmpty())
3103 return;
3104
3105 QString canonicalPath = QDir(path).canonicalPath();
3106 if (canonicalPath.isEmpty())
3107 return;
3108
3109 QCoreApplicationData *d = coreappdata;
3110 QMutexLocker locker(&d->libraryPathMutex);
3111
3112 QStringList *libpaths = &d->manual_libpaths;
3113 if (d->libPathsManuallySet()) {
3114 if (d->manual_libpaths.contains(canonicalPath))
3115 return;
3116 } else {
3117 // make sure that library paths are initialized
3118 libraryPathsLocked();
3119 QStringList *app_libpaths = &d->app_libpaths;
3120 if (app_libpaths->contains(canonicalPath))
3121 return;
3122
3123 *libpaths = *app_libpaths;
3124 }
3125
3126 libpaths->prepend(canonicalPath);
3127 Q_ASSERT(d->libPathsManuallySet());
3128 locker.unlock();
3129 QFactoryLoader::refreshAll();
3130}
3131
3132/*!
3133 Removes \a path from the library path list. If \a path is empty or not
3134 in the path list, the list is not changed.
3135
3136 The library paths are reset to the default when an instance of
3137 QCoreApplication is destructed.
3138
3139 \sa addLibraryPath(), libraryPaths(), setLibraryPaths()
3140*/
3141void QCoreApplication::removeLibraryPath(const QString &path)
3142{
3143 if (path.isEmpty())
3144 return;
3145
3146 QString canonicalPath = QDir(path).canonicalPath();
3147 if (canonicalPath.isEmpty())
3148 return;
3149
3150 QCoreApplicationData *d = coreappdata;
3151 QMutexLocker locker(&d->libraryPathMutex);
3152
3153 QStringList *libpaths = &d->manual_libpaths;
3154 if (d->libPathsManuallySet()) {
3155 if (libpaths->removeAll(canonicalPath) == 0)
3156 return;
3157 } else {
3158 // make sure that library paths is initialized
3159 libraryPathsLocked();
3160 QStringList *app_libpaths = &d->app_libpaths;
3161 if (!app_libpaths->contains(canonicalPath))
3162 return;
3163
3164 *libpaths = *app_libpaths;
3165 libpaths->removeAll(canonicalPath);
3166 Q_ASSERT(d->libPathsManuallySet());
3167 }
3168
3169 locker.unlock();
3170 QFactoryLoader::refreshAll();
3171}
3172
3173#endif // QT_CONFIG(library)
3174
3175#ifndef QT_NO_QOBJECT
3176
3177/*!
3178 Installs an event filter \a filterObj for all native events
3179 received by the application in the main thread.
3180
3181 The event filter \a filterObj receives events via its \l {QAbstractNativeEventFilter::}{nativeEventFilter()}
3182 function, which is called for all native events received in the main thread.
3183
3184 The QAbstractNativeEventFilter::nativeEventFilter() function should
3185 return true if the event should be filtered, i.e. stopped. It should
3186 return false to allow normal Qt processing to continue: the native
3187 event can then be translated into a QEvent and handled by the standard
3188 Qt \l{QEvent} {event} filtering, e.g. QObject::installEventFilter().
3189
3190 If multiple event filters are installed, the filter that was
3191 installed last is activated first.
3192
3193 \note The filter function set here receives native messages,
3194 i.e. MSG or XCB event structs.
3195
3196 \note Native event filters will be disabled in the application when the
3197 Qt::AA_PluginApplication attribute is set.
3198
3199 For maximum portability, you should always try to use QEvent
3200 and QObject::installEventFilter() whenever possible.
3201
3202 \sa QObject::installEventFilter()
3203
3204 \since 5.0
3205*/
3206void QCoreApplication::installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
3207{
3208 if (QCoreApplication::testAttribute(Qt::AA_PluginApplication)) {
3209 qWarning("Native event filters are not applied when the Qt::AA_PluginApplication attribute is set");
3210 return;
3211 }
3212
3213 QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(QCoreApplicationPrivate::theMainThread.loadAcquire());
3214 if (!filterObj || !eventDispatcher)
3215 return;
3216 eventDispatcher->installNativeEventFilter(filterObj);
3217}
3218
3219/*!
3220 Removes an event \a filterObject from this object. The
3221 request is ignored if such an event filter has not been installed.
3222
3223 All event filters for this object are automatically removed when
3224 this object is destroyed.
3225
3226 It is always safe to remove an event filter, even during event
3227 filter activation (i.e. from the nativeEventFilter() function).
3228
3229 \sa installNativeEventFilter()
3230 \since 5.0
3231*/
3232void QCoreApplication::removeNativeEventFilter(QAbstractNativeEventFilter *filterObject)
3233{
3234 QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(QCoreApplicationPrivate::theMainThread.loadAcquire());
3235 if (!filterObject || !eventDispatcher)
3236 return;
3237 eventDispatcher->removeNativeEventFilter(filterObject);
3238}
3239
3240/*!
3241 Returns a pointer to the event dispatcher object for the main thread. If no
3242 event dispatcher exists for the thread, this function returns \nullptr.
3243*/
3244QAbstractEventDispatcher *QCoreApplication::eventDispatcher()
3245{
3246 if (QCoreApplicationPrivate::theMainThread.loadAcquire())
3247 return QCoreApplicationPrivate::theMainThread.loadRelaxed()->eventDispatcher();
3248 return nullptr;
3249}
3250
3251/*!
3252 Sets the event dispatcher for the main thread to \a eventDispatcher. This
3253 is only possible as long as there is no event dispatcher installed yet. That
3254 is, before QCoreApplication has been instantiated. This method takes
3255 ownership of the object.
3256*/
3257void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
3258{
3259 QThread *mainThread = QCoreApplicationPrivate::theMainThread.loadAcquire();
3260 if (!mainThread)
3261 mainThread = QThread::currentThread(); // will also setup theMainThread
3262 mainThread->setEventDispatcher(eventDispatcher);
3263}
3264
3265#endif // QT_NO_QOBJECT
3266
3267/*!
3268 \macro Q_COREAPP_STARTUP_FUNCTION(QtStartUpFunction ptr)
3269 \since 5.1
3270 \relates QCoreApplication
3271 \reentrant
3272
3273 Adds a global function that will be called from the QCoreApplication
3274 constructor. This macro is normally used to initialize libraries
3275 for program-wide functionality, without requiring the application to
3276 call into the library for initialization.
3277
3278 The function specified by \a ptr should take no arguments and should
3279 return nothing. For example:
3280
3281 \snippet code/src_corelib_kernel_qcoreapplication.cpp 3
3282
3283 Note that the startup function will run at the end of the QCoreApplication constructor,
3284 before any GUI initialization. If GUI code is required in the function,
3285 use a timer (or a queued invocation) to perform the initialization later on,
3286 from the event loop.
3287
3288 If QCoreApplication is deleted and another QCoreApplication is created,
3289 the startup function will be invoked again.
3290
3291 \note This macro is not suitable for use in library code that is then
3292 statically linked into an application since the function may not be called
3293 at all due to being eliminated by the linker.
3294*/
3295
3296/*!
3297 \fn void qAddPostRoutine(QtCleanUpFunction ptr)
3298 \threadsafe
3299 \relates QCoreApplication
3300
3301 Adds a global routine that will be called from the QCoreApplication
3302 destructor. This function is normally used to add cleanup routines
3303 for program-wide functionality.
3304
3305 The cleanup routines are called in the reverse order of their addition.
3306
3307 The function specified by \a ptr should take no arguments and should
3308 return nothing. For example:
3309
3310 \snippet code/src_corelib_kernel_qcoreapplication.cpp 4
3311
3312 Note that for an application- or module-wide cleanup, qAddPostRoutine()
3313 is often not suitable. For example, if the program is split into dynamically
3314 loaded modules, the relevant module may be unloaded long before the
3315 QCoreApplication destructor is called. In such cases, if using qAddPostRoutine()
3316 is still desirable, qRemovePostRoutine() can be used to prevent a routine
3317 from being called by the QCoreApplication destructor. For example, if that
3318 routine was called before the module was unloaded.
3319
3320 For modules and libraries, using a reference-counted
3321 initialization manager or Qt's parent-child deletion mechanism may
3322 be better. Here is an example of a private class that uses the
3323 parent-child mechanism to call a cleanup function at the right
3324 time:
3325
3326 \snippet code/src_corelib_kernel_qcoreapplication.cpp 5
3327
3328 By selecting the right parent object, this can often be made to
3329 clean up the module's data at the right moment.
3330
3331 \note This function has been thread-safe since Qt 5.10.
3332
3333 \sa qRemovePostRoutine()
3334*/
3335
3336/*!
3337 \fn void qRemovePostRoutine(QtCleanUpFunction ptr)
3338 \threadsafe
3339 \relates QCoreApplication
3340 \since 5.3
3341
3342 Removes the cleanup routine specified by \a ptr from the list of
3343 routines called by the QCoreApplication destructor. The routine
3344 must have been previously added to the list by a call to
3345 qAddPostRoutine(), otherwise this function has no effect.
3346
3347 \note This function has been thread-safe since Qt 5.10.
3348
3349 \sa qAddPostRoutine()
3350*/
3351
3352/*!
3353 \macro Q_DECLARE_TR_FUNCTIONS(context)
3354 \relates QCoreApplication
3355
3356 The Q_DECLARE_TR_FUNCTIONS() macro declares and implements the
3357 translation function \c tr() with this signature:
3358
3359 \snippet code/src_corelib_kernel_qcoreapplication.cpp 6
3360
3361 This macro is useful if you want to use QObject::tr() in classes
3362 that don't inherit from QObject.
3363
3364 Q_DECLARE_TR_FUNCTIONS() must appear at the very top of the
3365 class definition (before the first \c{public:} or \c{protected:}).
3366 For example:
3367
3368 \snippet code/src_corelib_kernel_qcoreapplication.cpp 7
3369
3370 The \a context parameter is normally the class name, but it can
3371 be any text.
3372
3373 \sa Q_OBJECT, QObject::tr()
3374*/
3375
3376void *QCoreApplication::resolveInterface(const char *name, int revision) const
3377{
3378#if defined(Q_OS_ANDROID)
3379 // The QAndroidApplication is wrongly using static methods for
3380 // its native interface (QTBUG-128796). Until we fix that we at
3381 // least want the preferred way of resolving a native interface
3382 // to work, so provide a minimal subclass of the interface.
3383 using namespace QNativeInterface;
3384 struct AndroidApplication : public QAndroidApplication {};
3385 static AndroidApplication androidApplication;
3386 QT_NATIVE_INTERFACE_RETURN_IF(QAndroidApplication, &androidApplication);
3387#endif
3388 Q_UNUSED(name); Q_UNUSED(revision);
3389 return nullptr;
3390}
3391
3392QT_END_NAMESPACE
3393
3394#ifndef QT_NO_QOBJECT
3395#include "moc_qcoreapplication.cpp"
3396#endif
\inmodule QtCore
#define __has_include(x)
QString qAppName()
Q_TRACE_POINT(qtcore, QCoreApplication_notify_exit, bool consumed, bool filtered)
void QT_MANGLE_NAMESPACE qt_startup_hook()
static QString qAppFileName()
QList< QtStartUpFunction > QStartUpFuncList
Q_TRACE_METADATA(qtcore, "ENUM { AUTO, RANGE User ... MaxUser } QEvent::Type;")
QString qtTrId(const char *id, int n)
Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_exit)
static void qt_call_pre_routines()
qsizetype qGlobalPostedEventsCount()
static Q_CONSTINIT bool preRoutinesCalled
QList< QtCleanUpFunction > QVFuncList
static void replacePercentN(QString *result, int n)
Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_event_compressed, QObject *receiver, QEvent *event)
Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_entry, QObject *receiver, QEvent *event, QEvent::Type type)
Q_TRACE_PREFIX(qtcore, "#include <qcoreevent.h>")
Q_CORE_EXPORT void qAddPostRoutine(QtCleanUpFunction)
void(* QtCleanUpFunction)()
void(* QtStartUpFunction)()
Q_CORE_EXPORT void qAddPreRoutine(QtStartUpFunction)
Q_CORE_EXPORT void qRemovePostRoutine(QtCleanUpFunction)
#define qApp
Q_GLOBAL_STATIC(QReadWriteLock, g_updateMutex)