summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/kernel.pri28
-rw-r--r--src/corelib/kernel/qcore_mac_p.h14
-rw-r--r--src/corelib/kernel/qcore_unix_p.h2
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp56
-rw-r--r--src/corelib/kernel/qcoreapplication.h3
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h1
-rw-r--r--src/corelib/kernel/qcorecmdlineargs_p.h2
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib_p.h20
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h32
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp402
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt_p.h108
-rw-r--r--src/corelib/kernel/qfunctions_p.h2
-rw-r--r--src/corelib/kernel/qfunctions_winrt.cpp105
-rw-r--r--src/corelib/kernel/qfunctions_winrt.h122
-rw-r--r--src/corelib/kernel/qjni_p.h12
-rw-r--r--src/corelib/kernel/qmetaobject.cpp14
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp2
-rw-r--r--src/corelib/kernel/qobject.cpp133
-rw-r--r--src/corelib/kernel/qobject.h77
-rw-r--r--src/corelib/kernel/qobject_p.h1
-rw-r--r--src/corelib/kernel/qobjectdefs.h2
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h4
-rw-r--r--src/corelib/kernel/qppsattribute.cpp308
-rw-r--r--src/corelib/kernel/qppsattribute_p.h139
-rw-r--r--src/corelib/kernel/qppsattributeprivate_p.h91
-rw-r--r--src/corelib/kernel/qppsobject.cpp964
-rw-r--r--src/corelib/kernel/qppsobject_p.h130
-rw-r--r--src/corelib/kernel/qppsobjectprivate_p.h128
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp4
-rw-r--r--src/corelib/kernel/qsystemsemaphore_win.cpp2
-rw-r--r--src/corelib/kernel/qvariant.cpp2
-rw-r--r--src/corelib/kernel/qvariant_p.h2
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp4
33 files changed, 2837 insertions, 79 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 7625a74381..1fec528b31 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -68,16 +68,21 @@ SOURCES += \
win32 {
SOURCES += \
- kernel/qeventdispatcher_win.cpp \
kernel/qcoreapplication_win.cpp \
kernel/qwineventnotifier.cpp \
kernel/qsharedmemory_win.cpp \
kernel/qsystemsemaphore_win.cpp
HEADERS += \
- kernel/qeventdispatcher_win_p.h \
kernel/qwineventnotifier.h
-}
+ winrt {
+ SOURCES += kernel/qeventdispatcher_winrt.cpp
+ HEADERS += kernel/qeventdispatcher_winrt_p.h
+ } else {
+ SOURCES += kernel/qeventdispatcher_win.cpp
+ HEADERS += kernel/qeventdispatcher_win_p.h
+ }
+}
wince*: {
SOURCES += \
@@ -86,6 +91,13 @@ wince*: {
kernel/qfunctions_wince.h
}
+winrt {
+ SOURCES += \
+ kernel/qfunctions_winrt.cpp
+ HEADERS += \
+ kernel/qfunctions_winrt.h
+}
+
mac {
SOURCES += \
kernel/qcoreapplication_mac.cpp
@@ -152,9 +164,15 @@ vxworks {
blackberry {
SOURCES += \
- kernel/qeventdispatcher_blackberry.cpp
+ kernel/qeventdispatcher_blackberry.cpp \
+ kernel/qppsattribute.cpp \
+ kernel/qppsobject.cpp
HEADERS += \
- kernel/qeventdispatcher_blackberry_p.h
+ kernel/qeventdispatcher_blackberry_p.h \
+ kernel/qppsattribute_p.h \
+ kernel/qppsattributeprivate_p.h \
+ kernel/qppsobject_p.h \
+ kernel/qppsobjectprivate_p.h
}
android:!android-no-sdk {
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index f491be9768..e92a2d2978 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -105,13 +105,13 @@ public:
inline operator T() { return type; }
inline QCFType operator =(const QCFType &helper)
{
- if (helper.type)
- CFRetain(helper.type);
- CFTypeRef type2 = type;
- type = helper.type;
- if (type2)
- CFRelease(type2);
- return *this;
+ if (helper.type)
+ CFRetain(helper.type);
+ CFTypeRef type2 = type;
+ type = helper.type;
+ if (type2)
+ CFRelease(type2);
+ return *this;
}
inline T *operator&() { return &type; }
template <typename X> X as() const { return reinterpret_cast<X>(type); }
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index 8c0589fdc6..7ab632d7a0 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -117,6 +117,8 @@ inline bool operator<(const timespec &t1, const timespec &t2)
{ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec); }
inline bool operator==(const timespec &t1, const timespec &t2)
{ return t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec; }
+inline bool operator!=(const timespec &t1, const timespec &t2)
+{ return !(t1 == t2); }
inline timespec &operator+=(timespec &t1, const timespec &t2)
{
t1.tv_sec += t2.tv_sec;
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index e77d6894d0..2dd56423ac 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -85,7 +85,11 @@
# endif
#endif
#ifdef Q_OS_WIN
+# ifdef Q_OS_WINRT
+# include "qeventdispatcher_winrt_p.h"
+# else
# include "qeventdispatcher_win_p.h"
+# endif
#endif
#endif // QT_NO_QOBJECT
@@ -98,6 +102,7 @@
#ifdef Q_OS_UNIX
# include <locale.h>
# include <unistd.h>
+# include <sys/types.h>
#endif
#ifdef Q_OS_VXWORKS
@@ -134,6 +139,8 @@ extern QString qAppFileName();
#endif
int QCoreApplicationPrivate::app_compile_version = 0x050000; //we don't know exactly, but it's at least 5.0.0
+bool QCoreApplicationPrivate::setuidAllowed = false;
+
#if !defined(Q_OS_WIN)
#ifdef Q_OS_MAC
QString QCoreApplicationPrivate::macMenuBarName()
@@ -410,6 +417,11 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
QCoreApplicationPrivate::is_app_closing = false;
# if defined(Q_OS_UNIX)
+ if (!setuidAllowed && (geteuid() != getuid()))
+ qFatal("FATAL: The application binary appears to be running setuid, this is a security hole.");
+# endif // Q_OS_UNIX
+
+# if defined(Q_OS_UNIX)
qt_application_thread_id = QThread::currentThreadId();
# endif
@@ -471,6 +483,8 @@ void QCoreApplicationPrivate::createEventDispatcher()
# endif
eventDispatcher = new QEventDispatcherUNIX(q);
# endif
+#elif defined(Q_OS_WINRT)
+ eventDispatcher = new QEventDispatcherWinRT(q);
#elif defined(Q_OS_WIN)
eventDispatcher = new QEventDispatcherWin32(q);
#else
@@ -518,6 +532,10 @@ void QCoreApplicationPrivate::appendApplicationPathToLibraryPaths()
coreappdata()->app_libpaths = app_libpaths = new QStringList;
QString app_location = QCoreApplication::applicationFilePath();
app_location.truncate(app_location.lastIndexOf(QLatin1Char('/')));
+#ifdef Q_OS_WINRT
+ if (app_location.isEmpty())
+ app_location.append(QLatin1Char('/'));
+#endif
app_location = QDir(app_location).canonicalPath();
if (QFile::exists(app_location) && !app_libpaths->contains(app_location))
app_libpaths->append(app_location);
@@ -786,6 +804,44 @@ QCoreApplication::~QCoreApplication()
#endif
}
+/*!
+ \since 5.3
+
+ Allows the application to run setuid on UNIX platforms if \a allow
+ is true.
+
+ If \a allow is false (the default) and Qt detects the application is
+ running with an effective user id different than the real user id,
+ the application will be aborted when a QCoreApplication instance is
+ created.
+
+ Qt is not an appropriate solution for setuid programs due to its
+ large attack surface. However some applications may be required
+ to run in this manner for historical reasons. This flag will
+ prevent Qt from aborting the application when this is detected,
+ and must be set before a QCoreApplication instance is created.
+
+ \note It is strongly recommended not to enable this option since
+ it introduces security risks.
+*/
+void QCoreApplication::setSetuidAllowed(bool allow)
+{
+ QCoreApplicationPrivate::setuidAllowed = allow;
+}
+
+/*!
+ \since 5.3
+
+ Returns true if the application is allowed to run setuid on UNIX
+ platforms.
+
+ \sa QCoreApplication::setSetuidAllowed()
+*/
+bool QCoreApplication::isSetuidAllowed()
+{
+ return QCoreApplicationPrivate::setuidAllowed;
+}
+
/*!
Sets the attribute \a attribute if \a on is true;
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index ae17aeec0e..c2843030fd 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -112,6 +112,9 @@ public:
static void setApplicationVersion(const QString &version);
static QString applicationVersion();
+ static void setSetuidAllowed(bool allow);
+ static bool isSetuidAllowed();
+
static QCoreApplication *instance() { return self; }
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
index 0c00f396b5..c3d83112ae 100644
--- a/src/corelib/kernel/qcoreapplication_p.h
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -153,6 +153,7 @@ public:
static bool is_app_closing;
#endif
+ static bool setuidAllowed;
static uint attribs;
static inline bool testAttribute(uint flag) { return attribs & (1 << flag); }
static int app_compile_version;
diff --git a/src/corelib/kernel/qcorecmdlineargs_p.h b/src/corelib/kernel/qcorecmdlineargs_p.h
index bbbee7df25..93c80205ab 100644
--- a/src/corelib/kernel/qcorecmdlineargs_p.h
+++ b/src/corelib/kernel/qcorecmdlineargs_p.h
@@ -154,7 +154,7 @@ static inline QStringList qCmdLineArgs(int argc, char *argv[])
static inline QStringList qCmdLineArgs(int argc, char *argv[])
{
QStringList args;
- for (int i = 0; i != argc; ++i)
+ for (int i = 0; i != argc; ++i)
args += QString::fromLocal8Bit(argv[i]);
return args;
}
diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h
index 933faff5a5..a2e7b6b33e 100644
--- a/src/corelib/kernel/qeventdispatcher_glib_p.h
+++ b/src/corelib/kernel/qeventdispatcher_glib_p.h
@@ -77,19 +77,19 @@ public:
bool processEvents(QEventLoop::ProcessEventsFlags flags);
bool hasPendingEvents();
- void registerSocketNotifier(QSocketNotifier *socketNotifier);
- void unregisterSocketNotifier(QSocketNotifier *socketNotifier);
+ void registerSocketNotifier(QSocketNotifier *socketNotifier) Q_DECL_FINAL;
+ void unregisterSocketNotifier(QSocketNotifier *socketNotifier) Q_DECL_FINAL;
- void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object);
- bool unregisterTimer(int timerId);
- bool unregisterTimers(QObject *object);
- QList<TimerInfo> registeredTimers(QObject *object) const;
+ void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) Q_DECL_FINAL;
+ bool unregisterTimer(int timerId) Q_DECL_FINAL;
+ bool unregisterTimers(QObject *object) Q_DECL_FINAL;
+ QList<TimerInfo> registeredTimers(QObject *object) const Q_DECL_FINAL;
- int remainingTime(int timerId);
+ int remainingTime(int timerId) Q_DECL_FINAL;
- void wakeUp();
- void interrupt();
- void flush();
+ void wakeUp() Q_DECL_FINAL;
+ void interrupt() Q_DECL_FINAL;
+ void flush() Q_DECL_FINAL;
static bool versionSupported();
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index 5d69d5e396..242aa9e695 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -94,6 +94,12 @@ public:
class QEventDispatcherUNIXPrivate;
+#ifdef Q_OS_QNX
+# define FINAL_EXCEPT_BLACKBERRY
+#else
+# define FINAL_EXCEPT_BLACKBERRY Q_DECL_FINAL
+#endif
+
class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher
{
Q_OBJECT
@@ -106,18 +112,18 @@ public:
bool processEvents(QEventLoop::ProcessEventsFlags flags);
bool hasPendingEvents();
- void registerSocketNotifier(QSocketNotifier *notifier);
- void unregisterSocketNotifier(QSocketNotifier *notifier);
+ void registerSocketNotifier(QSocketNotifier *notifier) FINAL_EXCEPT_BLACKBERRY;
+ void unregisterSocketNotifier(QSocketNotifier *notifier) FINAL_EXCEPT_BLACKBERRY;
- void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object);
- bool unregisterTimer(int timerId);
- bool unregisterTimers(QObject *object);
- QList<TimerInfo> registeredTimers(QObject *object) const;
+ void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) Q_DECL_FINAL;
+ bool unregisterTimer(int timerId) Q_DECL_FINAL;
+ bool unregisterTimers(QObject *object) Q_DECL_FINAL;
+ QList<TimerInfo> registeredTimers(QObject *object) const Q_DECL_FINAL;
- int remainingTime(int timerId);
+ int remainingTime(int timerId) Q_DECL_FINAL;
- void wakeUp();
- void interrupt();
+ void wakeUp() FINAL_EXCEPT_BLACKBERRY;
+ void interrupt() Q_DECL_FINAL;
void flush();
protected:
@@ -130,7 +136,7 @@ protected:
virtual int select(int nfds,
fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
- timespec *timeout);
+ timespec *timeout) Q_DECL_FINAL;
};
class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate
@@ -142,8 +148,8 @@ public:
~QEventDispatcherUNIXPrivate();
int doSelect(QEventLoop::ProcessEventsFlags flags, timespec *timeout);
- virtual int initThreadWakeUp();
- virtual int processThreadWakeUp(int nsel);
+ virtual int initThreadWakeUp() FINAL_EXCEPT_BLACKBERRY;
+ virtual int processThreadWakeUp(int nsel) FINAL_EXCEPT_BLACKBERRY;
bool mainThread;
@@ -165,6 +171,8 @@ public:
QAtomicInt interrupt; // bool
};
+#undef FINAL_EXCEPT_BLACKBERRY
+
QT_END_NAMESPACE
#endif // QEVENTDISPATCHER_UNIX_P_H
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
new file mode 100644
index 0000000000..8639e925cd
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -0,0 +1,402 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventdispatcher_winrt_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QThread>
+#include <QtCore/QHash>
+
+#include <private/qcoreapplication_p.h>
+#include <private/qthread_p.h>
+#include <private/qabstracteventdispatcher_p.h>
+
+#include <wrl.h>
+#include <windows.foundation.h>
+#include <windows.system.threading.h>
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::System::Threading;
+using namespace ABI::Windows::Foundation;
+
+QT_BEGIN_NAMESPACE
+
+class QZeroTimerEvent : public QTimerEvent
+{
+public:
+ explicit inline QZeroTimerEvent(int timerId)
+ : QTimerEvent(timerId)
+ { t = QEvent::ZeroTimerEvent; }
+};
+
+struct WinRTTimerInfo // internal timer info
+{
+ WinRTTimerInfo() : timer(0) {}
+
+ int id;
+ int interval;
+ Qt::TimerType timerType;
+ quint64 timeout; // - when to actually fire
+ QObject *obj; // - object to receive events
+ bool inTimerEvent;
+ ComPtr<IThreadPoolTimer> timer;
+};
+
+class QEventDispatcherWinRTPrivate : public QAbstractEventDispatcherPrivate
+{
+ Q_DECLARE_PUBLIC(QEventDispatcherWinRT)
+
+public:
+ QEventDispatcherWinRTPrivate();
+ ~QEventDispatcherWinRTPrivate();
+
+ void registerTimer(WinRTTimerInfo *t);
+ void unregisterTimer(WinRTTimerInfo *t);
+ void sendTimerEvent(int timerId);
+
+
+private:
+ static HRESULT timerExpiredCallback(ABI::Windows::System::Threading::IThreadPoolTimer *source);
+ static int idForTimer(IThreadPoolTimer *timer)
+ {
+ QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher();
+ if (!eventDispatcher)
+ return -1;
+ if (QEventDispatcherWinRTPrivate *that = static_cast<QEventDispatcherWinRTPrivate *>(get(eventDispatcher)))
+ return that->timerIds.value(timer, -1);
+ return -1;
+ }
+
+ QHash<int, WinRTTimerInfo*> timerDict;
+ QHash<IThreadPoolTimer *, int> timerIds;
+
+ ComPtr<IThreadPoolTimerStatics> timerFactory;
+};
+
+QEventDispatcherWinRT::QEventDispatcherWinRT(QObject *parent)
+ : QAbstractEventDispatcher(*new QEventDispatcherWinRTPrivate, parent)
+{
+}
+
+QEventDispatcherWinRT::QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent)
+ : QAbstractEventDispatcher(dd, parent)
+{ }
+
+QEventDispatcherWinRT::~QEventDispatcherWinRT()
+{
+}
+
+bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_UNUSED(flags);
+
+ // we are awake, broadcast it
+ emit awake();
+ QCoreApplicationPrivate::sendPostedEvents(0, 0, QThreadData::current());
+
+ return false;
+}
+
+bool QEventDispatcherWinRT::hasPendingEvents()
+{
+ return qGlobalPostedEventsCount();
+}
+
+void QEventDispatcherWinRT::registerSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_UNUSED(notifier);
+ Q_UNIMPLEMENTED();
+}
+void QEventDispatcherWinRT::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_UNUSED(notifier);
+ Q_UNIMPLEMENTED();
+}
+
+void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
+{
+ Q_UNUSED(timerType);
+
+ if (timerId < 1 || interval < 0 || !object) {
+ qWarning("QEventDispatcherWinRT::registerTimer: invalid arguments");
+ return;
+ } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::startTimer: timers cannot be started from another thread");
+ return;
+ }
+
+ Q_D(QEventDispatcherWinRT);
+ WinRTTimerInfo *t = new WinRTTimerInfo();
+ t->id = timerId;
+ t->interval = interval;
+ t->timerType = timerType;
+ t->obj = object;
+ t->inTimerEvent = false;
+
+ d->registerTimer(t);
+ d->timerDict.insert(t->id, t);
+}
+
+bool QEventDispatcherWinRT::unregisterTimer(int timerId)
+{
+ if (timerId < 1) {
+ qWarning("QEventDispatcherWinRT::unregisterTimer: invalid argument");
+ return false;
+ }
+ if (thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ return false;
+ }
+
+ Q_D(QEventDispatcherWinRT);
+
+ WinRTTimerInfo *t = d->timerDict.value(timerId);
+ if (!t)
+ return false;
+
+ d->unregisterTimer(t);
+ return true;
+}
+
+bool QEventDispatcherWinRT::unregisterTimers(QObject *object)
+{
+ if (!object) {
+ qWarning("QEventDispatcherWinRT::unregisterTimers: invalid argument");
+ return false;
+ }
+ QThread *currentThread = QThread::currentThread();
+ if (object->thread() != thread() || thread() != currentThread) {
+ qWarning("QObject::killTimers: timers cannot be stopped from another thread");
+ return false;
+ }
+
+ Q_D(QEventDispatcherWinRT);
+ foreach (WinRTTimerInfo *t, d->timerDict) {
+ if (t->obj == object)
+ d->unregisterTimer(t);
+ }
+ return true;
+}
+
+QList<QAbstractEventDispatcher::TimerInfo> QEventDispatcherWinRT::registeredTimers(QObject *object) const
+{
+ if (!object) {
+ qWarning("QEventDispatcherWinRT:registeredTimers: invalid argument");
+ return QList<TimerInfo>();
+ }
+
+ Q_D(const QEventDispatcherWinRT);
+ QList<TimerInfo> list;
+ foreach (const WinRTTimerInfo *t, d->timerDict) {
+ if (t->obj == object)
+ list.append(TimerInfo(t->id, t->interval, t->timerType));
+ }
+ return list;
+}
+
+bool QEventDispatcherWinRT::registerEventNotifier(QWinEventNotifier *notifier)
+{
+ Q_UNUSED(notifier);
+ Q_UNIMPLEMENTED();
+ return false;
+}
+
+void QEventDispatcherWinRT::unregisterEventNotifier(QWinEventNotifier *notifier)
+{
+ Q_UNUSED(notifier);
+ Q_UNIMPLEMENTED();
+}
+
+int QEventDispatcherWinRT::remainingTime(int timerId)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1) {
+ qWarning("QEventDispatcherWinRT::remainingTime: invalid argument");
+ return -1;
+ }
+#endif
+
+ Q_D(QEventDispatcherWinRT);
+ if (WinRTTimerInfo *t = d->timerDict.value(timerId)) {
+ const quint64 currentTime = qt_msectime();
+ if (currentTime < t->timeout) {
+ // time to wait
+ return t->timeout - currentTime;
+ } else {
+ return 0;
+ }
+ }
+
+#ifndef QT_NO_DEBUG
+ qWarning("QEventDispatcherWinRT::remainingTime: timer id %d not found", timerId);
+#endif
+ return -1;
+}
+
+void QEventDispatcherWinRT::wakeUp()
+{
+}
+
+void QEventDispatcherWinRT::interrupt()
+{
+}
+
+void QEventDispatcherWinRT::flush()
+{
+}
+
+void QEventDispatcherWinRT::startingUp()
+{
+}
+
+void QEventDispatcherWinRT::closingDown()
+{
+ Q_D(QEventDispatcherWinRT);
+ foreach (WinRTTimerInfo *t, d->timerDict)
+ d->unregisterTimer(t);
+ d->timerDict.clear();
+ d->timerIds.clear();
+}
+
+bool QEventDispatcherWinRT::event(QEvent *e)
+{
+ Q_D(QEventDispatcherWinRT);
+ if (e->type() == QEvent::ZeroTimerEvent) {
+ QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
+ WinRTTimerInfo *t = d->timerDict.value(zte->timerId());
+ if (t) {
+ t->inTimerEvent = true;
+
+ QTimerEvent te(zte->timerId());
+ QCoreApplication::sendEvent(t->obj, &te);
+
+ t = d->timerDict.value(zte->timerId());
+ if (t) {
+ if (t->interval == 0 && t->inTimerEvent) {
+ // post the next zero timer event as long as the timer was not restarted
+ QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId()));
+ }
+
+ t->inTimerEvent = false;
+ }
+ }
+ return true;
+ } else if (e->type() == QEvent::Timer) {
+ QTimerEvent *te = static_cast<QTimerEvent*>(e);
+ d->sendTimerEvent(te->timerId());
+ }
+ return QAbstractEventDispatcher::event(e);
+}
+
+QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate()
+{
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+ HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Threading_ThreadPoolTimer).Get(), &timerFactory);
+ if (FAILED(hr))
+ qWarning("QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate: Could not obtain timer factory: %lx", hr);
+}
+
+QEventDispatcherWinRTPrivate::~QEventDispatcherWinRTPrivate()
+{
+ CoUninitialize();
+}
+
+void QEventDispatcherWinRTPrivate::registerTimer(WinRTTimerInfo *t)
+{
+ Q_Q(QEventDispatcherWinRT);
+
+ bool ok = false;
+ uint interval = t->interval;
+ if (interval == 0u) {
+ // optimization for single-shot-zero-timer
+ QCoreApplication::postEvent(q, new QZeroTimerEvent(t->id));
+ ok = true;
+ } else {
+ TimeSpan period;
+ period.Duration = interval * 10000; // TimeSpan is based on 100-nanosecond units
+ ok = SUCCEEDED(timerFactory->CreatePeriodicTimer(
+ Callback<ITimerElapsedHandler>(&QEventDispatcherWinRTPrivate::timerExpiredCallback).Get(), period, &t->timer));
+ if (ok)
+ timerIds.insert(t->timer.Get(), t->id);
+ }
+ t->timeout = qt_msectime() + interval;
+ if (!ok)
+ qErrnoWarning("QEventDispatcherWinRT::registerTimer: Failed to create a timer");
+}
+
+void QEventDispatcherWinRTPrivate::unregisterTimer(WinRTTimerInfo *t)
+{
+ if (t->timer) {
+ t->timer->Cancel();
+ timerIds.remove(t->timer.Get());
+ }
+ timerDict.remove(t->id);
+ delete t;
+}
+
+void QEventDispatcherWinRTPrivate::sendTimerEvent(int timerId)
+{
+ WinRTTimerInfo *t = timerDict.value(timerId);
+ if (t && !t->inTimerEvent) {
+ // send event, but don't allow it to recurse
+ t->inTimerEvent = true;
+
+ QTimerEvent e(t->id);
+ QCoreApplication::sendEvent(t->obj, &e);
+
+ // timer could have been removed
+ t = timerDict.value(timerId);
+ if (t)
+ t->inTimerEvent = false;
+ }
+}
+
+HRESULT QEventDispatcherWinRTPrivate::timerExpiredCallback(IThreadPoolTimer *source)
+{
+ int timerId = idForTimer(source);
+ if (timerId > 0)
+ QCoreApplication::postEvent(QCoreApplication::eventDispatcher(), new QTimerEvent(timerId));
+ else
+ qWarning("QEventDispatcherWinRT::timerExpiredCallback: Could not find timer %d in timer list", source);
+ return S_OK;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_winrt_p.h b/src/corelib/kernel/qeventdispatcher_winrt_p.h
new file mode 100644
index 0000000000..0631b2ea33
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_winrt_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QEVENTDISPATCHER_WINRT_P_H
+#define QEVENTDISPATCHER_WINRT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qabstracteventdispatcher.h"
+
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+int qt_msectime();
+
+class QEventDispatcherWinRTPrivate;
+
+class Q_CORE_EXPORT QEventDispatcherWinRT : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventDispatcherWinRT)
+
+public:
+ explicit QEventDispatcherWinRT(QObject *parent = 0);
+ ~QEventDispatcherWinRT();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void registerSocketNotifier(QSocketNotifier *notifier);
+ void unregisterSocketNotifier(QSocketNotifier *notifier);
+
+ void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<TimerInfo> registeredTimers(QObject *object) const;
+
+ int remainingTime(int timerId);
+
+ bool registerEventNotifier(QWinEventNotifier *notifier);
+ void unregisterEventNotifier(QWinEventNotifier *notifier);
+
+ void wakeUp();
+ void interrupt();
+ void flush();
+
+ void startingUp();
+ void closingDown();
+
+protected:
+ QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent = 0);
+
+ bool event(QEvent *);
+ int activateTimers();
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_WINRT_P_H
diff --git a/src/corelib/kernel/qfunctions_p.h b/src/corelib/kernel/qfunctions_p.h
index 6e094f1ed3..e3014a0dcf 100644
--- a/src/corelib/kernel/qfunctions_p.h
+++ b/src/corelib/kernel/qfunctions_p.h
@@ -61,6 +61,8 @@
# include "QtCore/qfunctions_vxworks.h"
#elif defined(Q_OS_NACL)
# include "QtCore/qfunctions_nacl.h"
+#elif defined(Q_OS_WINRT)
+# include "QtCore/qfunctions_winrt.h"
#endif
#ifdef Q_CC_RVCT
diff --git a/src/corelib/kernel/qfunctions_winrt.cpp b/src/corelib/kernel/qfunctions_winrt.cpp
new file mode 100644
index 0000000000..1348af2acb
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_winrt.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifdef Q_OS_WINRT
+
+#include "qfunctions_winrt.h"
+#include "qstring.h"
+#include "qbytearray.h"
+#include "qhash.h"
+
+QT_USE_NAMESPACE
+
+// Environment ------------------------------------------------------
+inline QHash<QByteArray, QByteArray> &qt_app_environment()
+{
+ static QHash<QByteArray, QByteArray> internalEnvironment;
+ return internalEnvironment;
+}
+
+errno_t qt_winrt_getenv_s(size_t* sizeNeeded, char* buffer, size_t bufferSize, const char* varName)
+{
+ if (!sizeNeeded)
+ return EINVAL;
+
+ if (!qt_app_environment().contains(varName)) {
+ if (buffer)
+ buffer[0] = '\0';
+ return ENOENT;
+ }
+
+ QByteArray value = qt_app_environment().value(varName);
+ if (!value.endsWith('\0')) // win32 guarantees terminated string
+ value.append('\0');
+
+ if (bufferSize < (size_t)value.size()) {
+ *sizeNeeded = value.size();
+ return ERANGE;
+ }
+
+ strcpy(buffer, value.constData());
+ return 0;
+}
+
+errno_t qt_winrt__putenv_s(const char* varName, const char* value)
+{
+ QByteArray input = value;
+ if (input.isEmpty()) {
+ if (qt_app_environment().contains(varName))
+ qt_app_environment().remove(varName);
+ } else {
+ // win32 on winrt guarantees terminated string
+ if (!input.endsWith('\0'))
+ input.append('\0');
+ qt_app_environment()[varName] = input;
+ }
+
+ return 0;
+}
+
+void qt_winrt_tzset()
+{
+}
+
+void qt_winrt__tzset()
+{
+}
+
+#endif // Q_OS_WINRT
diff --git a/src/corelib/kernel/qfunctions_winrt.h b/src/corelib/kernel/qfunctions_winrt.h
new file mode 100644
index 0000000000..fa2b2e12ff
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_winrt.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUNCTIONS_WINRT_H
+#define QFUNCTIONS_WINRT_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_WINRT
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_BUILD_CORE_LIB
+#endif
+
+QT_END_NAMESPACE
+
+// Environment ------------------------------------------------------
+errno_t qt_winrt_getenv_s(size_t*, char*, size_t, const char*);
+errno_t qt_winrt__putenv_s(const char*, const char*);
+void qt_winrt_tzset();
+void qt_winrt__tzset();
+
+// As Windows Runtime lacks some standard functions used in Qt, these got
+// reimplemented. Other projects do this as well. Inline functions are used
+// that there is a central place to disable functions for newer versions if
+// they get available. There are no defines used anymore, because this
+// will break member functions of classes which are called like these
+// functions.
+// The other declarations available in this file are being used per
+// define inside qplatformdefs.h of the corresponding WinRT mkspec.
+
+#define generate_inline_return_func0(funcname, returntype) \
+ inline returntype funcname() \
+ { \
+ return qt_winrt_##funcname(); \
+ }
+#define generate_inline_return_func1(funcname, returntype, param1) \
+ inline returntype funcname(param1 p1) \
+ { \
+ return qt_winrt_##funcname(p1); \
+ }
+#define generate_inline_return_func2(funcname, returntype, param1, param2) \
+ inline returntype funcname(param1 p1, param2 p2) \
+ { \
+ return qt_winrt_##funcname(p1, p2); \
+ }
+#define generate_inline_return_func3(funcname, returntype, param1, param2, param3) \
+ inline returntype funcname(param1 p1, param2 p2, param3 p3) \
+ { \
+ return qt_winrt_##funcname(p1, p2, p3); \
+ }
+#define generate_inline_return_func4(funcname, returntype, param1, param2, param3, param4) \
+ inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4) \
+ { \
+ return qt_winrt_##funcname(p1, p2, p3, p4); \
+ }
+#define generate_inline_return_func5(funcname, returntype, param1, param2, param3, param4, param5) \
+ inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \
+ { \
+ return qt_winrt_##funcname(p1, p2, p3, p4, p5); \
+ }
+#define generate_inline_return_func6(funcname, returntype, param1, param2, param3, param4, param5, param6) \
+ inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \
+ { \
+ return qt_winrt_##funcname(p1, p2, p3, p4, p5, p6); \
+ }
+#define generate_inline_return_func7(funcname, returntype, param1, param2, param3, param4, param5, param6, param7) \
+ inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \
+ { \
+ return qt_winrt_##funcname(p1, p2, p3, p4, p5, p6, p7); \
+ }
+
+typedef unsigned (__stdcall *StartAdressExFunc)(void *);
+typedef void(*StartAdressFunc)(void *);
+typedef int ( __cdecl *CompareFunc ) (const void *, const void *) ;
+
+generate_inline_return_func4(getenv_s, errno_t, size_t *, char *, size_t, const char *)
+generate_inline_return_func2(_putenv_s, errno_t, const char *, const char *)
+generate_inline_return_func0(tzset, void)
+generate_inline_return_func0(_tzset, void)
+
+#endif // Q_OS_WINRT
+#endif // QFUNCTIONS_WINRT_H
diff --git a/src/corelib/kernel/qjni_p.h b/src/corelib/kernel/qjni_p.h
index ab98aec1bf..b1f0011b94 100644
--- a/src/corelib/kernel/qjni_p.h
+++ b/src/corelib/kernel/qjni_p.h
@@ -178,11 +178,13 @@ public:
jobject jobj = static_cast<jobject>(o);
if (!isSameObject(jobj)) {
d = QSharedPointer<QJNIObjectData>(new QJNIObjectData());
- QJNIEnvironmentPrivate env;
- d->m_jobject = env->NewGlobalRef(jobj);
- jclass objectClass = env->GetObjectClass(jobj);
- d->m_jclass = static_cast<jclass>(env->NewGlobalRef(objectClass));
- env->DeleteLocalRef(objectClass);
+ if (jobj) {
+ QJNIEnvironmentPrivate env;
+ d->m_jobject = env->NewGlobalRef(jobj);
+ jclass objectClass = env->GetObjectClass(jobj);
+ d->m_jclass = static_cast<jclass>(env->NewGlobalRef(objectClass));
+ env->DeleteLocalRef(objectClass);
+ }
}
return *this;
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index ff2675dfc8..0e38f2a2bf 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -942,7 +942,7 @@ static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, co
return self;
if (self->d.relatedMetaObjects) {
Q_ASSERT(priv(self->d.data)->revision >= 2);
- const QMetaObject **e = self->d.relatedMetaObjects;
+ const QMetaObject * const *e = self->d.relatedMetaObjects;
if (e) {
while (*e) {
if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name))
@@ -2694,10 +2694,14 @@ int QMetaProperty::userType() const
if (type != QMetaType::UnknownType)
return type;
if (isEnumType()) {
- int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
- if (enumMetaTypeId == QMetaType::UnknownType)
- return QVariant::Int; // Match behavior of QMetaType::type()
- return enumMetaTypeId;
+ type = QMetaType::type(qualifiedName(menum));
+ if (type == QMetaType::UnknownType) {
+ void *argv[] = { &type };
+ mobj->static_metacall(QMetaObject::RegisterPropertyMetaType, idx, argv);
+ if (type == -1 || type == QMetaType::UnknownType)
+ return QVariant::Int; // Match behavior of QMetaType::type()
+ }
+ return type;
}
type = QMetaType::type(typeName());
if (type != QMetaType::UnknownType)
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index 11ab39af1a..09d8271413 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -741,7 +741,7 @@ void QMetaObjectBuilder::addMetaObject
if ((members & RelatedMetaObjects) != 0) {
Q_ASSERT(priv(prototype->d.data)->revision >= 2);
- const QMetaObject **objects = prototype->d.relatedMetaObjects;
+ const QMetaObject * const *objects = prototype->d.relatedMetaObjects;
if (objects) {
while (*objects != 0) {
addRelatedMetaObject(*objects);
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 43b88d21b5..876ed8f27b 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -491,6 +491,100 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
}
/*!
+ \class QSignalBlocker
+ \brief Exception-safe wrapper around QObject::blockSignals()
+ \since 5.3
+ \ingroup objectmodel
+
+ \reentrant
+
+ QSignalBlocker can be used whereever you would otherwise use a
+ pair of calls to blockSignals(). It blocks signals in its
+ constructor and in the destructor it resets the state to what
+ it was before the constructor ran.
+
+ \code
+ {
+ const QSignalBlocker blocker(someQObject);
+ // no signals here
+ }
+ \endcode
+ is thus equivalent to
+ \code
+ const bool wasBlocked = someQObject->blockSignals(true);
+ // no signals here
+ someQObject->blockSignals(false);
+ \endcode
+
+ except the code using QSignalBlocker is safe in the face of
+ exceptions.
+
+ \sa QMutexLocker, QEventLoopLocker
+*/
+
+/*!
+ \fn QSignalBlocker::QSignalBlocker(QObject *object)
+
+ Constructor. Calls \a{object}->blockSignals(true).
+*/
+
+/*!
+ \fn QSignalBlocker::QSignalBlocker(QObject &object)
+ \overload
+
+ Calls \a{object}.blockSignals(true).
+*/
+
+/*!
+ \fn QSignalBlocker::QSignalBlocker(QSignalBlocker &&other)
+
+ Move-constructs a signal blocker from \a other. \a other will have
+ a no-op destructor, while repsonsibility for restoring the
+ QObject::signalsBlocked() state is transferred to the new object.
+*/
+
+/*!
+ \fn QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other)
+
+ Move-assigns this signal blocker from \a other. \a other will have
+ a no-op destructor, while repsonsibility for restoring the
+ QObject::signalsBlocked() state is transferred to this object.
+
+ The object's signals this signal blocker was blocking prior to
+ being moved to, if any, are unblocked \em except in the case where
+ both instances block the same object's signals and \c *this is
+ unblocked while \a other is not, at the time of the move.
+*/
+
+/*!
+ \fn QSignalBlocker::~QSignalBlocker()
+
+ Destructor. Restores the QObject::signalsBlocked() state to what it
+ was before the constructor ran, unless unblock() has been called
+ without a following reblock(), in which case it does nothing.
+*/
+
+/*!
+ \fn void QSignalBlocker::reblock()
+
+ Re-blocks signals after a previous unblock().
+
+ The numbers of reblock() and unblock() calls are not counted, so
+ every reblock() undoes any number of unblock() calls.
+*/
+
+/*!
+ \fn void QSignalBlocker::unblock()
+
+ Temporarily restores the QObject::signalsBlocked() state to what
+ it was before this QSignaBlocker's constructor ran. To undo, use
+ reblock().
+
+ The numbers of reblock() and unblock() calls are not counted, so
+ every unblock() undoes any number of reblock() calls.
+*/
+
+/*!
\class QObject
\inmodule QtCore
\brief The QObject class is the base class of all Qt objects.
@@ -2235,11 +2329,19 @@ QObject *QObject::sender() const
int QObject::senderSignalIndex() const
{
Q_D(const QObject);
- int signal_index = d->senderSignalIndex();
- if (signal_index < 0)
- return signal_index;
- // Convert from signal range to method range
- return QMetaObjectPrivate::signal(sender()->metaObject(), signal_index).methodIndex();
+
+ QMutexLocker locker(signalSlotLock(this));
+ if (!d->currentSender)
+ return -1;
+
+ for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
+ if (c->sender == d->currentSender->sender) {
+ // Convert from signal range to method range
+ return QMetaObjectPrivate::signal(c->sender->metaObject(), d->currentSender->signal).methodIndex();
+ }
+ }
+
+ return -1;
}
/*!
@@ -3625,25 +3727,6 @@ void QMetaObject::activate(QObject *sender, int signal_index, void **argv)
/*!
\internal
- Implementation of QObject::senderSignalIndex()
-*/
-int QObjectPrivate::senderSignalIndex() const
-{
- Q_Q(const QObject);
- QMutexLocker locker(signalSlotLock(q));
- if (!currentSender)
- return -1;
-
- for (QObjectPrivate::Connection *c = senders; c; c = c->next) {
- if (c->sender == currentSender->sender)
- return currentSender->signal;
- }
-
- return -1;
-}
-
-/*!
- \internal
Returns the signal index used in the internal connectionLists vector.
It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod
@@ -3720,6 +3803,8 @@ bool QObject::setProperty(const char *name, const QVariant &value)
d->extraData->propertyNames.append(name);
d->extraData->propertyValues.append(value);
} else {
+ if (value == d->extraData->propertyValues.at(idx))
+ return false;
d->extraData->propertyValues[idx] = value;
}
}
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index e2000afc82..5197d98f19 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -549,6 +549,83 @@ template <class T> inline const char * qobject_interface_iid()
Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
#endif
+class Q_CORE_EXPORT QSignalBlocker
+{
+public:
+ inline explicit QSignalBlocker(QObject *o);
+ inline explicit QSignalBlocker(QObject &o);
+ inline ~QSignalBlocker();
+
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QSignalBlocker(QSignalBlocker &&other);
+ inline QSignalBlocker &operator=(QSignalBlocker &&other);
+#endif
+
+ inline void reblock();
+ inline void unblock();
+private:
+ Q_DISABLE_COPY(QSignalBlocker)
+ QObject * m_o;
+ bool m_blocked;
+ bool m_inhibited;
+};
+
+QSignalBlocker::QSignalBlocker(QObject *o)
+ : m_o(o),
+ m_blocked(o && o->blockSignals(true)),
+ m_inhibited(false)
+{}
+
+QSignalBlocker::QSignalBlocker(QObject &o)
+ : m_o(&o),
+ m_blocked(o.blockSignals(true)),
+ m_inhibited(false)
+{}
+
+#ifdef Q_COMPILER_RVALUE_REFS
+QSignalBlocker::QSignalBlocker(QSignalBlocker &&other)
+ : m_o(other.m_o),
+ m_blocked(other.m_blocked),
+ m_inhibited(other.m_inhibited)
+{
+ other.m_o = 0;
+}
+
+QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other)
+{
+ if (this != &other) {
+ // if both *this and other block the same object's signals:
+ // unblock *this iff our dtor would unblock, but other's wouldn't
+ if (m_o != other.m_o || (!m_inhibited && other.m_inhibited))
+ unblock();
+ m_o = other.m_o;
+ m_blocked = other.m_blocked;
+ m_inhibited = other.m_inhibited;
+ // disable other:
+ other.m_o = 0;
+ }
+ return *this;
+}
+#endif
+
+QSignalBlocker::~QSignalBlocker()
+{
+ if (m_o && !m_inhibited)
+ m_o->blockSignals(m_blocked);
+}
+
+void QSignalBlocker::reblock()
+{
+ if (m_o) m_o->blockSignals(true);
+ m_inhibited = false;
+}
+
+void QSignalBlocker::unblock()
+{
+ if (m_o) m_o->blockSignals(m_blocked);
+ m_inhibited = true;
+}
+
namespace QtPrivate {
inline QObject & deref_for_methodcall(QObject &o) { return o; }
inline QObject & deref_for_methodcall(QObject *o) { return *o; }
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 8cbb244451..9df438b518 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -199,7 +199,6 @@ public:
return o->d_func();
}
- int senderSignalIndex() const;
int signalIndex(const char *signalName, const QMetaObject **meta = 0) const;
inline bool isSignalConnected(uint signalIdx) const;
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 7354c3f0d0..c3141c1abb 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -447,7 +447,7 @@ struct Q_CORE_EXPORT QMetaObject
const uint *data;
typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **);
StaticMetacallFunction static_metacall;
- const QMetaObject **relatedMetaObjects;
+ const QMetaObject * const *relatedMetaObjects;
void *extradata; //reserved for future use
} d;
};
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h
index fb6601f21b..de6f65ab7d 100644
--- a/src/corelib/kernel/qobjectdefs_impl.h
+++ b/src/corelib/kernel/qobjectdefs_impl.h
@@ -567,9 +567,9 @@ namespace QtPrivate {
Q_STATIC_ASSERT(CheckCompatibleArguments<FunctionPointer<Signal>::Arguments, FunctionPointer<Slot>::Arguments>::value)
*/
template<typename A1, typename A2> struct AreArgumentsCompatible {
- static int test(A2);
+ static int test(const typename RemoveRef<A2>::Type&);
static char test(...);
- static A1 dummy();
+ static const typename RemoveRef<A1>::Type &dummy();
enum { value = sizeof(test(dummy())) == sizeof(int) };
};
template<typename A1, typename A2> struct AreArgumentsCompatible<A1, A2&> { enum { value = false }; };
diff --git a/src/corelib/kernel/qppsattribute.cpp b/src/corelib/kernel/qppsattribute.cpp
new file mode 100644
index 0000000000..f6745d2354
--- /dev/null
+++ b/src/corelib/kernel/qppsattribute.cpp
@@ -0,0 +1,308 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $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 Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/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 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "qppsattribute_p.h"
+#include "qppsattributeprivate_p.h"
+
+#include <QDebug>
+#include <QVariant>
+
+///////////////////////////
+//
+// QPpsAttributePrivate
+//
+///////////////////////////
+
+QPpsAttributePrivate::QPpsAttributePrivate() : type(QPpsAttribute::None)
+{
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(int value, QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::Number;
+ attribute.d->data = value;
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(long long value, QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::Number;
+ attribute.d->data = value;
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(double value, QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::Number;
+ attribute.d->data = value;
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(bool value, QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::Bool;
+ attribute.d->data = value;
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(const QString &value,
+ QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::String;
+ attribute.d->data = value;
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(const QPpsAttributeList &value,
+ QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::Array;
+ attribute.d->data = QVariant::fromValue(value);
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+QPpsAttribute QPpsAttributePrivate::createPpsAttribute(const QPpsAttributeMap &value,
+ QPpsAttribute::Flags flags)
+{
+ QPpsAttribute attribute;
+ attribute.d->type = QPpsAttribute::Object;
+ attribute.d->data = QVariant::fromValue(value);
+ attribute.d->flags = flags;
+ return attribute;
+}
+
+///////////////////////////
+//
+// QPpsAttribute
+//
+///////////////////////////
+
+QPpsAttribute::QPpsAttribute():
+ d(new QPpsAttributePrivate())
+{
+}
+
+QPpsAttribute::~QPpsAttribute()
+{
+}
+
+QPpsAttribute::QPpsAttribute(const QPpsAttribute &other): d(other.d)
+{
+}
+
+QPpsAttribute &QPpsAttribute::operator=(const QPpsAttribute &other)
+{
+ d = other.d;
+ return *this;
+}
+
+#ifdef Q_COMPILER_RVALUE_REFS
+QPpsAttribute::QPpsAttribute(QPpsAttribute &&other): d(other.d)
+{
+ other.d->type = QPpsAttribute::None;
+}
+
+QPpsAttribute &QPpsAttribute::operator=(QPpsAttribute &&other)
+{
+ qSwap(d, other.d);
+ return *this;
+}
+#endif
+
+bool QPpsAttribute::operator==(const QPpsAttribute &other) const
+{
+ if (type() != other.type())
+ return false;
+ if (flags() != other.flags())
+ return false;
+
+ switch (type()) {
+ case QPpsAttribute::Number:
+ case QPpsAttribute::Bool:
+ case QPpsAttribute::String:
+ // QVariant can compare double, int, longlong, bool, and QString for us.
+ return d->data == other.d->data;
+ case QPpsAttribute::Array:
+ // QVariant can't compare custom types (like QPpsAttributeList), always returning false.
+ // So we pull the lists out manually and compare them.
+ return toList() == other.toList();
+ case QPpsAttribute::Object:
+ // QVariant can't compare custom types (like QPpsAttributeMap), always returning false.
+ // So we pull the maps out manually and compare them.
+ return toMap() == other.toMap();
+ case QPpsAttribute::None:
+ // Both are "None" type, so the actual content doesn't matter.
+ return true;
+ }
+ return d->data == other.d->data;
+}
+
+bool QPpsAttribute::isValid() const
+{
+ return d->type != QPpsAttribute::None;
+}
+
+QPpsAttribute::Type QPpsAttribute::type() const
+{
+ return d->type;
+}
+
+bool QPpsAttribute::isNumber() const
+{
+ return type() == QPpsAttribute::Number;
+}
+
+bool QPpsAttribute::isBool() const
+{
+ return type() == QPpsAttribute::Bool;
+}
+
+bool QPpsAttribute::isString() const
+{
+ return type() == QPpsAttribute::String;
+}
+
+bool QPpsAttribute::isArray() const
+{
+ return type() == QPpsAttribute::Array;
+}
+
+bool QPpsAttribute::isObject() const
+{
+ return type() == QPpsAttribute::Object;
+}
+
+double QPpsAttribute::toDouble() const
+{
+ return d->data.toDouble();
+}
+
+qlonglong QPpsAttribute::toLongLong() const
+{
+ return d->data.toLongLong();
+}
+
+int QPpsAttribute::toInt() const
+{
+ return d->data.toInt();
+}
+
+bool QPpsAttribute::toBool() const
+{
+ return d->data.toBool();
+}
+
+QString QPpsAttribute::toString() const
+{
+ return d->data.toString();
+}
+
+QPpsAttributeList QPpsAttribute::toList() const
+{
+ return d->data.value< QPpsAttributeList >();
+}
+
+QPpsAttributeMap QPpsAttribute::toMap() const
+{
+ return d->data.value< QPpsAttributeMap >();
+}
+
+QPpsAttribute::Flags QPpsAttribute::flags() const
+{
+ return d->flags;
+}
+
+QVariant QPpsAttribute::toVariant() const
+{
+ return d->data;
+}
+
+QDebug operator<<(QDebug dbg, const QPpsAttribute &attribute)
+{
+ dbg << "QPpsAttribute(";
+
+ switch (attribute.type()) {
+ case QPpsAttribute::Number:
+ switch (attribute.toVariant().type()) {
+ case QVariant::Int:
+ dbg << "Number, " << attribute.flags() << ", " << attribute.toInt();
+ break;
+ case QVariant::LongLong:
+ dbg << "Number, " << attribute.flags() << ", " << attribute.toLongLong();
+ break;
+ default:
+ dbg << "Number, " << attribute.flags() << ", " << attribute.toDouble();
+ break;
+ }
+ break;
+ case QPpsAttribute::Bool:
+ dbg << "Bool, " << attribute.flags() << ", " << attribute.toBool();
+ break;
+ case QPpsAttribute::String:
+ dbg << "String, " << attribute.flags() << ", " << attribute.toString();
+ break;
+ case QPpsAttribute::Array:
+ dbg << "Array, " << attribute.flags() << ", " << attribute.toList();
+ break;
+ case QPpsAttribute::Object:
+ dbg << "Object, " << attribute.flags() << ", " << attribute.toMap();
+ break;
+ case QPpsAttribute::None:
+ dbg << "None";
+ break;
+ }
+
+ dbg << ')';
+
+ return dbg;
+}
diff --git a/src/corelib/kernel/qppsattribute_p.h b/src/corelib/kernel/qppsattribute_p.h
new file mode 100644
index 0000000000..03a0f98a17
--- /dev/null
+++ b/src/corelib/kernel/qppsattribute_p.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $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 Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/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 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#ifndef QPPSATTRIBUTE_P_H
+#define QPPSATTRIBUTE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QList>
+#include <QMap>
+#include <QSharedDataPointer>
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QPpsAttributePrivate;
+class QPpsAttribute;
+
+typedef QList<QPpsAttribute> QPpsAttributeList;
+typedef QMap<QString, QPpsAttribute> QPpsAttributeMap;
+Q_DECLARE_METATYPE(QPpsAttributeList)
+Q_DECLARE_METATYPE(QPpsAttributeMap)
+
+class Q_CORE_EXPORT QPpsAttribute
+{
+public:
+
+ enum Type {
+ None = 0,
+ Number = 1,
+ Bool = 2,
+ String = 3,
+ Array = 4,
+ Object = 5
+ };
+
+ enum Flag {
+ Incomplete = 0x01,
+ Deleted = 0x02,
+ Created = 0x04,
+ Truncated = 0x08,
+ Purged = 0x10
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QPpsAttribute();
+ QPpsAttribute(const QPpsAttribute &other);
+ ~QPpsAttribute();
+
+ QPpsAttribute &operator=(const QPpsAttribute &other);
+ bool operator==(const QPpsAttribute &other) const;
+ bool operator!=(const QPpsAttribute &other) const;
+
+#ifdef Q_COMPILER_RVALUE_REFS
+ QPpsAttribute(QPpsAttribute &&other);
+ QPpsAttribute &operator=(QPpsAttribute &&other);
+#endif
+
+ bool isValid() const;
+ Type type() const;
+ QPpsAttribute::Flags flags() const;
+
+ bool isNumber() const;
+ bool isBool() const;
+ bool isString() const;
+ bool isArray() const;
+ bool isObject() const;
+
+ double toDouble() const;
+ qlonglong toLongLong() const;
+ int toInt() const;
+ bool toBool() const;
+ QString toString() const;
+ QPpsAttributeList toList() const;
+ QPpsAttributeMap toMap() const;
+ QVariant toVariant() const;
+
+private:
+ QSharedDataPointer<QPpsAttributePrivate> d;
+ friend class QPpsAttributePrivate;
+};
+
+inline bool QPpsAttribute::operator!=(const QPpsAttribute &other) const
+{
+ return !(*this == other);
+}
+
+Q_CORE_EXPORT QDebug operator<<(QDebug dbg, const QPpsAttribute &attribute);
+
+QT_END_NAMESPACE
+
+#endif // QPPSATTRIBUTE_P_H
diff --git a/src/corelib/kernel/qppsattributeprivate_p.h b/src/corelib/kernel/qppsattributeprivate_p.h
new file mode 100644
index 0000000000..0aa29d0895
--- /dev/null
+++ b/src/corelib/kernel/qppsattributeprivate_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $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 Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/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 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#ifndef QPPSATTRIBUTEPRIVATE_P_H
+#define QPPSATTRIBUTEPRIVATE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qppsattribute_p.h"
+
+#include <QList>
+#include <QMap>
+#include <QSharedData>
+#include <QString>
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QPpsAttributePrivate : public QSharedData
+{
+public:
+ QPpsAttributePrivate();
+
+ static QPpsAttribute createPpsAttribute(double value, QPpsAttribute::Flags flags);
+ static QPpsAttribute createPpsAttribute(long long value, QPpsAttribute::Flags flags);
+ static QPpsAttribute createPpsAttribute(int value, QPpsAttribute::Flags flags);
+ static QPpsAttribute createPpsAttribute(bool value, QPpsAttribute::Flags flags);
+ static QPpsAttribute createPpsAttribute(const QString &value, QPpsAttribute::Flags flags);
+ static QPpsAttribute createPpsAttribute(const QPpsAttributeList &value,
+ QPpsAttribute::Flags flags);
+ static QPpsAttribute createPpsAttribute(const QPpsAttributeMap &value,
+ QPpsAttribute::Flags flags);
+
+private:
+ friend class QPpsAttribute;
+
+ QVariant data;
+ QPpsAttribute::Type type;
+ QPpsAttribute::Flags flags;
+};
+
+QT_END_NAMESPACE
+
+#endif // QPPSATTRIBUTEPRIVATE_P_H
diff --git a/src/corelib/kernel/qppsobject.cpp b/src/corelib/kernel/qppsobject.cpp
new file mode 100644
index 0000000000..eb8e69baff
--- /dev/null
+++ b/src/corelib/kernel/qppsobject.cpp
@@ -0,0 +1,964 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $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 Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/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 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+
+#include "qppsobject_p.h"
+
+#include "qppsobjectprivate_p.h"
+#include "qppsattribute_p.h"
+#include "qppsattributeprivate_p.h"
+#include "qcore_unix_p.h"
+
+#include <QObject>
+#include <QSocketNotifier>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <confname.h>
+
+#include <sys/pps.h>
+
+///////////////////////////////////////////////////////////////////////////////
+static inline void safeAssign(bool *pointer, bool value)
+{
+ if (pointer)
+ *pointer = value;
+}
+
+class QPpsMaxSize
+{
+public:
+ QPpsMaxSize()
+ {
+ int fd = qt_safe_open("/pps/.all", O_RDONLY);
+ if (fd == -1) {
+ qWarning() << "qppsobject.cpp: qt_safe_open failed";
+ value = -1;
+ }
+
+ // This tells us the maximum transfer size across PPS
+ value = ::fpathconf(fd, _PC_REC_MAX_XFER_SIZE);
+
+ qt_safe_close(fd);
+ }
+
+ int value;
+};
+
+Q_GLOBAL_STATIC(QPpsMaxSize, ppsMaxSize)
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// QPpsObjectPrivate
+//
+///////////////////////////////////////////////////////////////////////////////
+
+QPpsObjectPrivate::QPpsObjectPrivate(const QString &path) :
+ notifier(0),
+ path(path),
+ error(EOK),
+ fd(-1),
+ readyReadEnabled(true)
+{
+}
+
+QPpsAttributeMap QPpsObjectPrivate::decode(const QByteArray &rawData, bool *ok)
+{
+ QPpsAttributeMap attributeMap;
+ pps_decoder_t decoder;
+
+ QByteArray mutableData(rawData);
+ pps_decoder_error_t error = pps_decoder_initialize(&decoder, mutableData.data());
+ if (error == PPS_DECODER_OK) {
+ // no need to check ok in this case
+ attributeMap = decodeObject(&decoder, ok);
+ } else {
+ qWarning() << "QPpsObjectPrivate::decode: pps_decoder_initialize failed";
+ *ok = false;
+ }
+
+ pps_decoder_cleanup(&decoder);
+ return attributeMap;
+}
+
+QVariantMap QPpsObjectPrivate::variantMapFromPpsAttributeMap(const QPpsAttributeMap &data)
+{
+ QVariantMap variantMap;
+
+ for (QPpsAttributeMap::const_iterator it = data.constBegin(); it != data.constEnd(); ++it) {
+ QVariant variant = variantFromPpsAttribute(it.value());
+ if (!variant.isValid())
+ return QVariantMap();
+ variantMap[it.key()] = variant;
+ }
+
+ return variantMap;
+}
+
+QPpsAttribute::Flags QPpsObjectPrivate::readFlags(pps_decoder_t *decoder)
+{
+ int rawFlags = pps_decoder_flags(decoder, 0);
+
+ QPpsAttribute::Flags attributeFlags;
+
+ if (rawFlags & PPS_INCOMPLETE)
+ attributeFlags |= QPpsAttribute::Incomplete;
+ if (rawFlags & PPS_DELETED)
+ attributeFlags |= QPpsAttribute::Deleted;
+ if (rawFlags & PPS_CREATED)
+ attributeFlags |= QPpsAttribute::Created;
+ if (rawFlags & PPS_TRUNCATED)
+ attributeFlags |= QPpsAttribute::Truncated;
+ if (rawFlags & PPS_PURGED)
+ attributeFlags |= QPpsAttribute::Purged;
+
+ return attributeFlags;
+}
+
+QPpsAttribute QPpsObjectPrivate::decodeString(pps_decoder_t *decoder)
+{
+ const char *value = 0;
+ pps_decoder_error_t error = pps_decoder_get_string(decoder, 0, &value);
+
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeString: PPS_DECODER_GET_STRING failed";
+ return QPpsAttribute();
+ }
+
+ QPpsAttribute::Flags flags = readFlags(decoder);
+ return QPpsAttributePrivate::createPpsAttribute(QString::fromUtf8(value), flags);
+}
+
+QPpsAttribute QPpsObjectPrivate::decodeNumber(pps_decoder_t *decoder)
+{
+ // In order to support more number types, we have to do something stupid because the PPS
+ // library won't let us work any other way. Basically, we have to probe the encoded type in
+ // order to try to get exactly what we want.
+ long long llValue;
+ double dValue;
+ int iValue;
+ QPpsAttribute::Flags flags;
+
+ if (pps_decoder_is_integer(decoder, 0)) {
+ pps_decoder_error_t error = pps_decoder_get_int(decoder, 0, &iValue);
+ switch (error) {
+ case PPS_DECODER_OK:
+ flags = readFlags(decoder);
+ return QPpsAttributePrivate::createPpsAttribute(iValue, flags);
+ case PPS_DECODER_CONVERSION_FAILED:
+ error = pps_decoder_get_int64(decoder, 0, &llValue);
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeNumber: failed to decode integer";
+ return QPpsAttribute();
+ }
+ flags = readFlags(decoder);
+ return QPpsAttributePrivate::createPpsAttribute(llValue, flags);
+ default:
+ qWarning() << "QPpsObjectPrivate::decodeNumber: pps_decoder_get_int failed";
+ return QPpsAttribute();
+ }
+ } else {
+ pps_decoder_error_t error = pps_decoder_get_double(decoder, 0, &dValue);
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeNumber: pps_decoder_get_double failed";
+ return QPpsAttribute();
+ }
+ flags = readFlags(decoder);
+ return QPpsAttributePrivate::createPpsAttribute(dValue, flags);
+ }
+}
+
+QPpsAttribute QPpsObjectPrivate::decodeBool(pps_decoder_t *decoder)
+{
+ bool value;
+ pps_decoder_error_t error = pps_decoder_get_bool(decoder, 0, &value);
+
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeBool: pps_decoder_get_bool failed";
+ return QPpsAttribute();
+ }
+
+ QPpsAttribute::Flags flags = readFlags(decoder);
+ return QPpsAttributePrivate::createPpsAttribute(value, flags);
+}
+
+template<typename T>
+QPpsAttribute QPpsObjectPrivate::decodeNestedData(T (*decodeFunction)(pps_decoder_t *, bool *),
+ pps_decoder_t *decoder)
+{
+ // We must read the flags before we push into the object,
+ // otherwise we'll get the flags for the first element in the object.
+ QPpsAttribute::Flags flags = readFlags(decoder);
+
+ if (!decoderPush(decoder))
+ return QPpsAttribute();
+
+ bool ok = false;
+
+ T attributeContainer = decodeFunction(decoder, &ok);
+
+ if (!ok)
+ return QPpsAttribute();
+
+ QPpsAttribute returnVal = QPpsAttributePrivate::createPpsAttribute(attributeContainer, flags);
+
+ if (!decoderPop(decoder))
+ return QPpsAttribute();
+
+ return returnVal;
+}
+
+QPpsAttribute QPpsObjectPrivate::decodeData(pps_decoder_t *decoder)
+{
+ pps_node_type_t nodeType = pps_decoder_type(decoder, 0);
+ switch (nodeType) {
+ case PPS_TYPE_BOOL:
+ return decodeBool(decoder);
+ case PPS_TYPE_NUMBER:
+ return decodeNumber(decoder);
+ case PPS_TYPE_STRING:
+ return decodeString(decoder);
+ case PPS_TYPE_ARRAY:
+ return decodeNestedData(&QPpsObjectPrivate::decodeArray, decoder);
+ case PPS_TYPE_OBJECT:
+ return decodeNestedData(&QPpsObjectPrivate::decodeObject, decoder);
+ case PPS_TYPE_DELETED: {
+ // This should create an attribute with the flags set to PpsAttribute::Deleted.
+ // However, we need to create a valid QPpsAttribute while doing so. To do this,
+ // I'll create an empty map as a sentinel. Note that the readFlags() call with produce
+ // the correct set of flags. While I suspect that there will never be any other flags
+ // set in conjunction with this one, I'd rather not be surprised later.
+ QPpsAttributeMap emptyMap;
+ QPpsAttribute::Flags flags = readFlags(decoder);
+ QPpsAttribute returnVal = QPpsAttributePrivate::createPpsAttribute(emptyMap, flags);
+ return returnVal;
+ }
+ case PPS_TYPE_NULL:
+ case PPS_TYPE_NONE:
+ case PPS_TYPE_UNKNOWN:
+ default:
+ qWarning() << "QPpsObjectPrivate::decodeData: invalid pps_node_type";
+ return QPpsAttribute();
+ }
+}
+
+QPpsAttributeList QPpsObjectPrivate::decodeArray(pps_decoder_t *decoder, bool *ok)
+{
+ QPpsAttributeList list;
+
+ int length = pps_decoder_length(decoder);
+ for (int i = 0; i < length; ++i) {
+ // Force movement to a specific index.
+ pps_decoder_error_t error = pps_decoder_goto_index(decoder, i);
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeArray: pps_decoder_goto_index failed";
+ *ok = false;
+ return QPpsAttributeList();
+ }
+
+ QPpsAttribute ppsAttribute = decodeData(decoder);
+ if (!ppsAttribute.isValid()) {
+ *ok = false;
+ return QPpsAttributeList();
+ }
+
+ list << ppsAttribute;
+ }
+
+ *ok = true;
+ return list;
+}
+
+QPpsAttributeMap QPpsObjectPrivate::decodeObject(pps_decoder_t *decoder, bool *ok)
+{
+ QPpsAttributeMap map;
+
+ int length = pps_decoder_length(decoder);
+ for (int i = 0; i < length; ++i) {
+ // Force movement to a specific index.
+ pps_decoder_error_t error = pps_decoder_goto_index(decoder, i);
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeObject: pps_decoder_goto_index failed";
+ *ok = false;
+ return QPpsAttributeMap();
+ }
+ QString name = QString::fromUtf8(pps_decoder_name(decoder));
+ QPpsAttribute ppsAttribute = decodeData(decoder);
+ if (!ppsAttribute.isValid()) {
+ *ok = false;
+ return QPpsAttributeMap();
+ }
+ map[name] = ppsAttribute;
+ }
+
+ *ok = true;
+ return map;
+}
+
+QVariant QPpsObjectPrivate::variantFromPpsAttribute(const QPpsAttribute &attribute)
+{
+ switch (attribute.type()) {
+ case QPpsAttribute::Number:
+ switch (attribute.toVariant().type()) {
+ case QVariant::Int:
+ return attribute.toInt();
+ case QVariant::LongLong:
+ return attribute.toLongLong();
+ default:
+ return attribute.toDouble();
+ }
+ break;
+ case QPpsAttribute::Bool:
+ return attribute.toBool();
+ case QPpsAttribute::String:
+ return attribute.toString();
+ case QPpsAttribute::Array: {
+ QVariantList variantList;
+ Q_FOREACH (const QPpsAttribute &attr, attribute.toList()) {
+ QVariant variant = variantFromPpsAttribute(attr);
+ if (!variant.isValid())
+ return QVariantList();
+ variantList << variant;
+ }
+ return variantList;
+ }
+ case QPpsAttribute::Object:
+ return variantMapFromPpsAttributeMap(attribute.toMap());
+ case QPpsAttribute::None:
+ default:
+ qWarning() << "QPpsObjectPrivate::variantFromPpsAttribute: invalid attribute parameter";
+ return QVariant();
+ }
+}
+
+QByteArray QPpsObjectPrivate::encode(const QVariantMap &ppsData, bool *ok)
+{
+ pps_encoder_t encoder;
+ pps_encoder_initialize(&encoder, false);
+
+ encodeObject(&encoder, ppsData, ok);
+ const char *rawData = 0;
+ if (*ok) {
+ // rawData points to a memory owned by encoder.
+ // The memory will be freed when pps_encoder_cleanup is called.
+ rawData = pps_encoder_buffer(&encoder);
+ if (!rawData) {
+ qWarning() << "QPpsObjectPrivate::encode: pps_encoder_buffer failed";
+ *ok = false;
+ }
+ }
+
+ pps_encoder_cleanup(&encoder);
+ return QByteArray(rawData);
+}
+
+void QPpsObjectPrivate::encodeData(pps_encoder_t *encoder, const char *name, const QVariant &data,
+ bool *ok)
+{
+ QString errorFunction;
+ pps_encoder_error_t error = PPS_ENCODER_OK;
+ switch (data.type()) {
+ case QVariant::Bool:
+ error = pps_encoder_add_bool(encoder, name, data.toBool());
+ errorFunction = QStringLiteral("pps_encoder_add_bool");
+ break;
+ // We want to support encoding uint even though libpps doesn't support it directly.
+ // We can't encode uint as an int since that will lose precision (e.g. 2^31+1 can't be
+ // encoded that way). However, we can convert uint to double without losing precision.
+ // QVariant.toDouble() conveniently takes care of the conversion for us.
+ case QVariant::UInt:
+ case QVariant::Double:
+ error = pps_encoder_add_double(encoder, name, data.toDouble());
+ errorFunction = QStringLiteral("pps_encoder_add_double");
+ break;
+ case QVariant::Int:
+ error = pps_encoder_add_int(encoder, name, data.toInt());
+ errorFunction = QStringLiteral("pps_encoder_add_int");
+ break;
+ case QVariant::LongLong:
+ error = pps_encoder_add_int64(encoder, name, data.toLongLong());
+ errorFunction = QStringLiteral("pps_encoder_add_int64");
+ break;
+ case QVariant::String:
+ error = pps_encoder_add_string(encoder, name, data.toString().toUtf8().constData());
+ errorFunction = QStringLiteral("pps_encoder_add_string");
+ break;
+ case QVariant::List:
+ error = pps_encoder_start_array(encoder, name);
+ errorFunction = QStringLiteral("pps_encoder_start_array");
+ if (error == PPS_ENCODER_OK) {
+ encodeArray(encoder, data.toList(), ok);
+ error = pps_encoder_end_array(encoder);
+ errorFunction = QStringLiteral("pps_encoder_end_array");
+ }
+ break;
+ case QVariant::Map:
+ error = pps_encoder_start_object(encoder, name);
+ errorFunction = QStringLiteral("pps_encoder_start_object");
+ if (error == PPS_ENCODER_OK) {
+ encodeObject(encoder, data.toMap(), ok);
+ error = pps_encoder_end_object(encoder);
+ errorFunction = QStringLiteral("pps_encoder_end_object");
+ }
+ break;
+ case QVariant::Invalid:
+ error = pps_encoder_add_null(encoder, name);
+ errorFunction = QStringLiteral("pps_encoder_add_null");
+ break;
+ default:
+ qWarning() << "QPpsObjectPrivate::encodeData: the type of the parameter data is invalid";
+ *ok = false;
+ return;
+ }
+
+ if (error != PPS_ENCODER_OK) {
+ qWarning() << "QPpsObjectPrivate::encodeData: " << errorFunction << " failed";
+ *ok = false;
+ } else {
+ *ok = true;
+ }
+}
+
+void QPpsObjectPrivate::encodeArray(pps_encoder_t *encoder, const QVariantList &data, bool *ok)
+{
+ for (QVariantList::const_iterator it = data.constBegin(); it != data.constEnd(); ++it) {
+ encodeData(encoder, 0, *it, ok);
+ if (!(*ok))
+ return;
+ }
+ // if the passed data is empty, nothing went wrong and ok is set to true
+ *ok = true;
+}
+
+void QPpsObjectPrivate::encodeObject(pps_encoder_t *encoder, const QVariantMap &data, bool *ok)
+{
+ for (QVariantMap::const_iterator it = data.constBegin(); it != data.constEnd(); ++it) {
+ encodeData(encoder, it.key().toUtf8().constData(), it.value(), ok);
+ if (!(*ok))
+ return;
+ }
+ // if the passed data is empty, nothing went wrong and ok is set to true
+ *ok = true;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// QPpsObjectPrivate
+//
+///////////////////////////////////////////////////////////////////////////////
+
+QPpsObject::QPpsObject(const QString &path, QObject *parent) :
+ QObject(parent),
+ d_ptr(new QPpsObjectPrivate(path))
+{
+}
+
+QPpsObject::~QPpsObject()
+{
+ // RAII - ensure file gets closed
+ if (isOpen())
+ close();
+}
+
+int QPpsObject::error() const
+{
+ Q_D(const QPpsObject);
+ return d->error;
+}
+
+QString QPpsObject::errorString() const
+{
+ Q_D(const QPpsObject);
+ return qt_error_string(d->error);
+}
+
+bool QPpsObject::isReadyReadEnabled() const
+{
+ Q_D(const QPpsObject);
+
+ // query state of read ready signal
+ return d->readyReadEnabled;
+}
+
+void QPpsObject::setReadyReadEnabled(bool enable)
+{
+ Q_D(QPpsObject);
+
+ // toggle whether socket notifier will emit a signal on read ready
+ d->readyReadEnabled = enable;
+ if (isOpen())
+ d->notifier->setEnabled(enable);
+}
+
+bool QPpsObject::isBlocking() const
+{
+ Q_D(const QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->error = EBADF;
+ return false;
+ }
+
+ // query file status flags
+ int flags = fcntl(d->fd, F_GETFL);
+ if (flags == -1) {
+ d->error = errno;
+ return false;
+ }
+ // check if non-blocking flag is unset
+ return ((flags & O_NONBLOCK) != O_NONBLOCK);
+}
+
+bool QPpsObject::setBlocking(bool enable)
+{
+ Q_D(QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->error = EBADF;
+ return false;
+ }
+
+ // query file status flags
+ int flags = fcntl(d->fd, F_GETFL);
+ if (flags == -1) {
+ d->error = errno;
+ return false;
+ }
+
+ // configure non-blocking flag
+ if (enable)
+ flags &= ~O_NONBLOCK;
+ else
+ flags |= O_NONBLOCK;
+
+ // update file status flags
+ flags = fcntl(d->fd, F_SETFL, flags);
+ if (flags == -1) {
+ d->error = errno;
+ return false;
+ }
+
+ return true;
+}
+
+bool QPpsObject::isOpen() const
+{
+ Q_D(const QPpsObject);
+ return (d->fd != -1);
+}
+
+bool QPpsObject::open(QPpsObject::OpenModes mode)
+{
+ Q_D(QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // abort if file already open
+ if (isOpen()) {
+ d->error = EBUSY;
+ return false;
+ }
+
+ // convert pps flags to open flags
+ int oflags = 0;
+ if ((mode & QPpsObject::Publish) && (mode & QPpsObject::Subscribe))
+ oflags |= O_RDWR;
+ else if (mode & QPpsObject::Publish)
+ oflags |= O_WRONLY;
+ else if (mode & QPpsObject::Subscribe)
+ oflags |= O_RDONLY;
+
+ if (mode & QPpsObject::Create)
+ oflags |= O_CREAT | O_EXCL;
+
+ if (mode & QPpsObject::DeleteContents)
+ oflags |= O_TRUNC;
+
+ // open pps file
+ d->fd = qt_safe_open(d->path.toUtf8().data(), oflags, 0666);
+ if (d->fd == -1) {
+ d->error = errno;
+ return false;
+ }
+ // wire up socket notifier to know when reads are ready
+ d->notifier = new QSocketNotifier(d->fd, QSocketNotifier::Read, this);
+ d->notifier->setEnabled(d->readyReadEnabled);
+ QObject::connect(d->notifier, &QSocketNotifier::activated, this, &QPpsObject::readyRead);
+ return true;
+}
+
+bool QPpsObject::close()
+{
+ Q_D(QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->error = EBADF;
+ return false;
+ }
+
+ // shutdown socket notifier
+ delete d->notifier;
+ d->notifier = 0;
+
+ // close pps file
+ const int result = qt_safe_close(d->fd);
+ d->fd = -1;
+
+ // check success of operation
+ if (result != 0) {
+ d->error = errno;
+ return false;
+ }
+ return true;
+}
+
+QByteArray QPpsObject::read(bool *ok)
+{
+ Q_D(QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->error = EBADF;
+ safeAssign(ok, false);
+ return QByteArray();
+ }
+
+ const int maxSize = ppsMaxSize->value;
+ if (maxSize == -1) {
+ qWarning() << "QPpsObject::read: maxSize is equal to -1";
+ safeAssign(ok, false);
+ return QByteArray();
+ }
+
+ QByteArray byteArray;
+ byteArray.resize(maxSize); // resize doesn't initialize the data
+ const int result = qt_safe_read(d->fd, byteArray.data(), byteArray.size());
+
+ if (result == -1) {
+ d->error = errno;
+ qWarning() << "QPpsObject::read failed to read pps data, error " << errorString();
+ safeAssign(ok, false);
+ return QByteArray(); // Specifically return a default-constructed QByteArray.
+ }
+ if (result == 0) {
+ // normalize the behavior of read() when no data is ready so a pps object
+ // put in non-blocking mode via opening w/o wait (read returns 0) looks
+ // the same as a pps object put in non-blocking mode by setting O_NONBLOCK
+ // (read returns EAGAIN)
+ d->error = EAGAIN;
+ safeAssign(ok, false);
+ return QByteArray(); // Specifically return a default-constructed QByteArray.
+ }
+ // resize byte array to amount actually read
+ byteArray.resize(result);
+ safeAssign(ok, true);
+ return byteArray;
+}
+
+bool QPpsObject::write(const QByteArray &byteArray)
+{
+ Q_D(QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->error = EBADF;
+ return false;
+ }
+
+ // write entire byte array to pps file
+ const int result = qt_safe_write(d->fd, byteArray.data(), byteArray.size());
+ if (result == -1)
+ d->error = errno;
+
+ return (result == byteArray.size());
+}
+
+int QPpsObject::writeMessage(const QString &msg, const QVariantMap &dat)
+{
+ // Treat empty msg as an encoding error
+ if (msg.isEmpty())
+ return -1;
+
+ bool ok;
+ QByteArray byteArray = encodeMessage(msg, dat, &ok);
+
+ if (!ok)
+ return -1;
+
+ ok = write(byteArray);
+ if (!ok)
+ return error();
+
+ return EOK;
+}
+
+int QPpsObject::writeMessage(const QString &msg, const QString &id, const QVariantMap &dat)
+{
+ // Treat empty msg or id as an encoding error
+ if (msg.isEmpty() || id.isEmpty())
+ return -1;
+
+ bool ok;
+ QByteArray byteArray = encodeMessage(msg, id, dat, &ok);
+
+ if (!ok)
+ return -1;
+
+ ok = write(byteArray);
+ if (!ok)
+ return error();
+
+ return EOK;
+}
+
+bool QPpsObject::remove()
+{
+ Q_D(QPpsObject);
+
+ // reset last error
+ d->error = EOK;
+
+ // delete pps file
+ const int result = unlink(d->path.toUtf8().data());
+
+ // check success of operation
+ if (result != 0) {
+ d->error = errno;
+ return false;
+ }
+ return true;
+}
+
+// static
+QVariantMap QPpsObject::decode(const QByteArray &rawData, bool *ok)
+{
+ QPpsAttributeMap mapData = decodeWithFlags(rawData, 0, ok);
+
+ // If *ok is false, then mapData is empty, so the resulting QVariantMap
+ // will also be empty, as desired.
+ return QPpsObjectPrivate::variantMapFromPpsAttributeMap(mapData);
+}
+
+// static
+QPpsAttributeMap QPpsObject::decodeWithFlags(const QByteArray &rawData, bool *ok)
+{
+ return QPpsObject::decodeWithFlags(rawData, 0, ok);
+}
+
+// static
+QPpsAttributeMap QPpsObject::decodeWithFlags(const QByteArray &rawData,
+ QPpsAttribute *objectAttribute, bool *ok)
+{
+ safeAssign(ok, true);
+
+ bool success = false;
+ QPpsAttributeMap mapData = QPpsObjectPrivate::decode(rawData, &success);
+ if (!success) {
+ safeAssign(ok, false);
+ return QPpsAttributeMap();
+ }
+
+ // The object name is the key of the first element, and the flags of that attribute
+ // give the status for the object as a whole.
+ if (!mapData.isEmpty() && objectAttribute) {
+ QString extractedName = mapData.begin().key();
+ QPpsAttribute topmostAttribute = mapData.begin().value();
+ QPpsAttribute::Flags topmostFlags = topmostAttribute.flags();
+ QPpsAttribute toplevelAttribute =
+ QPpsAttributePrivate::createPpsAttribute(extractedName, topmostFlags);
+ *objectAttribute = toplevelAttribute;
+ }
+
+ return mapData;
+}
+
+
+// static
+QByteArray QPpsObject::encode(const QVariantMap &ppsData, bool *ok)
+{
+ safeAssign(ok, true);
+
+ bool success = false;
+ QByteArray byteArray = QPpsObjectPrivate::encode(ppsData, &success);
+ if (!success) {
+ safeAssign(ok, false);
+ return QByteArray();
+ }
+ return byteArray;
+}
+
+// static
+QByteArray QPpsObject::encodeMessage(const QString &msg, const QVariantMap &dat, bool *ok)
+{
+ safeAssign(ok, true);
+
+ // Treat empty msg as an encoding error
+ if (msg.isEmpty()) {
+ safeAssign(ok, false);
+ return QByteArray();
+ }
+
+ QVariantMap ppsData;
+ ppsData[QStringLiteral("msg")] = msg;
+ ppsData[QStringLiteral("dat")] = dat;
+
+ return QPpsObject::encode(ppsData, ok);
+}
+
+// static
+QByteArray QPpsObject::encodeMessage(const QString &msg, const QString &id, const QVariantMap &dat,
+ bool *ok)
+{
+ safeAssign(ok, true);
+
+ // Treat empty msg or id as an encoding error
+ if (msg.isEmpty() || id.isEmpty()) {
+ safeAssign(ok, false);
+ return QByteArray();
+ }
+
+ QVariantMap ppsData;
+ ppsData[QStringLiteral("msg")] = msg;
+ ppsData[QStringLiteral("id")] = id;
+ ppsData[QStringLiteral("dat")] = dat;
+
+ return QPpsObject::encode(ppsData, ok);
+}
+
+// static
+int QPpsObject::sendMessage(const QString &path, const QString &message)
+{
+ QPpsObject pps(path);
+
+ bool ok = pps.open(QPpsObject::Publish);
+ if (!ok)
+ return pps.error();
+
+ ok = pps.write(message.toLocal8Bit());
+ if (!ok)
+ return pps.error();
+
+ return EOK;
+}
+
+// static
+int QPpsObject::sendMessage(const QString &path, const QVariantMap &message)
+{
+ QPpsObject pps(path);
+
+ bool ok = pps.open(QPpsObject::Publish);
+ if (!ok)
+ return pps.error();
+
+ QByteArray payload = QPpsObject::encode(message, &ok);
+ if (!ok)
+ return -1;
+
+ ok = pps.write(payload);
+ if (!ok)
+ return pps.error();
+
+ return EOK;
+}
+
+// static
+int QPpsObject::sendMessage(const QString &path, const QString &msg, const QVariantMap &dat)
+{
+ // Treat empty msg as an encoding error
+ if (msg.isEmpty())
+ return -1;
+
+ QPpsObject pps(path);
+
+ bool ok = pps.open(QPpsObject::Publish);
+ if (!ok)
+ return pps.error();
+
+ QByteArray payload = QPpsObject::encodeMessage(msg, dat, &ok);
+ if (!ok)
+ return -1;
+
+ ok = pps.write(payload);
+ if (!ok)
+ return pps.error();
+
+ return EOK;
+}
+
+// static
+int QPpsObject::sendMessage(const QString &path, const QByteArray &ppsData)
+{
+ QPpsObject pps(path);
+
+ bool ok = pps.open(QPpsObject::Publish);
+ if (!ok)
+ return pps.error();
+
+ ok = pps.write(ppsData);
+ if (!ok)
+ return pps.error();
+
+ return EOK;
+}
diff --git a/src/corelib/kernel/qppsobject_p.h b/src/corelib/kernel/qppsobject_p.h
new file mode 100644
index 0000000000..1095796a13
--- /dev/null
+++ b/src/corelib/kernel/qppsobject_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $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 Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/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 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#ifndef QPPSOBJECT_P_H
+#define QPPSOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qppsattribute_p.h"
+
+#include <QMap>
+#include <QObject>
+#include <QVariantMap>
+
+QT_BEGIN_NAMESPACE
+
+class QPpsObjectPrivate;
+
+class Q_CORE_EXPORT QPpsObject : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum OpenMode {
+ Publish = 1,
+ Subscribe = 2,
+ PublishSubscribe = Publish | Subscribe,
+ Create = 4,
+ DeleteContents = 8
+ };
+ Q_DECLARE_FLAGS(OpenModes, OpenMode)
+
+ explicit QPpsObject(const QString &path, QObject *parent = 0);
+ virtual ~QPpsObject();
+
+ int error() const;
+ QString errorString() const;
+
+ bool isReadyReadEnabled() const;
+ bool isBlocking() const;
+ bool setBlocking(bool enable);
+ bool isOpen() const;
+
+ bool open(QPpsObject::OpenModes mode = QPpsObject::PublishSubscribe);
+ bool close();
+ bool remove();
+
+ QByteArray read(bool *ok = 0);
+ bool write(const QByteArray &byteArray);
+
+ int writeMessage(const QString &msg, const QVariantMap &dat);
+ int writeMessage(const QString &msg, const QString &id, const QVariantMap &dat);
+
+ static QVariantMap decode(const QByteArray &rawData, bool *ok = 0);
+ static QPpsAttributeMap decodeWithFlags(const QByteArray &rawData, bool *ok = 0);
+ static QPpsAttributeMap decodeWithFlags(const QByteArray &rawData,
+ QPpsAttribute *objectAttribute, bool *ok = 0);
+
+ static QByteArray encode(const QVariantMap &ppsData, bool *ok = 0);
+ static QByteArray encodeMessage(const QString &msg, const QVariantMap &dat, bool *ok = 0);
+ static QByteArray encodeMessage(const QString &msg, const QString &id, const QVariantMap &dat,
+ bool *ok = 0);
+
+ static int sendMessage(const QString &path, const QString &message);
+ static int sendMessage(const QString &path, const QVariantMap &message);
+ static int sendMessage(const QString &path, const QString &msg, const QVariantMap &dat);
+ static int sendMessage(const QString &path, const QByteArray &ppsData);
+
+public Q_SLOTS:
+ void setReadyReadEnabled(bool enable);
+
+Q_SIGNALS:
+ void readyRead();
+
+private:
+ QScopedPointer<QPpsObjectPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QPpsObject)
+ Q_DISABLE_COPY(QPpsObject)
+};
+
+QT_END_NAMESPACE
+
+#endif // QPPSOBJECT_P_H
diff --git a/src/corelib/kernel/qppsobjectprivate_p.h b/src/corelib/kernel/qppsobjectprivate_p.h
new file mode 100644
index 0000000000..d291d6b559
--- /dev/null
+++ b/src/corelib/kernel/qppsobjectprivate_p.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $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 Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/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 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#ifndef QPPSOBJECTPRIVATE_P_H_
+#define QPPSOBJECTPRIVATE_P_H_
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qppsattribute_p.h"
+
+#include <QMap>
+#include <QDebug>
+
+#include <sys/pps.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSocketNotifier;
+
+class QPpsObjectPrivate
+{
+public:
+ explicit QPpsObjectPrivate(const QString &path);
+
+ static QPpsAttributeMap decode(const QByteArray &rawData, bool *ok);
+ static QByteArray encode(const QVariantMap &ppsData, bool *ok);
+
+ static QVariantMap variantMapFromPpsAttributeMap(const QPpsAttributeMap &data);
+
+ QSocketNotifier *notifier;
+ QString path;
+ mutable int error;
+ int fd;
+ bool readyReadEnabled;
+
+private:
+ static QPpsAttribute::Flags readFlags(pps_decoder_t *decoder);
+ static QPpsAttribute decodeString(pps_decoder_t *decoder);
+ static QPpsAttribute decodeNumber(pps_decoder_t *decoder);
+ static QPpsAttribute decodeBool(pps_decoder_t *decoder);
+ static QPpsAttribute decodeData(pps_decoder_t *decoder);
+ static QPpsAttributeList decodeArray(pps_decoder_t *decoder, bool *ok);
+ static QPpsAttributeMap decodeObject(pps_decoder_t *decoder, bool *ok);
+ static bool decoderPush(pps_decoder_t *decoder, const char *name = 0);
+ static bool decoderPop(pps_decoder_t *decoder);
+
+ template<typename T>
+ static QPpsAttribute decodeNestedData(T (*decodeFunction)(pps_decoder_t *, bool *),
+ pps_decoder_t *decoder);
+
+ static void encodeData(pps_encoder_t *encoder, const char *name,
+ const QVariant &data, bool *ok);
+ static void encodeArray(pps_encoder_t *encoder, const QVariantList &data, bool *ok);
+ static void encodeObject(pps_encoder_t *encoder, const QVariantMap &data, bool *ok);
+
+ static QVariant variantFromPpsAttribute(const QPpsAttribute &attribute);
+};
+
+inline bool QPpsObjectPrivate::decoderPush(pps_decoder_t *decoder, const char *name)
+{
+ pps_decoder_error_t error = pps_decoder_push(decoder, name);
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeData: pps_decoder_push failed";
+ return false;
+ }
+ return true;
+}
+
+inline bool QPpsObjectPrivate::decoderPop(pps_decoder_t *decoder)
+{
+ pps_decoder_error_t error = pps_decoder_pop(decoder);
+ if (error != PPS_DECODER_OK) {
+ qWarning() << "QPpsObjectPrivate::decodeData: pps_decoder_pop failed";
+ return false;
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif /* QPPSOBJECTPRIVATE_P_H_ */
diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp
index 1f53b94c4d..407a6a4e02 100644
--- a/src/corelib/kernel/qsharedmemory.cpp
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE
*/
QString
QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
- const QString &prefix)
+ const QString &prefix)
{
if (key.isEmpty())
return QString();
@@ -350,7 +350,7 @@ bool QSharedMemory::create(int size, AccessMode mode)
if (size <= 0) {
d->error = QSharedMemory::InvalidSize;
d->errorString =
- QSharedMemory::tr("%1: create size is less then 0").arg(function);
+ QSharedMemory::tr("%1: create size is less then 0").arg(function);
return false;
}
diff --git a/src/corelib/kernel/qsystemsemaphore_win.cpp b/src/corelib/kernel/qsystemsemaphore_win.cpp
index edf90a31ac..77f7a60814 100644
--- a/src/corelib/kernel/qsystemsemaphore_win.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_win.cpp
@@ -115,7 +115,7 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count)
return false;
if (count > 0) {
- if (0 == ReleaseSemaphore(semaphore, count, 0)) {
+ if (0 == ReleaseSemaphore(semaphore, count, 0)) {
setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
#if defined QSYSTEMSEMAPHORE_DEBUG
qDebug() << QLatin1String("QSystemSemaphore::modifySemaphore ReleaseSemaphore failed");
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 69cfa7888f..91ccf3996e 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -868,7 +868,7 @@ static void customConstruct(QVariant::Private *d, const void *copy)
// this logic should match with QVariantIntegrator::CanUseInternalSpace
if (size <= sizeof(QVariant::Private::Data)
- && (type.flags() & QMetaType::MovableType)) {
+ && (type.flags() & (QMetaType::MovableType | QMetaType::IsEnumeration))) {
type.construct(&d->data.ptr, copy);
d->is_shared = false;
} else {
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index 4ec049e20d..b523d19187 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -67,7 +67,7 @@ template<typename T>
struct QVariantIntegrator
{
static const bool CanUseInternalSpace = sizeof(T) <= sizeof(QVariant::Private::Data)
- && (!QTypeInfo<T>::isStatic);
+ && ((!QTypeInfo<T>::isStatic) || Q_IS_ENUM(T));
};
Q_STATIC_ASSERT(QVariantIntegrator<double>::CanUseInternalSpace);
Q_STATIC_ASSERT(QVariantIntegrator<long int>::CanUseInternalSpace);
diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp
index eab5a37645..c694237dc3 100644
--- a/src/corelib/kernel/qwineventnotifier.cpp
+++ b/src/corelib/kernel/qwineventnotifier.cpp
@@ -41,7 +41,11 @@
#include "qwineventnotifier.h"
+#ifdef Q_OS_WINRT
+#include "qeventdispatcher_winrt_p.h"
+#else
#include "qeventdispatcher_win_p.h"
+#endif
#include "qcoreapplication.h"
#include <private/qthread_p.h>