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

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