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

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