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

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