From 51381e1454070960bc3c1d6acdfa8e742c37620c Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Tue, 6 Apr 2010 15:56:38 +1000 Subject: Labs (experimental) Gesture support. By popular demand. --- doc/src/declarative/elements.qdoc | 3 +- .../declarative/gestures/experimental-gestures.qml | 27 +++ src/declarative/qml/qdeclarativeparser_p.h | 2 +- src/imports/gestures/gestures.pro | 27 +++ src/imports/gestures/plugin.cpp | 66 +++++ src/imports/gestures/qdeclarativegesturearea.cpp | 265 +++++++++++++++++++++ src/imports/gestures/qdeclarativegesturearea_p.h | 102 ++++++++ src/imports/gestures/qmldir | 1 + 8 files changed, 491 insertions(+), 2 deletions(-) create mode 100644 examples/declarative/gestures/experimental-gestures.qml create mode 100644 src/imports/gestures/gestures.pro create mode 100644 src/imports/gestures/plugin.cpp create mode 100644 src/imports/gestures/qdeclarativegesturearea.cpp create mode 100644 src/imports/gestures/qdeclarativegesturearea_p.h create mode 100644 src/imports/gestures/qmldir diff --git a/doc/src/declarative/elements.qdoc b/doc/src/declarative/elements.qdoc index 5eaaf7e..1bb739d 100644 --- a/doc/src/declarative/elements.qdoc +++ b/doc/src/declarative/elements.qdoc @@ -132,6 +132,7 @@ The following table lists the QML elements provided by the Qt Declarative module \o \l FocusScope \o \l Flickable \o \l Flipable +\o \l GestureArea (experimental) \endlist \o @@ -194,7 +195,7 @@ The following table lists the QML elements provided by the Qt Declarative module \o \list -\o \l Particles +\o \l Particles (experimental) \list \o \l ParticleMotionLinear \o \l ParticleMotionGravity diff --git a/examples/declarative/gestures/experimental-gestures.qml b/examples/declarative/gestures/experimental-gestures.qml new file mode 100644 index 0000000..914d403 --- /dev/null +++ b/examples/declarative/gestures/experimental-gestures.qml @@ -0,0 +1,27 @@ +import Qt 4.7 +import Qt.labs.gestures 1.0 + +// Only works on platforms with Touch support. + +Rectangle { + id: rect + + GestureArea { + anchors.fill: parent + + // Only some of the many gesture properties are shown. See Gesture documentation. + + onTap: + console.log("tap pos = (",gesture.position.x,",",gesture.position.y,")") + onTapAndHold: + console.log("tap and hold pos = (",gesture.position.x,",",gesture.position.y,")") + onPan: + console.log("pan delta = (",gesture.delta.x,",",gesture.delta.y,") acceleration = ",gesture.acceleration) + onPinch: + console.log("pinch center = (",gesture.centerPoint.x,",",gesture.centerPoint.y,") rotation =",gesture.rotationAngle," scale =",gesture.scaleFactor) + onSwipe: + console.log("swipe angle=",gesture.swipeAngle) + onGesture: + console.log("gesture hot spot = (",gesture.hotSpot.x,",",gesture.hotSpot.y,")") + } +} diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h index f432024..be8f906 100644 --- a/src/declarative/qml/qdeclarativeparser_p.h +++ b/src/declarative/qml/qdeclarativeparser_p.h @@ -237,7 +237,7 @@ namespace QDeclarativeParser QList dynamicSlots; }; - class Variant + class Q_DECLARATIVE_EXPORT Variant { public: enum Type { diff --git a/src/imports/gestures/gestures.pro b/src/imports/gestures/gestures.pro new file mode 100644 index 0000000..b9c5b4e --- /dev/null +++ b/src/imports/gestures/gestures.pro @@ -0,0 +1,27 @@ +TARGET = gesturesqmlplugin +TARGETPATH = Qt/labs/gestures +include(../qimportbase.pri) + +QT += declarative + +SOURCES += qdeclarativegesturearea.cpp plugin.cpp +HEADERS += qdeclarativegesturearea_p.h + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/imports/$$TARGETPATH +target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH + +qmldir.files += $$PWD/qmldir +qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH + +symbian:{ + load(data_caging_paths) + include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) + + importFiles.sources = gesturesqmlplugin.dll \ + qmldir + importFiles.path = $$QT_IMPORTS_BASE_DIR/$$TARGETPATH + + DEPLOYMENT = importFiles +} + +INSTALLS += target qmldir diff --git a/src/imports/gestures/plugin.cpp b/src/imports/gestures/plugin.cpp new file mode 100644 index 0000000..9f5d923 --- /dev/null +++ b/src/imports/gestures/plugin.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "qdeclarativegesturearea_p.h" + +QT_BEGIN_NAMESPACE + +class GestureAreaQmlPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + virtual void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.gestures")); + qmlRegisterCustomType(uri,1,0, "GestureArea", "QDeclarativeGestureArea", + new QDeclarativeGestureAreaParser); + } +}; + +QT_END_NAMESPACE + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(gesturesqmlplugin, QT_PREPEND_NAMESPACE(GestureAreaQmlPlugin)); + diff --git a/src/imports/gestures/qdeclarativegesturearea.cpp b/src/imports/gestures/qdeclarativegesturearea.cpp new file mode 100644 index 0000000..9b4af03 --- /dev/null +++ b/src/imports/gestures/qdeclarativegesturearea.cpp @@ -0,0 +1,265 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegesturearea_p.h" + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeGestureAreaPrivate : public QDeclarativeItemPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeGestureArea) +public: + QDeclarativeGestureAreaPrivate() : componentcomplete(false), gesture(0) {} + + typedef QMap Bindings; + Bindings bindings; + + bool componentcomplete; + + QByteArray data; + + QGesture *gesture; + + bool gestureEvent(QGestureEvent *event); +}; + +/*! + \qmlclass GestureArea QDeclarativeGestureArea + \brief The GestureArea item enables simple gesture handling. + \inherits Item + + A GestureArea is like a MouseArea, but it has signals for gesture events. + + \e {This element is only functional on devices with touch input.} + + \qml + import Qt.labs.gestures 0.1 + + GestureArea { + anchors.fill: parent + onPan: ... gesture.acceleration ... + onPinch: ... gesture.rotationAngle ... + onSwipe: ... + onTapAndHold: ... + onTap: ... + onGesture: ... + } + \endqml + + Each signal has a \e gesture parameter that has the + properties of the gesture. + + \table + \header \o Signal \o Type \o Property \o Description + \row \o onTap \o point \o position \o the position of the tap + \row \o onTapAndHold \o point \o position \o the position of the tap + \row \o onPan \o real \o acceleration \o the acceleration of the pan + \row \o onPan \o point \o delta \o the offset from the previous input position to the current input + \row \o onPan \o point \o offset \o the total offset from the first input position to the current input position + \row \o onPan \o point \o lastOffset \o the previous value of offset + \row \o onPinch \o point \o centerPoint \o the midpoint between the two input points + \row \o onPinch \o point \o lastCenterPoint \o the previous value of centerPoint + \row \o onPinch \o point \o startCenterPoint \o the first value of centerPoint + \row \o onPinch \o real \o rotationAngle \o the angle covered by the gesture motion + \row \o onPinch \o real \o lastRotationAngle \o the previous value of rotationAngle + \row \o onPinch \o real \o totalRotationAngle \o the complete angle covered by the gesture + \row \o onPinch \o real \o scaleFactor \o the change in distance between the two input points + \row \o onPinch \o real \o lastScaleFactor \o the previous value of scaleFactor + \row \o onPinch \o real \o totalScaleFactor \o the complete scale factor of the gesture + \row \o onSwipe \o real \o swipeAngle \o the angle of the swipe + \endtable + + Custom gestures, handled by onGesture, will have custom properties. + + GestureArea is an invisible item: it is never painted. + + \sa Gesture, MouseArea +*/ + +/*! + \internal + \class QDeclarativeGestureArea + \brief The QDeclarativeGestureArea class provides simple gesture handling. + +*/ +QDeclarativeGestureArea::QDeclarativeGestureArea(QDeclarativeItem *parent) : + QDeclarativeItem(*(new QDeclarativeGestureAreaPrivate), parent) +{ + setAcceptedMouseButtons(Qt::LeftButton); + setAcceptTouchEvents(true); +} + +QDeclarativeGestureArea::~QDeclarativeGestureArea() +{ +} + +QByteArray +QDeclarativeGestureAreaParser::compile(const QList &props) +{ + QByteArray rv; + QDataStream ds(&rv, QIODevice::WriteOnly); + + for(int ii = 0; ii < props.count(); ++ii) + { + QString propName = QString::fromUtf8(props.at(ii).name()); + Qt::GestureType type; + + if (propName == QLatin1String("onTap")) { + type = Qt::TapGesture; + } else if (propName == QLatin1String("onTapAndHold")) { + type = Qt::TapAndHoldGesture; + } else if (propName == QLatin1String("onPan")) { + type = Qt::PanGesture; + } else if (propName == QLatin1String("onPinch")) { + type = Qt::PinchGesture; + } else if (propName == QLatin1String("onSwipe")) { + type = Qt::SwipeGesture; + } else if (propName == QLatin1String("onGesture")) { + type = Qt::CustomGesture; + } else { + error(props.at(ii), QDeclarativeGestureArea::tr("Cannot assign to non-existent property \"%1\"").arg(propName)); + return QByteArray(); + } + + QList values = props.at(ii).assignedValues(); + + for (int i = 0; i < values.count(); ++i) { + const QVariant &value = values.at(i); + + if (value.userType() == qMetaTypeId()) { + error(props.at(ii), QDeclarativeGestureArea::tr("GestureArea: nested objects not allowed")); + return QByteArray(); + } else if (value.userType() == qMetaTypeId()) { + error(props.at(ii), QDeclarativeGestureArea::tr("GestureArea: syntax error")); + return QByteArray(); + } else { + QDeclarativeParser::Variant v = qvariant_cast(value); + if (v.isScript()) { + ds << propName; + ds << int(type); + ds << v.asScript(); + } else { + error(props.at(ii), QDeclarativeGestureArea::tr("GestureArea: script expected")); + return QByteArray(); + } + } + } + } + + return rv; +} + +void QDeclarativeGestureAreaParser::setCustomData(QObject *object, + const QByteArray &data) +{ + QDeclarativeGestureArea *ga = static_cast(object); + ga->d_func()->data = data; +} + + +void QDeclarativeGestureArea::connectSignals() +{ + Q_D(QDeclarativeGestureArea); + if (!d->componentcomplete) + return; + + QDataStream ds(d->data); + while (!ds.atEnd()) { + QString propName; + ds >> propName; + int gesturetype; + ds >> gesturetype; + QString script; + ds >> script; + QDeclarativeExpression *exp = new QDeclarativeExpression(qmlContext(this), script, 0); + d->bindings.insert(Qt::GestureType(gesturetype),exp); + grabGesture(Qt::GestureType(gesturetype)); + } +} + +void QDeclarativeGestureArea::componentComplete() +{ + Q_D(QDeclarativeGestureArea); + d->componentcomplete=true; + connectSignals(); +} + +QGesture *QDeclarativeGestureArea::gesture() const +{ + Q_D(const QDeclarativeGestureArea); + return d->gesture; +} + +bool QDeclarativeGestureArea::sceneEvent(QEvent *event) +{ + Q_D(QDeclarativeGestureArea); + if (event->type() == QEvent::Gesture) + return d->gestureEvent(static_cast(event)); + return QDeclarativeItem::sceneEvent(event); +} + +bool QDeclarativeGestureAreaPrivate::gestureEvent(QGestureEvent *event) +{ + bool accept = true; + for (Bindings::Iterator it = bindings.begin(); it != bindings.end(); ++it) { + if ((gesture = event->gesture(it.key()))) { + it.value()->value(); + event->setAccepted(true); // XXX only if value returns true? + } + } + return accept; +} + +QT_END_NAMESPACE diff --git a/src/imports/gestures/qdeclarativegesturearea_p.h b/src/imports/gestures/qdeclarativegesturearea_p.h new file mode 100644 index 0000000..8d7fdfe --- /dev/null +++ b/src/imports/gestures/qdeclarativegesturearea_p.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGESTUREAREA_H +#define QDECLARATIVEGESTUREAREA_H + +#include +#include +#include + +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeBoundSignal; +class QDeclarativeContext; +class QDeclarativeGestureAreaPrivate; +class Q_DECLARATIVE_EXPORT QDeclarativeGestureArea : public QDeclarativeItem +{ + Q_OBJECT + + Q_PROPERTY(QGesture *gesture READ gesture) + + Q_INTERFACES(QDeclarativeParserStatus) + +public: + QDeclarativeGestureArea(QDeclarativeItem *parent=0); + ~QDeclarativeGestureArea(); + + QGesture *gesture() const; + +protected: + bool sceneEvent(QEvent *event); + +private: + void connectSignals(); + void componentComplete(); + friend class QDeclarativeGestureAreaParser; + + Q_DISABLE_COPY(QDeclarativeGestureArea) + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeGestureArea) +}; + +class QDeclarativeGestureAreaParser : public QDeclarativeCustomParser +{ +public: + virtual QByteArray compile(const QList &); + virtual void setCustomData(QObject *, const QByteArray &); +}; + + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeGestureArea) + +QT_END_HEADER + +#endif diff --git a/src/imports/gestures/qmldir b/src/imports/gestures/qmldir new file mode 100644 index 0000000..9d9d587 --- /dev/null +++ b/src/imports/gestures/qmldir @@ -0,0 +1 @@ +plugin gesturesqmlplugin -- cgit v0.12 From ab9c4f04fe86cbeed28800cbe0473738d9959871 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Tue, 6 Apr 2010 16:50:45 +1000 Subject: Fix anchors, etc. (pass parser status up to QDeclarativeItem) --- src/imports/gestures/qdeclarativegesturearea.cpp | 1 + src/imports/gestures/qdeclarativegesturearea_p.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/imports/gestures/qdeclarativegesturearea.cpp b/src/imports/gestures/qdeclarativegesturearea.cpp index 9b4af03..b8c8f57 100644 --- a/src/imports/gestures/qdeclarativegesturearea.cpp +++ b/src/imports/gestures/qdeclarativegesturearea.cpp @@ -231,6 +231,7 @@ void QDeclarativeGestureArea::connectSignals() void QDeclarativeGestureArea::componentComplete() { + QDeclarativeItem::componentComplete(); Q_D(QDeclarativeGestureArea); d->componentcomplete=true; connectSignals(); diff --git a/src/imports/gestures/qdeclarativegesturearea_p.h b/src/imports/gestures/qdeclarativegesturearea_p.h index 8d7fdfe..8e2c066 100644 --- a/src/imports/gestures/qdeclarativegesturearea_p.h +++ b/src/imports/gestures/qdeclarativegesturearea_p.h @@ -65,8 +65,6 @@ class Q_DECLARATIVE_EXPORT QDeclarativeGestureArea : public QDeclarativeItem Q_PROPERTY(QGesture *gesture READ gesture) - Q_INTERFACES(QDeclarativeParserStatus) - public: QDeclarativeGestureArea(QDeclarativeItem *parent=0); ~QDeclarativeGestureArea(); -- cgit v0.12 From 1a4ee517638e1ba3cdc622af70b3d53561d23392 Mon Sep 17 00:00:00 2001 From: Zeno Albisser Date: Thu, 25 Mar 2010 17:39:41 +0100 Subject: Added variable QMAKE_TARGET.arch to qmake to be used with MSVC++ The variable QMAKE_TARGET.arch shall be used to determine cross compiling for x64 on a x32 system. Reviewed-by: Marius Storm-Olsen Task-number: QTBUG-9160 --- qmake/project.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/qmake/project.cpp b/qmake/project.cpp index 01a3843..56707cf 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -3148,6 +3148,21 @@ QStringList &QMakeProject::values(const QString &_var, QMap[%s]", qPrintable(var), qPrintable(place[var].join("::"))); return place[var]; } -- cgit v0.12 From a354e98838e67e9bbd9473d4cd42b89f45d0e3fe Mon Sep 17 00:00:00 2001 From: Johan Hauan Date: Tue, 6 Apr 2010 11:34:57 +0200 Subject: Sunstudio12.1(5.10): Fix compile errors GTK style and other minor compile errors GTK Style A QHashableLatin1Literal was a bit too clever for sunstudio. Added and alternate constructor for sunstudio(ifdef) Should not affect other compilers. Other: Minor compile fixes, extra semicolon after macros etc. Merge-request: 547 Reviewed-by: Benjamin Poulain --- examples/qtconcurrent/map/main.cpp | 2 +- src/gui/styles/qgtkstyle_p.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/qtconcurrent/map/main.cpp b/examples/qtconcurrent/map/main.cpp index 6068d30..6afefca 100644 --- a/examples/qtconcurrent/map/main.cpp +++ b/examples/qtconcurrent/map/main.cpp @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) // Use QtConcurrentBlocking::mapped to apply the scale function to all the // images in the list. - QList thumbnails = QtConcurrent::blockingMapped(images, scale); + QList thumbnails = QtConcurrent::blockingMapped >(images, scale); return 0; } diff --git a/src/gui/styles/qgtkstyle_p.h b/src/gui/styles/qgtkstyle_p.h index 5bb7550..f0aee46 100644 --- a/src/gui/styles/qgtkstyle_p.h +++ b/src/gui/styles/qgtkstyle_p.h @@ -85,9 +85,14 @@ public: int size() const { return m_size; } const char *data() const { return m_data; } +#ifdef __SUNPRO_CC + QHashableLatin1Literal(const char* str) + : m_size(strlen(str)), m_data(str) {} +#else template QHashableLatin1Literal(const char (&str)[N]) : m_size(N - 1), m_data(str) {} +#endif QHashableLatin1Literal(const QHashableLatin1Literal &other) : m_size(other.m_size), m_data(other.m_data) -- cgit v0.12 From 822efb6807d6164304bc454f39c5f739bbe1f8e5 Mon Sep 17 00:00:00 2001 From: Benjamin Poulain Date: Tue, 6 Apr 2010 11:46:19 +0200 Subject: Fix a coding style issue of the GTK style A tab was introduced in 16614121f8eff813efadc999a7db9ce47eae769e --- src/gui/styles/qgtkstyle_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/styles/qgtkstyle_p.h b/src/gui/styles/qgtkstyle_p.h index f0aee46..68a04e9 100644 --- a/src/gui/styles/qgtkstyle_p.h +++ b/src/gui/styles/qgtkstyle_p.h @@ -87,7 +87,7 @@ public: #ifdef __SUNPRO_CC QHashableLatin1Literal(const char* str) - : m_size(strlen(str)), m_data(str) {} + : m_size(strlen(str)), m_data(str) {} #else template QHashableLatin1Literal(const char (&str)[N]) -- cgit v0.12 From 0c442405a9f85f402d508af2be0a668f34f35caf Mon Sep 17 00:00:00 2001 From: Carlos Manuel Duclos Vergara Date: Tue, 6 Apr 2010 13:47:24 +0200 Subject: [Cocoa] QDialogs with WindowStayOnStopHint parent The problem is with beginModalSession which reorders the windows and sends our window back. This patch queries the window level before calling beginModalSession and sets it after beginModalSession. Task-number: QTBUG-9392 Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qeventdispatcher_mac.mm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm index 62e1e81..a7f1224 100644 --- a/src/gui/kernel/qeventdispatcher_mac.mm +++ b/src/gui/kernel/qeventdispatcher_mac.mm @@ -831,7 +831,14 @@ NSModalSession QEventDispatcherMacPrivate::currentModalSession() QBoolBlocker block1(blockSendPostedEvents, true); info.nswindow = window; [(NSWindow*) info.nswindow retain]; - info.session = [NSApp beginModalSessionForWindow:window]; + // When creating a modal session cocoa will rearrange the windows. + // In order to avoid windows to be put behind another we need to + // keep the window level. + { + int level = [window level]; + info.session = [NSApp beginModalSessionForWindow:window]; + [window setLevel:level]; + } } currentModalSessionCached = info.session; } -- cgit v0.12 From 30f4ad046123449e53b8d4cf936300753df126ec Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 6 Apr 2010 18:09:15 +0200 Subject: Doc: Remove QDBusServer from the public documentation. Task-number: QTBUG-5066 --- src/dbus/qdbusserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp index 8f9323a..13b18a6 100644 --- a/src/dbus/qdbusserver.cpp +++ b/src/dbus/qdbusserver.cpp @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE /*! \class QDBusServer \inmodule QtDBus - \since 4.2 + \internal \brief The QDBusServer class provides peer-to-peer communication between processes on the same computer. -- cgit v0.12 From d65d3becc292523f0962aac9d2bf7b96d9c47c04 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 6 Apr 2010 18:15:00 +0200 Subject: Doc: update the QDBusPendingCallWatcher example to show where to delete Task-number: QTBUG-8865 --- doc/src/snippets/code/src.qdbus.qdbuspendingcall.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/src/snippets/code/src.qdbus.qdbuspendingcall.cpp b/doc/src/snippets/code/src.qdbus.qdbuspendingcall.cpp index 94a9f68..2867bd5a 100644 --- a/doc/src/snippets/code/src.qdbus.qdbuspendingcall.cpp +++ b/doc/src/snippets/code/src.qdbus.qdbuspendingcall.cpp @@ -61,5 +61,6 @@ void MyClass::callFinishedSlot(QDBusPendingCallWatcher *call) QByteArray data = reply.argumentAt<1>(); showReply(text, data); } + call->deleteLater(); } //! [1] -- cgit v0.12 From c1ce854d745b28e2f14057d29e726b8327034e9b Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 7 Apr 2010 11:01:03 +0200 Subject: fix QMenu::popup() Merge-request: 551 Reviewed-by: Benjamin Poulain --- src/gui/widgets/qmenu.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 404d46e..42f3a15 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -1913,10 +1913,9 @@ void QMenu::popup(const QPoint &p, QAction *atAction) pos.setX(screen.left() + desktopFrame); } if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) { - if(snapToMouse) - pos.setY(qMin(mouse.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1)); - else - pos.setY(qMax(p.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1)); + const int bestPos = (snapToMouse ? mouse.y() : p.y()) - desktopFrame - size.height() + 1; + const int fallbackPos = screen.bottom() - desktopFrame - size.height() + 1; + pos.setY(qMin(bestPos, fallbackPos)); } else if (pos.y() < screen.top() + desktopFrame) { pos.setY(screen.top() + desktopFrame); } -- cgit v0.12 From ee3a237262071721755075d6ae958aec744f5c87 Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 7 Apr 2010 11:01:04 +0200 Subject: QMenu::popup() code style fixes Merge-request: 551 Reviewed-by: Benjamin Poulain --- src/gui/widgets/qmenu.cpp | 50 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 42f3a15..b752ae2 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -1803,7 +1803,7 @@ QSize QMenu::sizeHint() const void QMenu::popup(const QPoint &p, QAction *atAction) { Q_D(QMenu); - if (d->scroll) { //reset scroll state from last popup + if (d->scroll) { // reset scroll state from last popup d->scroll->scrollOffset = 0; d->scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone; } @@ -1858,9 +1858,9 @@ void QMenu::popup(const QPoint &p, QAction *atAction) } #endif if (d->ncols > 1) { - pos.setY(screen.top()+desktopFrame); + pos.setY(screen.top() + desktopFrame); } else if (atAction) { - for(int i = 0, above_height = 0; i < d->actions.count(); i++) { + for (int i = 0, above_height = 0; i < d->actions.count(); i++) { QAction *action = d->actions.at(i); if (action == atAction) { int newY = pos.y() - above_height; @@ -1875,7 +1875,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction) if (d->scroll && d->scroll->scrollFlags != QMenuPrivate::QMenuScroller::ScrollNone && !style()->styleHint(QStyle::SH_Menu_FillScreenWithScroll, 0, this)) { int below_height = above_height + d->scroll->scrollOffset; - for(int i2 = i; i2 < d->actionRects.count(); i2++) + for (int i2 = i; i2 < d->actionRects.count(); i2++) below_height += d->actionRects.at(i2).height(); size.setHeight(below_height); } @@ -1888,28 +1888,28 @@ void QMenu::popup(const QPoint &p, QAction *atAction) QPoint mouse = QCursor::pos(); d->mousePopupPos = mouse; - const bool snapToMouse = (QRect(p.x()-3, p.y()-3, 6, 6).contains(mouse)); + const bool snapToMouse = (QRect(p.x() - 3, p.y() - 3, 6, 6).contains(mouse)); if (adjustToDesktop) { - //handle popup falling "off screen" + // handle popup falling "off screen" if (isRightToLeft()) { - if(snapToMouse) //position flowing left from the mouse - pos.setX(mouse.x()-size.width()); + if (snapToMouse) // position flowing left from the mouse + pos.setX(mouse.x() - size.width()); #ifndef QT_NO_MENUBAR - //if in a menubar, it should be right-aligned + // if in a menubar, it should be right-aligned if (qobject_cast(d->causedPopup.widget)) pos.rx() -= size.width(); #endif //QT_NO_MENUBAR - if (pos.x() < screen.left()+desktopFrame) - pos.setX(qMax(p.x(), screen.left()+desktopFrame)); - if (pos.x()+size.width()-1 > screen.right()-desktopFrame) - pos.setX(qMax(p.x()-size.width(), screen.right()-desktopFrame-size.width()+1)); + if (pos.x() < screen.left() + desktopFrame) + pos.setX(qMax(p.x(), screen.left() + desktopFrame)); + if (pos.x() + size.width() - 1 > screen.right() - desktopFrame) + pos.setX(qMax(p.x() - size.width(), screen.right() - desktopFrame - size.width() + 1)); } else { - if (pos.x()+size.width()-1 > screen.right()-desktopFrame) - pos.setX(screen.right()-desktopFrame-size.width()+1); - if (pos.x() < screen.left()+desktopFrame) + if (pos.x() + size.width() - 1 > screen.right() - desktopFrame) + pos.setX(screen.right() - desktopFrame - size.width() + 1); + if (pos.x() < screen.left() + desktopFrame) pos.setX(screen.left() + desktopFrame); } if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) { @@ -1922,14 +1922,14 @@ void QMenu::popup(const QPoint &p, QAction *atAction) if (pos.y() < screen.top() + desktopFrame) pos.setY(screen.top() + desktopFrame); - if (pos.y()+size.height()-1 > screen.bottom() - desktopFrame) { + if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) { if (d->scroll) { d->scroll->scrollFlags |= uint(QMenuPrivate::QMenuScroller::ScrollDown); int y = qMax(screen.y(),pos.y()); - size.setHeight(screen.bottom()-(desktopFrame*2)-y); + size.setHeight(screen.bottom() - (desktopFrame * 2) - y); } else { // Too big for screen, bias to see bottom of menu (for some reason) - pos.setY(screen.bottom()-size.height()+1); + pos.setY(screen.bottom() - size.height() + 1); } } } @@ -1938,19 +1938,19 @@ void QMenu::popup(const QPoint &p, QAction *atAction) int hGuess = isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll; int vGuess = QEffects::DownScroll; if (isRightToLeft()) { - if ((snapToMouse && (pos.x() + size.width()/2 > mouse.x())) || - (qobject_cast(d->causedPopup.widget) && pos.x() + size.width()/2 > d->causedPopup.widget->x())) + if ((snapToMouse && (pos.x() + size.width() / 2 > mouse.x())) || + (qobject_cast(d->causedPopup.widget) && pos.x() + size.width() / 2 > d->causedPopup.widget->x())) hGuess = QEffects::RightScroll; } else { - if ((snapToMouse && (pos.x() + size.width()/2 < mouse.x())) || - (qobject_cast(d->causedPopup.widget) && pos.x() + size.width()/2 < d->causedPopup.widget->x())) + if ((snapToMouse && (pos.x() + size.width() / 2 < mouse.x())) || + (qobject_cast(d->causedPopup.widget) && pos.x() + size.width() / 2 < d->causedPopup.widget->x())) hGuess = QEffects::LeftScroll; } #ifndef QT_NO_MENUBAR - if ((snapToMouse && (pos.y() + size.height()/2 < mouse.y())) || + if ((snapToMouse && (pos.y() + size.height() / 2 < mouse.y())) || (qobject_cast(d->causedPopup.widget) && - pos.y() + size.width()/2 < d->causedPopup.widget->mapToGlobal(d->causedPopup.widget->pos()).y())) + pos.y() + size.width() / 2 < d->causedPopup.widget->mapToGlobal(d->causedPopup.widget->pos()).y())) vGuess = QEffects::UpScroll; #endif if (QApplication::isEffectEnabled(Qt::UI_AnimateMenu)) { -- cgit v0.12 From 6947390e5d331ae653e91acecad70108915328e7 Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 7 Apr 2010 11:01:05 +0200 Subject: Test case for QMenu::popup() Verifies that the menu shown is fully contained on the screen. The actual menu position on the screen is checked as well. Merge-request: 551 Reviewed-by: Benjamin Poulain --- tests/auto/qmenu/tst_qmenu.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/auto/qmenu/tst_qmenu.cpp b/tests/auto/qmenu/tst_qmenu.cpp index e10d7ee..4be6fdd 100644 --- a/tests/auto/qmenu/tst_qmenu.cpp +++ b/tests/auto/qmenu/tst_qmenu.cpp @@ -106,6 +106,8 @@ private slots: void pushButtonPopulateOnAboutToShow(); void QTBUG7907_submenus_autoselect(); void QTBUG7411_submenus_activate(); + void menuGeometry_data(); + void menuGeometry(); protected slots: void onActivated(QAction*); void onHighlighted(QAction*); @@ -967,6 +969,60 @@ void tst_QMenu::QTBUG7411_submenus_activate() QTRY_VERIFY(sub1.isVisible()); } +void tst_QMenu::menuGeometry_data() +{ + QTest::addColumn("screen"); + QTest::addColumn("pos"); + QTest::addColumn("expectedPos"); + + QMenu menu("Test Menu"); + for (int i = 0; i < 3; ++i) + menu.addAction("Hello World!"); + + menu.adjustSize(); + + const int screenCount = QApplication::desktop()->screenCount(); + const int desktopFrame = menu.style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, &menu); + + for (int i = 0; i < screenCount; ++i) { + const QRect screen = QApplication::desktop()->screenGeometry(i); + + if (screen.width() < menu.width() || screen.height() < menu.height()) + continue; + + QTest::newRow("topLeft") << screen << screen.topLeft() + << QPoint(screen.left() + desktopFrame, screen.top() + desktopFrame); + + QTest::newRow("topRight") << screen << screen.topRight() + << QPoint(screen.right() - desktopFrame - menu.width() + 1, screen.top() + desktopFrame); + + QTest::newRow("bottomLeft") << screen << screen.bottomLeft() + << QPoint(screen.left() + desktopFrame, screen.bottom() - desktopFrame - menu.height() + 1); + + QTest::newRow("bottomRight") << screen << screen.bottomRight() + << QPoint(screen.right() - desktopFrame - menu.width() + 1, screen.bottom() - desktopFrame - menu.height() + 1); + + const QPoint pos = QPoint(screen.right() - qMax(desktopFrame, 20), screen.bottom() - qMax(desktopFrame, 20)); + QTest::newRow("position") << screen << pos + << QPoint(screen.right() - menu.width() + 1, pos.y() - menu.height() + 1); + } +} + +void tst_QMenu::menuGeometry() +{ + QFETCH(QRect, screen); + QFETCH(QPoint, pos); + QFETCH(QPoint, expectedPos); + + QMenu menu("Test Menu"); + for (int i = 0; i < 3; ++i) + menu.addAction("Hello World!"); + + menu.popup(pos); + QTest::qWaitForWindowShown(&menu); + QVERIFY(screen.contains(menu.geometry())); + QCOMPARE(menu.pos(), expectedPos); +} QTEST_MAIN(tst_QMenu) -- cgit v0.12