summaryrefslogtreecommitdiffstats
path: root/demos/chip/view.h
blob: c296e9f56a923ba61e9c270447109cd9f575b22d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the demonstration applications 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 either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** 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.0, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#ifndef VIEW_H
#define VIEW_H

#include <QFrame>

QT_FORWARD_DECLARE_CLASS(QGraphicsView)
QT_FORWARD_DECLARE_CLASS(QLabel)
QT_FORWARD_DECLARE_CLASS(QSlider)
QT_FORWARD_DECLARE_CLASS(QToolButton)

class View : public QFrame
{
    Q_OBJECT
public:
    View(const QString &name, QWidget *parent = 0);

    QGraphicsView *view() const;

private slots:
    void resetView();
    void setResetButtonEnabled();
    void setupMatrix();
    void toggleOpenGL();
    void toggleAntialiasing();
    void print();

    void zoomIn();
    void zoomOut();
    void rotateLeft();
    void rotateRight();
    
private:
    QGraphicsView *graphicsView;
    QLabel *label;
    QToolButton *openGlButton;
    QToolButton *antialiasButton;
    QToolButton *printButton;
    QToolButton *resetButton;
    QSlider *zoomSlider;
    QSlider *rotateSlider;
};

#endif
his touch point. +*/ +int QGraphicsSceneTouchEvent::TouchPoint::id() const +{ + return d->id; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setId(int id) +{ + d->id = id; +} + +/*! + Returns the state of this touch point at the time the + QGraphicsSceneTouchEvent occurred. +*/ +Qt::TouchPointState QGraphicsSceneTouchEvent::TouchPoint::state() const +{ + return d->state; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setState(Qt::TouchPointState state) +{ + d->state = state; +} + +/*! + Returns the current position of this touch point in item coordinates. + + \sa scenePos(), screenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::pos() const +{ + return d->pos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setPos(const QPointF &pos) +{ + d->pos = pos; +} + +/*! + Returns the starting position of this touch point in item coordinates. + + \sa startScenePos(), startScreenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::startPos() const +{ + return d->startPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setStartPos(const QPointF &startPos) +{ + d->startPos = startPos; +} + +/*! + Returns the previous position of this touch point in item coordinates. + + \sa lastScenePos(), lastScreenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::lastPos() const +{ + return d->lastPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setLastPos(const QPointF &lastPos) +{ + d->lastPos = lastPos; +} + +/*! + Returns the current position of this touch point in scene coordinates. + + \sa pos(), screenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::scenePos() const +{ + return d->scenePos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setScenePos(const QPointF &scenePos) +{ + d->scenePos = scenePos; +} + +/*! + Returns the starting position of this touch point in scene coordinates. + + \sa startPos(), startScreenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::startScenePos() const +{ + return d->startScenePos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setStartScenePos(const QPointF &startScenePos) +{ + d->startScenePos = startScenePos; +} + +/*! + Returns the previous position of this touch point in scene coordinates. + + \sa lastPos(), lastScreenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::lastScenePos() const +{ + return d->lastScenePos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setLastScenePos(const QPointF &lastScenePos) +{ + d->lastScenePos = lastScenePos; +} + +/*! + Returns the current position of this touch point in screen coordinates. + + \sa pos(), scenePos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::screenPos() const +{ + return d->screenPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setScreenPos(const QPointF &screenPos) +{ + d->screenPos = screenPos; +} + +/*! + Returns the starting position of this touch point in screen coordinates. + + \sa startPos(), startScenePos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::startScreenPos() const +{ + return d->startScreenPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setStartScreenPos(const QPointF &startScreenPos) +{ + d->startScreenPos = startScreenPos; +} + +/*! + Returns the previous position of this touch point in screen coordinates. + + \sa lastPos(), lastScenePos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::lastScreenPos() const +{ + return d->lastScreenPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setLastScreenPos(const QPointF &lastScreenPos) +{ + d->lastScreenPos = lastScreenPos; +} + +/*! + Returns the pressure of this touch point. +*/ +qreal QGraphicsSceneTouchEvent::TouchPoint::pressure() const +{ + return d->pressure; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setPressure(qreal pressure) +{ + d->pressure = pressure; +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h index be50e96..8ae3a99 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.h +++ b/src/gui/graphicsview/qgraphicssceneevent.h @@ -302,6 +302,70 @@ public: void setNewPos(const QPointF &pos); }; +class QGraphicsSceneTouchEventPrivate; +class QGraphicsSceneTouchEventTouchPointPrivate; +class Q_GUI_EXPORT QGraphicsSceneTouchEvent : public QGraphicsSceneEvent +{ +public: + QGraphicsSceneTouchEvent(Type type = None); + ~QGraphicsSceneTouchEvent(); + + class Q_GUI_EXPORT TouchPoint + { + public: + TouchPoint(); + ~TouchPoint(); + + int id() const; + void setId(int id); + + Qt::TouchPointState state() const; + void setState(Qt::TouchPointState state); + + QPointF pos() const; + void setPos(const QPointF &pos); + + QPointF startPos() const; + void setStartPos(const QPointF &startPos); + + QPointF lastPos() const; + void setLastPos(const QPointF &lastPos); + + QPointF scenePos() const; + void setScenePos(const QPointF &scenePos); + + QPointF startScenePos() const; + void setStartScenePos(const QPointF &startScenePos); + + QPointF lastScenePos() const; + void setLastScenePos(const QPointF &lastScenePos); + + QPointF screenPos() const; + void setScreenPos(const QPointF &screenPos); + + QPointF startScreenPos() const; + void setStartScreenPos(const QPointF &startScreenPos); + + QPointF lastScreenPos() const; + void setLastScreenPos(const QPointF &lastScreenPos); + + qreal pressure() const; // 0.0 -> 1.0 + void setPressure(qreal pressure); + + private: + QGraphicsSceneTouchEventTouchPointPrivate *d; + }; + + const QList &touchPoints() const; + void setTouchPoints(const QList &touchPoints); + + Qt::KeyboardModifiers modifiers() const; + void setModifiers(Qt::KeyboardModifiers modifiers); + +private: + Q_DECLARE_PRIVATE(QGraphicsSceneTouchEvent); +}; + #endif // QT_NO_GRAPHICSVIEW QT_END_NAMESPACE diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 3f1df5e..ff69c24 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3506,4 +3506,168 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) #endif +/*! \class QTouchEvent + \brief The QTouchEvent class contains parameters that describe a touch event +. + \since 4.6 + \ingroup events + + Touch events occur when pressing, releasing, or moving one or more + touch points on a touch device (such as a touch-screen or + track-pad), and if the widget has the Qt::WA_AcceptTouchEvents + attribute. + + Like QMouseEvent, Qt automatically grabs the touch device on the + first press inside a widget; the widget will receive all touch + events until the last touch point is released. + + A touch event contains a special accept flag that indicates + whether the receiver wants the event. By default, the event is + ignored. You should call accept() if the touch event is handled by + your widget. A touch event is propagated up the parent widget + chain until a widget accepts it with accept(), or an event filter + consumes it. If the touch event is neither accepted nor consumed, + then mouse events are simulated from the state of the first touch + point. + + All touch events are of type QEvent::Touch. The touchPoints() + function returns a list of all touch points contained in the + event. Information about each touch point can be retreived using + the QTouchEvent::TouchPoint class. + + The Qt::TouchPointState enum describes the different states that a + touch point may have. + + QTouchEvent::TouchPoint Qt::TouchPointState Qt::WA_AcceptTouchEvents +*/ + +/*! \enum Qt::TouchPointState + \since 4.6 + + This enum represents the state of a touch point at the time the + QTouchEvent occurred. + + \value TouchPointPressed The touch point is now pressed. + \value TouchPointMoved The touch point moved. + \value TouchPointStationary The touch point did not move. + \value TouchPointReleased The touch point was released. +*/ + +/*! \class QTouchEvent::TouchPoint + \brief The QTouchEvent::TouchPoint class provide information about a touch point in a QTouchEvent. + \since 4.6 +*/ + +/*! + Constructs a QTouchEvent with the given \a type and \a + touchPoints. The \a modifiers are the current keyboard modifiers + at the time of the event. +*/ +QTouchEvent::QTouchEvent(QEvent::Type type, + Qt::KeyboardModifiers modifiers, + const QList &touchPoints) + : QInputEvent(type, modifiers), _touchPoints(touchPoints) +{ } + +/*! \fn const QList &QTouchEvent::touchPoints() const + + Returns the list of touch points contained in the touch event. +*/ + +/*! \internal + + Constructs a QTouchEvent::TouchPoint for use in a QTouchEvent. +*/ +QTouchEvent::TouchPoint::TouchPoint(int id) + : d(new QTouchEventTouchPointPrivate(id)) +{ } + +/*! \internal + + Destroys the QTouchEvent::TouchPoint. +*/ +QTouchEvent::TouchPoint::~TouchPoint() +{ + delete d; +} + +/*! + Returns the id number of this touch point. Id numbers are + sequential, starting at zero, meaning the first touch point has id + 0, the second has id 1, and so on... +*/ +int QTouchEvent::TouchPoint::id() const +{ + return d->id; +} + +/*! + Returns the current state of this touch point. +*/ +Qt::TouchPointState QTouchEvent::TouchPoint::state() const +{ + return d->state; +} + +/*! + Returns the position of this touch point, relative to the widget + that received the event. +*/ +const QPointF &QTouchEvent::TouchPoint::pos() const +{ + return d->pos; +} + +/*! + Returns the starting position of this touch point, relative to the + widget that received the event. +*/ +const QPointF &QTouchEvent::TouchPoint::startPos() const +{ + return d->startPos; +} + +/*! + Returns the position of this touch point from the previous touch + event, relative to the widget that received the event. +*/ +const QPointF &QTouchEvent::TouchPoint::lastPos() const +{ + return d->lastPos; +} + +/*! + Returns the global position of this touch point. +*/ +const QPointF &QTouchEvent::TouchPoint::globalPos() const +{ + return d->globalPos; +} + +/*! + Returns the global starting position of this touch point. +*/ +const QPointF &QTouchEvent::TouchPoint::startGlobalPos() const +{ + return d->startGlobalPos; +} + +/*! + Returns the global position of this touch point from the previous + touch event. +*/ +const QPointF &QTouchEvent::TouchPoint::lastGlobalPos() const +{ + return d->lastGlobalPos; +} + +/*! + Returns the pressure of this touch point. The return value is in + the range 0.0 to 1.0. +*/ +qreal QTouchEvent::TouchPoint::pressure() const +{ + return d->pressure; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 449730d..3cb712d 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -719,6 +719,47 @@ inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ? inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);} #endif // QT_NO_SHORTCUT +class QTouchEventTouchPointPrivate; +class Q_GUI_EXPORT QTouchEvent : public QInputEvent +{ +public: + class Q_GUI_EXPORT TouchPoint + { + public: + TouchPoint(int id = -1); + ~TouchPoint(); + + int id() const; + + Qt::TouchPointState state() const; + + const QPointF &pos() const; + const QPointF &startPos() const; + const QPointF &lastPos() const; + + const QPointF &globalPos() const; + const QPointF &startGlobalPos() const; + const QPointF &lastGlobalPos() const; + + qreal pressure() const; // 0.0 -> 1.0 + + private: + QTouchEventTouchPointPrivate *d; + + friend class QApplicationPrivate; + }; + + QTouchEvent(QEvent::Type type, + Qt::KeyboardModifiers modifiers, + const QList &touchPoints); + + inline const QList &touchPoints() const { return _touchPoints; + } + +protected: + QList _touchPoints; +}; + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index cc94aad..5e24eeb 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -89,6 +89,22 @@ protected: friend class QMouseEvent; }; +class QTouchEventTouchPointPrivate +{ +public: + inline QTouchEventTouchPointPrivate(int id) + : id(id), + state(Qt::TouchPointReleased), + pressure(qreal(-1.)) + { } + + int id; + Qt::TouchPointState state; + QPointF pos, startPos, lastPos; + QPointF globalPos, startGlobalPos, lastGlobalPos; + qreal pressure; +}; + QT_END_NAMESPACE #endif // QEVENT_P_H -- cgit v0.12 From 075a8a30560e20fee94d47aa447daa15f4cb138f Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 24 Mar 2009 12:01:44 +0100 Subject: add QGraphicsItem::acceptTouchEvents() and setAcceptTouchEvents() like Qt::WA_AcceptTouchEvents, QGraphicsItems don't receive touch events unless touch events are explicitly enabled. --- src/gui/graphicsview/qgraphicsitem.cpp | 25 +++++++++++++++++++++++++ src/gui/graphicsview/qgraphicsitem.h | 2 ++ src/gui/graphicsview/qgraphicsitem_p.h | 2 ++ 3 files changed, 29 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index fc81f39..0b51c8c 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2063,6 +2063,31 @@ void QGraphicsItem::setAcceptsHoverEvents(bool enabled) d_ptr->acceptsHover = quint32(enabled); } +/*! \since 4.6 + + Returns true if an item accepts touch events + (QGraphicsSceneTouchEvent); otherwise, returns false. By default, + items do not accept touch events. + + \sa setAcceptTouchEvents() +*/ +bool QGraphicsItem::acceptTouchEvents() const +{ + return d_ptr->acceptTouchEvents; +} + +/*! + \since 4.6 + + If \a enabled is true, this item will accept touch events; + otherwise, it will ignore them. By default, items do not accept + touch events. +*/ +void QGraphicsItem::setAcceptTouchEvents(bool enabled) +{ + d_ptr->acceptTouchEvents = quint32(enabled); +} + /*! Returns true if this item handles child events (i.e., all events intended for any of its children are instead sent to this item); diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index b98882d..ec3373a 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -203,6 +203,8 @@ public: void setAcceptsHoverEvents(bool enabled); // obsolete bool acceptHoverEvents() const; void setAcceptHoverEvents(bool enabled); + bool acceptTouchEvents() const; + void setAcceptTouchEvents(bool enabled); bool handlesChildEvents() const; void setHandlesChildEvents(bool enabled); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index af0b077..228368c 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -138,6 +138,7 @@ public: dirty(0), dirtyChildren(0), localCollisionHack(0), + acceptTouchEvents(0), globalStackingOrder(-1), sceneTransformIndex(-1), q_ptr(0) @@ -272,6 +273,7 @@ public: quint32 dirty : 1; quint32 dirtyChildren : 1; quint32 localCollisionHack : 1; + quint32 acceptTouchEvents : 1; // Optional stacking order int globalStackingOrder; -- cgit v0.12 From b9b9fc18d8ea5e9ddc2508ac6e9ce24960a8c24a Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 24 Mar 2009 12:03:21 +0100 Subject: implement support for touch events in QGraphicsScene QGraphicsView will convert QTouchEvents to QGraphicsSceneTouchEvents and send them to the scene. The scene will then send the touch events to the appropriate item. Like mouse event support, the item that accepts the touch begin is the item that will get all subsequent touch events. if no item accepts the touch begin event, then no touch events are sent to any item (and mouse events are sent instead). --- src/gui/graphicsview/qgraphicsscene.cpp | 166 ++++++++++++++++++++++++++++++++ src/gui/graphicsview/qgraphicsscene_p.h | 6 ++ src/gui/graphicsview/qgraphicsview.cpp | 106 ++++++++++++++++++++ src/gui/graphicsview/qgraphicsview_p.h | 5 + 4 files changed, 283 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 553967c..b47ed5e 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -3609,6 +3609,9 @@ bool QGraphicsScene::event(QEvent *event) case QEvent::GraphicsSceneHoverEnter: case QEvent::GraphicsSceneHoverLeave: case QEvent::GraphicsSceneHoverMove: + case QEvent::GraphicsSceneTouchBegin: + case QEvent::GraphicsSceneTouchUpdate: + case QEvent::GraphicsSceneTouchEnd: // Reset the under-mouse list to ensure that this event gets fresh // item-under-mouse data. Be careful about this list; if people delete // items from inside event handlers, this list can quickly end up @@ -3760,6 +3763,15 @@ bool QGraphicsScene::event(QEvent *event) // geometries that do not have an explicit style set. update(); break; + case QEvent::GraphicsSceneTouchBegin: + d->touchBeginEvent(static_cast(event)); + break; + case QEvent::GraphicsSceneTouchUpdate: + d->touchUpdateEvent(static_cast(event)); + break; + case QEvent::GraphicsSceneTouchEnd: + d->touchEndEvent(static_cast(event)); + break; case QEvent::Timer: if (d->indexTimerId && static_cast(event)->timerId() == d->indexTimerId) { if (d->restartIndexTimer) { @@ -5370,6 +5382,160 @@ void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget) } } +// ### FIXME: the code for touch event support is mosly copied from +// ### QGraphicsScenePrivate::mousePressEventHandler() and friends, need to +// ### refactor to reduce code duplication + +void QGraphicsScenePrivate::sendTouchEvent(QGraphicsSceneTouchEvent *touchEvent) +{ + if (touchEvent->type() == QEvent::GraphicsSceneTouchEnd && lastMouseGrabberItemHasImplicitMouseGrab) { + clearMouseGrabber(); + return; + } + + QGraphicsItem *item = mouseGrabberItems.last(); + QList touchPoints = touchEvent->touchPoints(); + for (int i = 0; i < touchPoints.count(); ++i) { + QGraphicsSceneTouchEvent::TouchPoint *touchPoint = touchPoints.at(i); + touchPoint->setPos(item->d_ptr->genericMapFromScene(touchPoint->scenePos(), touchEvent->widget())); + touchPoint->setStartPos(item->d_ptr->genericMapFromScene(touchPoint->startScenePos(), touchEvent->widget())); + touchPoint->setLastPos(item->d_ptr->genericMapFromScene(touchPoint->lastScenePos(), touchEvent->widget())); + } + sendEvent(item, touchEvent); +} + +void QGraphicsScenePrivate::touchBeginEvent(QGraphicsSceneTouchEvent *touchEvent) +{ + Q_Q(QGraphicsScene); + + // Ignore by default, unless we find a mouse grabber that accepts it. + touchEvent->ignore(); + + // Deliver to any existing mouse grabber. + if (!mouseGrabberItems.isEmpty()) { + // The event is ignored by default, but we disregard the event's + // accepted state after delivery; the mouse is grabbed, after all. + sendTouchEvent(touchEvent); + return; + } + + // Start by determining the number of items at the current position. + // Reuse value from earlier calculations if possible. + if (cachedItemsUnderMouse.isEmpty()) { + QGraphicsSceneTouchEvent::TouchPoint *touchPoint = touchEvent->touchPoints().first(); + // ### FIXME: should the itemsAtPosition() function support sub-pixel screenPos? + cachedItemsUnderMouse = itemsAtPosition(touchPoint->screenPos().toPoint(), + touchPoint->scenePos(), + touchEvent->widget()); + } + + // Update window activation. + QGraphicsWidget *newActiveWindow = windowForItem(cachedItemsUnderMouse.value(0)); + if (newActiveWindow != activeWindow) + q->setActiveWindow(newActiveWindow); + + // Set focus on the topmost enabled item that can take focus. + bool setFocus = false; + foreach (QGraphicsItem *item, cachedItemsUnderMouse) { + if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) { + if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) { + setFocus = true; + if (item != q->focusItem()) + q->setFocusItem(item, Qt::MouseFocusReason); + break; + } + } + } + + // If nobody could take focus, clear it. + if (!stickyFocus && !setFocus) + q->setFocusItem(0, Qt::MouseFocusReason); + + // Find a mouse grabber by sending touch events to all mouse grabber + // candidates one at a time, until the event is accepted. It's accepted by + // default, so the receiver has to explicitly ignore it for it to pass + // through. + foreach (QGraphicsItem *item, cachedItemsUnderMouse) { + if (!item->acceptTouchEvents()) { + // Skip items that don't accept the touch events + continue; + } + + grabMouse(item, /* implicit = */ true); + touchEvent->accept(); + + // check if the item we are sending to are disabled (before we send the event) + bool disabled = !item->isEnabled(); + bool isWindow = item->isWindow(); + sendTouchEvent(touchEvent); + + bool dontSendUngrabEvents = mouseGrabberItems.isEmpty() || mouseGrabberItems.last() != item; + if (disabled) { + ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents); + break; + } + if (touchEvent->isAccepted()) { + lastMouseGrabberItem = item; + return; + } + ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents); + + // Don't propagate through windows. + if (isWindow) + break; + } + + // Is the event still ignored? Then the mouse press goes to the scene. + // Reset the mouse grabber, clear the selection, clear focus, and leave + // the event ignored so that it can propagate through the originating + // view. + if (!touchEvent->isAccepted()) { + clearMouseGrabber(); + + QGraphicsView *view = touchEvent->widget() ? qobject_cast(touchEvent->widget()->parentWidget()) : 0; + bool dontClearSelection = view && view->dragMode() == QGraphicsView::ScrollHandDrag; + if (!dontClearSelection) { + // Clear the selection if the originating view isn't in scroll + // hand drag mode. The view will clear the selection if no drag + // happened. + q->clearSelection(); + } + } +} + +void QGraphicsScenePrivate::touchUpdateEvent(QGraphicsSceneTouchEvent *touchEvent) +{ + if (mouseGrabberItems.isEmpty()) { + touchEvent->ignore(); + return; + } + + // Forward the event to the mouse grabber + sendTouchEvent(touchEvent); + touchEvent->accept(); +} + +void QGraphicsScenePrivate::touchEndEvent(QGraphicsSceneTouchEvent *touchEvent) +{ + if (mouseGrabberItems.isEmpty()) { + touchEvent->ignore(); + return; + } + + // Forward the event to the mouse grabber + sendTouchEvent(touchEvent); + touchEvent->accept(); + + // Reset the mouse grabber + if (!mouseGrabberItems.isEmpty()) { + lastMouseGrabberItem = mouseGrabberItems.last(); + if (lastMouseGrabberItemHasImplicitMouseGrab) + mouseGrabberItems.last()->ungrabMouse(); + } else { + lastMouseGrabberItem = 0; + } +} + QT_END_NAMESPACE #include "moc_qgraphicsscene.cpp" diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 7f441da..d5e539b 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -73,6 +73,7 @@ QT_BEGIN_NAMESPACE class QGraphicsView; class QGraphicsWidget; +class QGraphicsSceneTouchEvent; class QGraphicsScenePrivate : public QObjectPrivate { @@ -259,6 +260,11 @@ public: mutable QVector sceneTransformCache; mutable QBitArray validTransforms; mutable QVector freeSceneTransformSlots; + + void sendTouchEvent(QGraphicsSceneTouchEvent *touchEvent); + void touchBeginEvent(QGraphicsSceneTouchEvent *touchEvent); + void touchUpdateEvent(QGraphicsSceneTouchEvent *touchEvent); + void touchEndEvent(QGraphicsSceneTouchEvent *touchEvent); }; QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index a661441..f95d328 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2926,6 +2926,28 @@ bool QGraphicsView::viewportEvent(QEvent *event) d->scene->d_func()->updateAll = false; } break; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + { + if (!isEnabled()) + return false; + QTouchEvent *touchEvent = static_cast(event); + switch (touchEvent->type()) { + case QEvent::TouchBegin: + d->touchBeginEvent(touchEvent); + break; + case QEvent::TouchUpdate: + d->touchUpdateEvent(touchEvent); + break; + case QEvent::TouchEnd: + d->touchEndEvent(touchEvent); + break; + default: + break; + } + return true; + } default: break; } @@ -3864,6 +3886,90 @@ void QGraphicsView::resetTransform() setTransform(QTransform()); } +static void qt_convertTouchEventToGraphicsSceneTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *originalEvent, QGraphicsSceneTouchEvent *touchEvent) +{ + QList originalTouchPoints = originalEvent->touchPoints(); + QList touchPoints; + for (int i = 0; i < originalTouchPoints.count(); ++i) { + QTouchEvent::TouchPoint *originalTouchPoint = originalTouchPoints.at(i); + + QGraphicsSceneTouchEvent::TouchPoint *touchPoint = new QGraphicsSceneTouchEvent::TouchPoint(); + touchPoint->setId(originalTouchPoint->id()); + touchPoint->setState(originalTouchPoint->state()); + // the scene will set the pos before delivering to an item + touchPoint->setScenePos(d->mapToScene(originalTouchPoint->pos())); + touchPoint->setScreenPos(originalTouchPoint->globalPos()); + // the scene will set the startPos before delivering to an item + touchPoint->setStartScenePos(d->mapToScene(originalTouchPoint->startPos())); + touchPoint->setStartScreenPos(originalTouchPoint->startGlobalPos()); + // the scene will set the lastPos before delivering to an item + touchPoint->setLastScenePos(d->mapToScene(originalTouchPoint->lastPos())); + touchPoint->setLastScreenPos(originalTouchPoint->lastGlobalPos()); + touchPoint->setPressure(originalTouchPoint->pressure()); + + touchPoints.append(touchPoint); + } + + touchEvent->setTouchPoints(touchPoints); + touchEvent->setModifiers(originalEvent->modifiers()); +} + +QPointF QGraphicsViewPrivate::mapToScene(const QPointF &point) const +{ + QPointF p = point; + p.rx() += horizontalScroll(); + p.ry() += verticalScroll(); + return identityMatrix ? p : matrix.inverted().map(p); +} + +void QGraphicsViewPrivate::touchBeginEvent(QTouchEvent *event) +{ + Q_Q(QGraphicsView); + + if (!scene || !sceneInteractionAllowed) + return; + + // Convert and deliver the touch event to the scene. + QGraphicsSceneTouchEvent touchEvent(QEvent::GraphicsSceneTouchBegin); + touchEvent.setWidget(q->viewport()); + qt_convertTouchEventToGraphicsSceneTouchEvent(this, event, &touchEvent); + touchEvent.setAccepted(false); + QApplication::sendEvent(scene, &touchEvent); + event->setAccepted(touchEvent.isAccepted()); +} + +void QGraphicsViewPrivate::touchUpdateEvent(QTouchEvent *event) +{ + Q_Q(QGraphicsView); + + if (!scene || !sceneInteractionAllowed) + return; + + // Convert and deliver the touch event to the scene. + QGraphicsSceneTouchEvent touchEvent(QEvent::GraphicsSceneTouchUpdate); + touchEvent.setWidget(q->viewport()); + qt_convertTouchEventToGraphicsSceneTouchEvent(this, event, &touchEvent); + touchEvent.setAccepted(false); + QApplication::sendEvent(scene, &touchEvent); + event->setAccepted(touchEvent.isAccepted()); +} + +void QGraphicsViewPrivate::touchEndEvent(QTouchEvent *event) +{ + Q_Q(QGraphicsView); + + if (!scene || !sceneInteractionAllowed) + return; + + // Convert and deliver the touch event to the scene. + QGraphicsSceneTouchEvent touchEvent(QEvent::GraphicsSceneTouchEnd); + touchEvent.setWidget(q->viewport()); + qt_convertTouchEventToGraphicsSceneTouchEvent(this, event, &touchEvent); + touchEvent.setAccepted(false); + QApplication::sendEvent(scene, &touchEvent); + event->setAccepted(touchEvent.isAccepted()); +} + QT_END_NAMESPACE #include "moc_qgraphicsview.cpp" diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 2109673..e9479f3 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -182,6 +182,11 @@ public: const QTransform &worldTransform, bool allItems, const QRegion &exposedRegion) const; + + QPointF mapToScene(const QPointF &point) const; + void touchBeginEvent(QTouchEvent *event); + void touchUpdateEvent(QTouchEvent *event); + void touchEndEvent(QTouchEvent *event); }; QT_END_NAMESPACE -- cgit v0.12 From 96741cb1aba9feaf0099910884bee5241e52f794 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 24 Mar 2009 14:59:07 +0100 Subject: add a multitouch pinchzoom example, based on the collidingmice example --- examples/multitouch/multitouch.pro | 2 + examples/multitouch/pinchzoom/graphicsview.cpp | 78 +++++++++ examples/multitouch/pinchzoom/graphicsview.h | 53 +++++++ examples/multitouch/pinchzoom/images/cheese.jpg | Bin 0 -> 3029 bytes examples/multitouch/pinchzoom/main.cpp | 88 +++++++++++ examples/multitouch/pinchzoom/mice.qrc | 5 + examples/multitouch/pinchzoom/mouse.cpp | 200 ++++++++++++++++++++++++ examples/multitouch/pinchzoom/mouse.h | 72 +++++++++ examples/multitouch/pinchzoom/pinchzoom.pro | 16 ++ 9 files changed, 514 insertions(+) create mode 100644 examples/multitouch/multitouch.pro create mode 100644 examples/multitouch/pinchzoom/graphicsview.cpp create mode 100644 examples/multitouch/pinchzoom/graphicsview.h create mode 100644 examples/multitouch/pinchzoom/images/cheese.jpg create mode 100644 examples/multitouch/pinchzoom/main.cpp create mode 100644 examples/multitouch/pinchzoom/mice.qrc create mode 100644 examples/multitouch/pinchzoom/mouse.cpp create mode 100644 examples/multitouch/pinchzoom/mouse.h create mode 100644 examples/multitouch/pinchzoom/pinchzoom.pro diff --git a/examples/multitouch/multitouch.pro b/examples/multitouch/multitouch.pro new file mode 100644 index 0000000..7efa412 --- /dev/null +++ b/examples/multitouch/multitouch.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS = pinchzoom \ No newline at end of file diff --git a/examples/multitouch/pinchzoom/graphicsview.cpp b/examples/multitouch/pinchzoom/graphicsview.cpp new file mode 100644 index 0000000..b77c926 --- /dev/null +++ b/examples/multitouch/pinchzoom/graphicsview.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "graphicsview.h" + +#include + + +GraphicsView::GraphicsView(QGraphicsScene *scene, QWidget *parent) + : QGraphicsView(scene, parent) +{ + setAttribute(Qt::WA_AcceptTouchEvents); +} + +bool GraphicsView::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + { + qDebug("touch events"); + + QList touchPoints = static_cast(event)->touchPoints(); + if (touchPoints.count() == 2) { + // determine scale factor + const QTouchEvent::TouchPoint *touchPoint0 = touchPoints.first(); + const QTouchEvent::TouchPoint *touchPoint1 = touchPoints.last(); + const qreal scaleFactor = QLineF(touchPoint0->pos(), touchPoint1->pos()).length() + / QLineF(touchPoint0->startPos(), touchPoint1->startPos()).length(); + setTransform(QTransform().scale(scaleFactor, scaleFactor)); + } + event->accept(); + return true; + } + default: + break; + } + return QGraphicsView::event(event); +} diff --git a/examples/multitouch/pinchzoom/graphicsview.h b/examples/multitouch/pinchzoom/graphicsview.h new file mode 100644 index 0000000..626f23c --- /dev/null +++ b/examples/multitouch/pinchzoom/graphicsview.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once +#include + +class GraphicsView : public QGraphicsView +{ + Q_OBJECT + +public: + GraphicsView(QGraphicsScene *scene = 0, QWidget *parent = 0); + + bool event(QEvent *event); +}; diff --git a/examples/multitouch/pinchzoom/images/cheese.jpg b/examples/multitouch/pinchzoom/images/cheese.jpg new file mode 100644 index 0000000..dea5795 Binary files /dev/null and b/examples/multitouch/pinchzoom/images/cheese.jpg differ diff --git a/examples/multitouch/pinchzoom/main.cpp b/examples/multitouch/pinchzoom/main.cpp new file mode 100644 index 0000000..6b25060 --- /dev/null +++ b/examples/multitouch/pinchzoom/main.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "graphicsview.h" +#include "mouse.h" + +#include + +#include + +static const int MouseCount = 7; + +//! [0] +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); +//! [0] + +//! [1] + QGraphicsScene scene; + scene.setSceneRect(-300, -300, 600, 600); +//! [1] //! [2] + scene.setItemIndexMethod(QGraphicsScene::NoIndex); +//! [2] + +//! [3] + for (int i = 0; i < MouseCount; ++i) { + Mouse *mouse = new Mouse; + mouse->setPos(::sin((i * 6.28) / MouseCount) * 200, + ::cos((i * 6.28) / MouseCount) * 200); + scene.addItem(mouse); + } +//! [3] + +//! [4] + GraphicsView view(&scene); + view.setRenderHint(QPainter::Antialiasing); + view.setBackgroundBrush(QPixmap(":/images/cheese.jpg")); +//! [4] //! [5] + view.setCacheMode(QGraphicsView::CacheBackground); + view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + view.setDragMode(QGraphicsView::ScrollHandDrag); +//! [5] //! [6] + view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Colliding Mice")); + view.showMaximized(); + + return app.exec(); +} +//! [6] diff --git a/examples/multitouch/pinchzoom/mice.qrc b/examples/multitouch/pinchzoom/mice.qrc new file mode 100644 index 0000000..accdb4d --- /dev/null +++ b/examples/multitouch/pinchzoom/mice.qrc @@ -0,0 +1,5 @@ + + + images/cheese.jpg + + diff --git a/examples/multitouch/pinchzoom/mouse.cpp b/examples/multitouch/pinchzoom/mouse.cpp new file mode 100644 index 0000000..1d9fa89 --- /dev/null +++ b/examples/multitouch/pinchzoom/mouse.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mouse.h" + +#include +#include +#include + +#include + +static const double Pi = 3.14159265358979323846264338327950288419717; +static double TwoPi = 2.0 * Pi; + +static qreal normalizeAngle(qreal angle) +{ + while (angle < 0) + angle += TwoPi; + while (angle > TwoPi) + angle -= TwoPi; + return angle; +} + +//! [0] +Mouse::Mouse() + : angle(0), speed(0), mouseEyeDirection(0), + color(qrand() % 256, qrand() % 256, qrand() % 256) +{ + rotate(qrand() % (360 * 16)); + startTimer(1000 / 33); +} +//! [0] + +//! [1] +QRectF Mouse::boundingRect() const +{ + qreal adjust = 0.5; + return QRectF(-18 - adjust, -22 - adjust, + 36 + adjust, 60 + adjust); +} +//! [1] + +//! [2] +QPainterPath Mouse::shape() const +{ + QPainterPath path; + path.addRect(-10, -20, 20, 40); + return path; +} +//! [2] + +//! [3] +void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + // Body + painter->setBrush(color); + painter->drawEllipse(-10, -20, 20, 40); + + // Eyes + painter->setBrush(Qt::white); + painter->drawEllipse(-10, -17, 8, 8); + painter->drawEllipse(2, -17, 8, 8); + + // Nose + painter->setBrush(Qt::black); + painter->drawEllipse(QRectF(-2, -22, 4, 4)); + + // Pupils + painter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4)); + painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4)); + + // Ears + painter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::darkYellow : Qt::red); + painter->drawEllipse(-17, -12, 16, 16); + painter->drawEllipse(1, -12, 16, 16); + + // Tail + QPainterPath path(QPointF(0, 20)); + path.cubicTo(-5, 22, -5, 22, 0, 25); + path.cubicTo(5, 27, 5, 32, 0, 30); + path.cubicTo(-5, 32, -5, 42, 0, 35); + painter->setBrush(Qt::NoBrush); + painter->drawPath(path); +} +//! [3] + +//! [4] +void Mouse::timerEvent(QTimerEvent *) +{ +//! [4] + // Don't move too far away +//! [5] + QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0)); + if (lineToCenter.length() > 150) { + qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length()); + if (lineToCenter.dy() < 0) + angleToCenter = TwoPi - angleToCenter; + angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2); + + if (angleToCenter < Pi && angleToCenter > Pi / 4) { + // Rotate left + angle += (angle < -Pi / 2) ? 0.25 : -0.25; + } else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) { + // Rotate right + angle += (angle < Pi / 2) ? 0.25 : -0.25; + } + } else if (::sin(angle) < 0) { + angle += 0.25; + } else if (::sin(angle) > 0) { + angle -= 0.25; +//! [5] //! [6] + } +//! [6] + + // Try not to crash with any other mice +//! [7] + QList dangerMice = scene()->items(QPolygonF() + << mapToScene(0, 0) + << mapToScene(-30, -50) + << mapToScene(30, -50)); + foreach (QGraphicsItem *item, dangerMice) { + if (item == this) + continue; + + QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0)); + qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length()); + if (lineToMouse.dy() < 0) + angleToMouse = TwoPi - angleToMouse; + angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2); + + if (angleToMouse >= 0 && angleToMouse < Pi / 2) { + // Rotate right + angle += 0.5; + } else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) { + // Rotate left + angle -= 0.5; +//! [7] //! [8] + } +//! [8] //! [9] + } +//! [9] + + // Add some random movement +//! [10] + if (dangerMice.size() > 1 && (qrand() % 10) == 0) { + if (qrand() % 1) + angle += (qrand() % 100) / 500.0; + else + angle -= (qrand() % 100) / 500.0; + } +//! [10] + +//! [11] + speed += (-50 + qrand() % 100) / 100.0; + + qreal dx = ::sin(angle) * 10; + mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5; + + rotate(dx); + setPos(mapToParent(0, -(3 + sin(speed) * 3))); +} +//! [11] diff --git a/examples/multitouch/pinchzoom/mouse.h b/examples/multitouch/pinchzoom/mouse.h new file mode 100644 index 0000000..7545fe6 --- /dev/null +++ b/examples/multitouch/pinchzoom/mouse.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MOUSE_H +#define MOUSE_H + +#include +#include + +//! [0] +class Mouse : public QObject, public QGraphicsItem +{ + Q_OBJECT + +public: + Mouse(); + + QRectF boundingRect() const; + QPainterPath shape() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget); + +protected: + void timerEvent(QTimerEvent *event); + +private: + qreal angle; + qreal speed; + qreal mouseEyeDirection; + QColor color; +}; +//! [0] + +#endif diff --git a/examples/multitouch/pinchzoom/pinchzoom.pro b/examples/multitouch/pinchzoom/pinchzoom.pro new file mode 100644 index 0000000..bd87cf7 --- /dev/null +++ b/examples/multitouch/pinchzoom/pinchzoom.pro @@ -0,0 +1,16 @@ +HEADERS += \ + mouse.h \ + graphicsview.h +SOURCES += \ + main.cpp \ + mouse.cpp \ + graphicsview.cpp + +RESOURCES += \ + mice.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/multitouch/pinchzoom +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS pinchzoom.pro images +sources.path = $$[QT_INSTALL_EXAMPLES]/multitouch/pinchzoom +INSTALLS += target sources -- cgit v0.12 From 98619f427322ac7889b3db6f8991ca079209cec7 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 25 Mar 2009 11:31:33 +0100 Subject: add the multitouch fingerpaint example, based on the scribble example --- examples/multitouch/fingerpaint/fingerpaint.pro | 11 ++ examples/multitouch/fingerpaint/main.cpp | 52 ++++++ examples/multitouch/fingerpaint/mainwindow.cpp | 218 +++++++++++++++++++++++ examples/multitouch/fingerpaint/mainwindow.h | 89 +++++++++ examples/multitouch/fingerpaint/scribblearea.cpp | 213 ++++++++++++++++++++++ examples/multitouch/fingerpaint/scribblearea.h | 81 +++++++++ 6 files changed, 664 insertions(+) create mode 100644 examples/multitouch/fingerpaint/fingerpaint.pro create mode 100644 examples/multitouch/fingerpaint/main.cpp create mode 100644 examples/multitouch/fingerpaint/mainwindow.cpp create mode 100644 examples/multitouch/fingerpaint/mainwindow.h create mode 100644 examples/multitouch/fingerpaint/scribblearea.cpp create mode 100644 examples/multitouch/fingerpaint/scribblearea.h diff --git a/examples/multitouch/fingerpaint/fingerpaint.pro b/examples/multitouch/fingerpaint/fingerpaint.pro new file mode 100644 index 0000000..1d45635 --- /dev/null +++ b/examples/multitouch/fingerpaint/fingerpaint.pro @@ -0,0 +1,11 @@ +HEADERS = mainwindow.h \ + scribblearea.h +SOURCES = main.cpp \ + mainwindow.cpp \ + scribblearea.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/multitouch/fingerpaint +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS fingerpaint.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/multitouch/fingerpaint +INSTALLS += target sources diff --git a/examples/multitouch/fingerpaint/main.cpp b/examples/multitouch/fingerpaint/main.cpp new file mode 100644 index 0000000..49bf25b --- /dev/null +++ b/examples/multitouch/fingerpaint/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + MainWindow window; + window.showMaximized(); + return app.exec(); +} diff --git a/examples/multitouch/fingerpaint/mainwindow.cpp b/examples/multitouch/fingerpaint/mainwindow.cpp new file mode 100644 index 0000000..546c685 --- /dev/null +++ b/examples/multitouch/fingerpaint/mainwindow.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "mainwindow.h" +#include "scribblearea.h" + +//! [0] +MainWindow::MainWindow() +{ + scribbleArea = new ScribbleArea; + setCentralWidget(scribbleArea); + + createActions(); + createMenus(); + + setWindowTitle(tr("Scribble")); + resize(500, 500); +} +//! [0] + +//! [1] +void MainWindow::closeEvent(QCloseEvent *event) +//! [1] //! [2] +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} +//! [2] + +//! [3] +void MainWindow::open() +//! [3] //! [4] +{ + if (maybeSave()) { + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open File"), QDir::currentPath()); + if (!fileName.isEmpty()) + scribbleArea->openImage(fileName); + } +} +//! [4] + +//! [5] +void MainWindow::save() +//! [5] //! [6] +{ + QAction *action = qobject_cast(sender()); + QByteArray fileFormat = action->data().toByteArray(); + saveFile(fileFormat); +} +//! [6] + +//! [11] +void MainWindow::about() +//! [11] //! [12] +{ + QMessageBox::about(this, tr("About Scribble"), + tr("

The Scribble example shows how to use QMainWindow as the " + "base widget for an application, and how to reimplement some of " + "QWidget's event handlers to receive the events generated for " + "the application's widgets:

We reimplement the mouse event " + "handlers to facilitate drawing, the paint event handler to " + "update the application and the resize event handler to optimize " + "the application's appearance. In addition we reimplement the " + "close event handler to intercept the close events before " + "terminating the application.

The example also demonstrates " + "how to use QPainter to draw an image in real time, as well as " + "to repaint widgets.

")); +} +//! [12] + +//! [13] +void MainWindow::createActions() +//! [13] //! [14] +{ + openAct = new QAction(tr("&Open..."), this); + openAct->setShortcut(tr("Ctrl+O")); + connect(openAct, SIGNAL(triggered()), this, SLOT(open())); + + foreach (QByteArray format, QImageWriter::supportedImageFormats()) { + QString text = tr("%1...").arg(QString(format).toUpper()); + + QAction *action = new QAction(text, this); + action->setData(format); + connect(action, SIGNAL(triggered()), this, SLOT(save())); + saveAsActs.append(action); + } + + printAct = new QAction(tr("&Print..."), this); + connect(printAct, SIGNAL(triggered()), scribbleArea, SLOT(print())); + + exitAct = new QAction(tr("E&xit"), this); + exitAct->setShortcut(tr("Ctrl+Q")); + connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); + + clearScreenAct = new QAction(tr("&Clear Screen"), this); + clearScreenAct->setShortcut(tr("Ctrl+L")); + connect(clearScreenAct, SIGNAL(triggered()), + scribbleArea, SLOT(clearImage())); + + aboutAct = new QAction(tr("&About"), this); + connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); + + aboutQtAct = new QAction(tr("About &Qt"), this); + connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); +} +//! [14] + +//! [15] +void MainWindow::createMenus() +//! [15] //! [16] +{ + saveAsMenu = new QMenu(tr("&Save As"), this); + foreach (QAction *action, saveAsActs) + saveAsMenu->addAction(action); + + fileMenu = new QMenu(tr("&File"), this); + fileMenu->addAction(openAct); + fileMenu->addMenu(saveAsMenu); + fileMenu->addAction(printAct); + fileMenu->addSeparator(); + fileMenu->addAction(exitAct); + + optionMenu = new QMenu(tr("&Options"), this); + optionMenu->addAction(clearScreenAct); + + helpMenu = new QMenu(tr("&Help"), this); + helpMenu->addAction(aboutAct); + helpMenu->addAction(aboutQtAct); + + menuBar()->addMenu(fileMenu); + menuBar()->addMenu(optionMenu); + menuBar()->addMenu(helpMenu); +} +//! [16] + +//! [17] +bool MainWindow::maybeSave() +//! [17] //! [18] +{ + if (scribbleArea->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("Scribble"), + tr("The image has been modified.\n" + "Do you want to save your changes?"), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) { + return saveFile("png"); + } else if (ret == QMessageBox::Cancel) { + return false; + } + } + return true; +} +//! [18] + +//! [19] +bool MainWindow::saveFile(const QByteArray &fileFormat) +//! [19] //! [20] +{ + QString initialPath = QDir::currentPath() + "/untitled." + fileFormat; + + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), + initialPath, + tr("%1 Files (*.%2);;All Files (*)") + .arg(QString(fileFormat.toUpper())) + .arg(QString(fileFormat))); + if (fileName.isEmpty()) { + return false; + } else { + return scribbleArea->saveImage(fileName, fileFormat); + } +} +//! [20] diff --git a/examples/multitouch/fingerpaint/mainwindow.h b/examples/multitouch/fingerpaint/mainwindow.h new file mode 100644 index 0000000..fdb790d --- /dev/null +++ b/examples/multitouch/fingerpaint/mainwindow.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +class ScribbleArea; + +//! [0] +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(); + +protected: + void closeEvent(QCloseEvent *event); + +private slots: + void open(); + void save(); + void about(); + +private: + void createActions(); + void createMenus(); + bool maybeSave(); + bool saveFile(const QByteArray &fileFormat); + + ScribbleArea *scribbleArea; + + QMenu *saveAsMenu; + QMenu *fileMenu; + QMenu *optionMenu; + QMenu *helpMenu; + + QAction *openAct; + QList saveAsActs; + QAction *exitAct; + QAction *printAct; + QAction *clearScreenAct; + QAction *aboutAct; + QAction *aboutQtAct; +}; +//! [0] + +#endif diff --git a/examples/multitouch/fingerpaint/scribblearea.cpp b/examples/multitouch/fingerpaint/scribblearea.cpp new file mode 100644 index 0000000..a042fe7 --- /dev/null +++ b/examples/multitouch/fingerpaint/scribblearea.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "scribblearea.h" + +//! [0] +ScribbleArea::ScribbleArea(QWidget *parent) + : QWidget(parent) +{ + setAttribute(Qt::WA_AcceptTouchEvents); + setAttribute(Qt::WA_StaticContents); + modified = false; + + myPenColors + << QColor("green") + << QColor("purple") + << QColor("red") + << QColor("blue") + << QColor("yellow") + + << QColor("pink") + << QColor("orange") + << QColor("brown") + << QColor("grey") + << QColor("black"); +} +//! [0] + +//! [1] +bool ScribbleArea::openImage(const QString &fileName) +//! [1] //! [2] +{ + QImage loadedImage; + if (!loadedImage.load(fileName)) + return false; + + QSize newSize = loadedImage.size().expandedTo(size()); + resizeImage(&loadedImage, newSize); + image = loadedImage; + modified = false; + update(); + return true; +} +//! [2] + +//! [3] +bool ScribbleArea::saveImage(const QString &fileName, const char *fileFormat) +//! [3] //! [4] +{ + QImage visibleImage = image; + resizeImage(&visibleImage, size()); + + if (visibleImage.save(fileName, fileFormat)) { + modified = false; + return true; + } else { + return false; + } +} +//! [4] + +//! [9] +void ScribbleArea::clearImage() +//! [9] //! [10] +{ + image.fill(qRgb(255, 255, 255)); + modified = true; + update(); +} +//! [10] + +//! [12] //! [13] +void ScribbleArea::paintEvent(QPaintEvent *event) +//! [13] //! [14] +{ + QPainter painter(this); + const QRect rect = event->rect(); + painter.drawImage(rect.topLeft(), image, rect); +} +//! [14] + +//! [15] +void ScribbleArea::resizeEvent(QResizeEvent *event) +//! [15] //! [16] +{ + if (width() > image.width() || height() > image.height()) { + int newWidth = qMax(width() + 128, image.width()); + int newHeight = qMax(height() + 128, image.height()); + resizeImage(&image, QSize(newWidth, newHeight)); + update(); + } + QWidget::resizeEvent(event); +} +//! [16] + +//! [19] +void ScribbleArea::resizeImage(QImage *image, const QSize &newSize) +//! [19] //! [20] +{ + if (image->size() == newSize) + return; + + QImage newImage(newSize, QImage::Format_RGB32); + newImage.fill(qRgb(255, 255, 255)); + QPainter painter(&newImage); + painter.drawImage(QPoint(0, 0), *image); + *image = newImage; +} +//! [20] + +//! [21] +void ScribbleArea::print() +{ +#ifndef QT_NO_PRINTER + QPrinter printer(QPrinter::HighResolution); + + QPrintDialog *printDialog = new QPrintDialog(&printer, this); +//! [21] //! [22] + if (printDialog->exec() == QDialog::Accepted) { + QPainter painter(&printer); + QRect rect = painter.viewport(); + QSize size = image.size(); + size.scale(rect.size(), Qt::KeepAspectRatio); + painter.setViewport(rect.x(), rect.y(), size.width(), size.height()); + painter.setWindow(image.rect()); + painter.drawImage(0, 0, image); + } +#endif // QT_NO_PRINTER +} +//! [22] + +bool ScribbleArea::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + { + QList touchPoints = static_cast(event)->touchPoints(); + foreach (QTouchEvent::TouchPoint *touchPoint, touchPoints) { + switch (touchPoint->state()) { + case Qt::TouchPointStationary: + // don't do anything if this touch point hasn't moved + continue; + default: + { + int diameter = int(50 * touchPoint->pressure()); + QRectF rectF(0, 0, diameter, diameter); + rectF.moveCenter(touchPoint->pos()); + QRect rect = rectF.toRect(); + + QPainter painter(&image); + painter.setPen(Qt::NoPen); + painter.setBrush(myPenColors.at(touchPoint->id())); + painter.drawEllipse(rectF); + painter.end(); + + modified = true; + int rad = 2; + update(rect.adjusted(-rad,-rad, +rad, +rad)); + } + break; + } + } + + event->accept(); + return true; + } + default: + break; + } + return QWidget::event(event); +} diff --git a/examples/multitouch/fingerpaint/scribblearea.h b/examples/multitouch/fingerpaint/scribblearea.h new file mode 100644 index 0000000..8928ce1 --- /dev/null +++ b/examples/multitouch/fingerpaint/scribblearea.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SCRIBBLEAREA_H +#define SCRIBBLEAREA_H + +#include +#include +#include +#include + +//! [0] +class ScribbleArea : public QWidget +{ + Q_OBJECT + +public: + ScribbleArea(QWidget *parent = 0); + + bool openImage(const QString &fileName); + bool saveImage(const QString &fileName, const char *fileFormat); + + bool isModified() const { return modified; } + +public slots: + void clearImage(); + void print(); + +protected: + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); + bool event(QEvent *event); + +private: + void resizeImage(QImage *image, const QSize &newSize); + + bool modified; + QList myPenColors; + QImage image; +}; +//! [0] + +#endif -- cgit v0.12 From b5236dedd9ab72d6e0bd09151a6f55bb40a7034c Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 25 Mar 2009 11:32:52 +0100 Subject: have the window title in the fingerpaint example say Finger Paint, not Scribble --- examples/multitouch