Debugging this a little bit further (I like tricky bugs) shows a number of surprising facts.
1) One undo step sometimes calls Segment::notifyRemove more than once. This is because BasicCommand::unexecute() calls copyFrom() which does m_segment->erase(m_segment->findTime(m_modifiedEventsStart), m_segment->findTime(m_modifiedEventsEnd)); As the comment in BasicCommand.cpp:302 says, surely this copyFrom() should be done without firing notifications? Note however that this isn't the actual problem. It's just rather confusing while debugging ;) But even if MatrixScene::handleEventRemoved() is called multiple times, the update() in there has no effect after the first call. The first call sets d->updateAll to true (in QGraphicsScene), the following calls return immediately because updateAll is true. It gets set to false whenever actual drawing happens (QGraphicsScene::drawItems, called by QGraphicsView::paintEvent). 2) While debugging deep within Qt, I found out that the "dirty" region of the graphicsview's viewport is only 4 pixels wide, because Panned::showPositionPointer calls viewport()->update(oldRect) which is a 4 pixels wide rectangle. Normally the graphicsview is repainted via the scene's update() mechanism (which stores a dirtyRegion in QGraphicsView itself). I think the heart of the bug is a collision between the two update mechanisms. The scene thinks it's going to trigger a repaint of the whole view, but the view has stored only a tiny update region. I think it can be fixed by using scene()->update() instead. Patch attached, please test (I have of course reverted the commit that removes the update() call from MatrixScene::handleEventRemoved). But this makes me wonder, why is the "pointer" drawn in drawForeground, after these complex manual updates, instead of making the pointer a graphics item and letting QGraphicsScene/QGraphicsView take care of updating correctly for that item? -- David Faure, fa...@kde.org, http://www.davidfaure.fr Working on KDE Frameworks 5
diff --git c/src/gui/widgets/Panned.cpp i/src/gui/widgets/Panned.cpp index 9ade8f1c2..c9ee21904 100644 --- c/src/gui/widgets/Panned.cpp +++ i/src/gui/widgets/Panned.cpp @@ -152,21 +152,19 @@ void Panned::showPositionPointer(float x) // scene coord; full height { if (m_pointerVisible) { - QRect oldRect = QRect(mapFromScene(m_pointerTop), - QSize(4, viewport()->height())); + QRectF oldRect(m_pointerTop, QSizeF(4, height())); oldRect.moveTop(0); oldRect.moveLeft(oldRect.left() - 1); - viewport()->update(oldRect); + scene()->update(oldRect); // RG_DEBUG << "Panned::slotShowPositionPointer: old rect " << oldRect; } m_pointerVisible = true; m_pointerTop = QPointF(x, 0); m_pointerHeight = 0; - QRect newRect = QRect(mapFromScene(m_pointerTop), - QSize(4, viewport()->height())); + QRectF newRect(m_pointerTop, QSizeF(4, height())); newRect.moveTop(0); newRect.moveLeft(newRect.left() - 1); - viewport()->update(newRect); + scene()->update(newRect); // RG_DEBUG << "Panned::slotShowPositionPointer: new rect " << newRect; } @@ -176,7 +174,7 @@ Panned::showPositionPointer(QPointF top, float height) // scene coords m_pointerVisible = true; m_pointerTop = top; m_pointerHeight = height; - viewport()->update(); //!!! should update old and new pointer areas only, as in the previous function + scene()->update(); //!!! should update old and new pointer areas only, as in the previous function } void @@ -290,7 +288,7 @@ void Panned::hidePositionPointer() { m_pointerVisible = false; - viewport()->update(); //!!! should update old pointer area only, really + scene()->update(); //!!! should update old pointer area only, really } void
_______________________________________________ Rosegarden-devel mailing list Rosegarden-devel@lists.sourceforge.net - use the link below to unsubscribe https://lists.sourceforge.net/lists/listinfo/rosegarden-devel