From 5f42a207d0d0ceb98e855be570f23c03a303f364 2012-05-18 12:57:17 From: Jani Honkonen Date: 2012-05-18 12:57:17 Subject: [PATCH] Add gestures support for zoomlinechart example Also implemented new zooming and scrolling functions to help gesture handling. --- diff --git a/examples/zoomlinechart/chart.cpp b/examples/zoomlinechart/chart.cpp new file mode 100644 index 0000000..477eeea --- /dev/null +++ b/examples/zoomlinechart/chart.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Commercial Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** 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 Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "chart.h" +#include +#include +#include + +Chart::Chart(QGraphicsItem *parent, Qt::WindowFlags wFlags) + :QChart(parent, wFlags) +{ + // Seems that QGraphicsView (QChartView) does not grab gestures. + // They can only be grabbed here in the QGraphicsWidget (QChart). + grabGesture(Qt::PanGesture); + grabGesture(Qt::PinchGesture); +} + +Chart::~Chart() +{ + +} + +bool Chart::sceneEvent(QEvent *event) +{ + if (event->type() == QEvent::Gesture) + return gestureEvent(static_cast(event)); + return QChart::event(event); +} + +bool Chart::gestureEvent(QGestureEvent* event) +{ + if (QGesture *gesture = event->gesture(Qt::PanGesture)) { + QPanGesture *pan = static_cast(gesture); + scroll(pan->delta()); + } + + if (QGesture *gesture = event->gesture(Qt::PinchGesture)) { + QPinchGesture *pinch = static_cast(gesture); + if (pinch->changeFlags() & QPinchGesture::ScaleFactorChanged) + zoom(pinch->scaleFactor()); + } + + return true; +} diff --git a/examples/zoomlinechart/chart.h b/examples/zoomlinechart/chart.h new file mode 100644 index 0000000..4b106ff --- /dev/null +++ b/examples/zoomlinechart/chart.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Commercial Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** 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 Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CHART_H +#define CHART_H + +#include + +QTCOMMERCIALCHART_USE_NAMESPACE + +class Chart : public QChart +{ +public: + explicit Chart(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); + ~Chart(); + +protected: + bool sceneEvent(QEvent *event); + +private: + bool gestureEvent(QGestureEvent* event); + +private: + +}; + +#endif // CHART_H diff --git a/examples/zoomlinechart/chartview.cpp b/examples/zoomlinechart/chartview.cpp index 5e9bfe0..79c299e 100644 --- a/examples/zoomlinechart/chartview.cpp +++ b/examples/zoomlinechart/chartview.cpp @@ -22,41 +22,52 @@ #include ChartView::ChartView(QChart *chart, QWidget *parent) : - QChartView(chart, parent), m_rubberBand(QRubberBand::Rectangle, this), m_chart(chart) + QChartView(chart, parent), + m_isTouching(false) { + setRubberBand(QChartView::RectangleRubberBand); } -void ChartView::mousePressEvent(QMouseEvent *event) +bool ChartView::viewportEvent(QEvent *event) { - if (event->button() != Qt::LeftButton) - return; + if (event->type() == QEvent::TouchBegin) { + // By default touch events are converted to mouse events. So + // after this event we will get a mouse event also but we want + // to handle touch events as gestures only. So we need this safeguard + // to block mouse events that are actually generated from touch. + m_isTouching = true; - m_origin = event->pos(); - m_rubberBand.setGeometry(QRect(m_origin, QSize())); - m_rubberBand.show(); + // Turn off animations when handling gestures they + // will only slow us down. + chart()->setAnimationOptions(QChart::NoAnimation); + } + return QChartView::viewportEvent(event); +} - event->accept(); +void ChartView::mousePressEvent(QMouseEvent *event) +{ + if (m_isTouching) + return; + QChartView::mousePressEvent(event); } void ChartView::mouseMoveEvent(QMouseEvent *event) { - if (m_rubberBand.isVisible()) - m_rubberBand.setGeometry(QRect(m_origin, event->pos()).normalized()); + if (m_isTouching) + return; + QChartView::mouseMoveEvent(event); } void ChartView::mouseReleaseEvent(QMouseEvent *event) { - if (event->button() == Qt::LeftButton && m_rubberBand.isVisible()) { - m_rubberBand.hide(); + if (m_isTouching) + m_isTouching = false; - QRect rect = m_rubberBand.geometry(); - m_chart->zoomIn(rect); - event->accept(); - } + // Because we disabled animations when touch event was detected + // we must put them back on. + chart()->setAnimationOptions(QChart::SeriesAnimations); - if (event->button() == Qt::RightButton) { - m_chart->zoomOut(); - } + QChartView::mouseReleaseEvent(event); } //![1] @@ -64,23 +75,23 @@ void ChartView::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Plus: - m_chart->zoomIn(); + chart()->zoomIn(); break; case Qt::Key_Minus: - m_chart->zoomOut(); + chart()->zoomOut(); break; //![1] case Qt::Key_Left: - m_chart->scrollLeft(); + chart()->scrollLeft(); break; case Qt::Key_Right: - m_chart->scrollRight(); + chart()->scrollRight(); break; case Qt::Key_Up: - m_chart->scrollUp(); + chart()->scrollUp(); break; case Qt::Key_Down: - m_chart->scrollDown(); + chart()->scrollDown(); break; default: QGraphicsView::keyPressEvent(event); diff --git a/examples/zoomlinechart/chartview.h b/examples/zoomlinechart/chartview.h index 244f23c..9980f23 100644 --- a/examples/zoomlinechart/chartview.h +++ b/examples/zoomlinechart/chartview.h @@ -20,6 +20,7 @@ #ifndef CHARTVIEW_H #define CHARTVIEW_H + #include #include @@ -34,6 +35,7 @@ public: //![2] protected: + bool viewportEvent(QEvent *event); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); @@ -41,9 +43,7 @@ protected: //![2] private: - QRubberBand m_rubberBand; - QPoint m_origin; - QChart* m_chart; + bool m_isTouching; }; #endif diff --git a/examples/zoomlinechart/main.cpp b/examples/zoomlinechart/main.cpp index d161cd9..39d9967 100644 --- a/examples/zoomlinechart/main.cpp +++ b/examples/zoomlinechart/main.cpp @@ -18,6 +18,7 @@ ** ****************************************************************************/ +#include "chart.h" #include "chartview.h" #include #include @@ -39,10 +40,10 @@ int main(int argc, char *argv[]) } //![1] - QChart* chart = new QChart(); + Chart* chart = new Chart(); chart->addSeries(series); chart->setTitle("Zoom in/out example"); - chart->setAnimationOptions(QChart::AllAnimations); + chart->setAnimationOptions(QChart::SeriesAnimations); ChartView* chartView = new ChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); @@ -50,6 +51,8 @@ int main(int argc, char *argv[]) QMainWindow window; window.setCentralWidget(chartView); window.resize(400, 300); + window.grabGesture(Qt::PanGesture); + window.grabGesture(Qt::PinchGesture); window.show(); return a.exec(); diff --git a/examples/zoomlinechart/zoomlinechart.pro b/examples/zoomlinechart/zoomlinechart.pro index c4a77f2..92a294f 100644 --- a/examples/zoomlinechart/zoomlinechart.pro +++ b/examples/zoomlinechart/zoomlinechart.pro @@ -2,7 +2,8 @@ error( "Couldn't find the examples.pri file!" ) } TARGET = zoomlinechart -HEADERS += chartview.h -SOURCES += main.cpp chartview.cpp +HEADERS += chart.h chartview.h + +SOURCES += main.cpp chart.cpp chartview.cpp !system_build:mac: QMAKE_POST_LINK += "$$MAC_POST_LINK_PREFIX $$MAC_EXAMPLES_BIN_DIR" diff --git a/src/chartpresenter.cpp b/src/chartpresenter.cpp index ac3155d..6377360 100644 --- a/src/chartpresenter.cpp +++ b/src/chartpresenter.cpp @@ -228,11 +228,11 @@ void ChartPresenter::resetAllElements() } } -void ChartPresenter::zoomIn() +void ChartPresenter::zoomIn(qreal factor) { QRectF rect = chartGeometry(); - rect.setWidth(rect.width()/2); - rect.setHeight(rect.height()/2); + rect.setWidth(rect.width()/factor); + rect.setHeight(rect.height()/factor); rect.moveCenter(chartGeometry().center()); zoomIn(rect); } @@ -241,35 +241,38 @@ void ChartPresenter::zoomIn(const QRectF& rect) { QRectF r = rect.normalized(); r.translate(-m_chartMargins.topLeft()); - if(!r.isValid()) return; - if(m_animator) { + if (!r.isValid()) + return; + if (m_animator) { QPointF point(r.center().x()/chartGeometry().width(),r.center().y()/chartGeometry().height()); m_animator->setState(ChartAnimator::ZoomInState,point); } + m_dataset->zoomInDomain(r,chartGeometry().size()); - if(m_animator) { + + if (m_animator) m_animator->setState(ChartAnimator::ShowState); - } } -void ChartPresenter::zoomOut() +void ChartPresenter::zoomOut(qreal factor) { - if(m_animator) - { + if (m_animator) m_animator->setState(ChartAnimator::ZoomOutState); - } - QSizeF size = chartGeometry().size(); - QRectF rect = chartGeometry(); - rect.translate(-m_chartMargins.topLeft()); - if(!rect.isValid()) return; - m_dataset->zoomOutDomain(rect.adjusted(size.width()/4,size.height()/4,-size.width()/4,-size.height()/4),size); - //m_dataset->zoomOutDomain(m_zoomStack[m_zoomIndex-1],geometry().size()); + QRectF chartRect; + chartRect.setSize(chartGeometry().size()); - if(m_animator){ + QRectF rect; + rect.setSize(chartRect.size()/factor); + rect.moveCenter(chartRect.center()); + if (!rect.isValid()) + return; + + m_dataset->zoomOutDomain(rect, chartRect.size()); + + if (m_animator) m_animator->setState(ChartAnimator::ShowState); - } } void ChartPresenter::scroll(int dx,int dy) diff --git a/src/chartpresenter_p.h b/src/chartpresenter_p.h index 27a44c5..41bf3c4 100644 --- a/src/chartpresenter_p.h +++ b/src/chartpresenter_p.h @@ -66,9 +66,9 @@ public: void setAnimationOptions(QChart::AnimationOptions options); QChart::AnimationOptions animationOptions() const; - void zoomIn(); + void zoomIn(qreal factor); void zoomIn(const QRectF& rect); - void zoomOut(); + void zoomOut(qreal factor); void scroll(int dx,int dy); void setGeometry(const QRectF& rect); diff --git a/src/qchart.cpp b/src/qchart.cpp index 9489f48..670dd2d 100644 --- a/src/qchart.cpp +++ b/src/qchart.cpp @@ -252,7 +252,7 @@ QChart::ChartTheme QChart::theme() const */ void QChart::zoomIn() { - d_ptr->m_presenter->zoomIn(); + d_ptr->m_presenter->zoomIn(2.0); } /*! @@ -269,7 +269,29 @@ void QChart::zoomIn(const QRectF& rect) */ void QChart::zoomOut() { - d_ptr->m_presenter->zoomOut(); + d_ptr->m_presenter->zoomOut(2.0); +} + +/*! + Zooms in the view by a \a factor. + + A factor over 1.0 zooms the view in and factor between 0.0 and 1.0 zooms out. + */ +void QChart::zoom(qreal factor) +{ + if (qFuzzyIsNull(factor)) + return; + + if (qFuzzyCompare(factor, 1.0)) + return; + + if (factor < 0) + return; + + if (factor > 1.0) + d_ptr->m_presenter->zoomIn(factor); + else + d_ptr->m_presenter->zoomOut(1.0 / factor); } /*! @@ -366,6 +388,14 @@ void QChart::scrollDown() } /*! + Scrolls the visible area of the chart by the distance defined in the \a delta. + */ +void QChart::scroll(const QPointF &delta) +{ + d_ptr->m_presenter->scroll(-delta.x(), delta.y()); +} + +/*! Sets the chart background visibility state to \a visible */ void QChart::setBackgroundVisible(bool visible) diff --git a/src/qchart.h b/src/qchart.h index 7ae90a2..12b6f59 100644 --- a/src/qchart.h +++ b/src/qchart.h @@ -94,10 +94,12 @@ public: void zoomIn(); void zoomIn(const QRectF &rect); void zoomOut(); + void zoom(qreal factor); void scrollLeft(); void scrollRight(); void scrollUp(); void scrollDown(); + void scroll(const QPointF &delta); QAxis* axisX() const; QAxis* axisY(QAbstractSeries* series = 0) const;