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