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