Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qcoreapplication.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2021 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qcoreapplication.h"
7
8#ifndef QT_NO_QOBJECT
10#include "qcoreevent.h"
11#include "qcoreevent_p.h"
12#include "qeventloop.h"
13#endif
14#include "qmetaobject.h"
15#include <private/qproperty_p.h>
16#include "qcorecmdlineargs_p.h"
17#include <qdatastream.h>
18#include <qdebug.h>
19#include <qdir.h>
20#include <qfile.h>
21#include <qfileinfo.h>
22#include <qmutex.h>
23#include <private/qloggingregistry_p.h>
24#include <qscopeguard.h>
25#include <qstandardpaths.h>
26#ifndef QT_NO_QOBJECT
27#include <qthread.h>
28#include <qthreadstorage.h>
29#if QT_CONFIG(future)
30#include <QtCore/qpromise.h>
31#endif
32#include <private/qthread_p.h>
33#if QT_CONFIG(thread)
34#include <qthreadpool.h>
35#include <private/qthreadpool_p.h>
36#endif
37#endif
38#include <qlibraryinfo.h>
39#include <qpointer.h>
40#include <qvarlengtharray.h>
41#include <private/qfactoryloader_p.h>
42#include <private/qfunctions_p.h>
43#include <private/qlocale_p.h>
44#include <private/qlocking_p.h>
45#include <private/qhooks_p.h>
46
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)
55# else
56# if !defined(QT_NO_GLIB)
58# endif
59# endif
60# if !defined(Q_OS_WASM)
62# endif
63#endif
64#ifdef Q_OS_WIN
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
113
114#ifndef QT_NO_QOBJECT
115Q_LOGGING_CATEGORY(lcDeleteLater, "qt.core.qobject.deletelater")
116#endif
117
118using namespace Qt::StringLiterals;
119
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
139#if !defined(Q_OS_WIN)
140#ifdef Q_OS_DARWIN
141QString QCoreApplicationPrivate::infoDictionaryStringProperty(const QString &propertyName)
142{
143 QString bundleName;
144 QCFString cfPropertyName = propertyName.toCFString();
145 CFTypeRef string = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(),
146 cfPropertyName);
147 if (string)
148 bundleName = QString::fromCFString(static_cast<CFStringRef>(string));
149 return bundleName;
150}
151#endif
153{
154 QString applicationName;
155#ifdef Q_OS_DARWIN
156 applicationName = infoDictionaryStringProperty(QStringLiteral("CFBundleName"));
157#endif
158 if (applicationName.isEmpty() && argv[0]) {
159 char *p = strrchr(argv[0], '/');
160 applicationName = QString::fromLocal8Bit(p ? p + 1 : argv[0]);
161 }
162
163 return applicationName;
164}
166{
167 QString applicationVersion;
168#ifdef QT_BOOTSTRAPPED
169#elif defined(Q_OS_DARWIN)
170 applicationVersion = infoDictionaryStringProperty(QStringLiteral("CFBundleVersion"));
171#elif defined(Q_OS_ANDROID)
172 QJniObject context(QNativeInterface::QAndroidApplication::context());
173 if (context.isValid()) {
174 QJniObject pm = context.callObjectMethod(
175 "getPackageManager", "()Landroid/content/pm/PackageManager;");
176 QJniObject pn = context.callObjectMethod<jstring>("getPackageName");
177 if (pm.isValid() && pn.isValid()) {
178 QJniObject packageInfo = pm.callObjectMethod(
179 "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;",
180 pn.object(), 0);
181 if (packageInfo.isValid()) {
182 QJniObject versionName = packageInfo.getObjectField(
183 "versionName", "Ljava/lang/String;");
184 if (versionName.isValid())
185 return versionName.toString();
186 }
187 }
188 }
189#endif
190 return applicationVersion;
191}
192#endif // !Q_OS_WIN
193
195
197{
198 bool b = (QCoreApplication::self != nullptr);
199 if (!b)
200 qWarning("QApplication::%s: Please instantiate the QApplication object first", function);
201 return b;
202}
203
204#if QT_CONFIG(commandlineparser)
205void QCoreApplicationPrivate::addQtOptions(QList<QCommandLineOption> *options)
206{
207 options->append(QCommandLineOption(QStringLiteral("qmljsdebugger"),
208 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."),
209 QStringLiteral("value")));
210}
211#endif
212
214{
215 int j = argc ? 1 : 0;
216 for (int i = 1; i < argc; ++i) {
217 if (!argv[i])
218 continue;
219 if (*argv[i] != '-') {
220 argv[j++] = argv[i];
221 continue;
222 }
223 const char *arg = argv[i];
224 if (arg[1] == '-') // startsWith("--")
225 ++arg;
226 if (strncmp(arg, "-qmljsdebugger=", 15) == 0) {
228 } else if (strcmp(arg, "-qmljsdebugger") == 0 && i < argc - 1) {
229 ++i;
231 } else {
232 argv[j++] = argv[i];
233 }
234 }
235
236 if (j < argc) {
237 argv[j] = nullptr;
238 argc = j;
239 }
240}
241
242// Support for introspection
243
244extern "C" void
245#ifdef QT_SHARED
247#endif
249{
250}
251
252typedef QList<QtStartUpFunction> QStartUpFuncList;
255Q_GLOBAL_STATIC(QVFuncList, postRList)
257Q_CONSTINIT static bool preRoutinesCalled = false;
258
266{
267 QStartUpFuncList *list = preRList();
268 if (!list)
269 return;
270
271 if (preRoutinesCalled) {
273 p();
274 }
275
276 // Due to C++11 parallel dynamic initialization, this can be called
277 // from multiple threads.
278 const auto locker = qt_scoped_lock(globalRoutinesMutex);
279 list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines
280}
281
283{
284 QVFuncList *list = postRList();
285 if (!list)
286 return;
287 const auto locker = qt_scoped_lock(globalRoutinesMutex);
288 list->prepend(p);
289}
290
292{
293 QVFuncList *list = postRList();
294 if (!list)
295 return;
296 const auto locker = qt_scoped_lock(globalRoutinesMutex);
297 list->removeAll(p);
298}
299
301{
302 // After will be allowed invoke QtStartUpFunction when calling qAddPreRoutine
303 preRoutinesCalled = true;
304
305 if (!preRList.exists())
306 return;
307
308 const QStartUpFuncList list = [] {
309 const auto locker = qt_scoped_lock(globalRoutinesMutex);
310 // Unlike qt_call_post_routines, we don't empty the list, because
311 // Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
312 // the function to be executed every time QCoreApplication is created.
313 return *preRList;
314 }();
315
316 for (QtStartUpFunction f : list)
317 f();
318}
319
320void Q_CORE_EXPORT qt_call_post_routines()
321{
322 if (!postRList.exists())
323 return;
324
325 forever {
327 {
328 // extract the current list and make the stored list empty
329 const auto locker = qt_scoped_lock(globalRoutinesMutex);
330 qSwap(*postRList, list);
331 }
332
333 if (list.isEmpty())
334 break;
335 for (QtCleanUpFunction f : std::as_const(list))
336 f();
337 }
338}
339
340
341#ifndef QT_NO_QOBJECT
342
343// app starting up if false
344Q_CONSTINIT bool QCoreApplicationPrivate::is_app_running = false;
345 // app closing down if true
346Q_CONSTINIT bool QCoreApplicationPrivate::is_app_closing = false;
347
349{
350 const QPostEventList &l = QThreadData::current()->postEventList;
351 return l.size() - l.startOffset;
352}
353
355
356#endif // QT_NO_QOBJECT
357
358Q_CONSTINIT QCoreApplication *QCoreApplication::self = nullptr;
362
365 applicationNameSet = false;
366 applicationVersionSet = false;
367 }
369#ifndef QT_NO_QOBJECT
370 // cleanup the QAdoptedThread created for the main() thread
371 if (auto *t = QCoreApplicationPrivate::theMainThread.loadAcquire()) {
373 data->deref(); // deletes the data and the adopted thread
374 }
375#endif
376 }
377
379 QString application; // application name, initially from argv[0], can then be modified.
381 bool applicationNameSet; // true if setApplicationName was called
382 bool applicationVersionSet; // true if setApplicationVersion was called
383
384#if QT_CONFIG(library)
385 std::unique_ptr<QStringList> app_libpaths;
386 std::unique_ptr<QStringList> manual_libpaths;
387#endif
388
389};
390
392
393#ifndef QT_NO_QOBJECT
394Q_CONSTINIT static bool quitLockEnabled = true;
395#endif
396
397#if defined(Q_OS_WIN)
398// Check whether the command line arguments passed to QCoreApplication
399// match those passed into main(), to see if the user has modified them
400// before passing them on to us. We do this by comparing to the global
401// __argv/__argc (MS extension). Deep comparison is required since
402// argv/argc is rebuilt by our WinMain entrypoint.
403static inline bool isArgvModified(int argc, char **argv)
404{
405 if (__argc != argc || !__argv /* wmain() */)
406 return true;
407 if (__argv == argv)
408 return false;
409 for (int a = 0; a < argc; ++a) {
410 if (argv[a] != __argv[a] && strcmp(argv[a], __argv[a]))
411 return true;
412 }
413 return false;
414}
415
416static inline bool contains(int argc, char **argv, const char *needle)
417{
418 for (int a = 0; a < argc; ++a) {
419 if (!strcmp(argv[a], needle))
420 return true;
421 }
422 return false;
423}
424#endif // Q_OS_WIN
425
427 :
428#ifndef QT_NO_QOBJECT
430#endif
431 argc(aargc)
432 , argv(aargv)
433#if defined(Q_OS_WIN)
434 , origArgc(0)
435 , origArgv(nullptr)
436#endif
437 , application_type(QCoreApplicationPrivate::Tty)
438#ifndef QT_NO_QOBJECT
439 , in_exec(false)
440 , aboutToQuitEmitted(false)
441 , threadData_clean(false)
442#else
443 , q_ptr(nullptr)
444#endif
445{
446 static const char *const empty = "";
447 if (argc == 0 || argv == nullptr) {
448 argc = 0;
449 argv = const_cast<char **>(&empty);
450 }
451#if defined(Q_OS_WIN)
452 if (!isArgvModified(argc, argv)) {
453 origArgc = argc;
454 origArgv = new char *[argc];
455 std::copy(argv, argv + argc, QT_MAKE_CHECKED_ARRAY_ITERATOR(origArgv, argc));
456 }
457#endif // Q_OS_WIN
458
459#ifndef QT_NO_QOBJECT
461
462# if defined(Q_OS_UNIX)
463 if (Q_UNLIKELY(!setuidAllowed && (geteuid() != getuid())))
464 qFatal("FATAL: The application binary appears to be running setuid, this is a security hole.");
465# endif // Q_OS_UNIX
466
467 QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread!
468 if (cur != theMainThread.loadAcquire())
469 qWarning("WARNING: QApplication was not created in the main() thread.");
470#endif
471}
472
474{
475#ifndef QT_NO_QOBJECT
477#endif
478#if defined(Q_OS_WIN)
479 delete [] origArgv;
480 if (consoleAllocated)
481 FreeConsole();
482#endif
484}
485
486#ifndef QT_NO_QOBJECT
487
489{
490 auto thisThreadData = threadData.loadRelaxed();
491
492 if (thisThreadData && !threadData_clean) {
493#if QT_CONFIG(thread)
494 void *data = &thisThreadData->tls;
495 QThreadStorageData::finish((void **)data);
496#endif
497
498 // need to clear the state of the mainData, just in case a new QCoreApplication comes along.
499 const auto locker = qt_scoped_lock(thisThreadData->postEventList.mutex);
500 for (const QPostEvent &pe : std::as_const(thisThreadData->postEventList)) {
501 if (pe.event) {
502 --pe.receiver->d_func()->postedEvents;
503 pe.event->m_posted = false;
504 delete pe.event;
505 }
506 }
507 thisThreadData->postEventList.clear();
508 thisThreadData->postEventList.recursion = 0;
509 thisThreadData->quitNow = false;
510 threadData_clean = true;
511 }
512}
513
515{
516 Q_Q(QCoreApplication);
518 Q_ASSERT(!data->hasEventDispatcher());
519 eventDispatcher = data->createEventDispatcher();
520 eventDispatcher->setParent(q);
521}
522
526
527Q_CONSTINIT QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
528Q_CONSTINIT QBasicAtomicPointer<void> QCoreApplicationPrivate::theMainThreadId = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
530{
531 Q_ASSERT(theMainThread.loadRelaxed() != nullptr);
532 return theMainThread.loadRelaxed();
533}
534
536{
538 if (!data)
539 return true; // default setting
540 return data->requiresCoreApplication;
541}
542
544{
545 QThread *currentThread = QThread::currentThread();
546 QThread *thr = receiver->thread();
547 Q_ASSERT_X(currentThread == thr || !thr,
548 "QCoreApplication::sendEvent",
549 QString::asprintf("Cannot send events to objects owned by a different thread. "
550 "Current thread 0x%p. Receiver '%ls' (of type '%s') was created in thread 0x%p",
551 currentThread, qUtf16Printable(receiver->objectName()),
552 receiver->metaObject()->className(), thr)
553 .toLocal8Bit().data());
554 Q_UNUSED(currentThread);
555 Q_UNUSED(thr);
556}
557
558#endif // QT_NO_QOBJECT
559
561{
562#if QT_CONFIG(library)
563 QStringList *app_libpaths = coreappdata()->app_libpaths.get();
564 if (!app_libpaths)
565 coreappdata()->app_libpaths.reset(app_libpaths = new QStringList);
567 app_location.truncate(app_location.lastIndexOf(u'/'));
568 app_location = QDir(app_location).canonicalPath();
569 if (QFile::exists(app_location) && !app_libpaths->contains(app_location))
570 app_libpaths->append(app_location);
571#endif
572}
573
575{
577 return QString();
578 return QCoreApplication::instance()->d_func()->appName();
579}
580
582{
583#ifdef Q_OS_WINDOWS
584 const QString env = qEnvironmentVariable("QT_WIN_DEBUG_CONSOLE");
585 if (env.isEmpty())
586 return;
587 if (env.compare(u"new"_s, Qt::CaseInsensitive) == 0) {
588 if (AllocConsole() == FALSE)
589 return;
590 consoleAllocated = true;
591 } else if (env.compare(u"attach"_s, Qt::CaseInsensitive) == 0) {
592 // If the calling process is already attached to a console,
593 // the error code returned is ERROR_ACCESS_DENIED.
594 if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::GetLastError() != ERROR_ACCESS_DENIED)
595 return;
596 } else {
597 // Unknown input, don't make any decision for the user.
598 return;
599 }
600 // The std{in,out,err} handles are read-only, so we need to pass in dummies.
601 FILE *in = nullptr;
602 FILE *out = nullptr;
603 FILE *err = nullptr;
604 freopen_s(&in, "CONIN$", "r", stdin);
605 freopen_s(&out, "CONOUT$", "w", stdout);
606 freopen_s(&err, "CONOUT$", "w", stderr);
607 // However, things wouldn't work if the runtime did not preserve the pointers.
608 Q_ASSERT(in == stdin);
609 Q_ASSERT(out == stdout);
610 Q_ASSERT(err == stderr);
611#endif
612}
613
615{
616#if defined(QT_BOOTSTRAPPED)
617 // Don't try to control bootstrap library locale or encoding.
618#elif defined(Q_OS_UNIX)
619 Q_CONSTINIT static bool qt_locale_initialized = false;
620 if (qt_locale_initialized)
621 return;
622 qt_locale_initialized = true;
623
624 // By default the portable "C"/POSIX locale is selected and active.
625 // Apply the locale from the environment, via setlocale(), which will
626 // read LC_ALL, LC_<category>, and LANG, in order (for each category).
627 setlocale(LC_ALL, "");
628
629 // Next, let's ensure that LC_CTYPE is UTF-8, since QStringConverter's
630 // QLocal8Bit hard-codes this, and we need to be consistent.
631# if defined(Q_OS_INTEGRITY)
632 setlocale(LC_CTYPE, "UTF-8");
633# elif defined(Q_OS_QNX)
634 // QNX has no nl_langinfo, so we can't check.
635 // FIXME: Shouldn't we still setlocale("UTF-8")?
636# elif defined(Q_OS_ANDROID) && __ANDROID_API__ < __ANDROID_API_O__
637 // Android 6 still lacks nl_langinfo(), so we can't check.
638 // FIXME: Shouldn't we still setlocale("UTF-8")?
639# elif defined(Q_OS_VXWORKS)
640 // VxWorks has no nl_langinfo, so we can't check.
641# else
642 // std::string's SSO usually saves this the need to allocate:
643 const std::string oldEncoding = nl_langinfo(CODESET);
644 if (!Q_LIKELY(qstricmp(oldEncoding.data(), "UTF-8") == 0
645 || qstricmp(oldEncoding.data(), "utf8") == 0)) {
646 const QByteArray oldLocale = setlocale(LC_ALL, nullptr);
647 QByteArray newLocale;
648 bool warnOnOverride = true;
649# if defined(Q_OS_DARWIN)
650 // Don't warn unless the char encoding has been changed from the
651 // default "C" encoding, or the user touched any of the locale
652 // environment variables to force the "C" char encoding.
653 warnOnOverride = qstrcmp(setlocale(LC_CTYPE, nullptr), "C") != 0
654 || getenv("LC_ALL") || getenv("LC_CTYPE") || getenv("LANG");
655
656 // No need to try language or region specific CTYPEs, as they
657 // all point back to the same generic UTF-8 CTYPE.
658 newLocale = setlocale(LC_CTYPE, "UTF-8");
659# else
660 newLocale = setlocale(LC_CTYPE, nullptr);
661 if (qsizetype dot = newLocale.indexOf('.'); dot != -1)
662 newLocale.truncate(dot); // remove encoding, if any
663 if (qsizetype at = newLocale.indexOf('@'); at != -1)
664 newLocale.truncate(at); // remove variant, as the old de_DE@euro
665 newLocale += ".UTF-8";
666 newLocale = setlocale(LC_CTYPE, newLocale);
667
668 // If that locale doesn't exist, try some fallbacks:
669 if (newLocale.isEmpty())
670 newLocale = setlocale(LC_CTYPE, "C.UTF-8");
671 if (newLocale.isEmpty())
672 newLocale = setlocale(LC_CTYPE, "C.utf8");
673# endif
674
675 if (newLocale.isEmpty()) {
676 // Failed to set a UTF-8 locale.
677 qWarning("Detected locale \"%s\" with character encoding \"%s\", which is not UTF-8.\n"
678 "Qt depends on a UTF-8 locale, but has failed to switch to one.\n"
679 "If this causes problems, reconfigure your locale. See the locale(1) manual\n"
680 "for more information.", oldLocale.constData(), oldEncoding.data());
681 } else if (warnOnOverride) {
682 // Let the user know we over-rode their configuration.
683 qWarning("Detected locale \"%s\" with character encoding \"%s\", which is not UTF-8.\n"
684 "Qt depends on a UTF-8 locale, and has switched to \"%s\" instead.\n"
685 "If this causes problems, reconfigure your locale. See the locale(1) manual\n"
686 "for more information.",
687 oldLocale.constData(), oldEncoding.data(), newLocale.constData());
688 }
689 }
690# endif // Platform choice
691#endif // Unix
692}
693
694
784#ifdef QT_NO_QOBJECT
785 : d_ptr(&p)
786#else
787 : QObject(p, nullptr)
788#endif
789{
790 d_func()->q_ptr = this;
791 // note: it is the subclasses' job to call
792 // QCoreApplicationPrivate::eventDispatcher->startingUp();
793}
794
810#ifndef Q_QDOC
811 , int
812#endif
813 )
814#ifdef QT_NO_QOBJECT
815 : d_ptr(new QCoreApplicationPrivate(argc, argv))
816#else
817 : QObject(*new QCoreApplicationPrivate(argc, argv))
818#endif
819{
820 d_func()->q_ptr = this;
821 d_func()->init();
822#ifndef QT_NO_QOBJECT
824#endif
825}
826
835{
836 Q_TRACE_SCOPE(QCoreApplicationPrivate_init);
837
838#if defined(Q_OS_MACOS)
840#endif
841
842 Q_Q(QCoreApplication);
843
844 initConsole();
845
846 initLocale();
847
848 Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object");
849 QCoreApplication::self = q;
850
851#if QT_CONFIG(thread)
852#ifdef Q_OS_WASM
853 emscripten::val hardwareConcurrency = emscripten::val::global("navigator")["hardwareConcurrency"];
854 if (hardwareConcurrency.isUndefined())
855 QThreadPrivate::idealThreadCount = 2;
856 else
857 QThreadPrivate::idealThreadCount = hardwareConcurrency.as<int>();
858#endif
859#endif
860
861 // Store app name/version (so they're still available after QCoreApplication is destroyed)
862 if (!coreappdata()->applicationNameSet)
863 coreappdata()->application = appName();
864
865 if (!coreappdata()->applicationVersionSet)
866 coreappdata()->applicationVersion = appVersion();
867
868#if defined(Q_OS_ANDROID)
869 // We've deferred initializing the logging registry due to not being
870 // able to guarantee that logging happened on the same thread as the
871 // Qt main thread, but now that the Qt main thread is set up, we can
872 // enable categorized logging.
873 QLoggingRegistry::instance()->initializeRules();
874#endif
875
876#if QT_CONFIG(library)
877 // Reset the lib paths, so that they will be recomputed, taking the availability of argv[0]
878 // into account. If necessary, recompute right away and replay the manual changes on top of the
879 // new lib paths.
880 QStringList *appPaths = coreappdata()->app_libpaths.release();
881 QStringList *manualPaths = coreappdata()->manual_libpaths.release();
882 if (appPaths) {
883 if (manualPaths) {
884 // Replay the delta. As paths can only be prepended to the front or removed from
885 // anywhere in the list, we can just linearly scan the lists and find the items that
886 // have been removed. Once the original list is exhausted we know all the remaining
887 // items have been added.
888 QStringList newPaths(q->libraryPaths());
889 for (qsizetype i = manualPaths->size(), j = appPaths->size(); i > 0 || j > 0; qt_noop()) {
890 if (--j < 0) {
891 newPaths.prepend((*manualPaths)[--i]);
892 } else if (--i < 0) {
893 newPaths.removeAll((*appPaths)[j]);
894 } else if ((*manualPaths)[i] != (*appPaths)[j]) {
895 newPaths.removeAll((*appPaths)[j]);
896 ++i; // try again with next item.
897 }
898 }
899 delete manualPaths;
900 coreappdata()->manual_libpaths.reset(new QStringList(newPaths));
901 }
902 delete appPaths;
903 }
904#endif
905
906#ifndef QT_NO_QOBJECT
907 // use the event dispatcher created by the app programmer (if any)
909 auto thisThreadData = threadData.loadRelaxed();
910 eventDispatcher = thisThreadData->eventDispatcher.loadRelaxed();
911
912 // otherwise we create one
913 if (!eventDispatcher)
916
917 if (!eventDispatcher->parent()) {
918 eventDispatcher->moveToThread(thisThreadData->thread.loadAcquire());
919 eventDispatcher->setParent(q);
920 }
921
922 thisThreadData->eventDispatcher = eventDispatcher;
924#endif
925
927
930#ifndef QT_BOOTSTRAPPED
934#endif
935
936#ifndef QT_NO_QOBJECT
937 is_app_running = true; // No longer starting up.
938#endif
939}
940
945{
946 preRoutinesCalled = false;
947
949
950 self = nullptr;
951#ifndef QT_NO_QOBJECT
954#endif
955
956#if QT_CONFIG(thread)
957 // Synchronize and stop the global thread pool threads.
958 QThreadPool *globalThreadPool = nullptr;
959 QThreadPool *guiThreadPool = nullptr;
960 QT_TRY {
961 globalThreadPool = QThreadPool::globalInstance();
962 guiThreadPool = QThreadPoolPrivate::qtGuiInstance();
963 } QT_CATCH (...) {
964 // swallow the exception, since destructors shouldn't throw
965 }
966 if (globalThreadPool) {
967 globalThreadPool->waitForDone();
968 delete globalThreadPool;
969 }
970 if (guiThreadPool) {
971 guiThreadPool->waitForDone();
972 delete guiThreadPool;
973 }
974#endif
975
976#ifndef QT_NO_QOBJECT
977 d_func()->threadData.loadRelaxed()->eventDispatcher = nullptr;
981#endif
982
983#if QT_CONFIG(library)
984 coreappdata()->app_libpaths.reset();
985 coreappdata()->manual_libpaths.reset();
986#endif
987}
988
1016
1029
1041{
1042 // Since we bit-shift these values, we can't go higher than 32 on 32 bit operating systems
1043 // without changing the storage type of QCoreApplicationPrivate::attribs to quint64.
1044 static_assert(Qt::AA_AttributeCount <= sizeof(QCoreApplicationPrivate::attribs) * CHAR_BIT);
1045
1046 if (on)
1048 else
1050#if defined(QT_NO_QOBJECT)
1051 if (Q_UNLIKELY(qApp)) {
1052#else
1054#endif
1055 switch (attribute) {
1058 case Qt::AA_UseOpenGLES:
1061#ifdef QT_BOOTSTRAPPED
1062 qWarning("Attribute %d must be set before QCoreApplication is created.",
1063 attribute);
1064#else
1065 qWarning("Attribute Qt::%s must be set before QCoreApplication is created.",
1066 QMetaEnum::fromType<Qt::ApplicationAttribute>().valueToKey(attribute));
1067#endif
1068 break;
1069 default:
1070 break;
1071 }
1072 }
1073}
1074
1085
1086#ifndef QT_NO_QOBJECT
1087
1111
1112static bool doNotify(QObject *, QEvent *);
1113
1118
1126bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
1127{
1129 if (selfRequired && !self)
1130 return false;
1131
1132 // Make it possible for Qt Script to hook into events even
1133 // though QApplication is subclassed...
1134 bool result = false;
1135 void *cbdata[] = { receiver, event, &result };
1137 return result;
1138 }
1139
1140 // Qt enforces the rule that events can only be sent to objects in
1141 // the current thread, so receiver->d_func()->threadData is
1142 // equivalent to QThreadData::current(), just without the function
1143 // call overhead.
1144 QObjectPrivate *d = receiver->d_func();
1145 QThreadData *threadData = d->threadData.loadAcquire();
1146 QScopedScopeLevelCounter scopeLevelCounter(threadData);
1147 if (!selfRequired)
1148 return doNotify(receiver, event);
1149
1150#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
1152 return false;
1153#endif
1154 return self->notify(receiver, event);
1155}
1156
1164bool QCoreApplication::forwardEvent(QObject *receiver, QEvent *event, QEvent *originatingEvent)
1165{
1166 if (event && originatingEvent)
1167 event->m_spont = originatingEvent->m_spont;
1168
1169 return notifyInternal2(receiver, event);
1170}
1171
1226{
1227 Q_ASSERT(receiver);
1228 Q_ASSERT(event);
1229
1230#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
1231 Q_ASSERT(receiver->d_func()->threadData.loadAcquire()->thread.loadRelaxed()
1233#endif
1234
1235 // no events are delivered after ~QCoreApplication() has started
1237 return true;
1238 return doNotify(receiver, event);
1239}
1240
1241static bool doNotify(QObject *receiver, QEvent *event)
1242{
1243 Q_ASSERT(event);
1244
1245 // ### Qt 7: turn into an assert
1246 if (receiver == nullptr) { // serious error
1247 qWarning("QCoreApplication::notify: Unexpected null receiver");
1248 return true;
1249 }
1250
1251#ifndef QT_NO_DEBUG
1253#endif
1254
1255 return receiver->isWidgetType() ? false : QCoreApplicationPrivate::notify_helper(receiver, event);
1256}
1257
1259{
1260 // We can't access the application event filters outside of the main thread (race conditions)
1261 Q_ASSERT(receiver->d_func()->threadData.loadAcquire()->thread.loadRelaxed() == mainThread());
1262
1263 if (extraData) {
1264 // application event filters are only called for objects in the GUI thread
1265 for (qsizetype i = 0; i < extraData->eventFilters.size(); ++i) {
1266 QObject *obj = extraData->eventFilters.at(i);
1267 if (!obj)
1268 continue;
1269 if (obj->d_func()->threadData.loadRelaxed() != threadData.loadRelaxed()) {
1270 qWarning("QCoreApplication: Application event filter cannot be in a different thread.");
1271 continue;
1272 }
1273 if (obj->eventFilter(receiver, event))
1274 return true;
1275 }
1276 }
1277 return false;
1278}
1279
1281{
1282 if ((receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() != mainThread()
1283 || receiver != QCoreApplication::instance())
1284 && receiver->d_func()->extraData) {
1285 for (qsizetype i = 0; i < receiver->d_func()->extraData->eventFilters.size(); ++i) {
1286 QObject *obj = receiver->d_func()->extraData->eventFilters.at(i);
1287 if (!obj)
1288 continue;
1289 if (obj->d_func()->threadData.loadRelaxed() != receiver->d_func()->threadData.loadRelaxed()) {
1290 qWarning("QCoreApplication: Object event filter cannot be in a different thread.");
1291 continue;
1292 }
1293 if (obj->eventFilter(receiver, event))
1294 return true;
1295 }
1296 }
1297 return false;
1298}
1299
1306{
1307 // Note: when adjusting the tracepoints in here
1308 // consider adjusting QApplicationPrivate::notify_helper too.
1309 Q_TRACE(QCoreApplication_notify_entry, receiver, event, event->type());
1310 bool consumed = false;
1311 bool filtered = false;
1312 Q_TRACE_EXIT(QCoreApplication_notify_exit, consumed, filtered);
1313
1314 // send to all application event filters (only does anything in the main thread)
1315 if (receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()
1316 && QCoreApplication::self
1317 && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
1318 filtered = true;
1319 return filtered;
1320 }
1321 // send to all receiver event filters
1322 if (sendThroughObjectEventFilters(receiver, event)) {
1323 filtered = true;
1324 return filtered;
1325 }
1326
1327 // deliver the event
1328 consumed = receiver->event(event);
1329 return consumed;
1330}
1331
1343
1355
1356
1386void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
1387{
1389 if (!data->hasEventDispatcher())
1390 return;
1391 data->eventDispatcher.loadRelaxed()->processEvents(flags);
1392}
1393
1406void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int ms)
1407{
1409}
1410
1436{
1437 // ### TODO: consider splitting this method into a public and a private
1438 // one, so that a user-invoked processEvents can be detected
1439 // and handled properly.
1441 if (!data->hasEventDispatcher())
1442 return;
1443
1444 while (data->eventDispatcher.loadRelaxed()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
1445 if (deadline.hasExpired())
1446 break;
1447 }
1448}
1449
1450/*****************************************************************************
1451 Main event loop wrappers
1452 *****************************************************************************/
1453
1481{
1483 return -1;
1484
1485 QThreadData *threadData = self->d_func()->threadData.loadAcquire();
1486 if (threadData != QThreadData::current()) {
1487 qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
1488 return -1;
1489 }
1490 if (!threadData->eventLoops.isEmpty()) {
1491 qWarning("QCoreApplication::exec: The event loop is already running");
1492 return -1;
1493 }
1494
1495 threadData->quitNow = false;
1496 QEventLoop eventLoop;
1497 self->d_func()->in_exec = true;
1498 self->d_func()->aboutToQuitEmitted = false;
1499 int returnCode = eventLoop.exec(QEventLoop::ApplicationExec);
1500 threadData->quitNow = false;
1501
1502 if (self)
1503 self->d_func()->execCleanup();
1504
1505 return returnCode;
1506}
1507
1508
1509// Cleanup after eventLoop is done executing in QCoreApplication::exec().
1510// This is for use cases in which QCoreApplication is instantiated by a
1511// library and not by an application executable, for example, Active X
1512// servers.
1513
1515{
1516 threadData.loadRelaxed()->quitNow = false;
1517 in_exec = false;
1518
1519 qCDebug(lcDeleteLater) << "Sending deferred delete events as part of exec cleanup";
1521}
1522
1523
1554void QCoreApplication::exit(int returnCode)
1555{
1556 if (!self)
1557 return;
1558 QCoreApplicationPrivate *d = self->d_func();
1559 if (!d->aboutToQuitEmitted) {
1560 emit self->aboutToQuit(QCoreApplication::QPrivateSignal());
1561 d->aboutToQuitEmitted = true;
1562 }
1563 QThreadData *data = d->threadData.loadRelaxed();
1564 data->quitNow = true;
1565 for (qsizetype i = 0; i < data->eventLoops.size(); ++i) {
1566 QEventLoop *eventLoop = data->eventLoops.at(i);
1567 eventLoop->exit(returnCode);
1568 }
1569}
1570
1571/*****************************************************************************
1572 QCoreApplication management of posted events
1573 *****************************************************************************/
1574
1575#ifndef QT_NO_QOBJECT
1591{
1592 Q_ASSERT_X(receiver, "QCoreApplication::sendEvent", "Unexpected null receiver");
1593 Q_ASSERT_X(event, "QCoreApplication::sendEvent", "Unexpected null event");
1594
1595 Q_TRACE(QCoreApplication_sendEvent, receiver, event, event->type());
1596
1597 event->m_spont = false;
1598 return notifyInternal2(receiver, event);
1599}
1600
1604bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
1605{
1606 Q_ASSERT_X(receiver, "QCoreApplication::sendSpontaneousEvent", "Unexpected null receiver");
1607 Q_ASSERT_X(event, "QCoreApplication::sendSpontaneousEvent", "Unexpected null event");
1608
1609 Q_TRACE(QCoreApplication_sendSpontaneousEvent, receiver, event, event->type());
1610
1611 event->m_spont = true;
1612 return notifyInternal2(receiver, event);
1613}
1614
1615#endif // QT_NO_QOBJECT
1616
1618{
1619 QPostEventListLocker locker;
1620
1621 if (!object) {
1623 locker.locker = qt_unique_lock(locker.threadData->postEventList.mutex);
1624 return locker;
1625 }
1626
1627 auto &threadData = QObjectPrivate::get(object)->threadData;
1628
1629 // if object has moved to another thread, follow it
1630 for (;;) {
1631 // synchronizes with the storeRelease in QObject::moveToThread
1632 locker.threadData = threadData.loadAcquire();
1633 if (!locker.threadData) {
1634 // destruction in progress
1635 return locker;
1636 }
1637
1638 auto temporaryLocker = qt_unique_lock(locker.threadData->postEventList.mutex);
1639 if (locker.threadData == threadData.loadAcquire()) {
1640 locker.locker = std::move(temporaryLocker);
1641 break;
1642 }
1643 }
1644
1645 Q_ASSERT(locker.threadData);
1646 return locker;
1647}
1648
1674void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
1675{
1676 Q_ASSERT_X(event, "QCoreApplication::postEvent", "Unexpected null event");
1677
1678 Q_TRACE_SCOPE(QCoreApplication_postEvent, receiver, event, event->type());
1679
1680 // ### Qt 7: turn into an assert
1681 if (receiver == nullptr) {
1682 qWarning("QCoreApplication::postEvent: Unexpected null receiver");
1683 delete event;
1684 return;
1685 }
1686
1688 if (!locker.threadData) {
1689 // posting during destruction? just delete the event to prevent a leak
1690 delete event;
1691 return;
1692 }
1693
1694 QThreadData *data = locker.threadData;
1695
1696 // if this is one of the compressible events, do compression
1697 if (receiver->d_func()->postedEvents
1698 && self && self->compressEvent(event, receiver, &data->postEventList)) {
1699 Q_TRACE(QCoreApplication_postEvent_event_compressed, receiver, event);
1700 return;
1701 }
1702
1703 // delete the event on exceptions to protect against memory leaks till the event is
1704 // properly owned in the postEventList
1705 std::unique_ptr<QEvent> eventDeleter(event);
1706 Q_TRACE(QCoreApplication_postEvent_event_posted, receiver, event, event->type());
1707 data->postEventList.addEvent(QPostEvent(receiver, event, priority));
1708 Q_UNUSED(eventDeleter.release());
1709 event->m_posted = true;
1710 ++receiver->d_func()->postedEvents;
1711 data->canWait = false;
1712 locker.unlock();
1713
1714 QAbstractEventDispatcher* dispatcher = data->eventDispatcher.loadAcquire();
1715 if (dispatcher)
1716 dispatcher->wakeUp();
1717}
1718
1724{
1725 Q_ASSERT(event);
1726 Q_ASSERT(receiver);
1727 Q_ASSERT(postedEvents);
1728
1729 int receiverPostedEvents = receiver->d_func()->postedEvents.loadRelaxed();
1730 // compress posted timers to this object.
1731 if (event->type() == QEvent::Timer && receiverPostedEvents > 0) {
1732 int timerId = static_cast<QTimerEvent *>(event)->timerId();
1733 auto sameReceiver = [receiver](const QPostEvent &e) { return e.receiver == receiver; };
1734 auto it = std::find_if(postedEvents->cbegin(), postedEvents->cend(), sameReceiver);
1735 while (receiverPostedEvents > 0 && it != postedEvents->cend()) {
1736 if (it->event && it->event->type() == QEvent::Timer
1737 && static_cast<QTimerEvent *>(it->event)->timerId() == timerId) {
1738 delete event;
1739 return true;
1740 }
1741
1742 if (--receiverPostedEvents)
1743 it = std::find_if(it + 1, postedEvents->cend(), sameReceiver);
1744 }
1745 return false;
1746 }
1747
1748 if (event->type() == QEvent::Quit && receiverPostedEvents > 0) {
1749 for (const QPostEvent &cur : std::as_const(*postedEvents)) {
1750 if (cur.receiver != receiver
1751 || cur.event == nullptr
1752 || cur.event->type() != event->type())
1753 continue;
1754 // found an event for this receiver
1755 delete event;
1756 return true;
1757 }
1758 }
1759
1760 return false;
1761}
1762
1780void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type)
1781{
1782 // ### TODO: consider splitting this method into a public and a private
1783 // one, so that a user-invoked sendPostedEvents can be detected
1784 // and handled properly.
1786
1787 QCoreApplicationPrivate::sendPostedEvents(receiver, event_type, data);
1788}
1789
1792{
1793 if (event_type == -1) {
1794 // we were called by an obsolete event dispatcher.
1795 event_type = 0;
1796 }
1797
1798 if (receiver && receiver->d_func()->threadData.loadRelaxed() != data) {
1799 qWarning("QCoreApplication::sendPostedEvents: Cannot send "
1800 "posted events for objects in another thread");
1801 return;
1802 }
1803
1804 ++data->postEventList.recursion;
1805
1806 auto locker = qt_unique_lock(data->postEventList.mutex);
1807
1808 // by default, we assume that the event dispatcher can go to sleep after
1809 // processing all events. if any new events are posted while we send
1810 // events, canWait will be set to false.
1811 data->canWait = (data->postEventList.size() == 0);
1812
1813 if (data->postEventList.size() == 0 || (receiver && !receiver->d_func()->postedEvents)) {
1814 --data->postEventList.recursion;
1815 return;
1816 }
1817
1818 data->canWait = true;
1819
1820 // okay. here is the tricky loop. be careful about optimizing
1821 // this, it looks the way it does for good reasons.
1822 qsizetype startOffset = data->postEventList.startOffset;
1823 qsizetype &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset;
1824 data->postEventList.insertionOffset = data->postEventList.size();
1825
1826 // Exception-safe cleaning up without the need for a try/catch block
1827 struct CleanUp {
1828 QObject *receiver;
1829 int event_type;
1831 bool exceptionCaught;
1832
1833 inline CleanUp(QObject *receiver, int event_type, QThreadData *data) :
1834 receiver(receiver), event_type(event_type), data(data), exceptionCaught(true)
1835 {}
1836 inline ~CleanUp()
1837 {
1838 if (exceptionCaught) {
1839 // since we were interrupted, we need another pass to make sure we clean everything up
1840 data->canWait = false;
1841 }
1842
1843 --data->postEventList.recursion;
1844 if (!data->postEventList.recursion && !data->canWait && data->hasEventDispatcher())
1845 data->eventDispatcher.loadRelaxed()->wakeUp();
1846
1847 // clear the global list, i.e. remove everything that was
1848 // delivered.
1849 if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
1850 const QPostEventList::iterator it = data->postEventList.begin();
1851 data->postEventList.erase(it, it + data->postEventList.startOffset);
1852 data->postEventList.insertionOffset -= data->postEventList.startOffset;
1853 Q_ASSERT(data->postEventList.insertionOffset >= 0);
1854 data->postEventList.startOffset = 0;
1855 }
1856 }
1857 };
1858 CleanUp cleanup(receiver, event_type, data);
1859
1860 while (i < data->postEventList.size()) {
1861 // avoid live-lock
1862 if (i >= data->postEventList.insertionOffset)
1863 break;
1864
1865 const QPostEvent &pe = data->postEventList.at(i);
1866 ++i;
1867
1868 if (!pe.event)
1869 continue;
1870 if ((receiver && receiver != pe.receiver) || (event_type && event_type != pe.event->type())) {
1871 data->canWait = false;
1872 continue;
1873 }
1874
1875 if (pe.event->type() == QEvent::DeferredDelete) {
1876 // DeferredDelete events are sent either
1877 // 1) when the event loop that posted the event has returned; or
1878 // 2) if explicitly requested (with QEvent::DeferredDelete) for
1879 // events posted by the current event loop; or
1880 // 3) if the event was posted before the outermost event loop.
1881
1882 const auto *event = static_cast<QDeferredDeleteEvent *>(pe.event);
1883 qCDebug(lcDeleteLater) << "Processing deferred delete event for" << pe.receiver
1884 << "with loop level" << event->loopLevel() << "and scope level" << event->scopeLevel();
1885
1886 qCDebug(lcDeleteLater) << "Checking" << data->thread << "with loop level"
1887 << data->loopLevel << "and scope level" << data->scopeLevel;
1888
1889 bool allowDeferredDelete = false;
1890 if (event->loopLevel() == 0 && data->loopLevel > 0) {
1891 qCDebug(lcDeleteLater) << "Event was posted outside outermost event loop"
1892 << "and current thread has an event loop running.";
1893 allowDeferredDelete = true;
1894 } else {
1895 const int totalEventLevel = event->loopLevel() + event->scopeLevel();
1896 const int totalThreadLevel = data->loopLevel + data->scopeLevel;
1897
1898 if (totalEventLevel > totalThreadLevel) {
1899 qCDebug(lcDeleteLater) << "Combined levels of event" << totalEventLevel
1900 << "is higher than thread" << totalThreadLevel;
1901 allowDeferredDelete = true;
1902 } else if (event_type == QEvent::DeferredDelete && totalEventLevel == totalThreadLevel) {
1903 qCDebug(lcDeleteLater) << "Explicit send of DeferredDelete and"
1904 << "levels of event" << totalEventLevel
1905 << "is same as thread" << totalThreadLevel;
1906 allowDeferredDelete = true;
1907 }
1908 }
1909
1910 if (!allowDeferredDelete) {
1911 qCDebug(lcDeleteLater) << "Failed conditions for deferred delete. Deferring again";
1912
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(pe_copy);
1927 }
1928 continue;
1929 } else {
1930 qCDebug(lcDeleteLater) << "Sending deferred delete to" << pe.receiver;
1931 }
1932 }
1933
1934 // first, we diddle the event so that we can deliver
1935 // it, and that no one will try to touch it later.
1936 pe.event->m_posted = false;
1937 QEvent *e = pe.event;
1938 QObject * r = pe.receiver;
1939
1940 --r->d_func()->postedEvents;
1941 Q_ASSERT(r->d_func()->postedEvents >= 0);
1942
1943 // next, update the data structure so that we're ready
1944 // for the next event.
1945 const_cast<QPostEvent &>(pe).event = nullptr;
1946
1947 locker.unlock();
1948 const auto relocker = qScopeGuard([&locker] { locker.lock(); });
1949
1950 QScopedPointer<QEvent> event_deleter(e); // will delete the event (with the mutex unlocked)
1951
1952 // after all that work, it's time to deliver the event.
1954
1955 // careful when adding anything below this point - the
1956 // sendEvent() call might invalidate any invariants this
1957 // function depends on.
1958 }
1959
1960 cleanup.exceptionCaught = false;
1961}
1962
1982void QCoreApplication::removePostedEvents(QObject *receiver, int eventType)
1983{
1985 QThreadData *data = locker.threadData;
1986
1987 // the QObject destructor calls this function directly. this can
1988 // happen while the event loop is in the middle of posting events,
1989 // and when we get here, we may not have any more posted events
1990 // for this object.
1991 if (receiver && !receiver->d_func()->postedEvents)
1992 return;
1993
1994 //we will collect all the posted events for the QObject
1995 //and we'll delete after the mutex was unlocked
1996 QVarLengthArray<QEvent*> events;
1998 qsizetype j = 0;
1999
2000 for (qsizetype i = 0; i < n; ++i) {
2001 const QPostEvent &pe = data->postEventList.at(i);
2002
2003 if ((!receiver || pe.receiver == receiver)
2004 && (pe.event && (eventType == 0 || pe.event->type() == eventType))) {
2005 --pe.receiver->d_func()->postedEvents;
2006 pe.event->m_posted = false;
2007 events.append(pe.event);
2008 const_cast<QPostEvent &>(pe).event = nullptr;
2009 } else if (!data->postEventList.recursion) {
2010 if (i != j)
2011 qSwap(data->postEventList[i], data->postEventList[j]);
2012 ++j;
2013 }
2014 }
2015
2016#ifdef QT_DEBUG
2017 if (receiver && eventType == 0) {
2018 Q_ASSERT(!receiver->d_func()->postedEvents);
2019 }
2020#endif
2021
2022 if (!data->postEventList.recursion) {
2023 // truncate list
2024 data->postEventList.erase(data->postEventList.begin() + j, data->postEventList.end());
2025 }
2026
2027 locker.unlock();
2028 qDeleteAll(events);
2029}
2030
2042{
2043 if (!event || !event->m_posted)
2044 return;
2045
2047
2048 const auto locker = qt_scoped_lock(data->postEventList.mutex);
2049
2050 if (data->postEventList.size() == 0) {
2051#if defined(QT_DEBUG)
2052 qDebug("QCoreApplication::removePostedEvent: Internal error: %p %d is posted",
2053 (void*)event, event->type());
2054 return;
2055#endif
2056 }
2057
2058 for (const QPostEvent &pe : std::as_const(data->postEventList)) {
2059 if (pe.event == event) {
2060#ifndef QT_NO_DEBUG
2061 qWarning("QCoreApplication::removePostedEvent: Event of type %d deleted while posted to %s %s",
2062 event->type(),
2063 pe.receiver->metaObject()->className(),
2064 pe.receiver->objectName().toLocal8Bit().data());
2065#endif
2066 --pe.receiver->d_func()->postedEvents;
2067 pe.event->m_posted = false;
2068 delete pe.event;
2069 const_cast<QPostEvent &>(pe).event = nullptr;
2070 return;
2071 }
2072 }
2073}
2074
2079{
2080 if (e->type() == QEvent::Quit) {
2081 exit(0);
2082 return true;
2083 }
2084 return QObject::event(e);
2085}
2086
2088{
2089 quitLockRef.ref();
2090}
2091
2093{
2094 quitLockRef.deref();
2095
2096 if (quitLockEnabled && canQuitAutomatically())
2097 quitAutomatically();
2098}
2099
2101{
2102 if (!in_exec)
2103 return false;
2104
2105 // The automatic quit functionality is triggered by
2106 // both QEventLoopLocker and maybeLastWindowClosed.
2107 // In either case, we don't want to quit if there
2108 // are active QEventLoopLockers, even if quitLockEnabled
2109 // is not enabled, as the property signals whether to
2110 // trigger the automatic quit, not whether to block it.
2111 if (quitLockRef.loadRelaxed())
2112 return false;
2113
2114 return true;
2115}
2116
2118{
2119 Q_Q(QCoreApplication);
2120
2121 // Explicit requests by the user to quit() is plumbed via the platform
2122 // if possible, and delivers the quit event synchronously. For automatic
2123 // quits we implicitly support cancelling the quit by showing another
2124 // window, which currently relies on removing any posted quit events
2125 // from the event queue. As a result, we can't use the normal quit()
2126 // code path, and need to post manually.
2128}
2129
2165{
2166 if (!self)
2167 return;
2168
2169 if (!self->d_func()->in_exec)
2170 return;
2171
2172 self->d_func()->quit();
2173}
2174
2176{
2177 Q_Q(QCoreApplication);
2178
2180 QEvent quitEvent(QEvent::Quit);
2181 QCoreApplication::sendEvent(q, &quitEvent);
2182 } else {
2184 }
2185}
2186
2208#endif // QT_NO_QOBJECT
2209
2210#ifndef QT_NO_TRANSLATION
2240{
2241 if (!translationFile)
2242 return false;
2243
2244 if (!QCoreApplicationPrivate::checkInstance("installTranslator"))
2245 return false;
2246 QCoreApplicationPrivate *d = self->d_func();
2247 {
2248 QWriteLocker locker(&d->translateMutex);
2249 d->translators.prepend(translationFile);
2250 }
2251
2252#ifndef QT_NO_TRANSLATION_BUILDER
2253 if (translationFile->isEmpty())
2254 return false;
2255#endif
2256
2257#ifndef QT_NO_QOBJECT
2259 QCoreApplication::sendEvent(self, &ev);
2260#endif
2261
2262 return true;
2263}
2264
2276{
2277 if (!translationFile)
2278 return false;
2279 if (!QCoreApplicationPrivate::checkInstance("removeTranslator"))
2280 return false;
2281 QCoreApplicationPrivate *d = self->d_func();
2282 QWriteLocker locker(&d->translateMutex);
2283 if (d->translators.removeAll(translationFile)) {
2284#ifndef QT_NO_QOBJECT
2285 locker.unlock();
2286 if (!self->closingDown()) {
2288 QCoreApplication::sendEvent(self, &ev);
2289 }
2290#endif
2291 return true;
2292 }
2293 return false;
2294}
2295
2297{
2298 if (n >= 0) {
2299 qsizetype percentPos = 0;
2300 qsizetype len = 0;
2301 while ((percentPos = result->indexOf(u'%', percentPos + len)) != -1) {
2302 len = 1;
2303 if (percentPos + len == result->size())
2304 break;
2305 QString fmt;
2306 if (result->at(percentPos + len) == u'L') {
2307 ++len;
2308 if (percentPos + len == result->size())
2309 break;
2310 fmt = "%L1"_L1;
2311 } else {
2312 fmt = "%1"_L1;
2313 }
2314 if (result->at(percentPos + len) == u'n') {
2315 fmt = fmt.arg(n);
2316 ++len;
2317 result->replace(percentPos, len, fmt);
2318 len = fmt.size();
2319 }
2320 }
2321 }
2322}
2323
2357QString QCoreApplication::translate(const char *context, const char *sourceText,
2358 const char *disambiguation, int n)
2359{
2361
2362 if (!sourceText)
2363 return result;
2364
2365 if (self) {
2366 QCoreApplicationPrivate *d = self->d_func();
2367 QReadLocker locker(&d->translateMutex);
2368 if (!d->translators.isEmpty()) {
2370 QTranslator *translationFile;
2371 for (it = d->translators.constBegin(); it != d->translators.constEnd(); ++it) {
2372 translationFile = *it;
2373 result = translationFile->translate(context, sourceText, disambiguation, n);
2374 if (!result.isNull())
2375 break;
2376 }
2377 }
2378 }
2379
2380 if (result.isNull())
2381 result = QString::fromUtf8(sourceText);
2382
2384 return result;
2385}
2386
2387// Declared in qglobal.h
2388QString qtTrId(const char *id, int n)
2389{
2390 return QCoreApplication::translate(nullptr, id, nullptr, n);
2391}
2392
2394{
2395 if (!QCoreApplication::self)
2396 return false;
2397 QCoreApplicationPrivate *d = QCoreApplication::self->d_func();
2398 QReadLocker locker(&d->translateMutex);
2399 return d->translators.contains(translator);
2400}
2401
2402#else
2403
2404QString QCoreApplication::translate(const char *context, const char *sourceText,
2405 const char *disambiguation, int n)
2406{
2408 Q_UNUSED(disambiguation);
2409 QString ret = QString::fromUtf8(sourceText);
2410 if (n >= 0)
2411 ret.replace("%n"_L1, QString::number(n));
2412 return ret;
2413}
2414
2415#endif //QT_NO_TRANSLATION
2416
2417// Makes it possible to point QCoreApplication to a custom location to ensure
2418// the directory is added to the patch, and qt.conf and deployed plugins are
2419// found from there. This is for use cases in which QGuiApplication is
2420// instantiated by a library and not by an application executable, for example,
2421// Active X servers.
2422
2430
2451{
2452 if (!self) {
2453 qWarning("QCoreApplication::applicationDirPath: Please instantiate the QApplication object first");
2454 return QString();
2455 }
2456
2457 QCoreApplicationPrivate *d = self->d_func();
2458 if (d->cachedApplicationDirPath.isNull())
2459 d->cachedApplicationDirPath = QFileInfo(applicationFilePath()).path();
2460 return d->cachedApplicationDirPath;
2461}
2462
2463#if !defined(Q_OS_WIN) && !defined(Q_OS_DARWIN) // qcoreapplication_win.cpp or qcoreapplication_mac.cpp
2465{
2466# if defined(Q_OS_ANDROID)
2467 // the actual process on Android is the Java VM, so this doesn't help us
2468 return QString();
2469# elif defined(Q_OS_LINUX)
2470 // this includes the Embedded Android builds
2471 return QFile::decodeName(qt_readlink("/proc/self/exe"));
2472# elif defined(AT_EXECPATH)
2473 // seen on FreeBSD, but I suppose the other BSDs could adopt this API
2474 char execfn[PATH_MAX];
2475 if (elf_aux_info(AT_EXECPATH, execfn, sizeof(execfn)) != 0)
2476 execfn[0] = '\0';
2477
2478 qsizetype len = qstrlen(execfn);
2480# else
2481 // other OS or something
2482 return QString();
2483#endif
2484}
2485#endif
2486
2503{
2504 if (!self) {
2505 qWarning("QCoreApplication::applicationFilePath: Please instantiate the QApplication object first");
2506 return QString();
2507 }
2508
2509 QCoreApplicationPrivate *d = self->d_func();
2510
2511 if (d->argc) {
2512 static QByteArray procName = QByteArray(d->argv[0]);
2513 if (procName != QByteArrayView(d->argv[0])) {
2514 // clear the cache if the procname changes, so we reprocess it.
2516 procName.assign(d->argv[0]);
2517 }
2518 }
2519
2522
2523 QString absPath = qAppFileName();
2524 if (absPath.isEmpty() && !arguments().isEmpty()) {
2526
2527 if (!argv0.isEmpty() && argv0.at(0) == u'/') {
2528 /*
2529 If argv0 starts with a slash, it is already an absolute
2530 file path.
2531 */
2532 absPath = argv0;
2533 } else if (argv0.contains(u'/')) {
2534 /*
2535 If argv0 contains one or more slashes, it is a file path
2536 relative to the current directory.
2537 */
2538 absPath = QDir::current().absoluteFilePath(argv0);
2539 } else {
2540 /*
2541 Otherwise, the file path has to be determined using the
2542 PATH environment variable.
2543 */
2544 absPath = QStandardPaths::findExecutable(argv0);
2545 }
2546 }
2547
2548 absPath = QFileInfo(absPath).canonicalFilePath();
2549 if (!absPath.isEmpty()) {
2552 }
2553 return QString();
2554}
2555
2562{
2563#if defined(Q_OS_WIN)
2564 return GetCurrentProcessId();
2565#elif defined(Q_OS_VXWORKS)
2566 return (pid_t) taskIdCurrent;
2567#else
2568 return getpid();
2569#endif
2570}
2571
2604{
2606
2607 if (!self) {
2608 qWarning("QCoreApplication::arguments: Please instantiate the QApplication object first");
2609 return list;
2610 }
2611
2612 const QCoreApplicationPrivate *d = self->d_func();
2613
2614 const int argc = d->argc;
2615 char ** const argv = d->argv;
2616 list.reserve(argc);
2617
2618#if defined(Q_OS_WIN)
2619 const bool argsModifiedByUser = d->origArgv == nullptr;
2620 if (!argsModifiedByUser) {
2621 // On Windows, it is possible to pass Unicode arguments on
2622 // the command line, but we don't implement any of the wide
2623 // entry-points (wmain/wWinMain), so get the arguments from
2624 // the Windows API instead of using argv. Note that we only
2625 // do this when argv were not modified by the user in main().
2626 QString cmdline = QString::fromWCharArray(GetCommandLine());
2627 QStringList commandLineArguments = qWinCmdArgs(cmdline);
2628
2629 // Even if the user didn't modify argv before passing them
2630 // on to QCoreApplication, derived QApplications might have.
2631 // If that's the case argc will differ from origArgc.
2632 if (argc != d->origArgc) {
2633 // Note: On MingGW the arguments from GetCommandLine are
2634 // not wildcard expanded (if wildcard expansion is enabled),
2635 // as opposed to the arguments in argv. This means we can't
2636 // compare commandLineArguments to argv/origArgc, but
2637 // must remove elements by value, based on whether they
2638 // were filtered out from argc.
2639 for (int i = 0; i < d->origArgc; ++i) {
2640 if (!contains(argc, argv, d->origArgv[i]))
2641 commandLineArguments.removeAll(QString::fromLocal8Bit(d->origArgv[i]));
2642 }
2643 }
2644
2645 return commandLineArguments;
2646 } // Fall back to rebuilding from argv/argc when a modified argv was passed.
2647#endif // defined(Q_OS_WIN)
2648
2649 for (int a = 0; a < argc; ++a)
2650 list << QString::fromLocal8Bit(argv[a]);
2651
2652 return list;
2653}
2654
2680{
2681 if (coreappdata()->orgName == orgName)
2682 return;
2683 coreappdata()->orgName = orgName;
2684#ifndef QT_NO_QOBJECT
2685 if (QCoreApplication::self)
2686 emit QCoreApplication::self->organizationNameChanged();
2687#endif
2688}
2689
2691{
2692 return coreappdata()->orgName;
2693}
2694
2717{
2718 if (coreappdata()->orgDomain == orgDomain)
2719 return;
2720 coreappdata()->orgDomain = orgDomain;
2721#ifndef QT_NO_QOBJECT
2722 if (QCoreApplication::self)
2723 emit QCoreApplication::self->organizationDomainChanged();
2724#endif
2725}
2726
2728{
2729 return coreappdata()->orgDomain;
2730}
2731
2755{
2756 coreappdata()->applicationNameSet = !application.isEmpty();
2757 QString newAppName = application;
2758 if (newAppName.isEmpty() && QCoreApplication::self)
2759 newAppName = QCoreApplication::self->d_func()->appName();
2760 if (coreappdata()->application == newAppName)
2761 return;
2762 coreappdata()->application = newAppName;
2763#ifndef QT_NO_QOBJECT
2764 if (QCoreApplication::self)
2765 emit QCoreApplication::self->applicationNameChanged();
2766#endif
2767}
2768
2770{
2771 return coreappdata() ? coreappdata()->application : QString();
2772}
2773
2808{
2809 coreappdata()->applicationVersionSet = !version.isEmpty();
2810 QString newVersion = version;
2811 if (newVersion.isEmpty() && QCoreApplication::self)
2812 newVersion = QCoreApplication::self->d_func()->appVersion();
2813 if (coreappdata()->applicationVersion == newVersion)
2814 return;
2815 coreappdata()->applicationVersion = newVersion;
2816#ifndef QT_NO_QOBJECT
2817 if (QCoreApplication::self)
2818 emit QCoreApplication::self->applicationVersionChanged();
2819#endif
2820}
2821
2823{
2824 return coreappdata() ? coreappdata()->applicationVersion : QString();
2825}
2826
2827#if QT_CONFIG(permissions) || defined(Q_QDOC)
2828
2838Qt::PermissionStatus QCoreApplication::checkPermission(const QPermission &permission)
2839{
2840 return QPermissions::Private::checkPermission(permission);
2841}
2842
2917void QCoreApplication::requestPermission(const QPermission &requestedPermission,
2918 QtPrivate::QSlotObjectBase *slotObjRaw, const QObject *context)
2919{
2920 QtPrivate::SlotObjUniquePtr slotObj{slotObjRaw}; // adopts
2921 Q_ASSERT(slotObj);
2922
2924 qWarning(lcPermissions, "Permissions can only be requested from the GUI (main) thread");
2925 return;
2926 }
2927
2928 class PermissionReceiver : public QObject
2929 {
2930 public:
2931 explicit PermissionReceiver(QtPrivate::SlotObjUniquePtr &&slotObject, const QObject *context)
2932 : slotObject(std::move(slotObject)), context(context ? context : this)
2933 {
2934 Q_ASSERT(this->context);
2935 moveToThread(this->context->thread());
2936 }
2937
2938 void finalizePermissionRequest(const QPermission &permission)
2939 {
2940 Q_ASSERT(slotObject);
2941 // only execute if context object is still alive
2942 if (context) {
2943 void *args[] = { nullptr, const_cast<QPermission *>(&permission) };
2944 slotObject->call(const_cast<QObject *>(context.data()), args);
2945 }
2946 deleteLater();
2947 }
2948
2949 private:
2950 QtPrivate::SlotObjSharedPtr slotObject;
2951 QPointer<const QObject> context;
2952 };
2953
2954 PermissionReceiver *receiver = new PermissionReceiver(std::move(slotObj), context);
2955
2956 QPermissions::Private::requestPermission(requestedPermission, [=](Qt::PermissionStatus status) {
2957 if (status == Qt::PermissionStatus::Undetermined) {
2958 Q_ASSERT_X(false, "QPermission",
2959 "Internal error: requestPermission() should never return Undetermined");
2961 }
2962
2963 if (QCoreApplication::self) {
2964 QPermission permission = requestedPermission;
2965 permission.m_status = status;
2967 &PermissionReceiver::finalizePermissionRequest,
2969 permission);
2970 }
2971 });
2972}
2973
2974#endif // QT_CONFIG(permissions)
2975
2976#if QT_CONFIG(library)
2977
2978Q_GLOBAL_STATIC(QRecursiveMutex, libraryPathMutex)
2979
2980
3009QStringList QCoreApplication::libraryPaths()
3010{
3011 QMutexLocker locker(libraryPathMutex());
3012 return libraryPathsLocked();
3013}
3014
3018QStringList QCoreApplication::libraryPathsLocked()
3019{
3020 if (coreappdata()->manual_libpaths)
3021 return *(coreappdata()->manual_libpaths);
3022
3023 if (!coreappdata()->app_libpaths) {
3024 QStringList *app_libpaths = new QStringList;
3025 coreappdata()->app_libpaths.reset(app_libpaths);
3026
3027 auto setPathsFromEnv = [&](QString libPathEnv) {
3028 if (!libPathEnv.isEmpty()) {
3030 for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) {
3032 if (!canonicalPath.isEmpty()
3033 && !app_libpaths->contains(canonicalPath)) {
3034 app_libpaths->append(canonicalPath);
3035 }
3036 }
3037 }
3038 };
3039 setPathsFromEnv(qEnvironmentVariable("QT_PLUGIN_PATH"));
3040#ifdef Q_OS_DARWIN
3041 // Check the main bundle's PlugIns directory as this is a standard location for Apple OSes.
3042 // Note that the QLibraryInfo::PluginsPath below will coincidentally be the same as this value
3043 // but with a different casing, so it can't be relied upon when the underlying filesystem
3044 // is case sensitive (and this is always the case on newer OSes like iOS).
3045 if (CFBundleRef bundleRef = CFBundleGetMainBundle()) {
3046 if (QCFType<CFURLRef> urlRef = CFBundleCopyBuiltInPlugInsURL(bundleRef)) {
3047 if (QCFType<CFURLRef> absoluteUrlRef = CFURLCopyAbsoluteURL(urlRef)) {
3048 if (QCFString path = CFURLCopyFileSystemPath(absoluteUrlRef, kCFURLPOSIXPathStyle)) {
3049 if (QFile::exists(path)) {
3051 if (!app_libpaths->contains(path))
3052 app_libpaths->append(path);
3053 }
3054 }
3055 }
3056 }
3057 }
3058#endif // Q_OS_DARWIN
3059
3061 if (QFile::exists(installPathPlugins)) {
3062 // Make sure we convert from backslashes to slashes.
3063 installPathPlugins = QDir(installPathPlugins).canonicalPath();
3064 if (!app_libpaths->contains(installPathPlugins))
3065 app_libpaths->append(installPathPlugins);
3066 }
3067
3068 // If QCoreApplication is not yet instantiated,
3069 // make sure we add the application path when we construct the QCoreApplication
3070 if (self) self->d_func()->appendApplicationPathToLibraryPaths();
3071 }
3072 return *(coreappdata()->app_libpaths);
3073}
3074
3075
3076
3089void QCoreApplication::setLibraryPaths(const QStringList &paths)
3090{
3091 QMutexLocker locker(libraryPathMutex());
3092
3093 // setLibraryPaths() is considered a "remove everything and then add some new ones" operation.
3094 // When the application is constructed it should still amend the paths. So we keep the originals
3095 // around, and even create them if they don't exist, yet.
3096 if (!coreappdata()->app_libpaths)
3097 libraryPathsLocked();
3098
3099 if (coreappdata()->manual_libpaths)
3100 *(coreappdata()->manual_libpaths) = paths;
3101 else
3102 coreappdata()->manual_libpaths.reset(new QStringList(paths));
3103
3104 locker.unlock();
3105 QFactoryLoader::refreshAll();
3106}
3107
3124void QCoreApplication::addLibraryPath(const QString &path)
3125{
3126 if (path.isEmpty())
3127 return;
3128
3130 if (canonicalPath.isEmpty())
3131 return;
3132
3133 QMutexLocker locker(libraryPathMutex());
3134
3135 QStringList *libpaths = coreappdata()->manual_libpaths.get();
3136 if (libpaths) {
3137 if (libpaths->contains(canonicalPath))
3138 return;
3139 } else {
3140 // make sure that library paths are initialized
3141 libraryPathsLocked();
3142 QStringList *app_libpaths = coreappdata()->app_libpaths.get();
3143 if (app_libpaths->contains(canonicalPath))
3144 return;
3145
3146 coreappdata()->manual_libpaths.reset(libpaths = new QStringList(*app_libpaths));
3147 }
3148
3149 libpaths->prepend(canonicalPath);
3150 locker.unlock();
3151 QFactoryLoader::refreshAll();
3152}
3153
3163void QCoreApplication::removeLibraryPath(const QString &path)
3164{
3165 if (path.isEmpty())
3166 return;
3167
3169 if (canonicalPath.isEmpty())
3170 return;
3171
3172 QMutexLocker locker(libraryPathMutex());
3173
3174 QStringList *libpaths = coreappdata()->manual_libpaths.get();
3175 if (libpaths) {
3176 if (libpaths->removeAll(canonicalPath) == 0)
3177 return;
3178 } else {
3179 // make sure that library paths is initialized
3180 libraryPathsLocked();
3181 QStringList *app_libpaths = coreappdata()->app_libpaths.get();
3182 if (!app_libpaths->contains(canonicalPath))
3183 return;
3184
3185 coreappdata()->manual_libpaths.reset(libpaths = new QStringList(*app_libpaths));
3186 libpaths->removeAll(canonicalPath);
3187 }
3188
3189 locker.unlock();
3190 QFactoryLoader::refreshAll();
3191}
3192
3193#endif // QT_CONFIG(library)
3194
3195#ifndef QT_NO_QOBJECT
3196
3227{
3229 qWarning("Native event filters are not applied when the Qt::AA_PluginApplication attribute is set");
3230 return;
3231 }
3232
3234 if (!filterObj || !eventDispatcher)
3235 return;
3236 eventDispatcher->installNativeEventFilter(filterObj);
3237}
3238
3253{
3255 if (!filterObject || !eventDispatcher)
3256 return;
3257 eventDispatcher->removeNativeEventFilter(filterObject);
3258}
3259
3265{
3267 return QCoreApplicationPrivate::theMainThread.loadRelaxed()->eventDispatcher();
3268 return nullptr;
3269}
3270
3284
3285#endif // QT_NO_QOBJECT
3286
3396void *QCoreApplication::resolveInterface(const char *name, int revision) const
3397{
3398 Q_UNUSED(name); Q_UNUSED(revision);
3399 return nullptr;
3400}
3401
3403
3404#ifndef QT_NO_QOBJECT
3405#include "moc_qcoreapplication.cpp"
3406#endif
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
Returns a pointer to the event dispatcher object for the specified thread.
virtual void wakeUp()=0
\threadsafe
Type loadRelaxed() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:409
The QCommandLineOption class defines a possible command-line option. \inmodule QtCore.
static bool checkInstance(const char *method)
static bool isTranslatorInstalled(QTranslator *translator)
void appendApplicationPathToLibraryPaths(void)
static QPostEventListLocker lockThreadPostEventList(QObject *object)
static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data)
QCoreApplicationPrivate(int &aargc, char **aargv)
bool sendThroughApplicationEventFilters(QObject *, QEvent *)
static QString * cachedApplicationFilePath
virtual void eventDispatcherReady()
static bool sendThroughObjectEventFilters(QObject *, QEvent *)
static void checkReceiverThread(QObject *receiver)
static QAbstractEventDispatcher * eventDispatcher
static bool testAttribute(uint flag)
virtual void createEventDispatcher()
static void clearApplicationFilePath()
static QBasicAtomicPointer< void > theMainThreadId
static QThread * mainThread()
static void removePostedEvent(QEvent *)
Removes event from the queue of posted events, and emits a warning message if appropriate.
static void setApplicationFilePath(const QString &path)
static bool threadRequiresCoreApplication()
static QBasicAtomicPointer< QThread > theMainThread
static bool notify_helper(QObject *, QEvent *)
\inmodule QtCore
void * resolveInterface(const char *name, int revision) const
\macro Q_DECLARE_TR_FUNCTIONS(context)
static QAbstractEventDispatcher * eventDispatcher()
Returns a pointer to the event dispatcher object for the main thread.
static QString applicationFilePath()
Returns the file path of the application executable.
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static bool isSetuidAllowed()
bool event(QEvent *) override
\reimp
static void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
Sets the event dispatcher for the main thread to eventDispatcher.
virtual bool compressEvent(QEvent *, QObject *receiver, QPostEventList *)
void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj)
Removes an event filterObject from this object.
static void quit()
\threadsafe
virtual bool notify(QObject *, QEvent *)
Sends event to receiver: {receiver}->event(event).
static void removePostedEvents(QObject *receiver, int eventType=0)
static void processEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
Processes some pending events for the calling thread according to the specified flags.
static void setOrganizationDomain(const QString &orgDomain)
static bool isQuitLockEnabled()
static void setAttribute(Qt::ApplicationAttribute attribute, bool on=true)
Sets the attribute attribute if on is true; otherwise clears the attribute.
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
QString applicationVersion
the version of this application
static bool closingDown()
Returns true if the application objects are being destroyed; otherwise returns false.
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
Installs an event filter filterObj for all native events received by the application in the main thre...
static bool testAttribute(Qt::ApplicationAttribute attribute)
Returns true if attribute attribute is set; otherwise returns false.
QString organizationName
the name of the organization that wrote this application
static void setOrganizationName(const QString &orgName)
[11]
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
static QString applicationDirPath()
Returns the directory that contains the application executable.
static void setApplicationName(const QString &application)
static int exec()
Enters the main event loop and waits until exit() is called.
static bool installTranslator(QTranslator *messageFile)
Adds the translation file translationFile to the list of translation files to be used for translation...
static bool startingUp()
Returns true if an application object has not been created yet; otherwise returns false.
static qint64 applicationPid() Q_DECL_CONST_FUNCTION
static void setApplicationVersion(const QString &version)
static bool removeTranslator(QTranslator *messageFile)
Removes the translation file translationFile from the list of translation files used by this applicat...
static QStringList arguments()
static void setQuitLockEnabled(bool enabled)
~QCoreApplication()
Destroys the QCoreApplication object.
QString applicationName
the name of this application
static void setSetuidAllowed(bool allow)
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
Immediately dispatches all events which have been previously queued with QCoreApplication::postEvent(...
static void exit(int retcode=0)
Tells the application to exit with a return code.
bool quitLockEnabled
Whether the use of the QEventLoopLocker feature can cause the application to quit.
QString organizationDomain
the Internet domain of the organization that wrote this application
\inmodule QtCore
bool hasExpired() const noexcept
Returns true if this QDeadlineTimer object has expired, false if there remains time left.
\inmodule QtCore
Definition qdir.h:20
static QDir current()
Returns the application's current directory.
Definition qdir.h:219
QString canonicalPath() const
Returns the canonical path, i.e.
Definition qdir.cpp:692
static constexpr QChar listSeparator() noexcept
Definition qdir.h:200
\inmodule QtCore
Definition qeventloop.h:16
int exec(ProcessEventsFlags flags=AllEvents)
Enters the main event loop and waits until exit() is called.
@ ApplicationExec
Definition qeventloop.h:33
@ WaitForMoreEvents
Definition qeventloop.h:29
void exit(int returnCode=0)
Tells the event loop to exit with a return code.
\inmodule QtCore
Definition qcoreevent.h:45
Type
This enum type defines the valid event types in Qt.
Definition qcoreevent.h:51
@ DeferredDelete
Definition qcoreevent.h:100
@ LanguageChange
Definition qcoreevent.h:123
Type type() const
Returns the event type.
Definition qcoreevent.h:304
QString canonicalFilePath() const
Returns the file system entry's canonical path, including the entry's name, that is,...
QString path() const
Returns the path of the file system entry this QFileInfo refers to, excluding the entry's name.
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
Definition qfile.h:162
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
static bool activateCallbacks(Callback, void **)
Definition qglobal.cpp:154
@ EventNotifyCallback
\inmodule QtCore
static QString path(LibraryPath p)
Definition qlist.h:75
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
qsizetype removeAll(const AT &t)
Definition qlist.h:592
void prepend(rvalue_ref t)
Definition qlist.h:473
void reserve(qsizetype size)
Definition qlist.h:753
const_iterator cend() const noexcept
Definition qlist.h:631
const_iterator cbegin() const noexcept
Definition qlist.h:630
static QLoggingRegistry * instance()
\inmodule QtCore
Definition qmutex.h:313
\inmodule QtCore
Definition qmutex.h:281
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:150
QAtomicPointer< QThreadData > threadData
Definition qobject_p.h:203
\inmodule QtCore
Definition qobject.h:103
QString objectName
the name of this object
Definition qobject.h:107
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition qobject.cpp:1389
friend class QCoreApplication
Definition qobject.h:380
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1598
bool isWidgetType() const
Returns true if the object is a widget; otherwise returns false.
Definition qobject.h:131
\inmodule QtCore \inheaderfile QPermissions
qsizetype startOffset
Definition qthread_p.h:69
QObject * receiver
Definition qthread_p.h:42
\inmodule QtCore
\inmodule QtCore
Definition qmutex.h:309
iterator begin()
Definition qset.h:136
const_iterator constBegin() const noexcept
Definition qset.h:139
const_iterator constEnd() const noexcept
Definition qset.h:143
static QString findExecutable(const QString &executableName, const QStringList &paths=QStringList())
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString & replace(qsizetype i, qsizetype len, QChar after)
Definition qstring.cpp:3824
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5949
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8870
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6664
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1309
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
QString & append(QChar c)
Definition qstring.cpp:3252
static QString static QString asprintf(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
Definition qstring.cpp:7263
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
Definition qthread.cpp:1087
QStack< QEventLoop * > eventLoops
Definition qthread_p.h:321
static QThreadData * get2(QThread *thread)
Definition qthread_p.h:291
QPostEventList postEventList
Definition qthread_p.h:322
QAtomicPointer< QThread > thread
Definition qthread_p.h:323
static QThreadPool * qtGuiInstance()
Returns the QThreadPool instance for Qt Gui.
\inmodule QtCore
Definition qthreadpool.h:22
static QThreadPool * globalInstance()
Returns the global QThreadPool instance.
static QThread * currentThread()
Definition qthread.cpp:1039
\inmodule QtCore
Definition qcoreevent.h:366
int timerId() const
Returns the unique timer identifier, which is the same identifier as returned from QObject::startTime...
Definition qcoreevent.h:370
\inmodule QtCore
Definition qtranslator.h:19
\inmodule QtCore
#define this
Definition dialogs.cpp:9
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
void(* StartupCallback)()
Definition qhooks_p.h:40
@ Startup
Definition qhooks_p.h:33
void requestPermission(const QPermission &permission, const PermissionCallback &callback)
Qt::PermissionStatus checkPermission(const QPermission &permission)
Combined button and popup list for selecting options.
void initBindingStatusThreadId()
std::unique_ptr< QSlotObjectBase, QSlotObjectBase::Deleter > SlotObjUniquePtr
PermissionStatus
ApplicationAttribute
Definition qnamespace.h:424
@ AA_UseSoftwareOpenGL
Definition qnamespace.h:446
@ AA_UseDesktopOpenGL
Definition qnamespace.h:444
@ AA_SynthesizeMouseForUnhandledTabletEvents
Definition qnamespace.h:459
@ AA_AttributeCount
Definition qnamespace.h:469
@ AA_ShareOpenGLContexts
Definition qnamespace.h:447
@ AA_PluginApplication
Definition qnamespace.h:430
@ AA_UseOpenGLES
Definition qnamespace.h:445
@ AA_SynthesizeMouseForUnhandledTouchEvents
Definition qnamespace.h:437
@ CaseInsensitive
@ QueuedConnection
@ SkipEmptyParts
Definition qnamespace.h:128
static void * context
#define Q_BASIC_ATOMIC_INITIALIZER(a)
static QThread * mainThread
size_t qstrlen(const char *str)
Q_CORE_EXPORT int qstricmp(const char *, const char *)
Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2)
#define Q_UNLIKELY(x)
#define Q_LIKELY(x)
#define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N)
#define Q_DECL_EXPORT_OVERRIDABLE
QList< QString > QStringList
Constructs a string list that contains the given string, str.
QByteArray qt_readlink(const char *path)
QList< QtCleanUpFunction > QVFuncList
void qAddPreRoutine(QtStartUpFunction p)
static Q_CONSTINIT bool preRoutinesCalled
QString qAppName()
static Q_CONSTINIT bool quitLockEnabled
static QString qAppFileName()
void qAddPostRoutine(QtCleanUpFunction p)
void qt_startup_hook()
static void qt_call_pre_routines()
qsizetype qGlobalPostedEventsCount()
static Q_CONSTINIT QBasicMutex globalRoutinesMutex
static bool doNotify(QObject *, QEvent *)
QList< QtStartUpFunction > QStartUpFuncList
static void replacePercentN(QString *result, int n)
void Q_CORE_EXPORT qt_call_post_routines()
void qRemovePostRoutine(QtCleanUpFunction p)
void(* QtCleanUpFunction)()
void(* QtStartUpFunction)()
#define qApp
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint attribute
#define QT_CATCH(A)
#define QT_TRY
#define PATH_MAX
#define forever
Definition qforeach.h:78
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
QT_BEGIN_NAMESPACE quintptr Q_CORE_EXPORT qtHookData[]
Definition qhooks.cpp:9
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
#define qFatal
Definition qlogging.h:168
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
return ret
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLboolean r
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLfloat GLfloat f
GLenum type
GLsizei const GLuint * paths
GLbitfield flags
GLuint name
GLfloat n
struct _cl_event * event
GLhandleARB obj
[2]
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint in
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLenum GLsizei len
static qreal dot(const QPointF &a, const QPointF &b)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
SSL_CTX int void * arg
QString qAppFileName()
static QString canonicalPath(const QString &rootPath)
#define qUtf16Printable(string)
Definition qstring.h:1543
static char * toLocal8Bit(char *out, QStringView in, QStringConverter::State *state)
#define QStringLiteral(str)
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
Definition qswap.h:20
QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
#define emit
void qt_noop(void)
Definition qtnoop.h:14
#define Q_UNUSED(x)
#define Q_TRACE_METADATA(provider, metadata)
Definition qtrace_p.h:234
#define Q_TRACE_PREFIX(provider, prefix)
Definition qtrace_p.h:233
#define Q_TRACE_SCOPE(x,...)
Definition qtrace_p.h:146
#define Q_TRACE_INSTRUMENT(provider)
Definition qtrace_p.h:230
#define Q_TRACE(x,...)
Definition qtrace_p.h:144
#define Q_TRACE_EXIT(x,...)
Definition qtrace_p.h:145
#define Q_TRACE_POINT(provider, tracepoint,...)
Definition qtrace_p.h:232
Q_CORE_EXPORT QString qtTrId(const char *id, int n=-1)
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
QVideoFrameFormat::PixelFormat fmt
#define enabled
QList< int > list
[14]
if(qFloatDistance(a, b)<(1<< 7))
[0]
QTextStream out(stdout)
[7]
QDeadlineTimer deadline(30s)
QObject::connect nullptr
myObject moveToThread(QApplication::instance() ->thread())
[6]
QAction * at
QJSValueList args
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...