Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt: Properly integrating undo framework with QGraphicsScene

I'm writing a Qt app that is based around a QGraphicsScene canvas with movable shapes on it, and I'm trying to integrate undo-redo functionality. For most functions like creation and deletion of shapes it's fairly trivial to implement on the QGraphicsScene itself, but I want elements to be movable and for the movement to be undoable. Right now I'm using the rubber band dragmode on the scene and the ItemIsSelectable and ItemIsMovable flags on the items. The problem is that there seems to be no good place to create the QUndoCommand to represent shape movement. If I do it within the QGraphicsScene::itemChange method, then selecting and moving two or more shapes results in separate undo commands for different objects being interleaved and thus are not able to be merged, so undoing results in unexpected behaviour. There's no event in the QGraphicsScene that gets called when its items are moved around that I can see, so I'm kind of stuck.

The worst case scenario that I see is that I disable the ItemIsMovable flag on my custom QGraphicsItem objects and handle movement entirely in the QGraphicsScene mouse events, but reimplementing that functionality properly seems quite complicated (I checked how Qt does it internally and there is quite a lot of code for handling complicated cases, such as where an object and some of its children are both selected). This seems like the most obvious of use cases for the undo stack (so much so that the example program for the undo framework is a QGraphicsScene program much like mine, except without multiple object movement support) so it seems weird that there's no built-in way to do it without reimplementing a significant part of the core functionality. Does anyone have any insights or examples of programs that do this?

like image 808
Simon Broadhead Avatar asked Jan 31 '13 16:01

Simon Broadhead


1 Answers

I solved this somewhat hackishly I think. I added a preMovePoint property to my custom shapes and in the mousePressedEvent of the QGraphicsScene, I set the preMovePoint of each of the selected shapes to their respective current positions, and in mouseReleaseEvent, created a composite move command from the preMovePoint to the current pos of each shape. I would still be interested in knowing if there's a better way.

like image 85
Simon Broadhead Avatar answered Oct 31 '22 01:10

Simon Broadhead