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

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