From 0fac22badb86637bdaec0fec177a77dfc252de62 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Fri, 15 Jan 2016 14:09:52 +0200 Subject: [PATCH] If item's rect is bigger than view's rect ensureVisible works very unstable. --HG-- branch : release --- .../toolsinglepoint/vtoolbasepoint.cpp | 21 ++++++- src/libs/vtools/tools/vtooldetail.cpp | 60 ++++++++++++------- src/libs/vwidgets/vcontrolpointspline.cpp | 24 +++++++- src/libs/vwidgets/vgraphicssimpletextitem.cpp | 24 +++++++- src/libs/vwidgets/vmaingraphicsview.cpp | 13 ++-- src/libs/vwidgets/vmaingraphicsview.h | 1 + 6 files changed, 116 insertions(+), 27 deletions(-) diff --git a/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolbasepoint.cpp b/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolbasepoint.cpp index ec29035b8..645d8655f 100644 --- a/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolbasepoint.cpp +++ b/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolbasepoint.cpp @@ -145,7 +145,26 @@ QVariant VToolBasePoint::itemChange(QGraphicsItem::GraphicsItemChange change, co { if (QGraphicsView *view = viewList.at(0)) { - view->ensureVisible(this); + const int xmargin = 50; + const int ymargin = 50; + + const QRectF viewRect = VMainGraphicsView::SceneVisibleArea(view); + const QRectF itemRect = mapToScene(boundingRect()).boundingRect(); + + // If item's rect is bigger than view's rect ensureVisible works very unstable. + if (itemRect.height() + 2*ymargin < viewRect.height() && + itemRect.width() + 2*xmargin < viewRect.width()) + { + view->ensureVisible(itemRect, xmargin, ymargin); + } + else + { + // Ensure visible only small rect around a cursor + VMainGraphicsScene *currentScene = qobject_cast(scene()); + SCASSERT(currentScene); + const QPointF cursorPosition = currentScene->getScenePos(); + view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10)); + } } } changeFinished = true; diff --git a/src/libs/vtools/tools/vtooldetail.cpp b/src/libs/vtools/tools/vtooldetail.cpp index bf45dee5c..cb9509464 100644 --- a/src/libs/vtools/tools/vtooldetail.cpp +++ b/src/libs/vtools/tools/vtooldetail.cpp @@ -31,6 +31,7 @@ #include "../vgeometry/varc.h" #include "../vgeometry/vsplinepath.h" #include "../vwidgets/vmaingraphicsscene.h" +#include "../vwidgets/vmaingraphicsview.h" #include "../dialogs/tools/dialogtool.h" #include "../dialogs/tools/dialogdetail.h" #include "../undocommands/savedetailoptions.h" @@ -348,31 +349,50 @@ QVariant VToolDetail::itemChange(QGraphicsItem::GraphicsItemChange change, const { if (change == ItemPositionChange && scene()) { - // Each time we move something we call recalculation scene rect. In some cases this can cause moving - // objects positions. And this cause infinite redrawing. That's why we wait the finish of saving the last move. - static bool changeFinished = true; - if (changeFinished) - { - changeFinished = false; + // Each time we move something we call recalculation scene rect. In some cases this can cause moving + // objects positions. And this cause infinite redrawing. That's why we wait the finish of saving the last move. + static bool changeFinished = true; + if (changeFinished) + { + changeFinished = false; - // value - this is new position. - const QPointF newPos = value.toPointF(); + // value - this is new position. + const QPointF newPos = value.toPointF(); - MoveDetail *moveDet = new MoveDetail(doc, newPos.x(), newPos.y(), id, scene()); - connect(moveDet, &MoveDetail::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree); - qApp->getUndoStack()->push(moveDet); + MoveDetail *moveDet = new MoveDetail(doc, newPos.x(), newPos.y(), id, scene()); + connect(moveDet, &MoveDetail::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree); + qApp->getUndoStack()->push(moveDet); - const QList viewList = scene()->views(); - if (not viewList.isEmpty()) - { - if (QGraphicsView *view = viewList.at(0)) + const QList viewList = scene()->views(); + if (not viewList.isEmpty()) { - view->ensureVisible(mapToScene(boundingRect()|childrenBoundingRect()).boundingRect()); + if (QGraphicsView *view = viewList.at(0)) + { + const int xmargin = 50; + const int ymargin = 50; + + const QRectF viewRect = VMainGraphicsView::SceneVisibleArea(view); + const QRectF itemRect = mapToScene(boundingRect()|childrenBoundingRect()).boundingRect(); + + // If item's rect is bigger than view's rect ensureVisible works very unstable. + if (itemRect.height() + 2*ymargin < viewRect.height() && + itemRect.width() + 2*xmargin < viewRect.width()) + { + view->ensureVisible(itemRect, xmargin, ymargin); + } + else + { + // Ensure visible only small rect around a cursor + VMainGraphicsScene *currentScene = qobject_cast(scene()); + SCASSERT(currentScene); + const QPointF cursorPosition = currentScene->getScenePos(); + view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10)); + } + } } - } - // Don't forget to update geometry, because first change never call full parse - RefreshGeometry(); - changeFinished = true; + // Don't forget to update geometry, because first change never call full parse + RefreshGeometry(); + changeFinished = true; } } diff --git a/src/libs/vwidgets/vcontrolpointspline.cpp b/src/libs/vwidgets/vcontrolpointspline.cpp index 0540cb3a8..1047608e9 100644 --- a/src/libs/vwidgets/vcontrolpointspline.cpp +++ b/src/libs/vwidgets/vcontrolpointspline.cpp @@ -33,6 +33,9 @@ #include #include +#include "vmaingraphicsview.h" +#include "vmaingraphicsscene.h" + //--------------------------------------------------------------------------------------------------------------------- /** * @brief VControlPointSpline constructor. @@ -137,7 +140,26 @@ QVariant VControlPointSpline::itemChange(QGraphicsItem::GraphicsItemChange chang { if (QGraphicsView *view = viewList.at(0)) { - view->ensureVisible(this); + const int xmargin = 50; + const int ymargin = 50; + + const QRectF viewRect = VMainGraphicsView::SceneVisibleArea(view); + const QRectF itemRect = mapToScene(boundingRect()).boundingRect(); + + // If item's rect is bigger than view's rect ensureVisible works very unstable. + if (itemRect.height() + 2*ymargin < viewRect.height() && + itemRect.width() + 2*xmargin < viewRect.width()) + { + view->ensureVisible(itemRect, xmargin, ymargin); + } + else + { + // Ensure visible only small rect around a cursor + VMainGraphicsScene *currentScene = qobject_cast(scene()); + SCASSERT(currentScene); + const QPointF cursorPosition = currentScene->getScenePos(); + view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10)); + } } } } diff --git a/src/libs/vwidgets/vgraphicssimpletextitem.cpp b/src/libs/vwidgets/vgraphicssimpletextitem.cpp index 2ff37a5ec..5a92bac76 100644 --- a/src/libs/vwidgets/vgraphicssimpletextitem.cpp +++ b/src/libs/vwidgets/vgraphicssimpletextitem.cpp @@ -36,6 +36,9 @@ #include #include +#include "vmaingraphicsscene.h" +#include "vmaingraphicsview.h" + //--------------------------------------------------------------------------------------------------------------------- /** * @brief VGraphicsSimpleTextItem default constructor. @@ -131,7 +134,26 @@ QVariant VGraphicsSimpleTextItem::itemChange(GraphicsItemChange change, const QV { if (QGraphicsView *view = viewList.at(0)) { - view->ensureVisible(this); + const int xmargin = 50; + const int ymargin = 50; + + const QRectF viewRect = VMainGraphicsView::SceneVisibleArea(view); + const QRectF itemRect = mapToScene(boundingRect()).boundingRect(); + + // If item's rect is bigger than view's rect ensureVisible works very unstable. + if (itemRect.height() + 2*ymargin < viewRect.height() && + itemRect.width() + 2*xmargin < viewRect.width()) + { + view->ensureVisible(itemRect, xmargin, ymargin); + } + else + { + // Ensure visible only small rect around a cursor + VMainGraphicsScene *currentScene = qobject_cast(scene()); + SCASSERT(currentScene); + const QPointF cursorPosition = currentScene->getScenePos(); + view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10)); + } } } } diff --git a/src/libs/vwidgets/vmaingraphicsview.cpp b/src/libs/vwidgets/vmaingraphicsview.cpp index b889dc853..ef3ec0edd 100644 --- a/src/libs/vwidgets/vmaingraphicsview.cpp +++ b/src/libs/vwidgets/vmaingraphicsview.cpp @@ -358,10 +358,7 @@ void VMainGraphicsView::NewSceneRect(QGraphicsScene *sc, QGraphicsView *view) SCASSERT(view != nullptr); //Calculate view rect - //to receive the currently visible area, map the widgets bounds to the scene - const QPointF a = view->mapToScene(0, 0); - const QPointF b = view->mapToScene(view->width(), view->height()); - const QRectF viewRect = QRectF( a, b ); + const QRectF viewRect = SceneVisibleArea(view); //Calculate scene rect VMainGraphicsScene *currentScene = qobject_cast(sc); @@ -371,3 +368,11 @@ void VMainGraphicsView::NewSceneRect(QGraphicsScene *sc, QGraphicsView *view) //Unite two rects sc->setSceneRect(itemsRect.united(viewRect)); } + +//--------------------------------------------------------------------------------------------------------------------- +QRectF VMainGraphicsView::SceneVisibleArea(QGraphicsView *view) +{ + SCASSERT(view != nullptr); + //to receive the currently visible area, map the widgets bounds to the scene + return QRectF(view->mapToScene(0, 0), view->mapToScene(view->width(), view->height())); +} diff --git a/src/libs/vwidgets/vmaingraphicsview.h b/src/libs/vwidgets/vmaingraphicsview.h index aab80ee67..f73883be9 100644 --- a/src/libs/vwidgets/vmaingraphicsview.h +++ b/src/libs/vwidgets/vmaingraphicsview.h @@ -101,6 +101,7 @@ public: void setShowToolOptions(bool value); static void NewSceneRect(QGraphicsScene *sc, QGraphicsView *view); + static QRectF SceneVisibleArea(QGraphicsView *view); signals: /**