diff --git a/qad/graphic/graphic.cpp b/qad/graphic/graphic.cpp index 59c6c42..2a25b5b 100644 --- a/qad/graphic/graphic.cpp +++ b/qad/graphic/graphic.cpp @@ -25,8 +25,15 @@ Graphic::Graphic(QWidget * parent): QFrame(parent), line_x_min(this), line_x_max if (trans->isEmpty()) trans->load("lang/qad_graphic_" + QLocale::system().name().left(2)); qApp->installTranslator(trans); + gesture_angle = 45.; leg_update = true; - visible_update = fullscr = false; + visible_update = fullscr = need_mouse_pan = false; + gestures = +#ifdef Q_OS_ANDROID + true; +#else + false; +#endif ui = new Ui::Graphic(); ui->setupUi(this); /*line_x_min.resize(70, 22); @@ -53,32 +60,13 @@ Graphic::Graphic(QWidget * parent): QFrame(parent), line_x_min(this), line_x_max connect(&line_y_min, SIGNAL(valueChanged(double)), this, SLOT(lineYMinChanged(double))); connect(&line_y_max, SIGNAL(valueChanged(double)), this, SLOT(lineYMaxChanged(double))); connect(ui->canvas_raster, SIGNAL(paintEvent(QPaintEvent * )), this, SLOT(canvasPaintEvent())); - connect(ui->canvas_raster, SIGNAL(mouseMoveEvent(QMouseEvent * )), this, SLOT(canvasMouseMoveEvent(QMouseEvent * ))); - connect(ui->canvas_raster, SIGNAL(mousePressEvent(QMouseEvent * )), this, SLOT(canvasMousePressEvent(QMouseEvent * ))); - connect(ui->canvas_raster, SIGNAL(mouseReleaseEvent(QMouseEvent * )), this, SLOT(canvasMouseReleaseEvent(QMouseEvent * ))); - connect(ui->canvas_raster, SIGNAL(mouseDoubleClickEvent(QMouseEvent*)), this, SLOT(canvasMouseDoubleClickEvent(QMouseEvent * ))); - connect(ui->canvas_raster, SIGNAL(wheelEvent(QWheelEvent * )), this, SLOT(canvasWheelEvent(QWheelEvent * ))); - connect(ui->canvas_raster, SIGNAL(leaveEvent(QEvent * )), this, SLOT(canvasLeaveEvent(QEvent * ))); - connect(ui->canvas_raster, SIGNAL(keyPressEvent(QKeyEvent * )), this, SLOT(canvasKeyPressEvent(QKeyEvent * ))); + prepareCanvas(ui->canvas_raster); #ifdef HAS_GL canvas_gl = new UGLWidget(); ui->layoutCanvas->addWidget(canvas_gl); connect(canvas_gl, SIGNAL(paintSignal()), this, SLOT(canvasPaintEvent())); - connect(canvas_gl, SIGNAL(mouseMoveEvent(QMouseEvent * )), this, SLOT(canvasMouseMoveEvent(QMouseEvent * ))); - connect(canvas_gl, SIGNAL(mousePressEvent(QMouseEvent * )), this, SLOT(canvasMousePressEvent(QMouseEvent * ))); - connect(canvas_gl, SIGNAL(mouseReleaseEvent(QMouseEvent * )), this, SLOT(canvasMouseReleaseEvent(QMouseEvent * ))); - connect(canvas_gl, SIGNAL(mouseDoubleClickEvent(QMouseEvent*)), this, SLOT(canvasMouseDoubleClickEvent(QMouseEvent * ))); - connect(canvas_gl, SIGNAL(wheelEvent(QWheelEvent * )), this, SLOT(canvasWheelEvent(QWheelEvent * ))); - connect(canvas_gl, SIGNAL(leaveEvent(QEvent * )), this, SLOT(canvasLeaveEvent(QEvent * ))); - connect(canvas_gl, SIGNAL(keyPressEvent(QKeyEvent * )), this, SLOT(canvasKeyPressEvent(QKeyEvent * ))); - canvas_gl->grabGesture(Qt::PinchGesture); - canvas_gl->grabGesture(Qt::PanGesture); - canvas_gl->setMouseTracking(true); - canvas_gl->installEventFilter(this); + prepareCanvas(canvas_gl); #endif - ui->canvas_raster->grabGesture(Qt::PinchGesture); - ui->canvas_raster->grabGesture(Qt::PanGesture); - ui->canvas_raster->installEventFilter(this); icon_exp_x = QIcon(":/icons/expand_x.png"); icon_exp_y = QIcon(":/icons/expand_y.png"); icon_exp_sx = QIcon(":/icons/expand_s_x.png"); @@ -166,20 +154,107 @@ bool Graphic::eventFilter(QObject * o, QEvent * e) { //qDebug() << "event" << o << e; if (o == canvas) { switch (e->type()) { - case QEvent::Gesture: - foreach (QGesture * g, ((QGestureEvent*)e)->gestures()) - procGesture(g); + case QEvent::Gesture: + if (!gestures) break; + foreach (QGesture * g, ((QGestureEvent*)e)->gestures()) + procGesture(g); break; - default: break; + case QEvent::KeyPress: + if (((QKeyEvent*)e)->key() == Qt::Key_Back) + leaveFullscreen(); + break; + case QEvent::TouchBegin: + if (!gestures) break; + need_mouse_pan = true; + break; + case QEvent::TouchUpdate: { + if (!gestures) break; + QList tpl = ((QTouchEvent*)e)->touchPoints(); + if (tpl.size() == 2) { + need_mouse_pan = false; + QPointF dp = tpl[0].scenePos() - tpl[1].scenePos(); + gesture_angle = rad2deg_qpie * qAtan2(qAbs(dp.y()), qAbs(dp.x())); + } + } break; + default: break; } } return QFrame::eventFilter(o, e); } +void Graphic::prepareCanvas(QWidget * w) { + connect(w, SIGNAL(mouseMoveEvent(QMouseEvent * )), this, SLOT(canvasMouseMoveEvent(QMouseEvent * ))); + connect(w, SIGNAL(mousePressEvent(QMouseEvent * )), this, SLOT(canvasMousePressEvent(QMouseEvent * ))); + connect(w, SIGNAL(mouseReleaseEvent(QMouseEvent * )), this, SLOT(canvasMouseReleaseEvent(QMouseEvent * ))); + connect(w, SIGNAL(mouseDoubleClickEvent(QMouseEvent*)), this, SLOT(canvasMouseDoubleClickEvent(QMouseEvent * ))); + connect(w, SIGNAL(wheelEvent(QWheelEvent * )), this, SLOT(canvasWheelEvent(QWheelEvent * ))); + connect(w, SIGNAL(leaveEvent(QEvent * )), this, SLOT(canvasLeaveEvent(QEvent * ))); + connect(w, SIGNAL(keyPressEvent(QKeyEvent * )), this, SLOT(canvasKeyPressEvent(QKeyEvent * ))); + //w->grabGesture(Qt::TapGesture); + w->grabGesture(Qt::TapAndHoldGesture); + //w->grabGesture(Qt::PanGesture); + w->grabGesture(Qt::PinchGesture); + w->setMouseTracking(true); + w->installEventFilter(this); +} + + void Graphic::procGesture(QGesture * g) { if (!g) return; - qDebug() << g; + switch (g->gestureType()) { + case Qt::PanGesture: { + QPanGesture * pg = (QPanGesture*)g; + QPointF dp = -pg->delta(); + dp.rx() /= getScaleX(); + dp.ry() /= getScaleY(); + selrect.translate(dp); + totalUpdate(); + } break; + case Qt::PinchGesture: { + QPinchGesture * pg = (QPinchGesture*)g; + //qDebug() << pg->totalRotationAngle(); + Qt::KeyboardModifiers km = Qt::NoModifier; + if (gesture_angle <= 20.) km = Qt::ControlModifier; + if (gesture_angle >= 70.) km = Qt::ShiftModifier; + procZoom(pg->centerPoint(), (pg->scaleFactor() - 1.) * 300., km); + totalUpdate(); + } break; + case Qt::TapAndHoldGesture: { + QTapAndHoldGesture * pg = (QTapAndHoldGesture*)g; + if (pg->state() == Qt::GestureStarted) + fullscreen(); + } break; + default: + qDebug() << g; + break; + } + //qDebug() << g; +} + + +void Graphic::procZoom(QPointF view_center, double dzoom, Qt::KeyboardModifiers km) { + double scl, wid = canvas->width() - gridborder.x() - margins_.width() - margins_.left(), hei = canvas->height() - gridborder.y() - margins_.height() - margins_.top(); + double px = view_center.x() - gridborder.x() - margins_.left(), py = hei - view_center.y() + margins_.height(); + px = px / wid * selrect.width() + selrect.x(); + py = py / hei * selrect.height() + selrect.y(); + scl = 1. - dzoom / 300.; + if (km == Qt::NoModifier) + selrect.setRect(px - (px - selrect.x()) * scl, py - (py - selrect.y()) * scl, selrect.width() * scl, selrect.height() * scl); + else { + if (km == Qt::ControlModifier) + selrect.setRect(px - (px - selrect.x()) * scl, selrect.y(), selrect.width() * scl, selrect.height()); + if (km == Qt::ShiftModifier) + selrect.setRect(selrect.x(), py - (py - selrect.y()) * scl, selrect.width(), selrect.height() * scl); + } +} + + +void Graphic::totalUpdate() { + isFit = false; + emit visualRectChanged(); + update(true); + setRectToLines(); } @@ -277,7 +352,11 @@ void Graphic::canvasMouseMoveEvent(QMouseEvent * e) { return; } if (!navigation) return; - if (curaction != gaMove && (e->buttons() & Qt::RightButton) == Qt::RightButton) return; + if (gestures) { + if (!need_mouse_pan) return; + curaction = gaMove; + } else + if (curaction != gaMove && (e->buttons() & Qt::RightButton) == Qt::RightButton) return; switch (curaction) { case gaZoomInRect: ui->status->setText(tr("Selection") + ": " + pointCoords(startpos_r) + " -> " + @@ -305,10 +384,7 @@ void Graphic::canvasMouseMoveEvent(QMouseEvent * e) { if (e->modifiers() == Qt::ShiftModifier) dp.setX(0.); selrect.translate(dp); - isFit = false; - emit visualRectChanged(); - update(true); - setRectToLines(); + totalUpdate(); break; default: break; } @@ -319,6 +395,7 @@ void Graphic::canvasMouseMoveEvent(QMouseEvent * e) { void Graphic::canvasMousePressEvent(QMouseEvent * e) { emit graphicMousePressEvent(canvas2real(QPointF(e->pos())), e->buttons()); if (!navigation) return; + if (gestures && !need_mouse_pan) return; #ifdef HAS_GL canvas_gl->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor); #endif @@ -326,7 +403,7 @@ void Graphic::canvasMousePressEvent(QMouseEvent * e) { prevpos = e->pos(); startpos = prevpos; startpos_r = canvas2real(startpos); - if (cancel) return; + if (cancel || gestures) return; if (e->button() == Qt::MidButton) curaction = gaMove; if (e->button() == Qt::RightButton) { if (bufferActive) { @@ -361,6 +438,8 @@ void Graphic::canvasMousePressEvent(QMouseEvent * e) { void Graphic::canvasMouseReleaseEvent(QMouseEvent * e) { emit graphicMouseReleaseEvent(canvas2real(QPointF(e->pos())), e->buttons()); + if (gestures) return; + need_mouse_pan = false; if (!navigation) return; #ifdef HAS_GL canvas_gl->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor); @@ -416,25 +495,10 @@ void Graphic::canvasMouseDoubleClickEvent(QMouseEvent * ) { void Graphic::canvasWheelEvent(QWheelEvent * e) { //if (curaction != gaMove) return; emit graphicWheelEvent(canvas2real(QPointF(e->pos())), e->delta()); + if (gestures) return; if (!navigation) return; - double scl, wid = canvas->width() - gridborder.x() - margins_.width() - margins_.left(), hei = canvas->height() - gridborder.y() - margins_.height() - margins_.top(); - double px = e->pos().x() - gridborder.x() - margins_.left(), py = hei - e->pos().y() + margins_.height(); - px = px / wid * selrect.width() + selrect.x(); - py = py / hei * selrect.height() + selrect.y(); - if (e->delta() > 0) scl = 1. / 1.2; - else scl = 1.2; - if (e->modifiers() == Qt::NoModifier) - selrect.setRect(px - (px - selrect.x()) * scl, py - (py - selrect.y()) * scl, selrect.width() * scl, selrect.height() * scl); - else { - if (e->modifiers() == Qt::ControlModifier) - selrect.setRect(px - (px - selrect.x()) * scl, selrect.y(), selrect.width() * scl, selrect.height()); - if (e->modifiers() == Qt::ShiftModifier) - selrect.setRect(selrect.x(), py - (py - selrect.y()) * scl, selrect.width(), selrect.height() * scl); - } - isFit = false; - update(true); - setRectToLines(); - emit visualRectChanged(); + procZoom(e->pos(), e->delta(), e->modifiers()); + totalUpdate(); } @@ -550,6 +614,11 @@ void Graphic::setOnlyExpandX(bool yes) { } +void Graphic::setGesturesNavigation(bool yes) { + gestures = yes; +} + + Graphic::GraphicsData Graphic::graphicsData() const { GraphicsData ret; ret.resize(graphics.size()); diff --git a/qad/graphic/graphic.h b/qad/graphic/graphic.h index 7016168..52bcfec 100644 --- a/qad/graphic/graphic.h +++ b/qad/graphic/graphic.h @@ -25,7 +25,7 @@ QT_BEGIN_NAMESPACE namespace Ui { class Graphic; -}; +} class UGLWidget; @@ -76,6 +76,7 @@ class Graphic: public QFrame Q_PROPERTY(bool paused READ paused WRITE setPaused) Q_PROPERTY(bool onlyExpandY READ onlyExpandY WRITE setOnlyExpandY) Q_PROPERTY(bool onlyExpandX READ onlyExpandX WRITE setOnlyExpandX) + Q_PROPERTY(bool gesturesNavigation READ gesturesNavigation WRITE setGesturesNavigation) Q_PROPERTY(double historySize READ historySize WRITE setHistorySize) Q_PROPERTY(double maxVisibleTime READ maxVisibleTime WRITE setMaxVisibleTime) Q_PROPERTY(double autoXIncrement READ autoXIncrement WRITE setAutoXIncrement) @@ -162,6 +163,7 @@ public: bool paused() const {return pause_;} bool onlyExpandY() const {return only_expand_y;} bool onlyExpandX() const {return only_expand_x;} + bool gesturesNavigation() const {return gestures;} bool isAutofitted() const {return isFit;} int currentGraphic() const {return curGraphic;} int graphicsCount() const {return graphics.size();} @@ -273,6 +275,7 @@ public slots: void setMinimumRepaintInterval(const int & val) {min_repaint_int = val;} void setOnlyExpandY(bool yes); void setOnlyExpandX(bool yes); + void setGesturesNavigation(bool yes); void setHistogramMinIntervals(int value) {min_int = value; updateGraphics();} void setHistogramMaxIntervals(int value) {max_int = value; updateGraphics();} void setHistogramMinDeltaMultiplier(double value) {mdm = value; updateGraphics();} @@ -323,7 +326,10 @@ protected: virtual void timerEvent(QTimerEvent * ); virtual bool eventFilter(QObject * o, QEvent * e); + void prepareCanvas(QWidget * w); void procGesture(QGesture * g); + void procZoom(QPointF view_center, double dzoom, Qt::KeyboardModifiers km = Qt::NoModifier); + void totalUpdate(); void setCurrentAction(GraphicAction action); void findGraphicsRect(double start_x = 0., double end_x = 0., double start_y = 0., double end_y = 0.); void tick(int index, bool slide = true, bool update = true); @@ -377,9 +383,9 @@ protected: Graduation grad_x, grad_y; AxisType axis_type_x; double gridx, gridy, history, visible_time, inc_x, mdm, grid_numbers_x, grid_numbers_y, LN2, LN5, LN10; - double eminx, eminy, emaxx, emaxy, pause_phase; + double eminx, eminy, emaxx, emaxy, pause_phase, gesture_angle, need_mouse_pan; int legy, lastw, lasth, min_repaint_int, min_int, max_int, timer_pause, thick; - bool aalias, aupdate, mupdate, grid, guides, isFit, isEmpty, isOGL, isHover, bufferActive, cancel, pause_, isPrinting; + bool aalias, aupdate, mupdate, grid, guides, isFit, isEmpty, isOGL, isHover, bufferActive, cancel, pause_, isPrinting, gestures; bool hasLblX, hasLblY, navigation, only_expand_y, only_expand_x, is_lines_update, leg_update, visible_update, fullscr; protected slots: