/** * Constructor. */ QG_GraphicView::QG_GraphicView(QWidget* parent, Qt::WindowFlags f, RS_Document* doc) :RS_GraphicView(parent, f) ,device("Mouse") ,curCad(new QCursor(QPixmap(":ui/cur_cad_bmp.png"), CURSOR_SIZE, CURSOR_SIZE)) ,curDel(new QCursor(QPixmap(":ui/cur_del_bmp.png"), CURSOR_SIZE, CURSOR_SIZE)) ,curSelect(new QCursor(QPixmap(":ui/cur_select_bmp.png"), CURSOR_SIZE, CURSOR_SIZE)) ,curMagnifier(new QCursor(QPixmap(":ui/cur_glass_bmp.png"), CURSOR_SIZE, CURSOR_SIZE)) ,curHand(new QCursor(QPixmap(":ui/cur_hand_bmp.png"), CURSOR_SIZE, CURSOR_SIZE)) ,redrawMethod(RS2::RedrawAll) ,isSmoothScrolling(false) { RS_DEBUG->print("QG_GraphicView::QG_GraphicView().."); if (doc) { setContainer(doc); doc->setGraphicView(this); setDefaultAction(new RS_ActionDefault(*doc, *this)); } setFactorX(4.0); setFactorY(4.0); setBorders(10, 10, 10, 10); setMouseTracking(true); setFocusPolicy(Qt::NoFocus); // SourceForge issue 45 (Left-mouse drag shrinks window) setAttribute(Qt::WA_NoMousePropagation); view_rect = LC_Rect(toGraph(0, 0), toGraph(getWidth(), getHeight())); }
/** * zooms in by factor f */ void RS_GraphicView::zoomIn(double f, const RS_Vector& center) { if (f<1.0e-6) { RS_DEBUG->print(RS_Debug::D_WARNING, "RS_GraphicView::zoomIn: invalid factor"); return; } RS_Vector c = center; if (!c.valid) { //find mouse position c= getMousePosition(); } zoomWindow( toGraph(RS_Vector(0,0)) .scale(c, RS_Vector(1.0/f,1.0/f)), toGraph(RS_Vector(getWidth(),getHeight())) .scale(c, RS_Vector(1.0/f,1.0/f))); //adjustOffsetControls(); //adjustZoomControls(); // updateGrid(); redraw(); }
/** * Handles paint events by redrawing the graphic in this view. * usually that's very fast since we only paint the buffer we * have from the last call.. */ void QG_GraphicView::paintEvent(QPaintEvent *) { // Re-Create or get the layering pixmaps getPixmapForView(PixmapLayer1); getPixmapForView(PixmapLayer2); getPixmapForView(PixmapLayer3); // Draw Layer 1 if (redrawMethod & RS2::RedrawGrid) { PixmapLayer1->fill(background); RS_PainterQt painter1(PixmapLayer1.get()); drawLayer1((RS_Painter*)&painter1); painter1.end(); } if (redrawMethod & RS2::RedrawDrawing) { view_rect = LC_Rect(toGraph(0, 0), toGraph(getWidth(), getHeight())); // DRaw layer 2 PixmapLayer2->fill(Qt::transparent); RS_PainterQt painter2(PixmapLayer2.get()); if (antialiasing) { painter2.setRenderHint(QPainter::Antialiasing); } painter2.setDrawingMode(drawingMode); painter2.setDrawSelectedOnly(false); drawLayer2((RS_Painter*)&painter2); painter2.setDrawSelectedOnly(true); drawLayer2((RS_Painter*)&painter2); painter2.end(); } if (redrawMethod & RS2::RedrawOverlay) { PixmapLayer3->fill(Qt::transparent); RS_PainterQt painter3(PixmapLayer3.get()); if (antialiasing) { painter3.setRenderHint(QPainter::Antialiasing); } drawLayer3((RS_Painter*)&painter3); painter3.end(); } // Finally paint the layers back on the screen, bitblk to the rescue! RS_PainterQt wPainter(this); wPainter.drawPixmap(0,0,*PixmapLayer1); wPainter.drawPixmap(0,0,*PixmapLayer2); wPainter.drawPixmap(0,0,*PixmapLayer3); wPainter.end(); redrawMethod=RS2::RedrawNone; }
bool QG_GraphicView::event(QEvent *event) { #if QT_VERSION >= 0x050200 if (event->type() == QEvent::NativeGesture) { QNativeGestureEvent *nge = static_cast<QNativeGestureEvent *>(event); if (nge->gestureType() == Qt::ZoomNativeGesture) { double v = nge->value(); RS2::ZoomDirection direction; double factor; if (v < 0) { direction = RS2::Out; factor = 1-v; } else { direction = RS2::In; factor = 1+v; } // It seems the NativeGestureEvent::pos() incorrectly reports global coordinates QPoint g = mapFromGlobal(nge->globalPos()); RS_Vector mouse = toGraph(RS_Vector(g.x(), g.y())); setCurrentAction(new RS_ActionZoomIn(*container, *this, direction, RS2::Both, mouse, factor)); } return true; } #endif return QWidget::event(event); }
/** * mouse wheel event. zooms in/out or scrolls when * shift or ctrl is pressed. */ void QG_GraphicView::wheelEvent(QWheelEvent *e) { //RS_DEBUG->print("wheel: %d", e->delta()); //printf("state: %d\n", e->state()); //printf("ctrl: %d\n", Qt::ControlButton); if (container==NULL) { return; } RS_Vector mouse = toGraph(RS_Vector(e->x(), e->y())); bool scroll = false; RS2::Direction direction = RS2::Up; // scroll up / down: if (e->modifiers()==Qt::ControlModifier) { scroll = true; if (e->delta()>0) { direction = RS2::Up; } else { direction = RS2::Down; } } // scroll left / right: else if (e->modifiers()==Qt::ShiftModifier) { scroll = true; if (e->delta()>0) { direction = RS2::Right; } else { direction = RS2::Left; } } if (scroll) { setCurrentAction(new RS_ActionZoomScroll(direction, *container, *this)); } // zoom in / out: else if (e->modifiers()==0) { if (e->delta()>0) { setCurrentAction(new RS_ActionZoomIn(*container, *this, RS2::In, RS2::Both, mouse)); } else { setCurrentAction(new RS_ActionZoomIn(*container, *this, RS2::Out, RS2::Both, mouse)); } } redraw(); e->accept(); }
RS_Vector QG_GraphicView::getMousePosition() const { //find mouse position QPoint vp=mapFromGlobal(QCursor::pos()); //if cursor is not on widget, return the widget center position if(!rect().contains(vp)) vp=QPoint(width()/2, height()/2); return toGraph(vp.x(), vp.y()); }
void RS_GraphicView::mouseMoveEvent(QMouseEvent* e) { RS_DEBUG->print("RS_GraphicView::mouseMoveEvent begin"); RS_Graphic* graphic = nullptr; if (container->rtti()==RS2::EntityGraphic) { graphic = (RS_Graphic*)container; } RS_DEBUG->print("RS_GraphicView::mouseMoveEvent 001"); if (e) { mx = e->x(); my = e->y(); } RS_DEBUG->print("RS_GraphicView::mouseMoveEvent 002"); if (eventHandler) { eventHandler->mouseMoveEvent(e); } RS_DEBUG->print("RS_GraphicView::mouseMoveEvent 003"); if ( ((!eventHandler) || !eventHandler->hasAction()) && (graphic)) { RS_Vector mouse = toGraph(RS_Vector(mx, my)); RS_Vector relMouse = mouse - getRelativeZero(); if (RS_DIALOGFACTORY) RS_DIALOGFACTORY->updateCoordinateWidget(mouse, relMouse); } RS_DEBUG->print("RS_GraphicView::mouseMoveEvent end"); }
/** * mouse wheel event. zooms in/out or scrolls when * shift or ctrl is pressed. */ void QG_GraphicView::wheelEvent(QWheelEvent *e) { //RS_DEBUG->print("wheel: %d", e->delta()); //printf("state: %d\n", e->state()); //printf("ctrl: %d\n", Qt::ControlButton); if (container==NULL) { return; } RS_Vector mouse = toGraph(RS_Vector(e->x(), e->y())); #if QT_VERSION >= 0x050200 QPoint numPixels = e->pixelDelta(); // high-resolution scrolling triggers Pan instead of Zoom logic isSmoothScrolling |= !numPixels.isNull(); if (isSmoothScrolling) { if (e->phase() == Qt::ScrollEnd) isSmoothScrolling = false; if (!numPixels.isNull()) { if (e->modifiers()==Qt::ControlModifier) { // Hold ctrl to zoom. 1 % per pixel double v = -numPixels.y() / 100.; RS2::ZoomDirection direction; double factor; if (v < 0) { direction = RS2::Out; factor = 1-v; } else { direction = RS2::In; factor = 1+v; } setCurrentAction(new RS_ActionZoomIn(*container, *this, direction, RS2::Both, mouse, factor)); } else { // otherwise, scroll setCurrentAction(new RS_ActionZoomScroll(numPixels.x(), numPixels.y(), *container, *this)); } redraw(); } e->accept(); return; } #endif if (e->delta() == 0) { // A zero delta event occurs when smooth scrolling is ended. Ignore this e->accept(); return; } bool scroll = false; RS2::Direction direction = RS2::Up; // scroll up / down: if (e->modifiers()==Qt::ControlModifier) { scroll = true; switch(e->orientation()){ case Qt::Horizontal: direction=(e->delta()>0)?RS2::Left:RS2::Right; break; default: case Qt::Vertical: direction=(e->delta()>0)?RS2::Up:RS2::Down; } } // scroll left / right: else if (e->modifiers()==Qt::ShiftModifier) { scroll = true; switch(e->orientation()){ case Qt::Horizontal: direction=(e->delta()>0)?RS2::Up:RS2::Down; break; default: case Qt::Vertical: direction=(e->delta()>0)?RS2::Left:RS2::Right; } } if (scroll) { setCurrentAction(new RS_ActionZoomScroll(direction, *container, *this)); } // zoom in / out: else if (e->modifiers()==0) { if (e->delta()>0) { setCurrentAction(new RS_ActionZoomIn(*container, *this, RS2::In, RS2::Both, mouse)); } else { setCurrentAction(new RS_ActionZoomIn(*container, *this, RS2::Out, RS2::Both, mouse)); } } redraw(); e->accept(); }
/** * mouse wheel event. zooms in/out or scrolls when * shift or ctrl is pressed. */ void QG_GraphicView::wheelEvent(QWheelEvent *e) { //RS_DEBUG->print("wheel: %d", e->delta()); //printf("state: %d\n", e->state()); //printf("ctrl: %d\n", Qt::ControlButton); if (container==NULL) { return; } RS_Vector mouse = toGraph(e->x(), e->y()); if (device == "Trackpad") { QPoint numPixels = e->pixelDelta(); // high-resolution scrolling triggers Pan instead of Zoom logic isSmoothScrolling |= !numPixels.isNull(); if (isSmoothScrolling) { if (e->phase() == Qt::ScrollEnd) isSmoothScrolling = false; } else // Trackpads that without high-resolution scrolling // e.g. libinput-XWayland trackpads { numPixels = e->angleDelta() / 4; } if (!numPixels.isNull()) { if (e->modifiers()==Qt::ControlModifier) { RS_SETTINGS->beginGroup("/Defaults"); bool invZoom = (RS_SETTINGS->readNumEntry("/InvertZoomDirection", 0) == 1); RS_SETTINGS->endGroup(); // Hold ctrl to zoom. 1 % per pixel double v = (invZoom) ? (numPixels.y() / 100.) : (-numPixels.y() / 100.); RS2::ZoomDirection direction; double factor; if (v < 0) { direction = RS2::Out; factor = 1-v; } else { direction = RS2::In; factor = 1+v; } setCurrentAction(new RS_ActionZoomIn(*container, *this, direction, RS2::Both, &mouse, factor)); } else { RS_SETTINGS->beginGroup("/Defaults"); bool inv_h = (RS_SETTINGS->readNumEntry("/WheelScrollInvertH", 0) == 1); bool inv_v = (RS_SETTINGS->readNumEntry("/WheelScrollInvertV", 0) == 1); RS_SETTINGS->endGroup(); int hDelta = (inv_h) ? -numPixels.x() : numPixels.x(); int vDelta = (inv_v) ? -numPixels.y() : numPixels.y(); // scroll by scrollbars: issue #479 (it has its own issues) if (scrollbars) { hScrollBar->setValue(hScrollBar->value() - hDelta); vScrollBar->setValue(vScrollBar->value() - vDelta); } else { setCurrentAction(new RS_ActionZoomScroll(hDelta, vDelta, *container, *this)); } } redraw(); } e->accept(); return; } if (e->delta() == 0) { // A zero delta event occurs when smooth scrolling is ended. Ignore this e->accept(); return; } bool scroll = false; RS2::Direction direction = RS2::Up; // scroll up / down: if (e->modifiers()==Qt::ControlModifier) { scroll = true; switch(e->orientation()){ case Qt::Horizontal: direction=(e->delta()>0)?RS2::Left:RS2::Right; break; default: case Qt::Vertical: direction=(e->delta()>0)?RS2::Up:RS2::Down; } } // scroll left / right: else if (e->modifiers()==Qt::ShiftModifier) { scroll = true; switch(e->orientation()){ case Qt::Horizontal: direction=(e->delta()>0)?RS2::Up:RS2::Down; break; default: case Qt::Vertical: direction=(e->delta()>0)?RS2::Left:RS2::Right; } } if (scroll && scrollbars) { //scroll by scrollbars: issue #479 RS_SETTINGS->beginGroup("/Defaults"); bool inv_h = (RS_SETTINGS->readNumEntry("/WheelScrollInvertH", 0) == 1); bool inv_v = (RS_SETTINGS->readNumEntry("/WheelScrollInvertV", 0) == 1); RS_SETTINGS->endGroup(); int delta; switch(direction){ case RS2::Left: case RS2::Right: delta = (inv_h) ? -e->delta() : e->delta(); hScrollBar->setValue(hScrollBar->value()+delta); break; default: delta = (inv_v) ? -e->delta() : e->delta(); vScrollBar->setValue(vScrollBar->value()+delta); } // setCurrentAction(new RS_ActionZoomScroll(direction, // *container, *this)); } // zoom in / out: else if (e->modifiers()==0) { /* * The zoomFactor effects how quickly the scroll wheel will zoom in & out. * * Benchmarks: * 1.250 - the original; fast & usable, but seems a choppy & a bit 'jarring' * 1.175 - still a bit choppy * 1.150 - smoother than the original, but still 'quick' enough for good navigation. * 1.137 - seems to work well for me * 1.125 - about the lowest that would be acceptable and useful, a tad on the slow side for me * 1.100 - a very slow & deliberate zooming, but feels very "cautious", "controlled", "safe", and "precise". * 1.000 - goes nowhere. :) */ const double zoomFactor=1.137; RS_Vector mainViewCenter = toGraph(getWidth()/2, getHeight()/2); RS_SETTINGS->beginGroup("/Defaults"); bool invZoom = (RS_SETTINGS->readNumEntry("/InvertZoomDirection", 0) == 1); RS_SETTINGS->endGroup(); if ((e->delta()>0 && !invZoom) || (e->delta()<0 && invZoom)) { const double zoomInOvershoot=1.20; RS_Vector effect{mouse}; { effect-=mainViewCenter; effect.scale(zoomInOvershoot); effect+=mainViewCenter; } setCurrentAction(new RS_ActionZoomIn(*container, *this, RS2::In, RS2::Both, &effect, zoomFactor )); } else { const double zoomOutUndershoot=0.30; RS_Vector effect{mouse}; { effect-=mainViewCenter; effect.scale(zoomOutUndershoot); effect+=mainViewCenter; } setCurrentAction(new RS_ActionZoomIn(*container, *this, RS2::Out, RS2::Both, &effect, zoomFactor )); } } redraw(); QMouseEvent* event = new QMouseEvent(QEvent::MouseMove, QPoint(e->x(), e->y()), Qt::NoButton, Qt::NoButton, Qt::NoModifier); eventHandler->mouseMoveEvent(event); delete event; e->accept(); }