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