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