Qt 6.x
The Qt SDK
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 <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
46#if QT_CONFIG(permissions)
47#include <private/qpermissions_p.h>
48#endif
49
50#ifndef QT_NO_QOBJECT
51#if defined(Q_OS_UNIX)
52# if defined(Q_OS_DARWIN)
54# else
55# if !defined(QT_NO_GLIB)
56# include "qeventdispatcher_glib_p.h"
57# endif
58# endif
60#endif
61#ifdef Q_OS_WIN
63#endif
64#endif // QT_NO_QOBJECT
65
66#if defined(Q_OS_ANDROID)
67#include <QtCore/qjniobject.h>
68#endif
69
70#ifdef Q_OS_DARWIN
71# include "qcore_mac_p.h"
72#endif
73
74#include <stdlib.h>
75
76#ifdef Q_OS_UNIX
77# include <locale.h>
78# ifndef Q_OS_INTEGRITY
79# include <langinfo.h>
80# endif
81# include <unistd.h>
82# include <sys/types.h>
83
84# include "qcore_unix_p.h"
85#endif
86
87#if __has_include(<sys/auxv.h>) // Linux and FreeBSD
88# include <sys/auxv.h>
89#endif
90
91#ifdef Q_OS_VXWORKS
92# include <taskLib.h>
93#endif
94
95#ifdef Q_OS_WASM
96#include <emscripten/val.h>
97#endif
98
99#ifdef QT_BOOTSTRAPPED
100#include <private/qtrace_p.h>
101#else
102#include <qtcore_tracepoints_p.h>
103#endif
104
105#include <algorithm>
106#include <memory>
107#include <string>
108
110
111using namespace Qt::StringLiterals;
112
114 "#include <qcoreevent.h>"
115);
116Q_TRACE_METADATA(qtcore, "ENUM { AUTO, RANGE User ... MaxUser } QEvent::Type;");
117Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_entry, QObject *receiver, QEvent *event, QEvent::Type type);
118Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_exit);
119Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_event_compressed, QObject *receiver, QEvent *event);
120Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_event_posted, QObject *receiver, QEvent *event, QEvent::Type type);
121Q_TRACE_POINT(qtcore, QCoreApplication_sendEvent, QObject *receiver, QEvent *event, QEvent::Type type);
122Q_TRACE_POINT(qtcore, QCoreApplication_sendSpontaneousEvent, QObject *receiver, QEvent *event, QEvent::Type type);
123Q_TRACE_POINT(qtcore, QCoreApplication_notify_entry, QObject *receiver, QEvent *event, QEvent::Type type);
124Q_TRACE_POINT(qtcore, QCoreApplication_notify_exit, bool consumed, bool filtered);
125
126#if defined(Q_OS_WIN) || defined(Q_OS_DARWIN)
127extern QString qAppFileName();
128#endif
129
130Q_CONSTINIT bool QCoreApplicationPrivate::setuidAllowed = false;
131
132#if !defined(Q_OS_WIN)
133#ifdef Q_OS_DARWIN
134QString QCoreApplicationPrivate::infoDictionaryStringProperty(const QString &propertyName)
135{
136 QString bundleName;
137 QCFString cfPropertyName = propertyName.toCFString();
138 CFTypeRef string = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(),
139 cfPropertyName);
140 if (string)
141 bundleName = QString::fromCFString(static_cast<CFStringRef>(string));
142 return bundleName;
143}
144#endif
146{
147 QString applicationName;
148#ifdef Q_OS_DARWIN
149 applicationName = infoDictionaryStringProperty(QStringLiteral("CFBundleName"));
150#endif
151 if (applicationName.isEmpty() && argv[0]) {
152 char *p = strrchr(argv[0], '/');
153 applicationName = QString::fromLocal8Bit(p ? p + 1 : argv[0]);
154 }
155
156 return applicationName;
157}
159{
160 QString applicationVersion;
161#ifdef QT_BOOTSTRAPPED
162#elif defined(Q_OS_DARWIN)
163 applicationVersion = infoDictionaryStringProperty(QStringLiteral("CFBundleVersion"));
164#elif defined(Q_OS_ANDROID)
165 QJniObject context(QNativeInterface::QAndroidApplication::context());
166 if (context.isValid()) {
167 QJniObject pm = context.callObjectMethod(
168 "getPackageManager", "()Landroid/content/pm/PackageManager;");
169 QJniObject pn = context.callObjectMethod<jstring>("getPackageName");
170 if (pm.isValid() && pn.isValid()) {
171 QJniObject packageInfo = pm.callObjectMethod(
172 "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;",
173 pn.object(), 0);
174 if (packageInfo.isValid()) {
175 QJniObject versionName = packageInfo.getObjectField(
176 "versionName", "Ljava/lang/String;");
177 if (versionName.isValid())
178 return versionName.toString();
179 }
180 }
181 }
182#endif
183 return applicationVersion;
184}
185#endif // !Q_OS_WIN
186
188
190{
191 bool b = (QCoreApplication::self != nullptr);
192 if (!b)
193 qWarning("QApplication::%s: Please instantiate the QApplication object first", function);
194 return b;
195}
196
197#if QT_CONFIG(commandlineparser)
198void QCoreApplicationPrivate::addQtOptions(QList<QCommandLineOption> *options)
199{
200 options->append(QCommandLineOption(QStringLiteral("qmljsdebugger"),
201 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."),
202 QStringLiteral("value")));
203}
204#endif
205
207{
208 int j = argc ? 1 : 0;
209 for (int i = 1; i < argc; ++i) {
210 if (!argv[i])
211 continue;
212 if (*argv[i] != '-') {
213 argv[j++] = argv[i];
214 continue;
215 }
216 const char *arg = argv[i];
217 if (arg[1] == '-') // startsWith("--")
218 ++arg;
219 if (strncmp(arg, "-qmljsdebugger=", 15) == 0) {
221 } else if (strcmp(arg, "-qmljsdebugger") == 0 && i < argc - 1) {
222 ++i;
224 } else {
225 argv[j++] = argv[i];
226 }
227 }
228
229 if (j < argc) {
230 argv[j] = nullptr;
231 argc = j;
233}
234
235// Support for introspection
236
238{
239}
240
244Q_GLOBAL_STATIC(QVFuncList, postRList)
246Q_CONSTINIT static bool preRoutinesCalled = false;
247
255{
256 QStartUpFuncList *list = preRList();
257 if (!list)
258 return;
259
260 if (preRoutinesCalled) {
262 p();
263 }
264
265 // Due to C++11 parallel dynamic initialization, this can be called
266 // from multiple threads.
267 const auto locker = qt_scoped_lock(globalRoutinesMutex);
268 list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines
269}
270
272{
273 QVFuncList *list = postRList();
274 if (!list)
275 return;
276 const auto locker = qt_scoped_lock(globalRoutinesMutex);
277 list->prepend(p);
278}
279
281{
282 QVFuncList *list = postRList();
283 if (!list)
284 return;
285 const auto locker = qt_scoped_lock(globalRoutinesMutex);
286 list->removeAll(p);
287}
288
290{
291 // After will be allowed invoke QtStartUpFunction when calling qAddPreRoutine
292 preRoutinesCalled = true;
293
294 if (!preRList.exists())
295 return;
296
298 {
299 const auto locker = qt_scoped_lock(globalRoutinesMutex);
300 // Unlike qt_call_post_routines, we don't empty the list, because
301 // Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
302 // the function to be executed every time QCoreApplication is created.
303 list = *preRList;
304 }
305 for (QtCleanUpFunction f : std::as_const(list))
306 f();
307}
308
309void Q_CORE_EXPORT qt_call_post_routines()
310{
311 if (!postRList.exists())
312 return;
313
314 forever {
316 {
317 // extract the current list and make the stored list empty
318 const auto locker = qt_scoped_lock(globalRoutinesMutex);
319 qSwap(*postRList, list);
320 }
321
322 if (list.isEmpty())
323 break;
324 for (QtCleanUpFunction f : std::as_const(list))
325 f();
326 }
327}
328
329
330#ifndef QT_NO_QOBJECT
331
332// app starting up if false
333Q_CONSTINIT bool QCoreApplicationPrivate::is_app_running = false;
334 // app closing down if true
335Q_CONSTINIT bool QCoreApplicationPrivate::is_app_closing = false;
336
338{
340 return l.size() - l.startOffset;
341}
342
344
345#endif // QT_NO_QOBJECT
346
347Q_CONSTINIT QCoreApplication *QCoreApplication::self = nullptr;
351
354 applicationNameSet = false;
355 applicationVersionSet = false;
356 }
358#ifndef QT_NO_QOBJECT
359 // cleanup the QAdoptedThread created for the main() thread
360 if (auto *t = QCoreApplicationPrivate::theMainThread.loadAcquire()) {
362 data->deref(); // deletes the data and the adopted thread
363 }
364#endif
365 }
366
368 QString application; // application name, initially from argv[0], can then be modified.
370 bool applicationNameSet; // true if setApplicationName was called
371 bool applicationVersionSet; // true if setApplicationVersion was called
372
373#if QT_CONFIG(library)
374 std::unique_ptr<QStringList> app_libpaths;
375 std::unique_ptr<QStringList> manual_libpaths;
376#endif
377
378};
379
381
382#ifndef QT_NO_QOBJECT
383Q_CONSTINIT static bool quitLockEnabled = true;
384#endif
385
386#if defined(Q_OS_WIN)
387// Check whether the command line arguments passed to QCoreApplication
388// match those passed into main(), to see if the user has modified them
389// before passing them on to us. We do this by comparing to the global
390// __argv/__argc (MS extension). Deep comparison is required since
391// argv/argc is rebuilt by our WinMain entrypoint.
392static inline bool isArgvModified(int argc, char **argv)
393{
394 if (__argc != argc || !__argv /* wmain() */)
395 return true;
396 if (__argv == argv)
397 return false;
398 for (int a = 0; a < argc; ++a) {
399 if (argv[a] != __argv[a] && strcmp(argv[a], __argv[a]))
400 return true;
401 }
402 return false;
403}
404
405static inline bool contains(int argc, char **argv, const char *needle)
406{
407 for (int a = 0; a < argc; ++a) {
408 if (!strcmp(argv[a], needle))
409 return true;
410 }
411 return false;
412}
413#endif // Q_OS_WIN
414
416 :
417#ifndef QT_NO_QOBJECT
419#endif
420 argc(aargc)
421 , argv(aargv)
422#if defined(Q_OS_WIN)
423 , origArgc(0)
424 , origArgv(nullptr)
425#endif
426 , application_type(QCoreApplicationPrivate::Tty)
427#ifndef QT_NO_QOBJECT
428 , in_exec(false)
429 , aboutToQuitEmitted(false)
430 , threadData_clean(false)
431#else
432 , q_ptr(nullptr)
433#endif
434{
435 static const char *const empty = "";
436 if (argc == 0 || argv == nullptr) {
437 argc = 0;
438 argv = const_cast<char **>(&empty);
439 }
440#if defined(Q_OS_WIN)
441 if (!isArgvModified(argc, argv)) {
442 origArgc = argc;
443 origArgv = new char *[argc];
444 std::copy(argv, argv + argc, QT_MAKE_CHECKED_ARRAY_ITERATOR(origArgv, argc));
445 }
446#endif // Q_OS_WIN
447
448#ifndef QT_NO_QOBJECT
450
451# if defined(Q_OS_UNIX)
452 if (Q_UNLIKELY(!setuidAllowed && (geteuid() != getuid())))
453 qFatal("FATAL: The application binary appears to be running setuid, this is a security hole.");
454# endif // Q_OS_UNIX
455
456 QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread!
457 if (cur != theMainThread.loadAcquire())
458 qWarning("WARNING: QApplication was not created in the main() thread.");
459#endif
460}
461
463{
464#ifndef QT_NO_QOBJECT
466#endif
467#if defined(Q_OS_WIN)
468 delete [] origArgv;
469 if (consoleAllocated)
470 FreeConsole();
471#endif
473}
474
475#ifndef QT_NO_QOBJECT
476
478{
479 auto thisThreadData = threadData.loadRelaxed();
480
481 if (thisThreadData && !threadData_clean) {
482#if QT_CONFIG(thread)
483 void *data = &thisThreadData->tls;
484 QThreadStorageData::finish((void **)data);
485#endif
486
487 // need to clear the state of the mainData, just in case a new QCoreApplication comes along.
488 const auto locker = qt_scoped_lock(thisThreadData->postEventList.mutex);
489 for (const QPostEvent &pe : std::as_const(thisThreadData->postEventList)) {
490 if (pe.event) {
491 --pe.receiver->d_func()->postedEvents;
492 pe.event->m_posted = false;
493 delete pe.event;
494 }
495 }
496 thisThreadData->postEventList.clear();
497 thisThreadData->postEventList.recursion = 0;
498 thisThreadData->quitNow = false;
499 threadData_clean = true;
500 }
501}
502
504{
505 Q_Q(QCoreApplication);
507 Q_ASSERT(!data->hasEventDispatcher());
508 eventDispatcher = data->createEventDispatcher();
510}
511
513{
514}
515
518{
519 Q_ASSERT(theMainThread.loadRelaxed() != nullptr);
520 return theMainThread.loadRelaxed();
521}
522
524{
526 if (!data)
527 return true; // default setting
528 return data->requiresCoreApplication;
529}
530
532{
533 QThread *currentThread = QThread::currentThread();
534 QThread *thr = receiver->thread();
535 Q_ASSERT_X(currentThread == thr || !thr,
536 "QCoreApplication::sendEvent",
537 QString::asprintf("Cannot send events to objects owned by a different thread. "
538 "Current thread 0x%p. Receiver '%ls' (of type '%s') was created in thread 0x%p",
539 currentThread, qUtf16Printable(receiver->objectName()),
540 receiver->metaObject()->className(), thr)
541 .toLocal8Bit().data());
542 Q_UNUSED(currentThread);
543 Q_UNUSED(thr);
544}
545
546#endif // QT_NO_QOBJECT
547
549{
550#if QT_CONFIG(library)
551 QStringList *app_libpaths = coreappdata()->app_libpaths.get();
552 if (!app_libpaths)
553 coreappdata()->app_libpaths.reset(app_libpaths = new QStringList);
555 app_location.truncate(app_location.lastIndexOf(u'/'));
556 app_location = QDir(app_location).canonicalPath();
557 if (QFile::exists(app_location) && !app_libpaths->contains(app_location))
558 app_libpaths->append(app_location);
559#endif
560}
561
563{
565 return QString();
566 return QCoreApplication::instance()->d_func()->appName();
567}
568
570{
571#ifdef Q_OS_WINDOWS
572 const QString env = qEnvironmentVariable("QT_WIN_DEBUG_CONSOLE");
573 if (env.isEmpty())
574 return;
575 if (env.compare(u"new"_s, Qt::CaseInsensitive) == 0) {
576 if (AllocConsole() == FALSE)
577 return;
578 consoleAllocated = true;
579 } else if (env.compare(u"attach"_s, Qt::CaseInsensitive) == 0) {
580 if (AttachConsole(ATTACH_PARENT_PROCESS) == FALSE)
581 return;
582 } else {
583 // Unknown input, don't make any decision for the user.
584 return;
585 }
586 // The std{in,out,err} handles are read-only, so we need to pass in dummies.
587 FILE *in = nullptr;
588 FILE *out = nullptr;
589 FILE *err = nullptr;
590 freopen_s(&in, "CONIN$", "r", stdin);
591 freopen_s(&out, "CONOUT$", "w", stdout);
592 freopen_s(&err, "CONOUT$", "w", stderr);
593 // However, things wouldn't work if the runtime did not preserve the pointers.
594 Q_ASSERT(in == stdin);
595 Q_ASSERT(out == stdout);
596 Q_ASSERT(err == stderr);
597#endif
598}
599
601{
602#if defined(QT_BOOTSTRAPPED)
603 // Don't try to control bootstrap library locale or encoding.
604#elif defined(Q_OS_UNIX)
605 Q_CONSTINIT static bool qt_locale_initialized = false;
606 if (qt_locale_initialized)
607 return;
608 qt_locale_initialized = true;
609
610 // By default the portable "C"/POSIX locale is selected and active.
611 // Apply the locale from the environment, via setlocale(), which will
612 // read LC_ALL, LC_<category>, and LANG, in order (for each category).
613 setlocale(LC_ALL, "");
614
615 // Next, let's ensure that LC_CTYPE is UTF-8, since QStringConverter's
616 // QLocal8Bit hard-codes this, and we need to be consistent.
617# if defined(Q_OS_INTEGRITY)
618 setlocale(LC_CTYPE, "UTF-8");
619# elif defined(Q_OS_QNX)
620 // QNX has no nl_langinfo, so we can't check.
621 // FIXME: Shouldn't we still setlocale("UTF-8")?
622# elif defined(Q_OS_ANDROID) && __ANDROID_API__ < __ANDROID_API_O__
623 // Android 6 still lacks nl_langinfo(), so we can't check.
624 // FIXME: Shouldn't we still setlocale("UTF-8")?
625# else
626 // std::string's SSO usually saves this the need to allocate:
627 const std::string oldEncoding = nl_langinfo(CODESET);
628 if (!Q_LIKELY(qstricmp(oldEncoding.data(), "UTF-8") == 0
629 || qstricmp(oldEncoding.data(), "utf8") == 0)) {
630 const QByteArray oldLocale = setlocale(LC_ALL, nullptr);
631 QByteArray newLocale;
632 bool warnOnOverride = true;
633# if defined(Q_OS_DARWIN)
634 // Don't warn unless the char encoding has been changed from the
635 // default "C" encoding, or the user touched any of the locale
636 // environment variables to force the "C" char encoding.
637 warnOnOverride = qstrcmp(setlocale(LC_CTYPE, nullptr), "C") != 0
638 || getenv("LC_ALL") || getenv("LC_CTYPE") || getenv("LANG");
639
640 // No need to try language or region specific CTYPEs, as they
641 // all point back to the same generic UTF-8 CTYPE.
642 newLocale = setlocale(LC_CTYPE, "UTF-8");
643# else
644 newLocale = setlocale(LC_CTYPE, nullptr);
645 if (qsizetype dot = newLocale.indexOf('.'); dot != -1)
646 newLocale.truncate(dot); // remove encoding, if any
647 if (qsizetype at = newLocale.indexOf('@'); at != -1)
648 newLocale.truncate(at); // remove variant, as the old de_DE@euro
649 newLocale += ".UTF-8";
650 newLocale = setlocale(LC_CTYPE, newLocale);
651
652 // If that locale doesn't exist, try some fallbacks:
653 if (newLocale.isEmpty())
654 newLocale = setlocale(LC_CTYPE, "C.UTF-8");
655 if (newLocale.isEmpty())
656 newLocale = setlocale(LC_CTYPE, "C.utf8");
657# endif
658
659 if (newLocale.isEmpty()) {
660 // Failed to set a UTF-8 locale.
661 qWarning("Detected locale \"%s\" with character encoding \"%s\", which is not UTF-8.\n"
662 "Qt depends on a UTF-8 locale, but has failed to switch to one.\n"
663 "If this causes problems, reconfigure your locale. See the locale(1) manual\n"
664 "for more information.", oldLocale.constData(), oldEncoding.data());
665 } else if (warnOnOverride) {
666 // Let the user know we over-rode their configuration.
667 qWarning("Detected locale \"%s\" with character encoding \"%s\", which is not UTF-8.\n"
668 "Qt depends on a UTF-8 locale, and has switched to \"%s\" instead.\n"
669 "If this causes problems, reconfigure your locale. See the locale(1) manual\n"
670 "for more information.",
671 oldLocale.constData(), oldEncoding.data(), newLocale.constData());
672 }
673 }
674# endif // Platform choice
675#endif // Unix
676}
677
678
767#ifdef QT_NO_QOBJECT
768 : d_ptr(&p)
769#else
770 : QObject(p, nullptr)
771#endif
772{
773 d_func()->q_ptr = this;
774 // note: it is the subclasses' job to call
775 // QCoreApplicationPrivate::eventDispatcher->startingUp();
776}
777
793#ifndef Q_QDOC
794 , int
795#endif
796 )
797#ifdef QT_NO_QOBJECT
798 : d_ptr(new QCoreApplicationPrivate(argc, argv))
799#else
800 : QObject(*new QCoreApplicationPrivate(argc, argv))
801#endif
802{
803 d_func()->q_ptr = this;
804 d_func()->init();
805#ifndef QT_NO_QOBJECT
807#endif
808}
809
818{
819 Q_TRACE_SCOPE(QCoreApplicationPrivate_init);
820
821#if defined(Q_OS_MACOS)
823#endif
824
825 Q_Q(QCoreApplication);
826
827 initConsole();
828
829 initLocale();
830
831 Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object");
832 QCoreApplication::self = q;
833
834#if QT_CONFIG(thread)
835#ifdef Q_OS_WASM
836 emscripten::val hardwareConcurrency = emscripten::val::global("navigator")["hardwareConcurrency"];
837 if (hardwareConcurrency.isUndefined())
838 QThreadPrivate::idealThreadCount = 2;
839 else
840 QThreadPrivate::idealThreadCount = hardwareConcurrency.as<int>();
841#endif
842#endif
843
844 // Store app name/version (so they're still available after QCoreApplication is destroyed)
845 if (!coreappdata()->applicationNameSet)
846 coreappdata()->application = appName();
847
848 if (!coreappdata()->applicationVersionSet)
849 coreappdata()->applicationVersion = appVersion();
850
851#if defined(Q_OS_ANDROID)
852 // We've deferred initializing the logging registry due to not being
853 // able to guarantee that logging happened on the same thread as the
854 // Qt main thread, but now that the Qt main thread is set up, we can
855 // enable categorized logging.
857#endif
858
859#if QT_CONFIG(library)
860 // Reset the lib paths, so that they will be recomputed, taking the availability of argv[0]
861 // into account. If necessary, recompute right away and replay the manual changes on top of the
862 // new lib paths.
863 QStringList *appPaths = coreappdata()->app_libpaths.release();
864 QStringList *manualPaths = coreappdata()->manual_libpaths.release();
865 if (appPaths) {
866 if (manualPaths) {
867 // Replay the delta. As paths can only be prepended to the front or removed from
868 // anywhere in the list, we can just linearly scan the lists and find the items that
869 // have been removed. Once the original list is exhausted we know all the remaining
870 // items have been added.
871 QStringList newPaths(q->libraryPaths());
872 for (qsizetype i = manualPaths->size(), j = appPaths->size(); i > 0 || j > 0; qt_noop()) {
873 if (--j < 0) {
874 newPaths.prepend((*manualPaths)[--i]);
875 } else if (--i < 0) {
876 newPaths.removeAll((*appPaths)[j]);
877 } else if ((*manualPaths)[i] != (*appPaths)[j]) {
878 newPaths.removeAll((*appPaths)[j]);
879 ++i; // try again with next item.
880 }
881 }
882 delete manualPaths;
883 coreappdata()->manual_libpaths.reset(new QStringList(newPaths));
884 }
885 delete appPaths;
886 }
887#endif
888
889#ifndef QT_NO_QOBJECT
890 // use the event dispatcher created by the app programmer (if any)
892 auto thisThreadData = threadData.loadRelaxed();
893 eventDispatcher = thisThreadData->eventDispatcher.loadRelaxed();
894
895 // otherwise we create one
896 if (!eventDispatcher)
899
900 if (!eventDispatcher->parent()) {
901 eventDispatcher->moveToThread(thisThreadData->thread.loadAcquire());
903 }
904
905 thisThreadData->eventDispatcher = eventDispatcher;
907#endif
908
910
913#ifndef QT_BOOTSTRAPPED
917#endif
918
919#ifndef QT_NO_QOBJECT
920 is_app_running = true; // No longer starting up.
921#endif
922}
923
928{
929 preRoutinesCalled = false;
930
932
933 self = nullptr;
934#ifndef QT_NO_QOBJECT
937#endif
938
939#if QT_CONFIG(thread)
940 // Synchronize and stop the global thread pool threads.
941 QThreadPool *globalThreadPool = nullptr;
942 QThreadPool *guiThreadPool = nullptr;
943 QT_TRY {
944 globalThreadPool = QThreadPool::globalInstance();
945 guiThreadPool = QThreadPoolPrivate::qtGuiInstance();
946 } QT_CATCH (...) {
947 // swallow the exception, since destructors shouldn't throw
948 }
949 if (globalThreadPool) {
950 globalThreadPool->waitForDone();
951 delete globalThreadPool;
952 }
953 if (guiThreadPool) {
954 guiThreadPool->waitForDone();
955 delete guiThreadPool;
956 }
957#endif
958
959#ifndef QT_NO_QOBJECT
960 d_func()->threadData.loadRelaxed()->eventDispatcher = nullptr;
964#endif
965
966#if QT_CONFIG(library)
967 coreappdata()->app_libpaths.reset();
968 coreappdata()->manual_libpaths.reset();
969#endif
970}
971
996{
998}
999
1009{
1011}
1012
1013
1025{
1026 if (on)
1028 else
1030#if defined(QT_NO_QOBJECT)
1031 if (Q_UNLIKELY(qApp)) {
1032#else
1034#endif
1035 switch (attribute) {
1038 case Qt::AA_UseOpenGLES:
1041#ifdef QT_BOOTSTRAPPED
1042 qWarning("Attribute %d must be set before QCoreApplication is created.",
1043 attribute);
1044#else
1045 qWarning("Attribute Qt::%s must be set before QCoreApplication is created.",
1046 QMetaEnum::fromType<Qt::ApplicationAttribute>().valueToKey(attribute));
1047#endif
1048 break;
1049 default:
1050 break;
1051 }
1052 }
1053}
1054
1062{
1064}
1065
1066#ifndef QT_NO_QOBJECT
1067
1080{
1081 return quitLockEnabled;
1082}
1083
1084static bool doNotify(QObject *, QEvent *);
1085
1087{
1089}
1090
1098bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
1099{
1101 if (!self && selfRequired)
1102 return false;
1103
1104 // Make it possible for Qt Script to hook into events even
1105 // though QApplication is subclassed...
1106 bool result = false;
1107 void *cbdata[] = { receiver, event, &result };
1109 return result;
1110 }
1111
1112 // Qt enforces the rule that events can only be sent to objects in
1113 // the current thread, so receiver->d_func()->threadData is
1114 // equivalent to QThreadData::current(), just without the function
1115 // call overhead.
1116 QObjectPrivate *d = receiver->d_func();
1117 QThreadData *threadData = d->threadData.loadAcquire();
1118 QScopedScopeLevelCounter scopeLevelCounter(threadData);
1119 if (!selfRequired)
1120 return doNotify(receiver, event);
1121 return self->notify(receiver, event);
1122}
1123
1131bool QCoreApplication::forwardEvent(QObject *receiver, QEvent *event, QEvent *originatingEvent)
1132{
1133 if (event && originatingEvent)
1134 event->m_spont = originatingEvent->m_spont;
1135
1136 return notifyInternal2(receiver, event);
1137}
1138
1193{
1194 Q_ASSERT(receiver);
1195 Q_ASSERT(event);
1196
1197 // no events are delivered after ~QCoreApplication() has started
1199 return true;
1200 return doNotify(receiver, event);
1201}
1202
1203static bool doNotify(QObject *receiver, QEvent *event)
1204{
1205 Q_ASSERT(event);
1206
1207 // ### Qt 7: turn into an assert
1208 if (receiver == nullptr) { // serious error
1209 qWarning("QCoreApplication::notify: Unexpected null receiver");
1210 return true;
1211 }
1212
1213#ifndef QT_NO_DEBUG
1215#endif
1216
1217 return receiver->isWidgetType() ? false : QCoreApplicationPrivate::notify_helper(receiver, event);
1218}
1219
1221{
1222 // We can't access the application event filters outside of the main thread (race conditions)
1223 Q_ASSERT(receiver->d_func()->threadData.loadAcquire()->thread.loadRelaxed() == mainThread());
1224
1225 if (extraData) {
1226 // application event filters are only called for objects in the GUI thread
1227 for (qsizetype i = 0; i < extraData->eventFilters.size(); ++i) {
1228 QObject *obj = extraData->eventFilters.at(i);
1229 if (!obj)
1230 continue;
1231 if (obj->d_func()->threadData.loadRelaxed() != threadData.loadRelaxed()) {
1232 qWarning("QCoreApplication: Application event filter cannot be in a different thread.");
1233 continue;
1234 }
1235 if (obj->eventFilter(receiver, event))
1236 return true;
1237 }
1238 }
1239 return false;
1240}
1241
1243{
1244 if (receiver != QCoreApplication::instance() && receiver->d_func()->extraData) {
1245 for (qsizetype i = 0; i < receiver->d_func()->extraData->eventFilters.size(); ++i) {
1246 QObject *obj = receiver->d_func()->extraData->eventFilters.at(i);
1247 if (!obj)
1248 continue;
1249 if (obj->d_func()->threadData.loadRelaxed() != receiver->d_func()->threadData.loadRelaxed()) {
1250 qWarning("QCoreApplication: Object event filter cannot be in a different thread.");
1251 continue;
1252 }
1253 if (obj->eventFilter(receiver, event))
1254 return true;
1255 }
1256 }
1257 return false;
1258}
1259
1266{
1267 // Note: when adjusting the tracepoints in here
1268 // consider adjusting QApplicationPrivate::notify_helper too.
1269 Q_TRACE(QCoreApplication_notify_entry, receiver, event, event->type());
1270 bool consumed = false;
1271 bool filtered = false;
1272 Q_TRACE_EXIT(QCoreApplication_notify_exit, consumed, filtered);
1273
1274 // send to all application event filters (only does anything in the main thread)
1275 if (QCoreApplication::self
1276 && receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()
1277 && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
1278 filtered = true;
1279 return filtered;
1280 }
1281 // send to all receiver event filters
1282 if (sendThroughObjectEventFilters(receiver, event)) {
1283 filtered = true;
1284 return filtered;
1285 }
1286
1287 // deliver the event
1288 consumed = receiver->event(event);
1289 return consumed;
1290}
1291
1300{
1302}
1303
1312{
1314}
1315
1316
1345void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
1346{
1348 if (!data->hasEventDispatcher())
1349 return;
1350 data->eventDispatcher.loadRelaxed()->processEvents(flags);
1351}
1352
1365void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int ms)
1366{
1368}
1369
1395{
1396 // ### TODO: consider splitting this method into a public and a private
1397 // one, so that a user-invoked processEvents can be detected
1398 // and handled properly.
1400 if (!data->hasEventDispatcher())
1401 return;
1402
1403 while (data->eventDispatcher.loadRelaxed()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
1404 if (deadline.hasExpired())
1405 break;
1406 }
1407}
1408
1409/*****************************************************************************
1410 Main event loop wrappers
1411 *****************************************************************************/
1412
1440{
1442 return -1;
1443
1444 QThreadData *threadData = self->d_func()->threadData.loadAcquire();
1445 if (threadData != QThreadData::current()) {
1446 qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
1447 return -1;
1448 }
1449 if (!threadData->eventLoops.isEmpty()) {
1450 qWarning("QCoreApplication::exec: The event loop is already running");
1451 return -1;
1452 }
1453
1454 threadData->quitNow = false;
1455 QEventLoop eventLoop;
1456 self->d_func()->in_exec = true;
1457 self->d_func()->aboutToQuitEmitted = false;
1458 int returnCode = eventLoop.exec(QEventLoop::ApplicationExec);
1459 threadData->quitNow = false;
1460
1461 if (self)
1462 self->d_func()->execCleanup();
1463
1464 return returnCode;
1465}
1466
1467
1468// Cleanup after eventLoop is done executing in QCoreApplication::exec().
1469// This is for use cases in which QCoreApplication is instantiated by a
1470// library and not by an application executable, for example, Active X
1471// servers.
1472
1474{
1475 threadData.loadRelaxed()->quitNow = false;
1476 in_exec = false;
1478}
1479
1480
1511void QCoreApplication::exit(int returnCode)
1512{
1513 if (!self)
1514 return;
1515 QCoreApplicationPrivate *d = self->d_func();
1516 if (!d->aboutToQuitEmitted) {
1517 emit self->aboutToQuit(QCoreApplication::QPrivateSignal());
1518 d->aboutToQuitEmitted = true;
1519 }
1520 QThreadData *data = d->threadData.loadRelaxed();
1521 data->quitNow = true;
1522 for (qsizetype i = 0; i < data->eventLoops.size(); ++i) {
1523 QEventLoop *eventLoop = data->eventLoops.at(i);
1524 eventLoop->exit(returnCode);
1525 }
1526}
1527
1528/*****************************************************************************
1529 QCoreApplication management of posted events
1530 *****************************************************************************/
1531
1532#ifndef QT_NO_QOBJECT
1548{
1549 Q_ASSERT_X(receiver, "QCoreApplication::sendEvent", "Unexpected null receiver");
1550 Q_ASSERT_X(event, "QCoreApplication::sendEvent", "Unexpected null event");
1551
1552 Q_TRACE(QCoreApplication_sendEvent, receiver, event, event->type());
1553
1554 event->m_spont = false;
1555 return notifyInternal2(receiver, event);
1556}
1557
1561bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
1562{
1563 Q_ASSERT_X(receiver, "QCoreApplication::sendSpontaneousEvent", "Unexpected null receiver");
1564 Q_ASSERT_X(event, "QCoreApplication::sendSpontaneousEvent", "Unexpected null event");
1565
1566 Q_TRACE(QCoreApplication_sendSpontaneousEvent, receiver, event, event->type());
1567
1568 event->m_spont = true;
1569 return notifyInternal2(receiver, event);
1570}
1571
1572#endif // QT_NO_QOBJECT
1573
1575{
1576 QPostEventListLocker locker;
1577
1578 if (!object) {
1580 locker.locker = qt_unique_lock(locker.threadData->postEventList.mutex);
1581 return locker;
1582 }
1583
1584 auto &threadData = QObjectPrivate::get(object)->threadData;
1585
1586 // if object has moved to another thread, follow it
1587 for (;;) {
1588 // synchronizes with the storeRelease in QObject::moveToThread
1589 locker.threadData = threadData.loadAcquire();
1590 if (!locker.threadData) {
1591 // destruction in progress
1592 return locker;
1593 }
1594
1595 auto temporaryLocker = qt_unique_lock(locker.threadData->postEventList.mutex);
1596 if (locker.threadData == threadData.loadAcquire()) {
1597 locker.locker = std::move(temporaryLocker);
1598 break;
1599 }
1600 }
1601
1602 Q_ASSERT(locker.threadData);
1603 return locker;
1604}
1605
1631void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
1632{
1633 Q_ASSERT_X(event, "QCoreApplication::postEvent", "Unexpected null event");
1634
1635 Q_TRACE_SCOPE(QCoreApplication_postEvent, receiver, event, event->type());
1636
1637 // ### Qt 7: turn into an assert
1638 if (receiver == nullptr) {
1639 qWarning("QCoreApplication::postEvent: Unexpected null receiver");
1640 delete event;
1641 return;
1642 }
1643
1645 if (!locker.threadData) {
1646 // posting during destruction? just delete the event to prevent a leak
1647 delete event;
1648 return;
1649 }
1650
1651 QThreadData *data = locker.threadData;
1652
1653 // if this is one of the compressible events, do compression
1654 if (receiver->d_func()->postedEvents
1655 && self && self->compressEvent(event, receiver, &data->postEventList)) {
1656 Q_TRACE(QCoreApplication_postEvent_event_compressed, receiver, event);
1657 return;
1658 }
1659
1660 if (event->type() == QEvent::DeferredDelete)
1661 receiver->d_ptr->deleteLaterCalled = true;
1662
1663 if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
1664 // remember the current running eventloop for DeferredDelete
1665 // events posted in the receiver's thread.
1666
1667 // Events sent by non-Qt event handlers (such as glib) may not
1668 // have the scopeLevel set correctly. The scope level makes sure that
1669 // code like this:
1670 // foo->deleteLater();
1671 // qApp->processEvents(); // without passing QEvent::DeferredDelete
1672 // will not cause "foo" to be deleted before returning to the event loop.
1673
1674 // If the scope level is 0 while loopLevel != 0, we are called from a
1675 // non-conformant code path, and our best guess is that the scope level
1676 // should be 1. (Loop level 0 is special: it means that no event loops
1677 // are running.)
1678 int loopLevel = data->loopLevel;
1679 int scopeLevel = data->scopeLevel;
1680 if (scopeLevel == 0 && loopLevel != 0)
1681 scopeLevel = 1;
1682
1683 QDeferredDeleteEvent *deleteEvent = static_cast<QDeferredDeleteEvent *>(event);
1684 deleteEvent->m_loopLevel = loopLevel;
1685 deleteEvent->m_scopeLevel = scopeLevel;
1686 }
1687
1688 // delete the event on exceptions to protect against memory leaks till the event is
1689 // properly owned in the postEventList
1690 std::unique_ptr<QEvent> eventDeleter(event);
1691 Q_TRACE(QCoreApplication_postEvent_event_posted, receiver, event, event->type());
1692 data->postEventList.addEvent(QPostEvent(receiver, event, priority));
1693 Q_UNUSED(eventDeleter.release());
1694 event->m_posted = true;
1695 ++receiver->d_func()->postedEvents;
1696 data->canWait = false;
1697 locker.unlock();
1698
1699 QAbstractEventDispatcher* dispatcher = data->eventDispatcher.loadAcquire();
1700 if (dispatcher)
1701 dispatcher->wakeUp();
1702}
1703
1709{
1710 Q_ASSERT(event);
1711 Q_ASSERT(receiver);
1712 Q_ASSERT(postedEvents);
1713
1714#ifdef Q_OS_WIN
1715 // compress posted timers to this object.
1716 if (event->type() == QEvent::Timer && receiver->d_func()->postedEvents > 0) {
1717 int timerId = ((QTimerEvent *) event)->timerId();
1718 for (const QPostEvent &e : std::as_const(*postedEvents)) {
1719 if (e.receiver == receiver && e.event && e.event->type() == QEvent::Timer
1720 && ((QTimerEvent *) e.event)->timerId() == timerId) {
1721 delete event;
1722 return true;
1723 }
1724 }
1725 return false;
1726 }
1727#endif
1728
1729 if (event->type() == QEvent::DeferredDelete) {
1730 if (receiver->d_ptr->deleteLaterCalled) {
1731 // there was a previous DeferredDelete event, so we can drop the new one
1732 delete event;
1733 return true;
1734 }
1735 // deleteLaterCalled is set to true in postedEvents when queueing the very first
1736 // deferred deletion event.
1737 return false;
1738 }
1739
1740 if (event->type() == QEvent::Quit && receiver->d_func()->postedEvents > 0) {
1741 for (const QPostEvent &cur : std::as_const(*postedEvents)) {
1742 if (cur.receiver != receiver
1743 || cur.event == nullptr
1744 || cur.event->type() != event->type())
1745 continue;
1746 // found an event for this receiver
1747 delete event;
1748 return true;
1749 }
1750 }
1751
1752 return false;
1753}
1754
1772void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type)
1773{
1774 // ### TODO: consider splitting this method into a public and a private
1775 // one, so that a user-invoked sendPostedEvents can be detected
1776 // and handled properly.
1778
1779 QCoreApplicationPrivate::sendPostedEvents(receiver, event_type, data);
1780}
1781
1784{
1785 if (event_type == -1) {
1786 // we were called by an obsolete event dispatcher.
1787 event_type = 0;
1788 }
1789
1790 if (receiver && receiver->d_func()->threadData.loadRelaxed() != data) {
1791 qWarning("QCoreApplication::sendPostedEvents: Cannot send "
1792 "posted events for objects in another thread");
1793 return;
1794 }
1795
1796 ++data->postEventList.recursion;
1797
1798 auto locker = qt_unique_lock(data->postEventList.mutex);
1799
1800 // by default, we assume that the event dispatcher can go to sleep after
1801 // processing all events. if any new events are posted while we send
1802 // events, canWait will be set to false.
1803 data->canWait = (data->postEventList.size() == 0);
1804
1805 if (data->postEventList.size() == 0 || (receiver && !receiver->d_func()->postedEvents)) {
1806 --data->postEventList.recursion;
1807 return;
1808 }
1809
1810 data->canWait = true;
1811
1812 // okay. here is the tricky loop. be careful about optimizing
1813 // this, it looks the way it does for good reasons.
1814 qsizetype startOffset = data->postEventList.startOffset;
1815 qsizetype &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset;
1816 data->postEventList.insertionOffset = data->postEventList.size();
1817
1818 // Exception-safe cleaning up without the need for a try/catch block
1819 struct CleanUp {
1820 QObject *receiver;
1821 int event_type;
1823 bool exceptionCaught;
1824
1825 inline CleanUp(QObject *receiver, int event_type, QThreadData *data) :
1826 receiver(receiver), event_type(event_type), data(data), exceptionCaught(true)
1827 {}
1828 inline ~CleanUp()
1829 {
1830 if (exceptionCaught) {
1831 // since we were interrupted, we need another pass to make sure we clean everything up
1832 data->canWait = false;
1833 }
1834
1835 --data->postEventList.recursion;
1836 if (!data->postEventList.recursion && !data->canWait && data->hasEventDispatcher())
1837 data->eventDispatcher.loadRelaxed()->wakeUp();
1838
1839 // clear the global list, i.e. remove everything that was
1840 // delivered.
1841 if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
1842 const QPostEventList::iterator it = data->postEventList.begin();
1843 data->postEventList.erase(it, it + data->postEventList.startOffset);
1844 data->postEventList.insertionOffset -= data->postEventList.startOffset;
1845 Q_ASSERT(data->postEventList.insertionOffset >= 0);
1846 data->postEventList.startOffset = 0;
1847 }
1848 }
1849 };
1850 CleanUp cleanup(receiver, event_type, data);
1851
1852 while (i < data->postEventList.size()) {
1853 // avoid live-lock
1854 if (i >= data->postEventList.insertionOffset)
1855 break;
1856
1857 const QPostEvent &pe = data->postEventList.at(i);
1858 ++i;
1859
1860 if (!pe.event)
1861 continue;
1862 if ((receiver && receiver != pe.receiver) || (event_type && event_type != pe.event->type())) {
1863 data->canWait = false;
1864 continue;
1865 }
1866
1867 if (pe.event->type() == QEvent::DeferredDelete) {
1868 // DeferredDelete events are sent either
1869 // 1) when the event loop that posted the event has returned; or
1870 // 2) if explicitly requested (with QEvent::DeferredDelete) for
1871 // events posted by the current event loop; or
1872 // 3) if the event was posted before the outermost event loop.
1873
1874 const int eventLoopLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->loopLevel();
1875 const int eventScopeLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->scopeLevel();
1876
1877 const bool postedBeforeOutermostLoop = eventLoopLevel == 0;
1878 const bool allowDeferredDelete =
1879 (eventLoopLevel + eventScopeLevel > data->loopLevel + data->scopeLevel
1880 || (postedBeforeOutermostLoop && data->loopLevel > 0)
1881 || (event_type == QEvent::DeferredDelete
1882 && eventLoopLevel + eventScopeLevel == data->loopLevel + data->scopeLevel));
1883 if (!allowDeferredDelete) {
1884 // cannot send deferred delete
1885 if (!event_type && !receiver) {
1886 // we must copy it first; we want to re-post the event
1887 // with the event pointer intact, but we can't delay
1888 // nulling the event ptr until after re-posting, as
1889 // addEvent may invalidate pe.
1890 QPostEvent pe_copy = pe;
1891
1892 // null out the event so if sendPostedEvents recurses, it
1893 // will ignore this one, as it's been re-posted.
1894 const_cast<QPostEvent &>(pe).event = nullptr;
1895
1896 // re-post the copied event so it isn't lost
1897 data->postEventList.addEvent(pe_copy);
1898 }
1899 continue;
1900 }
1901 }
1902
1903 // first, we diddle the event so that we can deliver
1904 // it, and that no one will try to touch it later.
1905 pe.event->m_posted = false;
1906 QEvent *e = pe.event;
1907 QObject * r = pe.receiver;
1908
1909 --r->d_func()->postedEvents;
1910 Q_ASSERT(r->d_func()->postedEvents >= 0);
1911
1912 // next, update the data structure so that we're ready
1913 // for the next event.
1914 const_cast<QPostEvent &>(pe).event = nullptr;
1915
1916 locker.unlock();
1917 const auto relocker = qScopeGuard([&locker] { locker.lock(); });
1918
1919 QScopedPointer<QEvent> event_deleter(e); // will delete the event (with the mutex unlocked)
1920
1921 // after all that work, it's time to deliver the event.
1923
1924 // careful when adding anything below this point - the
1925 // sendEvent() call might invalidate any invariants this
1926 // function depends on.
1927 }
1928
1929 cleanup.exceptionCaught = false;
1930}
1931
1951void QCoreApplication::removePostedEvents(QObject *receiver, int eventType)
1952{
1954 QThreadData *data = locker.threadData;
1955
1956 // the QObject destructor calls this function directly. this can
1957 // happen while the event loop is in the middle of posting events,
1958 // and when we get here, we may not have any more posted events
1959 // for this object.
1960 if (receiver && !receiver->d_func()->postedEvents)
1961 return;
1962
1963 //we will collect all the posted events for the QObject
1964 //and we'll delete after the mutex was unlocked
1966 qsizetype n = data->postEventList.size();
1967 qsizetype j = 0;
1968
1969 for (qsizetype i = 0; i < n; ++i) {
1970 const QPostEvent &pe = data->postEventList.at(i);
1971
1972 if ((!receiver || pe.receiver == receiver)
1973 && (pe.event && (eventType == 0 || pe.event->type() == eventType))) {
1974 --pe.receiver->d_func()->postedEvents;
1975 pe.event->m_posted = false;
1976 events.append(pe.event);
1977 const_cast<QPostEvent &>(pe).event = nullptr;
1978 } else if (!data->postEventList.recursion) {
1979 if (i != j)
1980 qSwap(data->postEventList[i], data->postEventList[j]);
1981 ++j;
1982 }
1983 }
1984
1985#ifdef QT_DEBUG
1986 if (receiver && eventType == 0) {
1987 Q_ASSERT(!receiver->d_func()->postedEvents);
1988 }
1989#endif
1990
1991 if (!data->postEventList.recursion) {
1992 // truncate list
1993 data->postEventList.erase(data->postEventList.begin() + j, data->postEventList.end());
1994 }
1995
1996 locker.unlock();
1997 qDeleteAll(events);
1998}
1999
2011{
2012 if (!event || !event->m_posted)
2013 return;
2014
2016
2017 const auto locker = qt_scoped_lock(data->postEventList.mutex);
2018
2019 if (data->postEventList.size() == 0) {
2020#if defined(QT_DEBUG)
2021 qDebug("QCoreApplication::removePostedEvent: Internal error: %p %d is posted",
2022 (void*)event, event->type());
2023 return;
2024#endif
2025 }
2026
2027 for (const QPostEvent &pe : std::as_const(data->postEventList)) {
2028 if (pe.event == event) {
2029#ifndef QT_NO_DEBUG
2030 qWarning("QCoreApplication::removePostedEvent: Event of type %d deleted while posted to %s %s",
2031 event->type(),
2032 pe.receiver->metaObject()->className(),
2033 pe.receiver->objectName().toLocal8Bit().data());
2034#endif
2035 --pe.receiver->d_func()->postedEvents;
2036 pe.event->m_posted = false;
2037 delete pe.event;
2038 const_cast<QPostEvent &>(pe).event = nullptr;
2039 return;
2040 }
2041 }
2042}
2043
2048{
2049 if (e->type() == QEvent::Quit) {
2050 exit(0);
2051 return true;
2052 }
2053 return QObject::event(e);
2054}
2055
2057{
2058 quitLockRef.ref();
2059}
2060
2062{
2063 quitLockRef.deref();
2064
2065 if (quitLockEnabled && canQuitAutomatically())
2066 quitAutomatically();
2067}
2068
2070{
2071 if (!in_exec)
2072 return false;
2073
2074 if (quitLockEnabled && quitLockRef.loadRelaxed())
2075 return false;
2076
2077 return true;
2078}
2079
2081{
2082 Q_Q(QCoreApplication);
2083
2084 // Explicit requests by the user to quit() is plumbed via the platform
2085 // if possible, and delivers the quit event synchronously. For automatic
2086 // quits we implicitly support cancelling the quit by showing another
2087 // window, which currently relies on removing any posted quit events
2088 // from the event queue. As a result, we can't use the normal quit()
2089 // code path, and need to post manually.
2091}
2092
2128{
2129 if (!self)
2130 return;
2131
2132 if (!self->d_func()->in_exec)
2133 return;
2134
2135 self->d_func()->quit();
2136}
2137
2139{
2140 Q_Q(QCoreApplication);
2141
2142 if (QThread::currentThread() == mainThread()) {
2143 QEvent quitEvent(QEvent::Quit);
2144 QCoreApplication::sendEvent(q, &quitEvent);
2145 } else {
2147 }
2148}
2149
2165#endif // QT_NO_QOBJECT
2166
2167#ifndef QT_NO_TRANSLATION
2197{
2198 if (!translationFile)
2199 return false;
2200
2201 if (!QCoreApplicationPrivate::checkInstance("installTranslator"))
2202 return false;
2203 QCoreApplicationPrivate *d = self->d_func();
2204 {
2205 QWriteLocker locker(&d->translateMutex);
2206 d->translators.prepend(translationFile);
2207 }
2208
2209#ifndef QT_NO_TRANSLATION_BUILDER
2210 if (translationFile->isEmpty())
2211 return false;
2212#endif
2213
2214#ifndef QT_NO_QOBJECT
2216 QCoreApplication::sendEvent(self, &ev);
2217#endif
2218
2219 return true;
2220}
2221
2233{
2234 if (!translationFile)
2235 return false;
2236 if (!QCoreApplicationPrivate::checkInstance("removeTranslator"))
2237 return false;
2238 QCoreApplicationPrivate *d = self->d_func();
2239 QWriteLocker locker(&d->translateMutex);
2240 if (d->translators.removeAll(translationFile)) {
2241#ifndef QT_NO_QOBJECT
2242 locker.unlock();
2243 if (!self->closingDown()) {
2245 QCoreApplication::sendEvent(self, &ev);
2246 }
2247#endif
2248 return true;
2249 }
2250 return false;
2251}
2252
2254{
2255 if (n >= 0) {
2256 qsizetype percentPos = 0;
2257 qsizetype len = 0;
2258 while ((percentPos = result->indexOf(u'%', percentPos + len)) != -1) {
2259 len = 1;
2260 if (percentPos + len == result->size())
2261 break;
2262 QString fmt;
2263 if (result->at(percentPos + len) == u'L') {
2264 ++len;
2265 if (percentPos + len == result->size())
2266 break;
2267 fmt = "%L1"_L1;
2268 } else {
2269 fmt = "%1"_L1;
2270 }
2271 if (result->at(percentPos + len) == u'n') {
2272 fmt = fmt.arg(n);
2273 ++len;
2274 result->replace(percentPos, len, fmt);
2275 len = fmt.size();
2276 }
2277 }
2278 }
2279}
2280
2314QString QCoreApplication::translate(const char *context, const char *sourceText,
2315 const char *disambiguation, int n)
2316{
2318
2319 if (!sourceText)
2320 return result;
2321
2322 if (self) {
2323 QCoreApplicationPrivate *d = self->d_func();
2324 QReadLocker locker(&d->translateMutex);
2325 if (!d->translators.isEmpty()) {
2327 QTranslator *translationFile;
2328 for (it = d->translators.constBegin(); it != d->translators.constEnd(); ++it) {
2329 translationFile = *it;
2330 result = translationFile->translate(context, sourceText, disambiguation, n);
2331 if (!result.isNull())
2332 break;
2333 }
2334 }
2335 }
2336
2337 if (result.isNull())
2338 result = QString::fromUtf8(sourceText);
2339
2341 return result;
2342}
2343
2344// Declared in qglobal.h
2345QString qtTrId(const char *id, int n)
2346{
2347 return QCoreApplication::translate(nullptr, id, nullptr, n);
2348}
2349
2351{
2352 if (!QCoreApplication::self)
2353 return false;
2354 QCoreApplicationPrivate *d = QCoreApplication::self->d_func();
2355 QReadLocker locker(&d->translateMutex);
2356 return d->translators.contains(translator);
2357}
2358
2359#else
2360
2361QString QCoreApplication::translate(const char *context, const char *sourceText,
2362 const char *disambiguation, int n)
2363{
2365 Q_UNUSED(disambiguation);
2366 QString ret = QString::fromUtf8(sourceText);
2367 if (n >= 0)
2368 ret.replace("%n"_L1, QString::number(n));
2369 return ret;
2370}
2371
2372#endif //QT_NO_TRANSLATION
2373
2374// Makes it possible to point QCoreApplication to a custom location to ensure
2375// the directory is added to the patch, and qt.conf and deployed plugins are
2376// found from there. This is for use cases in which QGuiApplication is
2377// instantiated by a library and not by an application executable, for example,
2378// Active X servers.
2379
2381{
2384 else
2386}
2387
2408{
2409 if (!self) {
2410 qWarning("QCoreApplication::applicationDirPath: Please instantiate the QApplication object first");
2411 return QString();
2412 }
2413
2414 QCoreApplicationPrivate *d = self->d_func();
2415 if (d->cachedApplicationDirPath.isNull())
2416 d->cachedApplicationDirPath = QFileInfo(applicationFilePath()).path();
2417 return d->cachedApplicationDirPath;
2418}
2419
2420#if !defined(Q_OS_WIN) && !defined(Q_OS_DARWIN) // qcoreapplication_win.cpp or qcoreapplication_mac.cpp
2422{
2423# if defined(Q_OS_ANDROID)
2424 // the actual process on Android is the Java VM, so this doesn't help us
2425 return QString();
2426# elif defined(Q_OS_LINUX)
2427 // this includes the Embedded Android builds
2428 return QFile::decodeName(qt_readlink("/proc/self/exe"));
2429# elif defined(AT_EXECPATH)
2430 // seen on FreeBSD, but I suppose the other BSDs could adopt this API
2431 char execfn[PATH_MAX];
2432 if (elf_aux_info(AT_EXECPATH, execfn, sizeof(execfn)) != 0)
2433 execfn[0] = '\0';
2434
2435 qsizetype len = qstrlen(execfn);
2437# else
2438 // other OS or something
2439 return QString();
2440#endif
2441}
2442#endif
2443
2460{
2461 if (!self) {
2462 qWarning("QCoreApplication::applicationFilePath: Please instantiate the QApplication object first");
2463 return QString();
2464 }
2465
2466 QCoreApplicationPrivate *d = self->d_func();
2467
2468 if (d->argc) {
2469 static QByteArray procName = QByteArray(d->argv[0]);
2470 if (procName != d->argv[0]) {
2471 // clear the cache if the procname changes, so we reprocess it.
2473 procName = QByteArray(d->argv[0]);
2474 }
2475 }
2476
2479
2480 QString absPath = qAppFileName();
2481 if (absPath.isEmpty() && !arguments().isEmpty()) {
2483
2484 if (!argv0.isEmpty() && argv0.at(0) == u'/') {
2485 /*
2486 If argv0 starts with a slash, it is already an absolute
2487 file path.
2488 */
2489 absPath = argv0;
2490 } else if (argv0.contains(u'/')) {
2491 /*
2492 If argv0 contains one or more slashes, it is a file path
2493 relative to the current directory.
2494 */
2495 absPath = QDir::current().absoluteFilePath(argv0);
2496 } else {
2497 /*
2498 Otherwise, the file path has to be determined using the
2499 PATH environment variable.
2500 */
2501 absPath = QStandardPaths::findExecutable(argv0);
2502 }
2503 }
2504
2505 absPath = QFileInfo(absPath).canonicalFilePath();
2506 if (!absPath.isEmpty()) {
2509 }
2510 return QString();
2511}
2512
2519{
2520#if defined(Q_OS_WIN)
2521 return GetCurrentProcessId();
2522#elif defined(Q_OS_VXWORKS)
2523 return (pid_t) taskIdCurrent;
2524#else
2525 return getpid();
2526#endif
2527}
2528
2561{
2563
2564 if (!self) {
2565 qWarning("QCoreApplication::arguments: Please instantiate the QApplication object first");
2566 return list;
2567 }
2568
2569 const QCoreApplicationPrivate *d = self->d_func();
2570
2571 const int argc = d->argc;
2572 char ** const argv = d->argv;
2573 list.reserve(argc);
2574
2575#if defined(Q_OS_WIN)
2576 const bool argsModifiedByUser = d->origArgv == nullptr;
2577 if (!argsModifiedByUser) {
2578 // On Windows, it is possible to pass Unicode arguments on
2579 // the command line, but we don't implement any of the wide
2580 // entry-points (wmain/wWinMain), so get the arguments from
2581 // the Windows API instead of using argv. Note that we only
2582 // do this when argv were not modified by the user in main().
2583 QString cmdline = QString::fromWCharArray(GetCommandLine());
2584 QStringList commandLineArguments = qWinCmdArgs(cmdline);
2585
2586 // Even if the user didn't modify argv before passing them
2587 // on to QCoreApplication, derived QApplications might have.
2588 // If that's the case argc will differ from origArgc.
2589 if (argc != d->origArgc) {
2590 // Note: On MingGW the arguments from GetCommandLine are
2591 // not wildcard expanded (if wildcard expansion is enabled),
2592 // as opposed to the arguments in argv. This means we can't
2593 // compare commandLineArguments to argv/origArgc, but
2594 // must remove elements by value, based on whether they
2595 // were filtered out from argc.
2596 for (int i = 0; i < d->origArgc; ++i) {
2597 if (!contains(argc, argv, d->origArgv[i]))
2598 commandLineArguments.removeAll(QString::fromLocal8Bit(d->origArgv[i]));
2599 }
2600 }
2601
2602 return commandLineArguments;
2603 } // Fall back to rebuilding from argv/argc when a modified argv was passed.
2604#endif // defined(Q_OS_WIN)
2605
2606 for (int a = 0; a < argc; ++a)
2607 list << QString::fromLocal8Bit(argv[a]);
2608
2609 return list;
2610}
2611
2637{
2638 if (coreappdata()->orgName == orgName)
2639 return;
2640 coreappdata()->orgName = orgName;
2641#ifndef QT_NO_QOBJECT
2642 if (QCoreApplication::self)
2643 emit QCoreApplication::self->organizationNameChanged();
2644#endif
2645}
2646
2648{
2649 return coreappdata()->orgName;
2650}
2651
2674{
2675 if (coreappdata()->orgDomain == orgDomain)
2676 return;
2677 coreappdata()->orgDomain = orgDomain;
2678#ifndef QT_NO_QOBJECT
2679 if (QCoreApplication::self)
2680 emit QCoreApplication::self->organizationDomainChanged();
2681#endif
2682}
2683
2685{
2686 return coreappdata()->orgDomain;
2687}
2688
2712{
2713 coreappdata()->applicationNameSet = !application.isEmpty();
2714 QString newAppName = application;
2715 if (newAppName.isEmpty() && QCoreApplication::self)
2716 newAppName = QCoreApplication::self->d_func()->appName();
2717 if (coreappdata()->application == newAppName)
2718 return;
2719 coreappdata()->application = newAppName;
2720#ifndef QT_NO_QOBJECT
2721 if (QCoreApplication::self)
2722 emit QCoreApplication::self->applicationNameChanged();
2723#endif
2724}
2725
2727{
2728 return coreappdata() ? coreappdata()->application : QString();
2729}
2730
2765{
2766 coreappdata()->applicationVersionSet = !version.isEmpty();
2767 QString newVersion = version;
2768 if (newVersion.isEmpty() && QCoreApplication::self)
2769 newVersion = QCoreApplication::self->d_func()->appVersion();
2770 if (coreappdata()->applicationVersion == newVersion)
2771 return;
2772 coreappdata()->applicationVersion = newVersion;
2773#ifndef QT_NO_QOBJECT
2774 if (QCoreApplication::self)
2775 emit QCoreApplication::self->applicationVersionChanged();
2776#endif
2777}
2778
2780{
2781 return coreappdata() ? coreappdata()->applicationVersion : QString();
2782}
2783
2784#if QT_CONFIG(permissions) || defined(Q_QDOC)
2785
2795Qt::PermissionStatus QCoreApplication::checkPermission(const QPermission &permission)
2796{
2797 return QPermissions::Private::checkPermission(permission);
2798}
2799
2874void QCoreApplication::requestPermission(const QPermission &requestedPermission,
2876{
2878 qWarning(lcPermissions, "Permissions can only be requested from the GUI (main) thread");
2879 return;
2880 }
2881
2882 Q_ASSERT(slotObj);
2883
2884 // Used as the signalID in the metacall event and only used to
2885 // verify that we are not processing an unrelated event, not to
2886 // emit the right signal. So using a value that can never clash
2887 // with any signal index. Clang doesn't like this to be a static
2888 // member of the PermissionReceiver.
2889 static constexpr ushort PermissionReceivedID = 0xffff;
2890
2891 // If we have a context object, then we dispatch the permission response
2892 // asynchronously through a received object that lives in the same thread
2893 // as the context object. Otherwise we call the functor synchronously when
2894 // we get a response (which might still be asynchronous for the caller).
2895 class PermissionReceiver : public QObject
2896 {
2897 public:
2898 PermissionReceiver(QtPrivate::QSlotObjectBase *slotObject, const QObject *context)
2899 : slotObject(slotObject), context(context)
2900 {}
2901
2902 protected:
2903 bool event(QEvent *event) override {
2904 if (event->type() == QEvent::MetaCall) {
2905 auto metaCallEvent = static_cast<QMetaCallEvent *>(event);
2906 if (metaCallEvent->id() == PermissionReceivedID) {
2907 Q_ASSERT(slotObject);
2908 // only execute if context object is still alive
2909 if (context)
2910 slotObject->call(const_cast<QObject*>(context.data()), metaCallEvent->args());
2911 slotObject->destroyIfLastRef();
2912 deleteLater();
2913
2914 return true;
2915 }
2916 }
2917 return QObject::event(event);
2918 }
2919 private:
2920 QtPrivate::QSlotObjectBase *slotObject;
2922 };
2923 PermissionReceiver *receiver = nullptr;
2924 if (context) {
2925 receiver = new PermissionReceiver(slotObj, context);
2926 receiver->moveToThread(context->thread());
2927 }
2928
2929 QPermissions::Private::requestPermission(requestedPermission, [=](Qt::PermissionStatus status) {
2930 Q_ASSERT_X(status != Qt::PermissionStatus::Undetermined, "QPermission",
2931 "QCoreApplication::requestPermission() should never return Undetermined");
2934
2935 if (QCoreApplication::self) {
2936 QPermission permission = requestedPermission;
2937 permission.m_status = status;
2938
2939 if (receiver) {
2940 auto metaCallEvent = QMetaCallEvent::create(slotObj, qApp,
2941 PermissionReceivedID, permission);
2942 qApp->postEvent(receiver, metaCallEvent);
2943 } else {
2944 void *argv[] = { nullptr, &permission };
2945 slotObj->call(const_cast<QObject*>(context), argv);
2946 }
2947 }
2948
2949 if (!receiver)
2950 slotObj->destroyIfLastRef();
2951 });
2952}
2953
2954#endif // QT_CONFIG(permissions)
2955
2956#if QT_CONFIG(library)
2957
2958Q_GLOBAL_STATIC(QRecursiveMutex, libraryPathMutex)
2959
2960
2994QStringList QCoreApplication::libraryPaths()
2995{
2996 QMutexLocker locker(libraryPathMutex());
2997 return libraryPathsLocked();
2998}
2999
3003QStringList QCoreApplication::libraryPathsLocked()
3004{
3005 if (coreappdata()->manual_libpaths)
3006 return *(coreappdata()->manual_libpaths);
3007
3008 if (!coreappdata()->app_libpaths) {
3009 QStringList *app_libpaths = new QStringList;
3010 coreappdata()->app_libpaths.reset(app_libpaths);
3011
3012 auto setPathsFromEnv = [&](QString libPathEnv) {
3013 if (!libPathEnv.isEmpty()) {
3015 for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) {
3017 if (!canonicalPath.isEmpty()
3018 && !app_libpaths->contains(canonicalPath)) {
3019 app_libpaths->append(canonicalPath);
3020 }
3021 }
3022 }
3023 };
3024 setPathsFromEnv(qEnvironmentVariable("QT_PLUGIN_PATH"));
3025#ifdef Q_OS_DARWIN
3026 // Check the main bundle's PlugIns directory as this is a standard location for Apple OSes.
3027 // Note that the QLibraryInfo::PluginsPath below will coincidentally be the same as this value
3028 // but with a different casing, so it can't be relied upon when the underlying filesystem
3029 // is case sensitive (and this is always the case on newer OSes like iOS).
3030 if (CFBundleRef bundleRef = CFBundleGetMainBundle()) {
3031 if (QCFType<CFURLRef> urlRef = CFBundleCopyBuiltInPlugInsURL(bundleRef)) {
3032 if (QCFType<CFURLRef> absoluteUrlRef = CFURLCopyAbsoluteURL(urlRef)) {
3033 if (QCFString path = CFURLCopyFileSystemPath(absoluteUrlRef, kCFURLPOSIXPathStyle)) {
3034 if (QFile::exists(path)) {
3036 if (!app_libpaths->contains(path))
3037 app_libpaths->append(path);
3038 }
3039 }
3040 }
3041 }
3042 }
3043#endif // Q_OS_DARWIN
3044
3046 if (QFile::exists(installPathPlugins)) {
3047 // Make sure we convert from backslashes to slashes.
3048 installPathPlugins = QDir(installPathPlugins).canonicalPath();
3049 if (!app_libpaths->contains(installPathPlugins))
3050 app_libpaths->append(installPathPlugins);
3051 }
3052
3053 // If QCoreApplication is not yet instantiated,
3054 // make sure we add the application path when we construct the QCoreApplication
3055 if (self) self->d_func()->appendApplicationPathToLibraryPaths();
3056 }
3057 return *(coreappdata()->app_libpaths);
3058}
3059
3060
3061
3074void QCoreApplication::setLibraryPaths(const QStringList &paths)
3075{
3076 QMutexLocker locker(libraryPathMutex());
3077
3078 // setLibraryPaths() is considered a "remove everything and then add some new ones" operation.
3079 // When the application is constructed it should still amend the paths. So we keep the originals
3080 // around, and even create them if they don't exist, yet.
3081 if (!coreappdata()->app_libpaths)
3082 libraryPathsLocked();
3083
3084 if (coreappdata()->manual_libpaths)
3085 *(coreappdata()->manual_libpaths) = paths;
3086 else
3087 coreappdata()->manual_libpaths.reset(new QStringList(paths));
3088
3089 locker.unlock();
3090 QFactoryLoader::refreshAll();
3091}
3092
3109void QCoreApplication::addLibraryPath(const QString &path)
3110{
3111 if (path.isEmpty())
3112 return;
3113
3115 if (canonicalPath.isEmpty())
3116 return;
3117
3118 QMutexLocker locker(libraryPathMutex());
3119
3120 QStringList *libpaths = coreappdata()->manual_libpaths.get();
3121 if (libpaths) {
3122 if (libpaths->contains(canonicalPath))
3123 return;
3124 } else {
3125 // make sure that library paths are initialized
3126 libraryPathsLocked();
3127 QStringList *app_libpaths = coreappdata()->app_libpaths.get();
3128 if (app_libpaths->contains(canonicalPath))
3129 return;
3130
3131 coreappdata()->manual_libpaths.reset(libpaths = new QStringList(*app_libpaths));
3132 }
3133
3134 libpaths->prepend(canonicalPath);
3135 locker.unlock();
3136 QFactoryLoader::refreshAll();
3137}
3138
3148void QCoreApplication::removeLibraryPath(const QString &path)
3149{
3150 if (path.isEmpty())
3151 return;
3152
3154 if (canonicalPath.isEmpty())
3155 return;
3156
3157 QMutexLocker locker(libraryPathMutex());
3158
3159 QStringList *libpaths = coreappdata()->manual_libpaths.get();
3160 if (libpaths) {
3161 if (libpaths->removeAll(canonicalPath) == 0)
3162 return;
3163 } else {
3164 // make sure that library paths is initialized
3165 libraryPathsLocked();
3166 QStringList *app_libpaths = coreappdata()->app_libpaths.get();
3167 if (!app_libpaths->contains(canonicalPath))
3168 return;
3169
3170 coreappdata()->manual_libpaths.reset(libpaths = new QStringList(*app_libpaths));
3171 libpaths->removeAll(canonicalPath);
3172 }
3173
3174 locker.unlock();
3175 QFactoryLoader::refreshAll();
3176}
3177
3178#endif // QT_CONFIG(library)
3179
3180#ifndef QT_NO_QOBJECT
3181
3212{
3214 qWarning("Native event filters are not applied when the Qt::AA_PluginApplication attribute is set");
3215 return;
3216 }
3217
3219 if (!filterObj || !eventDispatcher)
3220 return;
3222}
3223
3238{
3240 if (!filterObject || !eventDispatcher)
3241 return;
3243}
3244
3250{
3253 return nullptr;
3254}
3255
3263{
3265 if (!mainThread)
3266 mainThread = QThread::currentThread(); // will also setup theMainThread
3268}
3269
3270#endif // QT_NO_QOBJECT
3271
3381void *QCoreApplication::resolveInterface(const char *name, int revision) const
3382{
3383 Q_UNUSED(name); Q_UNUSED(revision);
3384 return nullptr;
3385}
3386
3388
3389#ifndef QT_NO_QOBJECT
3390#include "moc_qcoreapplication.cpp"
3391#endif
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
Returns a pointer to the event dispatcher object for the specified thread.
virtual void wakeUp()=0
\threadsafe
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
\variable QAbstractEventDispatcher::TimerInfo::timerId
void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj)
Removes the event filter filter from this object.
Type loadAcquire() const noexcept
Type loadRelaxed() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:534
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
qsizetype indexOf(char c, qsizetype from=0) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
void truncate(qsizetype pos)
Truncates the byte array at index position pos.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:106
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:394
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 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.
void organizationDomainChanged()
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)
void applicationNameChanged()
static bool isQuitLockEnabled()
void organizationNameChanged()
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)
void aboutToQuit(QPrivateSignal)
This signal is emitted when the application is about to quit the main event loop, e....
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
void applicationVersionChanged()
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:19
static QDir current()
Returns the application's current directory.
Definition qdir.h:216
QString canonicalPath() const
Returns the canonical path, i.e.
Definition qdir.cpp:692
QString absoluteFilePath(const QString &fileName) const
Returns the absolute path name of a file in the directory.
Definition qdir.cpp:809
static constexpr QChar listSeparator() noexcept
Definition qdir.h:197
\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
@ MetaCall
Definition qcoreevent.h:97
@ DeferredDelete
Definition qcoreevent.h:100
@ LanguageChange
Definition qcoreevent.h:123
Type type() const
Returns the event type.
Definition qcoreevent.h:299
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString canonicalFilePath() const
Returns the canonical path including the file name, i.e.
QString path() const
Returns the file's path.
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:198
@ EventNotifyCallback
\inmodule QtCore
static QString path(LibraryPath p)
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
qsizetype removeAll(const AT &t)
Definition qlist.h:575
void prepend(rvalue_ref t)
Definition qlist.h:456
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
static QLoggingRegistry * instance()
static QMetaCallEvent * create(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, int signal_index, const Args &...argv)
Definition qobject_p.h:391
\inmodule QtCore
Definition qmutex.h:317
\inmodule QtCore
Definition qmutex.h:285
uint deleteLaterCalled
Definition qobject.h:71
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:153
QAtomicPointer< QThreadData > threadData
Definition qobject_p.h:202
\inmodule QtCore
Definition qobject.h:90
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
void moveToThread(QThread *thread)
Changes the thread affinity for this object and its children.
Definition qobject.cpp:1606
QString objectName
the name of this object
Definition qobject.h:94
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:1363
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2142
friend class QCoreApplication
Definition qobject.h:345
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1561
QScopedPointer< QObjectData > d_ptr
Definition qobject.h:338
bool isWidgetType() const
Returns true if the object is a widget; otherwise returns false.
Definition qobject.h:118
\inmodule QtCore \inheaderfile QPermissions
\inmodule QtCore
Definition qpointer.h:18
qsizetype startOffset
Definition qthread_p.h:69
QObject * receiver
Definition qthread_p.h:42
QEvent * event
Definition qthread_p.h:43
\inmodule QtCore
\inmodule QtCore
Definition qmutex.h:313
\inmodule QtCore
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:127
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:279
void truncate(qsizetype pos)
Truncates the string at the given position index.
Definition qstring.cpp:6159
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5788
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1079
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6498
QByteArray toLocal8Bit() const &
Definition qstring.h:567
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.h:1217
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1164
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:7822
static QString static QString asprintf(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
Definition qstring.cpp:7005
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
Definition qthread.cpp:1005
QStack< QEventLoop * > eventLoops
Definition qthread_p.h:320
static QThreadData * get2(QThread *thread)
Definition qthread_p.h:290
QPostEventList postEventList
Definition qthread_p.h:321
static QThreadPool * qtGuiInstance()
Returns the QThreadPool instance for Qt Gui.
\inmodule QtCore
Definition qthreadpool.h:20
static QThreadPool * globalInstance()
Returns the global QThreadPool instance.
bool waitForDone(int msecs=-1)
Waits up to msecs milliseconds for all threads to exit and removes all threads from the thread pool.
QAbstractEventDispatcher * eventDispatcher() const
Definition qthread.cpp:1064
static QThread * currentThread()
Definition qthread.cpp:966
void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
Definition qthread.cpp:1082
\inmodule QtCore
Definition qcoreevent.h:359
\inmodule QtCore
Definition qtranslator.h:19
virtual bool isEmpty() const
Returns true if this translator is empty, otherwise returns false.
virtual QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
Returns the translation for the key (context, sourceText, disambiguation).
constexpr size_type size() const noexcept
void append(const T &t)
\inmodule QtCore
void call(QObject *r, void **a)
qSwap(pi, e)
qDeleteAll(list.begin(), list.end())
double e
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()
PermissionStatus
ApplicationAttribute
Definition qnamespace.h:423
@ AA_UseSoftwareOpenGL
Definition qnamespace.h:445
@ AA_UseDesktopOpenGL
Definition qnamespace.h:443
@ AA_SynthesizeMouseForUnhandledTabletEvents
Definition qnamespace.h:458
@ AA_ShareOpenGLContexts
Definition qnamespace.h:446
@ AA_PluginApplication
Definition qnamespace.h:429
@ AA_UseOpenGLES
Definition qnamespace.h:444
@ AA_SynthesizeMouseForUnhandledTouchEvents
Definition qnamespace.h:436
@ CaseInsensitive
@ SkipEmptyParts
Definition qnamespace.h:127
static void * context
#define Q_BASIC_ATOMIC_INITIALIZER(a)
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
QT_BEGIN_NAMESPACE QByteArray qt_readlink(const char *path)
void qAddPreRoutine(QtStartUpFunction p)
void Q_DECL_EXPORT_OVERRIDABLE qt_startup_hook()
static Q_CONSTINIT bool preRoutinesCalled
QString qAppName()
static Q_CONSTINIT bool quitLockEnabled
static QString qAppFileName()
void qAddPostRoutine(QtCleanUpFunction p)
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
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
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:160
#define qWarning
Definition qlogging.h:162
#define qFatal
Definition qlogging.h:164
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]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLfloat GLfloat f
GLenum type
GLsizei const GLuint * paths
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
GLfloat n
struct _cl_event * event
GLhandleARB obj
[2]
GLenum GLsizei len
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]
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:1403
static char * toLocal8Bit(char *out, QStringView in, QStringConverter::State *state)
#define QStringLiteral(str)
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:70
unsigned int uint
Definition qtypes.h:29
long long qint64
Definition qtypes.h:55
unsigned short ushort
Definition qtypes.h:28
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
QAction * at