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

source code of qtbase/src/corelib/kernel/qcoreapplication.cpp