summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/angle/src/config.pri2
-rw-r--r--src/corelib/global/qglobal.cpp2
-rw-r--r--src/corelib/global/qlogging.cpp29
-rw-r--r--src/corelib/kernel/qbasictimer.cpp38
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp6
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp6
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp12
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp12
-rw-r--r--src/corelib/kernel/qobject.cpp31
-rw-r--r--src/corelib/kernel/qsocketnotifier.cpp4
-rw-r--r--src/corelib/kernel/qtimer.cpp4
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp10
-rw-r--r--src/corelib/tools/qversionnumber.cpp8
-rw-r--r--src/gui/image/qimage.cpp8
-rw-r--r--src/gui/kernel/qevent.cpp11
-rw-r--r--src/gui/kernel/qplatformcursor.cpp9
-rw-r--r--src/gui/opengl/qopenglpaintengine.cpp26
-rw-r--r--src/gui/painting/qregion.cpp2
-rw-r--r--src/gui/text/qfontengine.cpp2
-rw-r--r--src/network/socket/qabstractsocket.cpp2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm1
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp37
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp2
-rw-r--r--src/plugins/platforms/ios/ios.pro2
-rw-r--r--src/plugins/platforms/ios/qiosmenu.h144
-rw-r--r--src/plugins/platforms/ios/qiosmenu.mm525
-rw-r--r--src/plugins/platforms/ios/qiostheme.h3
-rw-r--r--src/plugins/platforms/ios/qiostheme.mm12
-rw-r--r--src/plugins/platforms/ios/quiview.mm8
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp2
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp48
-rw-r--r--src/sql/models/qsqltablemodel.cpp2
-rw-r--r--src/testlib/qtestblacklist.cpp1
-rw-r--r--src/testlib/qtestcase.cpp6
-rw-r--r--src/widgets/itemviews/qheaderview.cpp3
-rw-r--r--src/widgets/kernel/qdesktopwidget.cpp13
-rw-r--r--src/widgets/kernel/qdesktopwidget.h1
-rw-r--r--src/widgets/kernel/qdesktopwidget_p.h1
-rw-r--r--src/widgets/styles/qcommonstyle.cpp15
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp16
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp17
-rw-r--r--src/widgets/widgets/qabstractspinbox.cpp7
-rw-r--r--src/widgets/widgets/qabstractspinbox_p.h1
-rw-r--r--src/widgets/widgets/qcalendartextnavigator_p.h112
-rw-r--r--src/widgets/widgets/qcalendarwidget.cpp47
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp31
-rw-r--r--src/widgets/widgets/qplaintextedit.h1
-rw-r--r--src/widgets/widgets/qtextedit.cpp31
-rw-r--r--src/widgets/widgets/qtextedit.h2
-rw-r--r--src/widgets/widgets/widgets.pri1
52 files changed, 1045 insertions, 275 deletions
diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri
index 07a18620da..f23bebef44 100644
--- a/src/angle/src/config.pri
+++ b/src/angle/src/config.pri
@@ -41,6 +41,8 @@ DEFINES += _WINDOWS \
CONFIG += angle_d3d11 # Remove to disable D3D11 renderer
+equals(QMAKE_TARGET_OS, xp): CONFIG -= angle_d3d11
+
angle_d3d11 {
DEFINES += ANGLE_ENABLE_D3D11 ANGLE_DEFAULT_D3D11=1
!build_pass: message("Enabling D3D11 mode for ANGLE")
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index a0c943df62..6571c39385 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -4237,7 +4237,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
\relates <QtGlobal>
Forward-declares a mutable Core Foundation \a type. This includes the actual
- type and the ref type. For example, Q_FORWARD_DECLARE_CF_TYPE(CFString)
+ type and the ref type. For example, Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(CFMutableString)
declares __CFMutableString and CFMutableStringRef.
*/
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 8b4245ccdc..39d6f9539a 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1275,23 +1275,6 @@ static void android_default_message_handler(QtMsgType type,
static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context,
const QString &buf)
{
- // to determine logging destination and marking logging environment variable as deprecated
- // ### remove when deprecated
- struct LogDestination {
- LogDestination(const char *deprecated, bool forceConsole) {
- const char* replacement = "QT_LOGGING_TO_CONSOLE";
- bool newEnv = qEnvironmentVariableIsSet(replacement);
- bool oldEnv = qEnvironmentVariableIsSet(deprecated);
- if (oldEnv && !newEnv && !forceConsole) {
- fprintf(stderr, "Warning: Environment variable %s is deprecated, "
- "use %s instead.\n", deprecated, replacement);
- fflush(stderr);
- }
- toConsole = newEnv || oldEnv || forceConsole;
- }
- bool toConsole;
- };
-
QString logMessage = qFormatLogMessage(type, context, buf);
#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
@@ -1301,8 +1284,8 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con
}
#endif // Q_OS_WIN
-#if defined(QT_USE_SLOG2)
static const bool logToConsole = qEnvironmentVariableIsSet("QT_LOGGING_TO_CONSOLE");
+#if defined(QT_USE_SLOG2)
if (!logToConsole) {
slog2_default_handler(type, logMessage.toLocal8Bit().constData());
} else {
@@ -1310,11 +1293,9 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con
fflush(stderr);
}
#elif defined(QT_USE_JOURNALD) && !defined(QT_BOOTSTRAPPED)
- // We use isatty to catch the obvious case of someone running something interactively.
- // We also support environment variables for Qt Creator use, or more complicated cases
+ // We support environment variables for Qt Creator use, or more complicated cases
// like subprocesses.
- static const LogDestination logdest("QT_NO_JOURNALD_LOG", isatty(fileno(stdin)));
- if (Q_LIKELY(!logdest.toConsole)) {
+ if (!logToConsole) {
// remove trailing \n, systemd appears to want them newline-less
logMessage.chop(1);
systemd_default_message_handler(type, context, logMessage);
@@ -1323,8 +1304,7 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con
fflush(stderr);
}
#elif defined(Q_OS_ANDROID)
- static const LogDestination logdest("QT_ANDROID_PLAIN_LOG", false);
- if (!logdest.toConsole) {
+ if (!logToConsole) {
android_default_message_handler(type, context, logMessage);
} else {
fprintf(stderr, "%s", logMessage.toLocal8Bit().constData());
@@ -1334,6 +1314,7 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con
fprintf(stderr, "%s", logMessage.toLocal8Bit().constData());
fflush(stderr);
#endif
+ Q_UNUSED(logToConsole);
}
/*!
diff --git a/src/corelib/kernel/qbasictimer.cpp b/src/corelib/kernel/qbasictimer.cpp
index f3366489d5..377c45219c 100644
--- a/src/corelib/kernel/qbasictimer.cpp
+++ b/src/corelib/kernel/qbasictimer.cpp
@@ -118,13 +118,19 @@ QT_BEGIN_NAMESPACE
void QBasicTimer::start(int msec, QObject *obj)
{
QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
- if (!eventDispatcher) {
+ if (Q_UNLIKELY(!eventDispatcher)) {
qWarning("QBasicTimer::start: QBasicTimer can only be used with threads started with QThread");
return;
}
+ if (Q_UNLIKELY(obj && obj->thread() != eventDispatcher->thread())) {
+ qWarning("QBasicTimer::start: Timers cannot be started from another thread");
+ return;
+ }
if (id) {
- eventDispatcher->unregisterTimer(id);
- QAbstractEventDispatcherPrivate::releaseTimerId(id);
+ if (Q_LIKELY(eventDispatcher->unregisterTimer(id)))
+ QAbstractEventDispatcherPrivate::releaseTimerId(id);
+ else
+ qWarning("QBasicTimer::start: Stopping previous timer failed. Possibly trying to stop from a different thread");
}
id = 0;
if (obj)
@@ -145,13 +151,23 @@ void QBasicTimer::start(int msec, QObject *obj)
void QBasicTimer::start(int msec, Qt::TimerType timerType, QObject *obj)
{
QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
- if (!eventDispatcher) {
+ if (Q_UNLIKELY(msec < 0)) {
+ qWarning("QBasicTimer::start: Timers cannot have negative timeouts");
+ return;
+ }
+ if (Q_UNLIKELY(!eventDispatcher)) {
qWarning("QBasicTimer::start: QBasicTimer can only be used with threads started with QThread");
return;
}
+ if (Q_UNLIKELY(obj && obj->thread() != eventDispatcher->thread())) {
+ qWarning("QBasicTimer::start: Timers cannot be started from another thread");
+ return;
+ }
if (id) {
- eventDispatcher->unregisterTimer(id);
- QAbstractEventDispatcherPrivate::releaseTimerId(id);
+ if (Q_LIKELY(eventDispatcher->unregisterTimer(id)))
+ QAbstractEventDispatcherPrivate::releaseTimerId(id);
+ else
+ qWarning("QBasicTimer::start: Stopping previous timer failed. Possibly trying to stop from a different thread");
}
id = 0;
if (obj)
@@ -167,9 +183,13 @@ void QBasicTimer::stop()
{
if (id) {
QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
- if (eventDispatcher)
- eventDispatcher->unregisterTimer(id);
- QAbstractEventDispatcherPrivate::releaseTimerId(id);
+ if (eventDispatcher) {
+ if (Q_UNLIKELY(!eventDispatcher->unregisterTimer(id))) {
+ qWarning("QBasicTimer::stop: Failed. Possibly trying to stop from a different thread");
+ return;
+ }
+ QAbstractEventDispatcherPrivate::releaseTimerId(id);
+ }
}
id = 0;
}
diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp
index e87e830c39..c4a5fc1ea8 100644
--- a/src/corelib/kernel/qeventdispatcher_glib.cpp
+++ b/src/corelib/kernel/qeventdispatcher_glib.cpp
@@ -518,7 +518,7 @@ void QEventDispatcherGlib::registerTimer(int timerId, int interval, Qt::TimerTyp
qWarning("QEventDispatcherGlib::registerTimer: invalid arguments");
return;
} else if (object->thread() != thread() || thread() != QThread::currentThread()) {
- qWarning("QObject::startTimer: timers cannot be started from another thread");
+ qWarning("QEventDispatcherGlib::registerTimer: timers cannot be started from another thread");
return;
}
#endif
@@ -534,7 +534,7 @@ bool QEventDispatcherGlib::unregisterTimer(int timerId)
qWarning("QEventDispatcherGlib::unregisterTimer: invalid argument");
return false;
} else if (thread() != QThread::currentThread()) {
- qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ qWarning("QEventDispatcherGlib::unregisterTimer: timers cannot be stopped from another thread");
return false;
}
#endif
@@ -550,7 +550,7 @@ bool QEventDispatcherGlib::unregisterTimers(QObject *object)
qWarning("QEventDispatcherGlib::unregisterTimers: invalid argument");
return false;
} else if (object->thread() != thread() || thread() != QThread::currentThread()) {
- qWarning("QObject::killTimers: timers cannot be stopped from another thread");
+ qWarning("QEventDispatcherGlib::unregisterTimers: timers cannot be stopped from another thread");
return false;
}
#endif
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index 69363bc3c9..9674fd5417 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -338,7 +338,7 @@ void QEventDispatcherUNIX::registerTimer(int timerId, int interval, Qt::TimerTyp
qWarning("QEventDispatcherUNIX::registerTimer: invalid arguments");
return;
} else if (obj->thread() != thread() || thread() != QThread::currentThread()) {
- qWarning("QObject::startTimer: timers cannot be started from another thread");
+ qWarning("QEventDispatcherUNIX::registerTimer: timers cannot be started from another thread");
return;
}
#endif
@@ -357,7 +357,7 @@ bool QEventDispatcherUNIX::unregisterTimer(int timerId)
qWarning("QEventDispatcherUNIX::unregisterTimer: invalid argument");
return false;
} else if (thread() != QThread::currentThread()) {
- qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ qWarning("QEventDispatcherUNIX::unregisterTimer: timers cannot be stopped from another thread");
return false;
}
#endif
@@ -376,7 +376,7 @@ bool QEventDispatcherUNIX::unregisterTimers(QObject *object)
qWarning("QEventDispatcherUNIX::unregisterTimers: invalid argument");
return false;
} else if (object->thread() != thread() || thread() != QThread::currentThread()) {
- qWarning("QObject::killTimers: timers cannot be stopped from another thread");
+ qWarning("QEventDispatcherUNIX::unregisterTimers: timers cannot be stopped from another thread");
return false;
}
#endif
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index f38ac7bf26..b7594d1dd3 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -908,13 +908,15 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
{
+#ifndef QT_NO_DEBUG
if (timerId < 1 || interval < 0 || !object) {
qWarning("QEventDispatcherWin32::registerTimer: invalid arguments");
return;
} else if (object->thread() != thread() || thread() != QThread::currentThread()) {
- qWarning("QObject::startTimer: timers cannot be started from another thread");
+ qWarning("QEventDispatcherWin32::registerTimer: timers cannot be started from another thread");
return;
}
+#endif
Q_D(QEventDispatcherWin32);
@@ -936,15 +938,17 @@ void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerTy
bool QEventDispatcherWin32::unregisterTimer(int timerId)
{
+#ifndef QT_NO_DEBUG
if (timerId < 1) {
qWarning("QEventDispatcherWin32::unregisterTimer: invalid argument");
return false;
}
QThread *currentThread = QThread::currentThread();
if (thread() != currentThread) {
- qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ qWarning("QEventDispatcherWin32::unregisterTimer: timers cannot be stopped from another thread");
return false;
}
+#endif
Q_D(QEventDispatcherWin32);
if (d->timerVec.isEmpty() || timerId <= 0)
@@ -962,15 +966,17 @@ bool QEventDispatcherWin32::unregisterTimer(int timerId)
bool QEventDispatcherWin32::unregisterTimers(QObject *object)
{
+#ifndef QT_NO_DEBUG
if (!object) {
qWarning("QEventDispatcherWin32::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");
+ qWarning("QEventDispatcherWin32::unregisterTimers: timers cannot be stopped from another thread");
return false;
}
+#endif
Q_D(QEventDispatcherWin32);
if (d->timerVec.isEmpty())
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index aec0981677..d75d30f48e 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -254,13 +254,15 @@ void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerTy
{
Q_UNUSED(timerType);
+#ifndef QT_NO_DEBUG
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");
+ qWarning("QEventDispatcherWinRT::registerTimer: timers cannot be started from another thread");
return;
}
+#endif
Q_D(QEventDispatcherWinRT);
@@ -289,14 +291,16 @@ void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerTy
bool QEventDispatcherWinRT::unregisterTimer(int timerId)
{
+#ifndef QT_NO_DEBUG
if (timerId < 1) {
qWarning("QEventDispatcherWinRT::unregisterTimer: invalid argument");
return false;
}
if (thread() != QThread::currentThread()) {
- qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ qWarning("QEventDispatcherWinRT::unregisterTimer: timers cannot be stopped from another thread");
return false;
}
+#endif
Q_D(QEventDispatcherWinRT);
@@ -310,15 +314,17 @@ bool QEventDispatcherWinRT::unregisterTimer(int timerId)
bool QEventDispatcherWinRT::unregisterTimers(QObject *object)
{
+#ifndef QT_NO_DEBUG
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");
+ qWarning("QEventDispatcherWinRT::unregisterTimers: timers cannot be stopped from another thread");
return false;
}
+#endif
Q_D(QEventDispatcherWinRT);
for (QHash<int, WinRTTimerInfo *>::iterator it = d->timerDict.begin(); it != d->timerDict.end();) {
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 2c53ed8f17..f72a679b82 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -225,13 +225,17 @@ QObjectPrivate::QObjectPrivate(int version)
QObjectPrivate::~QObjectPrivate()
{
if (extraData && !extraData->runningTimers.isEmpty()) {
- // unregister pending timers
- if (threadData->eventDispatcher.load())
- threadData->eventDispatcher.load()->unregisterTimers(q_ptr);
-
- // release the timer ids back to the pool
- for (int i = 0; i < extraData->runningTimers.size(); ++i)
- QAbstractEventDispatcherPrivate::releaseTimerId(extraData->runningTimers.at(i));
+ if (Q_LIKELY(threadData->thread == QThread::currentThread())) {
+ // unregister pending timers
+ if (threadData->eventDispatcher.load())
+ threadData->eventDispatcher.load()->unregisterTimers(q_ptr);
+
+ // release the timer ids back to the pool
+ for (int i = 0; i < extraData->runningTimers.size(); ++i)
+ QAbstractEventDispatcherPrivate::releaseTimerId(extraData->runningTimers.at(i));
+ } else {
+ qWarning("QObject::~QObject: Timers cannot be stopped from another thread");
+ }
}
if (postedEvents)
@@ -1612,15 +1616,18 @@ int QObject::startTimer(int interval, Qt::TimerType timerType)
{
Q_D(QObject);
- if (interval < 0) {
+ if (Q_UNLIKELY(interval < 0)) {
qWarning("QObject::startTimer: Timers cannot have negative intervals");
return 0;
}
-
- if (!d->threadData->eventDispatcher.load()) {
+ if (Q_UNLIKELY(!d->threadData->eventDispatcher.load())) {
qWarning("QObject::startTimer: Timers can only be used with threads started with QThread");
return 0;
}
+ if (Q_UNLIKELY(thread() != QThread::currentThread())) {
+ qWarning("QObject::startTimer: Timers cannot be started from another thread");
+ return 0;
+ }
int timerId = d->threadData->eventDispatcher.load()->registerTimer(interval, timerType, this);
if (!d->extraData)
d->extraData = new QObjectPrivate::ExtraData;
@@ -1640,6 +1647,10 @@ int QObject::startTimer(int interval, Qt::TimerType timerType)
void QObject::killTimer(int id)
{
Q_D(QObject);
+ if (Q_UNLIKELY(thread() != QThread::currentThread())) {
+ qWarning("QObject::killTimer: Timers cannot be stopped from another thread");
+ return;
+ }
if (id) {
int at = d->extraData ? d->extraData->runningTimers.indexOf(id) : -1;
if (at == -1) {
diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp
index 6470873d9a..2598f02a19 100644
--- a/src/corelib/kernel/qsocketnotifier.cpp
+++ b/src/corelib/kernel/qsocketnotifier.cpp
@@ -274,6 +274,10 @@ void QSocketNotifier::setEnabled(bool enable)
if (!d->threadData->eventDispatcher.load()) // perhaps application/thread is shutting down
return;
+ if (Q_UNLIKELY(thread() != QThread::currentThread())) {
+ qWarning("QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread");
+ return;
+ }
if (d->snenabled)
d->threadData->eventDispatcher.load()->registerSocketNotifier(this);
else
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index 97aae6f7e0..5c09b483c6 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -395,6 +395,10 @@ void QTimer::singleShot(int msec, const QObject *receiver, const char *member)
*/
void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member)
{
+ if (Q_UNLIKELY(msec < 0)) {
+ qWarning("QTimer::singleShot: Timers cannot have negative timeouts");
+ return;
+ }
if (receiver && member) {
if (msec == 0) {
// special code shortpath for 0-timers
diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp
index c694237dc3..d2c623d489 100644
--- a/src/corelib/kernel/qwineventnotifier.cpp
+++ b/src/corelib/kernel/qwineventnotifier.cpp
@@ -140,11 +140,11 @@ QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent)
{
Q_D(QWinEventNotifier);
QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.load();
- if (!eventDispatcher) {
+ if (Q_UNLIKELY(!eventDispatcher)) {
qWarning("QWinEventNotifier: Can only be used with threads started with QThread");
- } else {
- eventDispatcher->registerEventNotifier(this);
+ return;
}
+ eventDispatcher->registerEventNotifier(this);
d->enabled = true;
}
@@ -215,6 +215,10 @@ void QWinEventNotifier::setEnabled(bool enable)
QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.load();
if (!eventDispatcher) // perhaps application is shutting down
return;
+ if (Q_UNLIKELY(thread() != QThread::currentThread())) {
+ qWarning("QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread");
+ return;
+ }
if (enable)
eventDispatcher->registerEventNotifier(this);
diff --git a/src/corelib/tools/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp
index 933f7fa6b3..4d148249c0 100644
--- a/src/corelib/tools/qversionnumber.cpp
+++ b/src/corelib/tools/qversionnumber.cpp
@@ -54,6 +54,7 @@
#endif
#include <algorithm>
+#include <limits>
QT_BEGIN_NAMESPACE
@@ -390,14 +391,13 @@ QVersionNumber QVersionNumber::fromString(const QString &string, int *suffixInde
const char *end = start;
const char *lastGoodEnd = start;
const char *endOfString = cString.constData() + cString.size();
- int value;
do {
bool ok = false;
- value = int(qstrtoull(start, &end, 10, &ok));
- if (!ok)
+ const qulonglong value = qstrtoull(start, &end, 10, &ok);
+ if (!ok || value > qulonglong(std::numeric_limits<int>::max()))
break;
- seg.append(value);
+ seg.append(int(value));
start = end + 1;
lastGoodEnd = end;
} while (start < endOfString && (end < endOfString && *end == '.'));
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 72972ff163..50dcc9eca2 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -4664,7 +4664,7 @@ static Q_CONSTEXPR QPixelFormat pixelformats[] = {
//QImage::Format_Invalid:
QPixelFormat(),
//QImage::Format_Mono:
- QPixelFormat(QPixelFormat::Grayscale,
+ QPixelFormat(QPixelFormat::Indexed,
/*RED*/ 1,
/*GREEN*/ 0,
/*BLUE*/ 0,
@@ -4677,7 +4677,7 @@ static Q_CONSTEXPR QPixelFormat pixelformats[] = {
/*INTERPRETATION*/ QPixelFormat::UnsignedByte,
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
//QImage::Format_MonoLSB:
- QPixelFormat(QPixelFormat::Grayscale,
+ QPixelFormat(QPixelFormat::Indexed,
/*RED*/ 1,
/*GREEN*/ 0,
/*BLUE*/ 0,
@@ -4789,7 +4789,7 @@ static Q_CONSTEXPR QPixelFormat pixelformats[] = {
/*FIFTH*/ 0,
/*ALPHA*/ 6,
/*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
- /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
/*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
/*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
@@ -4854,7 +4854,7 @@ static Q_CONSTEXPR QPixelFormat pixelformats[] = {
/*FIFTH*/ 0,
/*ALPHA*/ 4,
/*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
- /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
/*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
/*INTERPRETATION*/ QPixelFormat::UnsignedShort,
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 958df48f17..57c9da2dda 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -642,6 +642,10 @@ QWheelEvent::QWheelEvent(const QPointF &pos, int delta,
: QInputEvent(Wheel, modifiers), p(pos), qt4D(delta), qt4O(orient), mouseState(buttons)
{
g = QCursor::pos();
+ if (orient == Qt::Vertical)
+ angleD = QPoint(0, delta);
+ else
+ angleD = QPoint(delta, 0);
}
/*!
@@ -670,7 +674,12 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
Qt::Orientation orient)
: QInputEvent(Wheel, modifiers), p(pos), g(globalPos), qt4D(delta), qt4O(orient), mouseState(buttons)
-{}
+{
+ if (orient == Qt::Vertical)
+ angleD = QPoint(0, delta);
+ else
+ angleD = QPoint(delta, 0);
+}
/*!
Constructs a wheel event object.
diff --git a/src/gui/kernel/qplatformcursor.cpp b/src/gui/kernel/qplatformcursor.cpp
index c2f510b496..0162360718 100644
--- a/src/gui/kernel/qplatformcursor.cpp
+++ b/src/gui/kernel/qplatformcursor.cpp
@@ -122,8 +122,13 @@ QPoint QPlatformCursor::pos() const
void QPlatformCursor::setPos(const QPoint &pos)
{
- Q_UNUSED(pos);
- qWarning("This plugin does not support QCursor::setPos()");
+ static bool firstCall = true;
+ if (firstCall) {
+ firstCall = false;
+ qWarning("This plugin does not support QCursor::setPos()"
+ "; emulating movement within the application.");
+ }
+ QWindowSystemInterface::handleMouseEvent(0, pos, pos, Qt::NoButton);
}
// End of display and pointer event handling code
diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp
index d82abd73dc..fb1f582214 100644
--- a/src/gui/opengl/qopenglpaintengine.cpp
+++ b/src/gui/opengl/qopenglpaintengine.cpp
@@ -501,7 +501,6 @@ void QOpenGL2PaintEngineExPrivate::drawTexture(const QOpenGLRect& dest, const QO
{
// Setup for texture drawing
currentBrush = noBrush;
- shaderManager->setSrcPixelType(pattern ? QOpenGLEngineShaderManager::PatternSrc : QOpenGLEngineShaderManager::ImageSrc);
if (snapToPixelGrid) {
snapToPixelGrid = false;
@@ -1367,6 +1366,11 @@ void QOpenGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixma
Q_D(QOpenGL2PaintEngineEx);
QOpenGLContext *ctx = d->ctx;
+ // Draw pixmaps that are really images as images since drawImage has
+ // better handling of non-default image formats.
+ if (pixmap.paintEngine()->type() == QPaintEngine::Raster && !pixmap.isQBitmap())
+ return drawImage(dest, pixmap.toImage(), src);
+
int max_texture_size = ctx->d_func()->maxTextureSize();
if (pixmap.width() > max_texture_size || pixmap.height() > max_texture_size) {
QPixmap scaled = pixmap.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio);
@@ -1391,6 +1395,8 @@ void QOpenGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixma
d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
state()->renderHints & QPainter::SmoothPixmapTransform, id);
+
+ d->shaderManager->setSrcPixelType(isBitmap ? QOpenGLEngineShaderManager::PatternSrc : QOpenGLEngineShaderManager::ImageSrc);
d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap);
}
@@ -1414,12 +1420,25 @@ void QOpenGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, c
ensureActive();
d->transferMode(ImageDrawingMode);
- d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ QOpenGLTextureCache::BindOptions bindOption = QOpenGLTextureCache::PremultipliedAlphaBindOption;
+ // Use specialized bind for formats we have specialized shaders for.
+ switch (image.format()) {
+ case QImage::Format_RGBA8888:
+ case QImage::Format_ARGB32:
+ d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::NonPremultipliedImageSrc);
+ bindOption = 0;
+ break;
+ default:
+ d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
+ break;
+ }
- GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, image);
+ d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, image, bindOption);
d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
state()->renderHints & QPainter::SmoothPixmapTransform, id);
+
d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel());
}
@@ -1466,6 +1485,7 @@ bool QOpenGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, co
d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
state()->renderHints & QPainter::SmoothPixmapTransform, textureId);
+ d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
d->drawTexture(dest, srcRect, size, false);
return true;
}
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 1e778af3f6..26f4dfd3cf 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -2955,11 +2955,11 @@ typedef struct {
typedef struct _EdgeTableEntry {
int ymax; /* ycoord at which we exit this edge. */
+ int ClockWise; /* flag for winding number rule */
BRESINFO bres; /* Bresenham info to run the edge */
struct _EdgeTableEntry *next; /* next in the list */
struct _EdgeTableEntry *back; /* for insertion sort */
struct _EdgeTableEntry *nextWETE; /* for winding num rule */
- int ClockWise; /* flag for winding number rule */
} EdgeTableEntry;
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 5f801c3bf4..4faa018a40 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -374,7 +374,7 @@ bool QFontEngine::supportsScript(QChar::Script script) const
hb_tag_t script_tag_1, script_tag_2;
hb_ot_tags_from_script(hb_qt_script_to_script(script), &script_tag_1, &script_tag_2);
- unsigned int script_index = -1;
+ unsigned int script_index;
ret = hb_ot_layout_table_find_script(face, HB_OT_TAG_GSUB, script_tag_1, &script_index);
if (!ret) {
ret = hb_ot_layout_table_find_script(face, HB_OT_TAG_GSUB, script_tag_2, &script_index);
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index e572745d51..d9185d5efb 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -2420,7 +2420,7 @@ qint64 QAbstractSocket::readData(char *data, qint64 maxSize)
return 0;
// This is for a buffered QTcpSocket
- if (d->isBuffered && d->buffer.isEmpty())
+ if (d->isBuffered)
// if we're still connected, return 0 indicating there may be more data in the future
// if we're not connected, return -1 indicating EOF
return d->state == QAbstractSocket::ConnectedState ? qint64(0) : qint64(-1);
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 204e0ed98b..1ade985b79 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -158,6 +158,7 @@ static void populateRoleMap()
roleMap[QAccessible::Heading] = @"AXHeading";
roleMap[QAccessible::Note] = NSAccessibilityGroupRole;
roleMap[QAccessible::ComplementaryContent] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::Graphic] = NSAccessibilityImageRole;
}
/*
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
index 1d28befe41..e765812024 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -109,13 +109,6 @@ static inline ID2D1Factory1 *factory()
return QWindowsDirect2DContext::instance()->d2dFactory();
}
-inline static FLOAT pixelSizeToDIP(int pixelSize)
-{
- FLOAT dpiX, dpiY;
- QWindowsDirect2DContext::instance()->d2dFactory()->GetDesktopDpi(&dpiX, &dpiY);
- return FLOAT(pixelSize) * 96.0f / dpiY;
-}
-
class Direct2DPathGeometryWriter
{
public:
@@ -300,6 +293,14 @@ public:
: D2D1_ANTIALIAS_MODE_ALIASED;
}
+ inline D2D1_LAYER_OPTIONS1 layerOptions() const
+ {
+ if (flags & QWindowsDirect2DPaintEngine::TranslucentTopLevelWindow)
+ return D2D1_LAYER_OPTIONS1_NONE;
+ else
+ return D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND;
+ }
+
void updateTransform(const QTransform &transform)
{
dc()->SetTransform(to_d2d_matrix_3x2_f(transform));
@@ -345,7 +346,7 @@ public:
D2D1::IdentityMatrix(),
1.0,
NULL,
- D2D1_LAYER_OPTIONS1_NONE),
+ layerOptions()),
NULL);
pushedClips.push(LayerClip);
}
@@ -858,19 +859,19 @@ public:
Q_Q(QWindowsDirect2DPaintEngine);
DWRITE_GLYPH_RUN glyphRun = {
- fontFace, // IDWriteFontFace *fontFace;
- pixelSizeToDIP(fontDef.pixelSize), // FLOAT fontEmSize;
- numGlyphs, // UINT32 glyphCount;
- glyphIndices, // const UINT16 *glyphIndices;
- glyphAdvances, // const FLOAT *glyphAdvances;
- glyphOffsets, // const DWRITE_GLYPH_OFFSET *glyphOffsets;
- FALSE, // BOOL isSideways;
- rtl ? 1 : 0 // UINT32 bidiLevel;
+ fontFace, // IDWriteFontFace *fontFace;
+ fontDef.pixelSize, // FLOAT fontEmSize;
+ numGlyphs, // UINT32 glyphCount;
+ glyphIndices, // const UINT16 *glyphIndices;
+ glyphAdvances, // const FLOAT *glyphAdvances;
+ glyphOffsets, // const DWRITE_GLYPH_OFFSET *glyphOffsets;
+ FALSE, // BOOL isSideways;
+ rtl ? 1 : 0 // UINT32 bidiLevel;
};
const bool antiAlias = bool((q->state()->renderHints & QPainter::TextAntialiasing)
&& !(fontDef.styleStrategy & QFont::NoAntialias));
- const D2D1_TEXT_ANTIALIAS_MODE antialiasMode = (flags & QWindowsDirect2DPaintEngine::UseGrayscaleAntialiasing)
+ const D2D1_TEXT_ANTIALIAS_MODE antialiasMode = (flags & QWindowsDirect2DPaintEngine::TranslucentTopLevelWindow)
? D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE : D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
dc()->SetTextAntialiasMode(antiAlias ? antialiasMode : D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
@@ -956,7 +957,7 @@ bool QWindowsDirect2DPaintEngine::begin(QPaintDevice * pdev)
D2D1::IdentityMatrix(),
1.0,
NULL,
- D2D1_LAYER_OPTIONS1_NONE),
+ d->layerOptions()),
NULL);
} else {
QRect clip(0, 0, pdev->width(), pdev->height());
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
index 4ed817b75f..af0aaf93f7 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
@@ -61,7 +61,7 @@ class QWindowsDirect2DPaintEngine : public QPaintEngineEx
public:
enum Flag {
NoFlag = 0,
- UseGrayscaleAntialiasing = 1,
+ TranslucentTopLevelWindow = 1
};
Q_DECLARE_FLAGS(Flags, Flag)
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
index f739493c1a..36e306929d 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
@@ -310,7 +310,7 @@ void QWindowsDirect2DWindow::setupBitmap()
QWindowsDirect2DPaintEngine::Flags flags = QWindowsDirect2DPaintEngine::NoFlag;
if (!m_directRendering)
- flags |= QWindowsDirect2DPaintEngine::UseGrayscaleAntialiasing;
+ flags |= QWindowsDirect2DPaintEngine::TranslucentTopLevelWindow;
QWindowsDirect2DPlatformPixmap *pp = new QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixmapType,
flags,
m_bitmap.data());
diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro
index 82f0bd91c4..6b67a42f69 100644
--- a/src/plugins/platforms/ios/ios.pro
+++ b/src/plugins/platforms/ios/ios.pro
@@ -28,6 +28,7 @@ OBJECTIVE_SOURCES = \
quiaccessibilityelement.mm \
qiosplatformaccessibility.mm \
qiostextresponder.mm \
+ qiosmenu.mm \
HEADERS = \
qiosintegration.h \
@@ -48,6 +49,7 @@ HEADERS = \
quiaccessibilityelement.h \
qiosplatformaccessibility.h \
qiostextresponder.h \
+ qiosmenu.h \
OTHER_FILES = \
quiview_textinput.mm \
diff --git a/src/plugins/platforms/ios/qiosmenu.h b/src/plugins/platforms/ios/qiosmenu.h
new file mode 100644
index 0000000000..9897483a3e
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosmenu.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins 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 QIOSMENU_H
+#define QIOSMENU_H
+
+#import <UIKit/UIKit.h>
+
+#include <QtCore/QtCore>
+#include <qpa/qplatformmenu.h>
+
+#import "quiview.h"
+
+@class QUIMenuController;
+@class QUIPickerView;
+
+class QIOSMenuItem : public QPlatformMenuItem
+{
+public:
+ QIOSMenuItem();
+
+ void setTag(quintptr tag) Q_DECL_OVERRIDE;
+ quintptr tag()const Q_DECL_OVERRIDE;
+
+ void setText(const QString &text) Q_DECL_OVERRIDE;
+ void setIcon(const QIcon &) Q_DECL_OVERRIDE {}
+ void setMenu(QPlatformMenu *) Q_DECL_OVERRIDE {}
+ void setVisible(bool isVisible) Q_DECL_OVERRIDE;
+ void setIsSeparator(bool) Q_DECL_OVERRIDE {}
+ void setFont(const QFont &) Q_DECL_OVERRIDE {}
+ void setRole(MenuRole role) Q_DECL_OVERRIDE;
+ void setCheckable(bool) Q_DECL_OVERRIDE {}
+ void setChecked(bool) Q_DECL_OVERRIDE {}
+ void setShortcut(const QKeySequence&) Q_DECL_OVERRIDE {}
+ void setEnabled(bool enabled) Q_DECL_OVERRIDE;
+ void setIconSize(int) Q_DECL_OVERRIDE {}
+
+ quintptr m_tag;
+ bool m_visible;
+ QString m_text;
+ MenuRole m_role;
+ bool m_enabled;
+
+private:
+ QString removeMnemonics(const QString &original);
+};
+
+typedef QList<QIOSMenuItem *> QIOSMenuItemList;
+
+class QIOSMenu : public QPlatformMenu
+{
+public:
+ QIOSMenu();
+ ~QIOSMenu();
+
+ void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) Q_DECL_OVERRIDE;
+ void removeMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
+ void syncMenuItem(QPlatformMenuItem *) Q_DECL_OVERRIDE {}
+ void syncSeparatorsCollapsible(bool) Q_DECL_OVERRIDE {}
+
+ void setTag(quintptr tag) Q_DECL_OVERRIDE;
+ quintptr tag()const Q_DECL_OVERRIDE;
+
+ void setText(const QString &) Q_DECL_OVERRIDE;
+ void setIcon(const QIcon &) Q_DECL_OVERRIDE {}
+ void setEnabled(bool enabled) Q_DECL_OVERRIDE;
+ void setVisible(bool visible) Q_DECL_OVERRIDE;
+ void setMenuType(MenuType type) Q_DECL_OVERRIDE;
+
+ void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) Q_DECL_OVERRIDE;
+ void dismiss() Q_DECL_OVERRIDE;
+
+ QPlatformMenuItem *menuItemAt(int position) const Q_DECL_OVERRIDE;
+ QPlatformMenuItem *menuItemForTag(quintptr tag) const Q_DECL_OVERRIDE;
+
+ static QIOSMenu *currentMenu() { return m_currentMenu; }
+ static id menuActionTarget() { return m_currentMenu ? m_currentMenu->m_menuController : 0; }
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event);
+
+private:
+ quintptr m_tag;
+ bool m_enabled;
+ bool m_visible;
+ bool m_effectiveVisible;
+ QString m_text;
+ MenuType m_menuType;
+ MenuType m_effectiveMenuType;
+ QRect m_targetRect;
+ const QIOSMenuItem *m_targetItem;
+ QUIMenuController *m_menuController;
+ QUIPickerView *m_pickerView;
+ QIOSMenuItemList m_menuItems;
+
+ static QIOSMenu *m_currentMenu;
+
+ void updateVisibility();
+ void updateVisibilityUsingUIMenuController();
+ void updateVisibilityUsingUIPickerView();
+ QIOSMenuItemList visibleMenuItems() const;
+ void repositionMenu();
+ void hide() { setVisible(false); }
+};
+
+#endif // QIOSMENU_H
diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm
new file mode 100644
index 0000000000..8f7baa9756
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosmenu.mm
@@ -0,0 +1,525 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins 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 <qglobal.h>
+#include <qguiapplication.h>
+
+#include "qiosglobal.h"
+#include "qiosmenu.h"
+#include "qioswindow.h"
+#include "qiosinputcontext.h"
+#include "qiosintegration.h"
+#include "qiostextresponder.h"
+
+// m_currentMenu points to the currently visible menu.
+// Only one menu will be visible at a time, and if a second menu
+// is shown on top of a first, the first one will be told to hide.
+QIOSMenu *QIOSMenu::m_currentMenu = 0;
+
+// -------------------------------------------------------------------------
+
+static NSString *const kSelectorPrefix = @"_qtMenuItem_";
+
+@interface QUIMenuController : UIResponder {
+ QIOSMenuItemList m_visibleMenuItems;
+}
+@end
+
+@implementation QUIMenuController
+
+- (id)initWithVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems
+{
+ if (self = [super init]) {
+ m_visibleMenuItems = visibleMenuItems;
+ NSMutableArray *menuItemArray = [NSMutableArray arrayWithCapacity:m_visibleMenuItems.size()];
+ // Create an array of UIMenuItems, one for each visible QIOSMenuItem. Each
+ // UIMenuItem needs a callback assigned, so we assign one of the placeholder methods
+ // added to UIWindow (QIOSMenuActionTargets) below. Each method knows its own index, which
+ // corresponds to the index of the corresponding QIOSMenuItem in m_visibleMenuItems. When
+ // triggered, menuItemActionCallback will end up being called.
+ for (int i = 0; i < m_visibleMenuItems.count(); ++i) {
+ QIOSMenuItem *item = m_visibleMenuItems.at(i);
+ SEL sel = NSSelectorFromString([NSString stringWithFormat:@"%@%i:", kSelectorPrefix, i]);
+ [menuItemArray addObject:[[[UIMenuItem alloc] initWithTitle:item->m_text.toNSString() action:sel] autorelease]];
+ }
+ [UIMenuController sharedMenuController].menuItems = menuItemArray;
+ }
+
+ return self;
+}
+
+- (id)targetForAction:(SEL)action withSender:(id)sender
+{
+ BOOL containsPrefix = ([NSStringFromSelector(action) rangeOfString:kSelectorPrefix].location != NSNotFound);
+ return (containsPrefix && [sender isKindOfClass:[UIMenuController class]]) ? self : 0;
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
+{
+ Q_UNUSED(selector);
+ // Just return a dummy signature that NSObject can create an NSInvocation from.
+ // We end up only checking selector in forwardInvocation anyway.
+ return [super methodSignatureForSelector:@selector(methodSignatureForSelector:)];
+}
+
+- (void)forwardInvocation:(NSInvocation *)invocation
+{
+ // Since none of the menu item selector methods actually exist, this function
+ // will end up being called as a final resort. We can then handle the action.
+ NSString *selector = NSStringFromSelector(invocation.selector);
+ NSRange range = NSMakeRange(kSelectorPrefix.length, selector.length - kSelectorPrefix.length - 1);
+ NSInteger selectedIndex = [[selector substringWithRange:range] integerValue];
+
+ emit m_visibleMenuItems.at(selectedIndex)->activated();
+ QIOSMenu::currentMenu()->setVisible(false);
+}
+
+@end
+
+// -------------------------------------------------------------------------
+
+@interface QUIPickerView : UIPickerView <UIPickerViewDelegate, UIPickerViewDataSource> {
+ QIOSMenuItemList m_visibleMenuItems;
+ QPointer<QObject> m_focusObjectWithPickerView;
+ NSInteger m_selectedRow;
+}
+
+@property(retain) UIToolbar *toolbar;
+
+@end
+
+@implementation QUIPickerView
+
+- (id)initWithVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems selectItem:(const QIOSMenuItem *)selectItem
+{
+ if (self = [super init]) {
+ self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+ m_visibleMenuItems = visibleMenuItems;
+ m_selectedRow = visibleMenuItems.indexOf(const_cast<QIOSMenuItem *>(selectItem));
+ if (m_selectedRow == -1)
+ m_selectedRow = 0;
+
+ self.toolbar = [[[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 100, 44)] autorelease];
+ self.toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ UIBarButtonItem *doneButton = [[[UIBarButtonItem alloc]
+ initWithBarButtonSystemItem:UIBarButtonSystemItemDone
+ target:self action:@selector(closeMenu)] autorelease];
+ UIBarButtonItem *spaceButton = [[[UIBarButtonItem alloc]
+ initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
+ target:self action:@selector(closeMenu)] autorelease];
+ UIBarButtonItem *cancelButton = [[[UIBarButtonItem alloc]
+ initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
+ target:self action:@selector(cancelMenu)] autorelease];
+ [self.toolbar setItems:[NSArray arrayWithObjects:doneButton, spaceButton, cancelButton, nil]];
+
+ [self setDelegate:self];
+ [self setDataSource:self];
+ [self selectRow:m_selectedRow inComponent:0 animated:false];
+ }
+
+ return self;
+}
+
+-(void)dealloc
+{
+ self.toolbar = 0;
+ [super dealloc];
+}
+
+- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
+{
+ Q_UNUSED(pickerView);
+ Q_UNUSED(component);
+ return m_visibleMenuItems.at(row)->m_text.toNSString();
+}
+
+- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
+{
+ Q_UNUSED(pickerView);
+ return 1;
+}
+
+- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
+{
+ Q_UNUSED(pickerView);
+ Q_UNUSED(component);
+ return m_visibleMenuItems.length();
+}
+
+- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
+{
+ Q_UNUSED(pickerView);
+ Q_UNUSED(component);
+ m_selectedRow = row;
+}
+
+- (void)closeMenu
+{
+ if (!m_visibleMenuItems.isEmpty())
+ emit m_visibleMenuItems.at(m_selectedRow)->activated();
+ QIOSMenu::currentMenu()->setVisible(false);
+}
+
+- (void)cancelMenu
+{
+ QIOSMenu::currentMenu()->setVisible(false);
+}
+
+@end
+
+// -------------------------------------------------------------------------
+
+QIOSMenuItem::QIOSMenuItem()
+ : QPlatformMenuItem()
+ , m_tag(0)
+ , m_visible(true)
+ , m_text(QString())
+ , m_role(MenuRole(0))
+ , m_enabled(true)
+{
+}
+
+void QIOSMenuItem::setTag(quintptr tag)
+{
+ m_tag = tag;
+}
+
+quintptr QIOSMenuItem::tag() const
+{
+ return m_tag;
+}
+
+void QIOSMenuItem::setText(const QString &text)
+{
+ m_text = removeMnemonics(text);
+}
+
+void QIOSMenuItem::setVisible(bool isVisible)
+{
+ m_visible = isVisible;
+}
+
+void QIOSMenuItem::setRole(QPlatformMenuItem::MenuRole role)
+{
+ m_role = role;
+}
+
+void QIOSMenuItem::setEnabled(bool enabled)
+{
+ m_enabled = enabled;
+}
+
+QString QIOSMenuItem::removeMnemonics(const QString &original)
+{
+ // Copied from qcocoahelpers
+ QString returnText(original.size(), 0);
+ int finalDest = 0;
+ int currPos = 0;
+ int l = original.length();
+ while (l) {
+ if (original.at(currPos) == QLatin1Char('&')
+ && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) {
+ ++currPos;
+ --l;
+ if (l == 0)
+ break;
+ } else if (original.at(currPos) == QLatin1Char('(') && l >= 4 &&
+ original.at(currPos + 1) == QLatin1Char('&') &&
+ original.at(currPos + 2) != QLatin1Char('&') &&
+ original.at(currPos + 3) == QLatin1Char(')')) {
+ /* remove mnemonics its format is "\s*(&X)" */
+ int n = 0;
+ while (finalDest > n && returnText.at(finalDest - n - 1).isSpace())
+ ++n;
+ finalDest -= n;
+ currPos += 4;
+ l -= 4;
+ continue;
+ }
+ returnText[finalDest] = original.at(currPos);
+ ++currPos;
+ ++finalDest;
+ --l;
+ }
+ returnText.truncate(finalDest);
+ return returnText;
+}
+
+QIOSMenu::QIOSMenu()
+ : QPlatformMenu()
+ , m_tag(0)
+ , m_enabled(true)
+ , m_visible(false)
+ , m_effectiveVisible(false)
+ , m_text(QString())
+ , m_menuType(DefaultMenu)
+ , m_effectiveMenuType(DefaultMenu)
+ , m_targetRect(QRect(qGuiApp->primaryScreen()->availableGeometry().center(), QSize()))
+ , m_targetItem(0)
+ , m_menuController(0)
+ , m_pickerView(0)
+{
+}
+
+QIOSMenu::~QIOSMenu()
+{
+ dismiss();
+}
+
+void QIOSMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
+{
+ if (!before) {
+ m_menuItems.append(static_cast<QIOSMenuItem *>(menuItem));
+ } else {
+ int index = m_menuItems.indexOf(static_cast<QIOSMenuItem *>(before)) + 1;
+ m_menuItems.insert(index, static_cast<QIOSMenuItem *>(menuItem));
+ }
+}
+
+void QIOSMenu::removeMenuItem(QPlatformMenuItem *menuItem)
+{
+ m_menuItems.removeOne(static_cast<QIOSMenuItem *>(menuItem));
+}
+
+void QIOSMenu::setTag(quintptr tag)
+{
+ m_tag = tag;
+}
+
+quintptr QIOSMenu::tag() const
+{
+ return m_tag;
+}
+
+void QIOSMenu::setText(const QString &text)
+{
+ m_text = text;
+}
+
+void QIOSMenu::setEnabled(bool enabled)
+{
+ if (m_enabled == enabled)
+ return;
+
+ m_enabled = enabled;
+ updateVisibility();
+}
+
+void QIOSMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item)
+{
+ if (!parentWindow->isActive())
+ const_cast<QWindow *>(parentWindow)->requestActivate();
+ m_targetRect = QRect(parentWindow->mapToGlobal(targetRect.topLeft()), targetRect.size());
+ m_targetItem = static_cast<const QIOSMenuItem *>(item);
+ setVisible(true);
+}
+
+void QIOSMenu::dismiss()
+{
+ setVisible(false);
+}
+
+void QIOSMenu::setVisible(bool visible)
+{
+ if (m_visible == visible)
+ return;
+
+ m_visible = visible;
+ updateVisibility();
+}
+
+void QIOSMenu::updateVisibility()
+{
+ bool visibleAndEnabled = m_visible && m_enabled;
+ if ((visibleAndEnabled && m_effectiveVisible) || (!visibleAndEnabled && m_currentMenu != this))
+ return;
+
+ if (visibleAndEnabled && !qApp->focusObject()) {
+ // Since the menus depend on communicating with a focus object, a focus object is required to show
+ // the menu. Note that QIOSMenu::showPopup() will activate the parent window (and set a focus object)
+ // before this function is called, so this should normally be the case. Not having a focus object is only
+ // expected in a hybrid environment where the first responder can be something else than a QUIView (then
+ // no QWindow will be active). If the focus object changes while the menu is visible, the menu will hide.
+ qWarning() << "QIOSMenu: cannot open menu without any active QWindows!";
+ return;
+ }
+
+ m_effectiveVisible = visibleAndEnabled;
+
+ if (m_effectiveVisible) {
+ Q_ASSERT(m_currentMenu != this);
+ if (m_currentMenu) {
+ // The current implementation allow only one visible
+ // menu at a time, so close the one currently showing.
+ m_currentMenu->setVisible(false);
+ }
+
+ m_currentMenu = this;
+ m_effectiveMenuType = m_menuType;
+ connect(qGuiApp, &QGuiApplication::focusObjectChanged, this, &QIOSMenu::hide);
+ } else {
+ disconnect(qGuiApp, &QGuiApplication::focusObjectChanged, this, &QIOSMenu::hide);
+ m_currentMenu = 0;
+ }
+
+ switch (m_effectiveMenuType) {
+ case EditMenu:
+ updateVisibilityUsingUIMenuController();
+ break;
+ default:
+ updateVisibilityUsingUIPickerView();
+ break;
+ }
+
+ // Emit the signal after the fact in case a
+ // receiver opens a new menu when receiving it.
+ emit (m_effectiveVisible ? aboutToShow() : aboutToHide());
+}
+
+void QIOSMenu::setMenuType(QPlatformMenu::MenuType type)
+{
+ m_menuType = type;
+}
+
+void QIOSMenu::updateVisibilityUsingUIMenuController()
+{
+ if (m_effectiveVisible) {
+ Q_ASSERT(!m_menuController);
+ m_menuController = [[QUIMenuController alloc] initWithVisibleMenuItems:visibleMenuItems()];
+ repositionMenu();
+ connect(qGuiApp->inputMethod(), &QInputMethod::keyboardRectangleChanged, this, &QIOSMenu::repositionMenu);
+ } else {
+ disconnect(qGuiApp->inputMethod(), &QInputMethod::keyboardRectangleChanged, this, &QIOSMenu::repositionMenu);
+
+ Q_ASSERT(m_menuController);
+ [[UIMenuController sharedMenuController] setMenuVisible:NO animated:YES];
+ [m_menuController release];
+ m_menuController = 0;
+ }
+}
+
+void QIOSMenu::updateVisibilityUsingUIPickerView()
+{
+ static QObject *focusObjectWithPickerView = 0;
+
+ if (m_effectiveVisible) {
+ Q_ASSERT(!m_pickerView);
+ m_pickerView = [[QUIPickerView alloc] initWithVisibleMenuItems:visibleMenuItems() selectItem:m_targetItem];
+
+ Q_ASSERT(!focusObjectWithPickerView);
+ focusObjectWithPickerView = qApp->focusWindow()->focusObject();
+ focusObjectWithPickerView->installEventFilter(this);
+ qApp->inputMethod()->update(Qt::ImPlatformData);
+ } else {
+ Q_ASSERT(focusObjectWithPickerView);
+ focusObjectWithPickerView->removeEventFilter(this);
+ qApp->inputMethod()->update(Qt::ImPlatformData);
+ focusObjectWithPickerView = 0;
+
+ Q_ASSERT(m_pickerView);
+ [m_pickerView release];
+ m_pickerView = 0;
+ }
+}
+
+bool QIOSMenu::eventFilter(QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::InputMethodQuery) {
+ QInputMethodQueryEvent *queryEvent = static_cast<QInputMethodQueryEvent *>(event);
+ if (queryEvent->queries() & Qt::ImPlatformData) {
+ // Let object fill inn default query results
+ obj->event(queryEvent);
+
+ QVariantMap imPlatformData = queryEvent->value(Qt::ImPlatformData).toMap();
+ imPlatformData.insert(kImePlatformDataInputView, QVariant::fromValue(static_cast<void *>(m_pickerView)));
+ imPlatformData.insert(kImePlatformDataInputAccessoryView, QVariant::fromValue(static_cast<void *>(m_pickerView.toolbar)));
+ queryEvent->setValue(Qt::ImPlatformData, imPlatformData);
+
+ return true;
+ }
+ }
+
+ return QObject::eventFilter(obj, event);
+}
+
+QIOSMenuItemList QIOSMenu::visibleMenuItems() const
+{
+ QIOSMenuItemList visibleMenuItems = m_menuItems;
+
+ for (int i = visibleMenuItems.count() - 1; i >= 0; --i) {
+ QIOSMenuItem *item = visibleMenuItems.at(i);
+ if (!item->m_enabled || !item->m_visible)
+ visibleMenuItems.removeAt(i);
+ }
+
+ return visibleMenuItems;
+}
+
+void QIOSMenu::repositionMenu()
+{
+ switch (m_effectiveMenuType) {
+ case EditMenu: {
+ UIView *view = [UIApplication sharedApplication].keyWindow.rootViewController.view;
+ [[UIMenuController sharedMenuController] setTargetRect:toCGRect(m_targetRect) inView:view];
+ [[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES];
+ break; }
+ default:
+ break;
+ }
+}
+
+QPlatformMenuItem *QIOSMenu::menuItemAt(int position) const
+{
+ if (position < 0 || position >= m_menuItems.size())
+ return 0;
+ return m_menuItems.at(position);
+}
+
+QPlatformMenuItem *QIOSMenu::menuItemForTag(quintptr tag) const
+{
+ for (int i = 0; i < m_menuItems.size(); ++i) {
+ QPlatformMenuItem *item = m_menuItems.at(i);
+ if (item->tag() == tag)
+ return item;
+ }
+ return 0;
+}
diff --git a/src/plugins/platforms/ios/qiostheme.h b/src/plugins/platforms/ios/qiostheme.h
index b03f65f556..b4b7b8977b 100644
--- a/src/plugins/platforms/ios/qiostheme.h
+++ b/src/plugins/platforms/ios/qiostheme.h
@@ -55,6 +55,9 @@ public:
QVariant themeHint(ThemeHint hint) const;
+ QPlatformMenuItem* createPlatformMenuItem() const Q_DECL_OVERRIDE;
+ QPlatformMenu* createPlatformMenu() const Q_DECL_OVERRIDE;
+
const QFont *font(Font type = SystemFont) const;
static const char *name;
diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm
index e51e97bd5a..cbeb157cf2 100644
--- a/src/plugins/platforms/ios/qiostheme.mm
+++ b/src/plugins/platforms/ios/qiostheme.mm
@@ -53,6 +53,8 @@
#include <UIKit/UIFont.h>
#include <UIKit/UIInterface.h>
+#include "qiosmenu.h"
+
QT_BEGIN_NAMESPACE
const char *QIOSTheme::name = "ios";
@@ -66,6 +68,16 @@ QIOSTheme::~QIOSTheme()
qDeleteAll(m_fonts);
}
+QPlatformMenuItem* QIOSTheme::createPlatformMenuItem() const
+{
+ return new QIOSMenuItem();
+}
+
+QPlatformMenu* QIOSTheme::createPlatformMenu() const
+{
+ return new QIOSMenu();
+}
+
QVariant QIOSTheme::themeHint(ThemeHint hint) const
{
switch (hint) {
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 5687c078ea..3040e89864 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -44,6 +44,7 @@
#include "qiosglobal.h"
#include "qiosintegration.h"
#include "qioswindow.h"
+#include "qiosmenu.h"
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qwindow_p.h>
@@ -347,6 +348,13 @@
QWindowSystemInterface::flushWindowSystemEvents();
}
+- (id)targetForAction:(SEL)action withSender:(id)sender
+{
+ // Check first if QIOSMenu should handle the action before continuing up the responder chain
+ id target = [QIOSMenu::menuActionTarget() targetForAction:action withSender:sender];
+ return target ? target : [super targetForAction:action withSender:sender];
+}
+
@end
@implementation UIView (QtHelpers)
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 6a3930dc78..a23b3cb4bb 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -144,7 +144,7 @@ static inline QColor mixColors(const QColor &c1, const QColor &c2)
static inline QColor getSysColor(int index)
{
- return qColorToCOLORREF(GetSysColor(index));
+ return COLORREFToQColor(GetSysColor(index));
}
// from QStyle::standardPalette
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index a18bd2834e..888ca3d598 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -1007,8 +1007,8 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
HRESULT QWinRTScreen::onAutomationProviderRequested(ICoreWindow *, IAutomationProviderRequestedEventArgs *args)
{
- Q_D(const QWinRTScreen);
#ifndef Q_OS_WINPHONE
+ Q_D(const QWinRTScreen);
args->put_AutomationProvider(d->inputContext.Get());
#else
Q_UNUSED(args)
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index bd62b07a09..72bd22983e 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -193,17 +193,43 @@ void QXcbConnection::xi2SetupDevices()
}
bool isTablet = false;
#ifndef QT_NO_TABLETEVENT
- // If we have found the valuators which we expect a tablet to have, assume it's a tablet.
+ // If we have found the valuators which we expect a tablet to have, it might be a tablet.
if (tabletData.valuatorInfo.contains(QXcbAtom::AbsX) &&
tabletData.valuatorInfo.contains(QXcbAtom::AbsY) &&
- tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure)) {
- tabletData.deviceId = devices[i].deviceid;
+ tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure))
+ isTablet = true;
+
+ // But we need to be careful not to take the touch and tablet-button devices as tablets.
+ QByteArray name = QByteArray(devices[i].name).toLower();
+ QString dbgType = QLatin1String("UNKNOWN");
+ if (name.contains("eraser")) {
+ isTablet = true;
+ tabletData.pointerType = QTabletEvent::Eraser;
+ dbgType = QLatin1String("eraser");
+ } else if (name.contains("cursor")) {
+ isTablet = true;
+ tabletData.pointerType = QTabletEvent::Cursor;
+ dbgType = QLatin1String("cursor");
+ } else if ((name.contains("pen") || name.contains("stylus")) && isTablet) {
tabletData.pointerType = QTabletEvent::Pen;
- if (QByteArray(devices[i].name).toLower().contains("eraser"))
- tabletData.pointerType = QTabletEvent::Eraser;
- m_tabletData.append(tabletData);
+ dbgType = QLatin1String("pen");
+ } else if (name.contains("wacom") && isTablet && !name.contains("touch")) {
+ // combined device (evdev) rather than separate pen/eraser (wacom driver)
+ tabletData.pointerType = QTabletEvent::Pen;
+ dbgType = QLatin1String("pen");
+ } else if (name.contains("aiptek") /* && device == QXcbAtom::KEYBOARD */) {
+ // some "Genius" tablets
isTablet = true;
- qCDebug(lcQpaXInputDevices) << " it's a tablet with pointer type" << tabletData.pointerType;
+ tabletData.pointerType = QTabletEvent::Pen;
+ dbgType = QLatin1String("pen");
+ } else {
+ isTablet = false;
+ }
+
+ if (isTablet) {
+ tabletData.deviceId = devices[i].deviceid;
+ m_tabletData.append(tabletData);
+ qCDebug(lcQpaXInputDevices) << " it's a tablet with pointer type" << dbgType;
}
#endif // QT_NO_TABLETEVENT
@@ -381,6 +407,10 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
} else if (vci->label == atom(QXcbAtom::RelY)) {
hasRelativeCoords = true;
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
+ } else if (vci->label == atom(QXcbAtom::AbsX)) {
+ dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
+ } else if (vci->label == atom(QXcbAtom::AbsY)) {
+ dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
}
break;
}
@@ -495,6 +525,10 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
nx = valuatorNormalized(value, vci);
} else if (vci->label == atom(QXcbAtom::RelY)) {
ny = valuatorNormalized(value, vci);
+ } else if (vci->label == atom(QXcbAtom::AbsX)) {
+ nx = valuatorNormalized(value, vci);
+ } else if (vci->label == atom(QXcbAtom::AbsY)) {
+ ny = valuatorNormalized(value, vci);
} else if (vci->label == atom(QXcbAtom::AbsMTPositionX)) {
nx = valuatorNormalized(value, vci);
} else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) {
diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp
index 0eed6ea4d3..d411076649 100644
--- a/src/sql/models/qsqltablemodel.cpp
+++ b/src/sql/models/qsqltablemodel.cpp
@@ -931,7 +931,7 @@ void QSqlTableModel::setPrimaryKey(const QSqlIndex &key)
}
/*!
- Returns a pointer to the used QSqlDatabase or 0 if no database was set.
+ Returns the model's database connection.
*/
QSqlDatabase QSqlTableModel::database() const
{
diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp
index 7921b350b5..69f8ae4ca5 100644
--- a/src/testlib/qtestblacklist.cpp
+++ b/src/testlib/qtestblacklist.cpp
@@ -70,6 +70,7 @@ QT_BEGIN_NAMESPACE
// this table can be extended with new keywords as required
const char *matchedConditions[] =
{
+ "*",
#ifdef Q_OS_LINUX
"linux",
#endif
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 877be81fb9..00e7ac62c0 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -2372,6 +2372,11 @@ static LONG WINAPI windowsFaultHandler(struct _EXCEPTION_POINTERS *exInfo)
}
#endif // Q_OS_WIN) && !Q_OS_WINCE && !Q_OS_WINRT
+static void initEnvironment()
+{
+ qputenv("QT_LOGGING_TO_CONSOLE", "1");
+}
+
/*!
Executes tests declared in \a testObject. In addition, the private slots
\c{initTestCase()}, \c{cleanupTestCase()}, \c{init()} and \c{cleanup()}
@@ -2412,6 +2417,7 @@ static LONG WINAPI windowsFaultHandler(struct _EXCEPTION_POINTERS *exInfo)
int QTest::qExec(QObject *testObject, int argc, char **argv)
{
+ initEnvironment();
QBenchmarkGlobalData benchmarkData;
QBenchmarkGlobalData::current = &benchmarkData;
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index c074652cf3..95e845d196 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -2671,8 +2671,9 @@ void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logical
opt.iconAlignment = Qt::AlignVCenter;
opt.text = d->model->headerData(logicalIndex, d->orientation,
Qt::DisplayRole).toString();
+ const int margin = 2 * style()->pixelMetric(QStyle::PM_HeaderMargin, 0, this);
if (d->textElideMode != Qt::ElideNone)
- opt.text = opt.fontMetrics.elidedText(opt.text, d->textElideMode , rect.width() - 4);
+ opt.text = opt.fontMetrics.elidedText(opt.text, d->textElideMode , rect.width() - margin);
QVariant variant = d->model->headerData(logicalIndex, d->orientation,
Qt::DecorationRole);
diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp
index 3975e423a0..2ac1893256 100644
--- a/src/widgets/kernel/qdesktopwidget.cpp
+++ b/src/widgets/kernel/qdesktopwidget.cpp
@@ -97,6 +97,8 @@ void QDesktopWidgetPrivate::_q_updateScreens()
screenWidget->setGeometry(qScreen->geometry());
QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)),
q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
+ QObject::connect(qScreen, SIGNAL(availableGeometryChanged(QRect)),
+ q, SLOT(_q_availableGeometryChanged()), Qt::QueuedConnection);
QObject::connect(qScreen, SIGNAL(destroyed()),
q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
screens.append(screenWidget);
@@ -122,10 +124,15 @@ void QDesktopWidgetPrivate::_q_updateScreens()
if (oldLength != targetLength)
emit q->screenCountChanged(targetLength);
- foreach (int changedScreen, changedScreens) {
+ foreach (int changedScreen, changedScreens)
emit q->resized(changedScreen);
- emit q->workAreaResized(changedScreen);
- }
+}
+
+void QDesktopWidgetPrivate::_q_availableGeometryChanged()
+{
+ Q_Q(QDesktopWidget);
+ if (QScreen *screen = qobject_cast<QScreen *>(q->sender()))
+ emit q->workAreaResized(QGuiApplication::screens().indexOf(screen));
}
QDesktopWidget::QDesktopWidget()
diff --git a/src/widgets/kernel/qdesktopwidget.h b/src/widgets/kernel/qdesktopwidget.h
index 42c338f696..4bfbf599c1 100644
--- a/src/widgets/kernel/qdesktopwidget.h
+++ b/src/widgets/kernel/qdesktopwidget.h
@@ -93,6 +93,7 @@ private:
Q_DISABLE_COPY(QDesktopWidget)
Q_DECLARE_PRIVATE(QDesktopWidget)
Q_PRIVATE_SLOT(d_func(), void _q_updateScreens())
+ Q_PRIVATE_SLOT(d_func(), void _q_availableGeometryChanged())
friend class QApplication;
friend class QApplicationPrivate;
diff --git a/src/widgets/kernel/qdesktopwidget_p.h b/src/widgets/kernel/qdesktopwidget_p.h
index 160807cf23..89c70e53b0 100644
--- a/src/widgets/kernel/qdesktopwidget_p.h
+++ b/src/widgets/kernel/qdesktopwidget_p.h
@@ -75,6 +75,7 @@ class QDesktopWidgetPrivate : public QWidgetPrivate {
public:
~QDesktopWidgetPrivate() {foreach(QDesktopScreenWidget *s, screens) delete s; }
void _q_updateScreens();
+ void _q_availableGeometryChanged();
QList<QDesktopScreenWidget *> screens;
};
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 6fbae53804..110682a7b6 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -418,8 +418,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
#ifndef QT_NO_GROUPBOX
case PE_FrameGroupBox:
if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
- const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt);
- if (frame2 && (frame2->features & QStyleOptionFrameV2::Flat)) {
+ if (frame->features & QStyleOptionFrame::Flat) {
QRect fr = frame->rect;
QPoint p1(fr.x(), fr.y() + 1);
QPoint p2(fr.x() + fr.width(), p1.y());
@@ -2234,7 +2233,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
#endif // QT_NO_ITEMVIEWS
#ifndef QT_NO_FRAME
case CE_ShapedFrame:
- if (const QStyleOptionFrameV3 *f = qstyleoption_cast<const QStyleOptionFrameV3 *>(opt)) {
+ if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
int frameShape = f->frameShape;
int frameShadow = QFrame::Plain;
if (f->state & QStyle::State_Sunken) {
@@ -2824,14 +2823,14 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
}
break;
case SE_FrameContents:
- if (const QStyleOptionFrameV2 *f = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt)) {
+ if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, f, widget);
r = opt->rect.adjusted(fw, fw, -fw, -fw);
r = visualRect(opt->direction, opt->rect, r);
}
break;
case SE_ShapedFrameContents:
- if (const QStyleOptionFrameV3 *f = qstyleoption_cast<const QStyleOptionFrameV3 *>(opt)) {
+ if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
int frameShape = f->frameShape;
int frameShadow = QFrame::Plain;
if (f->state & QStyle::State_Sunken) {
@@ -3652,7 +3651,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
QRect textRect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, widget);
QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, widget);
if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
- QStyleOptionFrameV2 frame;
+ QStyleOptionFrame frame;
frame.QStyleOption::operator=(*groupBox);
frame.features = groupBox->features;
frame.lineWidth = groupBox->lineWidth;
@@ -4243,7 +4242,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
}
int frameWidth = 0;
- if ((groupBox->features & QStyleOptionFrameV2::Flat) == 0)
+ if ((groupBox->features & QStyleOptionFrame::Flat) == 0)
frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth, groupBox, widget);
ret = frameRect.adjusted(frameWidth, frameWidth + topHeight - topMargin,
-frameWidth, -frameWidth);
@@ -4255,7 +4254,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
QFontMetrics fontMetrics = groupBox->fontMetrics;
int h = fontMetrics.height();
int tw = fontMetrics.size(Qt::TextShowMnemonic, groupBox->text + QLatin1Char(' ')).width();
- int marg = (groupBox->features & QStyleOptionFrameV2::Flat) ? 0 : 8;
+ int marg = (groupBox->features & QStyleOptionFrame::Flat) ? 0 : 8;
ret = groupBox->rect.adjusted(marg, 0, -marg, 0);
ret.setHeight(h);
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 4d9f3a48e2..5e6e528f6d 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -1827,7 +1827,7 @@ QRenderRule QStyleSheetStyle::renderRule(const QObject *obj, const QStyleOption
extraClass |= PseudoClass_Frameless;
#endif // QT_NO_SPINBOX
} else if (const QStyleOptionGroupBox *gb = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
- if (gb->features & QStyleOptionFrameV2::Flat)
+ if (gb->features & QStyleOptionFrame::Flat)
extraClass |= PseudoClass_Flat;
if (gb->lineWidth == 0)
extraClass |= PseudoClass_Frameless;
@@ -1934,10 +1934,8 @@ QRenderRule QStyleSheetStyle::renderRule(const QObject *obj, const QStyleOption
} else if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
if (frm->lineWidth == 0)
extraClass |= PseudoClass_Frameless;
- if (const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt)) {
- if (frame2->features & QStyleOptionFrameV2::Flat)
- extraClass |= PseudoClass_Flat;
- }
+ if (frm->features & QStyleOptionFrame::Flat)
+ extraClass |= PseudoClass_Flat;
}
#ifndef QT_NO_TOOLBAR
else if (const QStyleOptionToolBar *tb = qstyleoption_cast<const QStyleOptionToolBar *>(opt)) {
@@ -2994,7 +2992,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
}
frameRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, w);
- QStyleOptionFrameV2 frame;
+ QStyleOptionFrame frame;
frame.QStyleOption::operator=(*gb);
frame.features = gb->features;
frame.lineWidth = gb->lineWidth;
@@ -4089,7 +4087,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
case CE_ShapedFrame:
if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
if (rule.hasNativeBorder()) {
- QStyleOptionFrameV3 frmOpt(*frm);
+ QStyleOptionFrame frmOpt(*frm);
rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base);
frmOpt.rect = rule.borderRect(frmOpt.rect);
baseStyle()->drawControl(ce, &frmOpt, p, w);
@@ -4224,10 +4222,8 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
case PE_Frame:
if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
if (rule.hasNativeBorder()) {
- QStyleOptionFrameV2 frmOpt(*frm);
+ QStyleOptionFrame frmOpt(*frm);
rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base);
- if (!qstyleoption_cast<const QStyleOptionFrameV3 *>(opt)) //if it comes from CE_ShapedFrame, the margins are already sustracted
- frmOpt.rect = rule.borderRect(frmOpt.rect);
baseStyle()->drawPrimitive(pe, &frmOpt, p, w);
} else {
rule.drawBorder(p, rule.borderRect(opt->rect));
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index bdc5a6ce0e..2d09230436 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -1183,7 +1183,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
case CE_MenuItem:
if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
// windows always has a check column, regardless whether we have an icon or not
- int checkcol = 25;
+ int checkcol = 25 / QWindowsXPStylePrivate::devicePixelRatio(widget);
+ const int gutterWidth = 3 / QWindowsXPStylePrivate::devicePixelRatio(widget);
{
XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme,
MENU_POPUPCHECKBACKGROUND, MBI_HOT);
@@ -1192,7 +1193,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
themeSize.stateId = 0;
const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget);
const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget);
- checkcol = qMax(menuitem->maxIconWidth, int(3 + size.width() + margins.left() + margins.right()));
+ checkcol = qMax(menuitem->maxIconWidth, gutterWidth + size.width() + margins.left() + margins.right());
}
QRect rect = option->rect;
@@ -1201,7 +1202,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
checkcol += rect.x();
QPoint p1 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.top()));
QPoint p2 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.bottom()));
- QRect gutterRect(p1.x(), p1.y(), 3, p2.y() - p1.y() + 1);
+ QRect gutterRect(p1.x(), p1.y(), gutterWidth, p2.y() - p1.y() + 1);
XPThemeData theme2(widget, painter, QWindowsXPStylePrivate::MenuTheme,
MENU_POPUPGUTTER, stateId, gutterRect);
d->drawBackground(theme2);
@@ -1216,10 +1217,12 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) {
int yoff = y-2 + h / 2;
+ const int separatorSize = 6 / QWindowsXPStylePrivate::devicePixelRatio(widget);
QPoint p1 = QPoint(x + checkcol, yoff);
- QPoint p2 = QPoint(x + w + 6 , yoff);
+ QPoint p2 = QPoint(x + w + separatorSize, yoff);
stateId = MBI_HOT;
- QRect subRect(p1.x() + (3 - menuitem->rect.x()), p1.y(), p2.x() - p1.x(), 6);
+ QRect subRect(p1.x() + (gutterWidth - menuitem->rect.x()), p1.y(),
+ p2.x() - p1.x(), separatorSize);
subRect = QStyle::visualRect(option->direction, option->rect, subRect );
XPThemeData theme2(widget, painter,
QWindowsXPStylePrivate::MenuTheme,
@@ -1229,7 +1232,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
}
QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(),
- menuitem->rect.y(), checkcol - (3 + menuitem->rect.x()), menuitem->rect.height()));
+ menuitem->rect.y(), checkcol - (gutterWidth + menuitem->rect.x()), menuitem->rect.height()));
if (act) {
stateId = dis ? MBI_DISABLED : MBI_HOT;
@@ -1294,7 +1297,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (dis)
painter->setPen(textColor);
- int xm = windowsItemFrame + checkcol + windowsItemHMargin + (3 - menuitem->rect.x()) - 1;
+ int xm = windowsItemFrame + checkcol + windowsItemHMargin + (gutterWidth - menuitem->rect.x()) - 1;
int xpos = menuitem->rect.x() + xm;
QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin);
QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect);
diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp
index 4aed153932..0d8c7957e2 100644
--- a/src/widgets/widgets/qabstractspinbox.cpp
+++ b/src/widgets/widgets/qabstractspinbox.cpp
@@ -1100,7 +1100,10 @@ void QAbstractSpinBox::keyReleaseEvent(QKeyEvent *event)
#ifndef QT_NO_WHEELEVENT
void QAbstractSpinBox::wheelEvent(QWheelEvent *event)
{
- const int steps = (event->delta() > 0 ? 1 : -1);
+ Q_D(QAbstractSpinBox);
+ d->wheelDeltaRemainder += event->angleDelta().y();
+ const int steps = d->wheelDeltaRemainder / 120;
+ d->wheelDeltaRemainder -= steps * 120;
if (stepEnabled() & (steps > 0 ? StepUpEnabled : StepDownEnabled))
stepBy(event->modifiers() & Qt::ControlModifier ? steps * 10 : steps);
event->accept();
@@ -1344,7 +1347,7 @@ QAbstractSpinBoxPrivate::QAbstractSpinBoxPrivate()
ignoreCursorPositionChanged(false), frame(true), accelerate(false), keyboardTracking(true),
cleared(false), ignoreUpdateEdit(false), correctionMode(QAbstractSpinBox::CorrectToPreviousValue),
acceleration(0), hoverControl(QStyle::SC_None), buttonSymbols(QAbstractSpinBox::UpDownArrows), validator(0),
- showGroupSeparator(0)
+ showGroupSeparator(0), wheelDeltaRemainder(0)
{
}
diff --git a/src/widgets/widgets/qabstractspinbox_p.h b/src/widgets/widgets/qabstractspinbox_p.h
index da9f1d9757..055fe92591 100644
--- a/src/widgets/widgets/qabstractspinbox_p.h
+++ b/src/widgets/widgets/qabstractspinbox_p.h
@@ -151,6 +151,7 @@ public:
QAbstractSpinBox::ButtonSymbols buttonSymbols;
QSpinBoxValidator *validator;
uint showGroupSeparator : 1;
+ int wheelDeltaRemainder;
};
class QSpinBoxValidator : public QValidator
diff --git a/src/widgets/widgets/qcalendartextnavigator_p.h b/src/widgets/widgets/qcalendartextnavigator_p.h
deleted file mode 100644
index 88bd3c6a71..0000000000
--- a/src/widgets/widgets/qcalendartextnavigator_p.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtWidgets 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 QCALENDARTEXTNAVIGATOR_P_H
-#define QCALENDARTEXTNAVIGATOR_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/qobject.h>
-#include <QtCore/qdatetime.h>
-#include <QtCore/qbasictimer.h>
-
-#ifndef QT_NO_CALENDARWIDGET
-
-QT_BEGIN_NAMESPACE
-
-class QLabel;
-class QCalendarDateValidator;
-class QFrame;
-
-class QCalendarTextNavigator: public QObject
-{
- Q_OBJECT
-public:
- QCalendarTextNavigator(QObject *parent = 0)
- : QObject(parent), m_dateText(0), m_dateFrame(0), m_dateValidator(0), m_widget(0), m_editDelay(1500), m_date(QDate::currentDate()) { }
-
- QWidget *widget() const;
- void setWidget(QWidget *widget);
-
- int dateEditAcceptDelay() const;
- void setDateEditAcceptDelay(int delay);
-
- QDate date() const;
- void setDate(const QDate &date);
-
- bool eventFilter(QObject *o, QEvent *e);
- void timerEvent(QTimerEvent *e);
-
-signals:
- void dateChanged(const QDate &date);
- void editingFinished();
-
-private:
- void applyDate();
- void updateDateLabel();
- void createDateLabel();
- void removeDateLabel();
-
- QLabel *m_dateText;
- QFrame *m_dateFrame;
- QBasicTimer m_acceptTimer;
- QCalendarDateValidator *m_dateValidator;
- QWidget *m_widget;
- int m_editDelay;
-
- QDate m_date;
-};
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_CALENDARWIDGET
-
-#endif
-
diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp
index 8755f99288..b281b98cb0 100644
--- a/src/widgets/widgets/qcalendarwidget.cpp
+++ b/src/widgets/widgets/qcalendarwidget.cpp
@@ -60,7 +60,6 @@
#include <qapplication.h>
#include <qbasictimer.h>
#include <qstylepainter.h>
-#include <private/qcalendartextnavigator_p.h>
QT_BEGIN_NAMESPACE
@@ -72,6 +71,8 @@ enum {
MinimumDayOffset = 1
};
+namespace {
+
class QCalendarDateSectionValidator
{
public:
@@ -589,6 +590,7 @@ void QCalendarDateValidator::setFormat(const QString &format)
const QChar nextChar = format.at(pos);
if (quoting) {
separator += nextChar;
+ quoting = false;
} else {
SectionToken *token = 0;
if (nextChar == QLatin1Char('d')) {
@@ -671,6 +673,47 @@ void QCalendarDateValidator::handleKeyEvent(QKeyEvent *keyEvent)
toPreviousToken();
}
+//////////////////////////////////
+
+class QCalendarTextNavigator: public QObject
+{
+ Q_OBJECT
+public:
+ QCalendarTextNavigator(QObject *parent = 0)
+ : QObject(parent), m_dateText(0), m_dateFrame(0), m_dateValidator(0), m_widget(0), m_editDelay(1500), m_date(QDate::currentDate()) { }
+
+ QWidget *widget() const;
+ void setWidget(QWidget *widget);
+
+ int dateEditAcceptDelay() const;
+ void setDateEditAcceptDelay(int delay);
+
+ QDate date() const;
+ void setDate(const QDate &date);
+
+ bool eventFilter(QObject *o, QEvent *e);
+ void timerEvent(QTimerEvent *e);
+
+signals:
+ void dateChanged(const QDate &date);
+ void editingFinished();
+
+private:
+ void applyDate();
+ void updateDateLabel();
+ void createDateLabel();
+ void removeDateLabel();
+
+ QLabel *m_dateText;
+ QFrame *m_dateFrame;
+ QBasicTimer m_acceptTimer;
+ QCalendarDateValidator *m_dateValidator;
+ QWidget *m_widget;
+ int m_editDelay;
+
+ QDate m_date;
+};
+
QWidget *QCalendarTextNavigator::widget() const
{
return m_widget;
@@ -1573,6 +1616,8 @@ protected:
}
};
+} // unnamed namespace
+
class QCalendarWidgetPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QCalendarWidget)
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index 3ff8e8cbbf..f1471cc6e4 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -2277,11 +2277,8 @@ void QPlainTextEdit::wheelEvent(QWheelEvent *e)
Q_D(QPlainTextEdit);
if (!(d->control->textInteractionFlags() & Qt::TextEditable)) {
if (e->modifiers() & Qt::ControlModifier) {
- const int delta = e->delta();
- if (delta < 0)
- zoomOut();
- else if (delta > 0)
- zoomIn();
+ float delta = e->angleDelta().y() / 120.f;
+ zoomInF(delta);
return;
}
}
@@ -2301,12 +2298,7 @@ void QPlainTextEdit::wheelEvent(QWheelEvent *e)
*/
void QPlainTextEdit::zoomIn(int range)
{
- QFont f = font();
- const int newSize = f.pointSize() + range;
- if (newSize <= 0)
- return;
- f.setPointSize(newSize);
- setFont(f);
+ zoomInF(range);
}
/*!
@@ -2322,7 +2314,22 @@ void QPlainTextEdit::zoomIn(int range)
*/
void QPlainTextEdit::zoomOut(int range)
{
- zoomIn(-range);
+ zoomInF(-range);
+}
+
+/*!
+ \internal
+*/
+void QPlainTextEdit::zoomInF(float range)
+{
+ if (range == 0.f)
+ return;
+ QFont f = font();
+ const float newSize = f.pointSizeF() + range;
+ if (newSize <= 0)
+ return;
+ f.setPointSizeF(newSize);
+ setFont(f);
}
#ifndef QT_NO_CONTEXTMENU
diff --git a/src/widgets/widgets/qplaintextedit.h b/src/widgets/widgets/qplaintextedit.h
index 54cd3e14ed..f61d9c3aaa 100644
--- a/src/widgets/widgets/qplaintextedit.h
+++ b/src/widgets/widgets/qplaintextedit.h
@@ -271,6 +271,7 @@ protected:
QRectF blockBoundingGeometry(const QTextBlock &block) const;
QAbstractTextDocumentLayout::PaintContext getPaintContext() const;
+ void zoomInF(float range);
private:
Q_DISABLE_COPY(QPlainTextEdit)
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index f106b70c12..b4dd09d6d4 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -1813,11 +1813,8 @@ void QTextEdit::wheelEvent(QWheelEvent *e)
Q_D(QTextEdit);
if (!(d->control->textInteractionFlags() & Qt::TextEditable)) {
if (e->modifiers() & Qt::ControlModifier) {
- const int delta = e->delta();
- if (delta < 0)
- zoomOut();
- else if (delta > 0)
- zoomIn();
+ float delta = e->angleDelta().y() / 120.f;
+ zoomInF(delta);
return;
}
}
@@ -2276,12 +2273,7 @@ void QTextEdit::scrollToAnchor(const QString &name)
*/
void QTextEdit::zoomIn(int range)
{
- QFont f = font();
- const int newSize = f.pointSize() + range;
- if (newSize <= 0)
- return;
- f.setPointSize(newSize);
- setFont(f);
+ zoomInF(range);
}
/*!
@@ -2297,7 +2289,22 @@ void QTextEdit::zoomIn(int range)
*/
void QTextEdit::zoomOut(int range)
{
- zoomIn(-range);
+ zoomInF(-range);
+}
+
+/*!
+ \internal
+*/
+void QTextEdit::zoomInF(float range)
+{
+ if (range == 0.f)
+ return;
+ QFont f = font();
+ const float newSize = f.pointSizeF() + range;
+ if (newSize <= 0)
+ return;
+ f.setPointSizeF(newSize);
+ setFont(f);
}
/*!
diff --git a/src/widgets/widgets/qtextedit.h b/src/widgets/widgets/qtextedit.h
index a283a51b90..d23d2d59ce 100644
--- a/src/widgets/widgets/qtextedit.h
+++ b/src/widgets/widgets/qtextedit.h
@@ -304,6 +304,8 @@ protected:
virtual void scrollContentsBy(int dx, int dy);
virtual void doSetTextCursor(const QTextCursor &cursor);
+ void zoomInF(float range);
+
private:
Q_DISABLE_COPY(QTextEdit)
Q_PRIVATE_SLOT(d_func(), void _q_repaintContents(const QRectF &r))
diff --git a/src/widgets/widgets/widgets.pri b/src/widgets/widgets/widgets.pri
index a924ba9acc..342d2093db 100644
--- a/src/widgets/widgets/widgets.pri
+++ b/src/widgets/widgets/widgets.pri
@@ -8,7 +8,6 @@ HEADERS += \
widgets/qabstractslider_p.h \
widgets/qabstractspinbox.h \
widgets/qabstractspinbox_p.h \
- widgets/qcalendartextnavigator_p.h \
widgets/qcalendarwidget.h \
widgets/qcheckbox.h \
widgets/qcombobox.h \