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