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, [email protected], 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
[email protected] - use the link below to unsubscribe
https://lists.sourceforge.net/lists/listinfo/rosegarden-devel