diff options
Diffstat (limited to 'src/corelib/kernel/qcoreapplication.cpp')
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 207 |
1 files changed, 80 insertions, 127 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 48d70f2747..79a3254a39 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1,32 +1,38 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2015 Intel Corporation. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Intel Corporation. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -66,19 +72,14 @@ #ifndef QT_NO_QOBJECT #if defined(Q_OS_UNIX) -# if defined(Q_OS_BLACKBERRY) -# include "qeventdispatcher_blackberry_p.h" -# include <process.h> -# include <unistd.h> -# elif defined(Q_OS_OSX) -# include "qeventdispatcher_cf_p.h" -# include "qeventdispatcher_unix_p.h" -# else -# if !defined(QT_NO_GLIB) -# include "qeventdispatcher_glib_p.h" -# endif -# include "qeventdispatcher_unix_p.h" +# if defined(Q_OS_OSX) +# include "qeventdispatcher_cf_p.h" +# else +# if !defined(QT_NO_GLIB) +# include "qeventdispatcher_glib_p.h" # endif +# endif +# include "qeventdispatcher_unix_p.h" #endif #ifdef Q_OS_WIN # ifdef Q_OS_WINRT @@ -340,34 +341,6 @@ struct QCoreApplicationData { #endif } -#ifdef Q_OS_BLACKBERRY - //The QCoreApplicationData struct is only populated on demand, because it is rarely needed and would - //affect startup time - void loadManifest() { - static bool manifestLoadAttempt = false; - if (manifestLoadAttempt) - return; - - manifestLoadAttempt = true; - - QFile metafile(QStringLiteral("app/META-INF/MANIFEST.MF")); - if (!metafile.open(QIODevice::ReadOnly)) { - qWarning("Could not open application metafile for reading") - } else { - while (!metafile.atEnd() && (application.isEmpty() || applicationVersion.isEmpty() || orgName.isEmpty())) { - QByteArray line = metafile.readLine(); - if (line.startsWith("Application-Name:")) - application = QString::fromUtf8(line.mid(18).trimmed()); - else if (line.startsWith("Application-Version:")) - applicationVersion = QString::fromUtf8(line.mid(21).trimmed()); - else if (line.startsWith("Package-Author:")) - orgName = QString::fromUtf8(line.mid(16).trimmed()); - } - metafile.close(); - } - } -#endif - QString orgName, orgDomain; QString application; // application name, initially from argv[0], can then be modified. QString applicationVersion; @@ -452,7 +425,7 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint QCoreApplicationPrivate::is_app_closing = false; # if defined(Q_OS_UNIX) - if (!setuidAllowed && (geteuid() != getuid())) + if (Q_UNLIKELY(!setuidAllowed && (geteuid() != getuid()))) qFatal("FATAL: The application binary appears to be running setuid, this is a security hole."); # endif // Q_OS_UNIX @@ -508,9 +481,7 @@ void QCoreApplicationPrivate::createEventDispatcher() { Q_Q(QCoreApplication); #if defined(Q_OS_UNIX) -# if defined(Q_OS_BLACKBERRY) - eventDispatcher = new QEventDispatcherBlackberry(q); -# elif defined(Q_OS_OSX) +# if defined(Q_OS_OSX) bool ok = false; int value = qEnvironmentVariableIntValue("QT_EVENT_DISPATCHER_CORE_FOUNDATION", &ok); if (ok && value > 0) @@ -602,7 +573,7 @@ void QCoreApplicationPrivate::initLocale() if (qt_locale_initialized) return; qt_locale_initialized = true; -#ifdef Q_OS_UNIX +#if defined(Q_OS_UNIX) && !defined(QT_BOOTSTRAPPED) setlocale(LC_ALL, ""); #endif } @@ -617,7 +588,8 @@ void QCoreApplicationPrivate::initLocale() This class is used by non-GUI applications to provide their event loop. For non-GUI application that uses Qt, there should be exactly one QCoreApplication object. For GUI applications, see - QApplication. + QGuiApplication. For applications that use the Qt Widgets module, + see QApplication. QCoreApplication contains the main event loop, where all events from the operating system (e.g., timer and network events) and @@ -631,10 +603,10 @@ void QCoreApplicationPrivate::initLocale() operations can call processEvents() to keep the application responsive. - In general, we recommend that you create a QCoreApplication or a - QApplication object in your \c main() function as early as - possible. exec() will not return until the event loop exits; e.g., - when quit() is called. + In general, we recommend that you create a QCoreApplication, + QGuiApplication or a QApplication object in your \c main() + function as early as possible. exec() will not return until + the event loop exits; e.g., when quit() is called. Several static convenience functions are also provided. The QCoreApplication object is available from instance(). Events can @@ -676,8 +648,8 @@ void QCoreApplicationPrivate::initLocale() instance, when converting between data types such as floats and strings, since the notation may differ between locales. To get around this problem, call the POSIX function \c{setlocale(LC_NUMERIC,"C")} - right after initializing QApplication or QCoreApplication to reset - the locale that is used for number formatting to "C"-locale. + right after initializing QApplication, QGuiApplication or QCoreApplication + to reset the locale that is used for number formatting to "C"-locale. \sa QGuiApplication, QAbstractEventDispatcher, QEventLoop, {Semaphores Example}, {Wait Conditions Example} @@ -687,7 +659,7 @@ void QCoreApplicationPrivate::initLocale() \fn static QCoreApplication *QCoreApplication::instance() Returns a pointer to the application's QCoreApplication (or - QApplication) instance. + QGuiApplication/QApplication) instance. If no instance has been allocated, \c null is returned. */ @@ -1009,7 +981,7 @@ bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event) // call overhead. QObjectPrivate *d = receiver->d_func(); QThreadData *threadData = d->threadData; - QScopedLoopLevelCounter loopLevelCounter(threadData); + QScopedScopeLevelCounter scopeLevelCounter(threadData); if (!selfRequired) return doNotify(receiver, event); return self->notify(receiver, event); @@ -1222,6 +1194,9 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags) */ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime) { + // ### Qt 6: consider splitting this method into a public and a private + // one, so that a user-invoked processEvents can be detected + // and handled properly. QThreadData *data = QThreadData::current(); if (!data->hasEventDispatcher()) return; @@ -1425,8 +1400,24 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority) if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) { // remember the current running eventloop for DeferredDelete - // events posted in the receiver's thread - static_cast<QDeferredDeleteEvent *>(event)->level = data->loopLevel; + // events posted in the receiver's thread. + + // Events sent by non-Qt event handlers (such as glib) may not + // have the scopeLevel set correctly. The scope level makes sure that + // code like this: + // foo->deleteLater(); + // qApp->processEvents(); // without passing QEvent::DeferredDelete + // will not cause "foo" to be deleted before returning to the event loop. + + // If the scope level is 0 while loopLevel != 0, we are called from a + // non-conformant code path, and our best guess is that the scope level + // should be 1. (Loop level 0 is special: it means that no event loops + // are running.) + int loopLevel = data->loopLevel; + int scopeLevel = data->scopeLevel; + if (scopeLevel == 0 && loopLevel != 0) + scopeLevel = 1; + static_cast<QDeferredDeleteEvent *>(event)->level = loopLevel + scopeLevel; } // delete the event on exceptions to protect against memory leaks till the event is @@ -1503,6 +1494,9 @@ bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEven */ void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type) { + // ### Qt 6: consider splitting this method into a public and a private + // one, so that a user-invoked sendPostedEvents can be detected + // and handled properly. QThreadData *data = QThreadData::current(); QCoreApplicationPrivate::sendPostedEvents(receiver, event_type, data); @@ -1594,15 +1588,19 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type } if (pe.event->type() == QEvent::DeferredDelete) { - // DeferredDelete events are only sent when we are explicitly asked to - // (s.a. QEvent::DeferredDelete), and then only if the event loop that - // posted the event has returned. - int loopLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->loopLevel(); + // DeferredDelete events are sent either + // 1) when the event loop that posted the event has returned; or + // 2) if explicitly requested (with QEvent::DeferredDelete) for + // events posted by the current event loop; or + // 3) if the event was posted before the outermost event loop. + + int eventLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->loopLevel(); + int loopLevel = data->loopLevel + data->scopeLevel; const bool allowDeferredDelete = - (loopLevel > data->loopLevel - || (!loopLevel && data->loopLevel > 0) + (eventLevel > loopLevel + || (!eventLevel && loopLevel > 0) || (event_type == QEvent::DeferredDelete - && loopLevel == data->loopLevel)); + && eventLevel == loopLevel)); if (!allowDeferredDelete) { // cannot send deferred delete if (!event_type && !receiver) { @@ -1868,7 +1866,7 @@ void QCoreApplication::quit() Installing or removing a QTranslator, or changing an installed QTranslator generates a \l{QEvent::LanguageChange}{LanguageChange} event for the - QCoreApplication instance. A QApplication instance will propagate the event + QCoreApplication instance. A QGuiApplication instance will propagate the event to all toplevel windows, where a reimplementation of changeEvent can re-translate the user interface by passing user-visible strings via the tr() function to the respective property setters. User-interface classes @@ -2137,33 +2135,6 @@ QString QCoreApplication::applicationFilePath() #if defined(Q_OS_WIN) QCoreApplicationPrivate::setApplicationFilePath(QFileInfo(qAppFileName()).filePath()); return *QCoreApplicationPrivate::cachedApplicationFilePath; -#elif defined(Q_OS_BLACKBERRY) - if (!arguments().isEmpty()) { // args is never empty, but the navigator can change behaviour some day - QFileInfo fileInfo(arguments().at(0)); - const bool zygotized = fileInfo.exists(); - if (zygotized) { - // Handle the zygotized case: - QCoreApplicationPrivate::setApplicationFilePath(QDir::cleanPath(fileInfo.absoluteFilePath())); - return *QCoreApplicationPrivate::cachedApplicationFilePath; - } - } - - // Handle the non-zygotized case: - const size_t maximum_path = static_cast<size_t>(pathconf("/",_PC_PATH_MAX)); - char buff[maximum_path+1]; - if (_cmdname(buff)) { - QCoreApplicationPrivate::setApplicationFilePath(QDir::cleanPath(QString::fromLocal8Bit(buff))); - } else { - qWarning("QCoreApplication::applicationFilePath: _cmdname() failed"); - // _cmdname() won't fail, but just in case, fallback to the old method - QDir dir(QStringLiteral("./app/native/")); - QStringList executables = dir.entryList(QDir::Executable | QDir::Files); - if (!executables.empty()) { - //We assume that there is only one executable in the folder - QCoreApplicationPrivate::setApplicationFilePath(dir.absoluteFilePath(executables.first())); - } - } - return *QCoreApplicationPrivate::cachedApplicationFilePath; #elif defined(Q_OS_MAC) QString qAppFileName_str = qAppFileName(); if(!qAppFileName_str.isEmpty()) { @@ -2329,9 +2300,6 @@ QStringList QCoreApplication::arguments() organizationName(). On all other platforms, QSettings uses organizationName() as the organization. - On BlackBerry this property is read-only. It is obtained from the - BAR application descriptor file. - \sa organizationDomain, applicationName */ @@ -2356,9 +2324,6 @@ void QCoreApplication::setOrganizationName(const QString &orgName) QString QCoreApplication::organizationName() { -#ifdef Q_OS_BLACKBERRY - coreappdata()->loadManifest(); -#endif return coreappdata()->orgName; } @@ -2409,9 +2374,6 @@ QString QCoreApplication::organizationDomain() If not set, the application name defaults to the executable name (since 5.0). - On BlackBerry this property is read-only. It is obtained from the - BAR application descriptor file. - \sa organizationName, organizationDomain, applicationVersion, applicationFilePath() */ /*! @@ -2437,9 +2399,6 @@ void QCoreApplication::setApplicationName(const QString &application) QString QCoreApplication::applicationName() { -#ifdef Q_OS_BLACKBERRY - coreappdata()->loadManifest(); -#endif return coreappdata() ? coreappdata()->application : QString(); } @@ -2454,9 +2413,6 @@ Q_CORE_EXPORT QString qt_applicationName_noFallback() \since 4.4 \brief the version of this application - On BlackBerry this property is read-only. It is obtained from the - BAR application descriptor file. - \sa applicationName, organizationName, organizationDomain */ /*! @@ -2478,9 +2434,6 @@ void QCoreApplication::setApplicationVersion(const QString &version) QString QCoreApplication::applicationVersion() { -#ifdef Q_OS_BLACKBERRY - coreappdata()->loadManifest(); -#endif return coreappdata()->applicationVersion; } @@ -2700,7 +2653,7 @@ void QCoreApplication::removeLibraryPath(const QString &path) i.e. MSG or XCB event structs. \note Native event filters will be disabled in the application when the - Qt::AA_MacPluginApplication attribute is set. + Qt::AA_PluginApplication attribute is set. For maximum portability, you should always try to use QEvent and QObject::installEventFilter() whenever possible. @@ -2711,8 +2664,8 @@ void QCoreApplication::removeLibraryPath(const QString &path) */ void QCoreApplication::installNativeEventFilter(QAbstractNativeEventFilter *filterObj) { - if (QCoreApplication::testAttribute(Qt::AA_MacPluginApplication)) { - qWarning("Native event filters are not applied when the Qt::AA_MacPluginApplication attribute is set"); + if (QCoreApplication::testAttribute(Qt::AA_PluginApplication)) { + qWarning("Native event filters are not applied when the Qt::AA_PluginApplication attribute is set"); return; } |