PDA

View Full Version : How to get a return value from QUndoCommand::redo?



wayfaerer
8th March 2012, 01:08
I'm using a custom QGraphicsScene in which you can click to create a custom QGraphicsItem, then drag (with the mouse still held down) to resize it. To do this, overrode QGraphicsItem::mousePressEvent and mouseMoveEvent, and it worked fine. It was something like this:


MyScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
itemBeingCreated = new MyItem(event->pos()) // "itemBeingCreated" is declared in myscene.h
}

MyScene::mouseMoveEvent(QGraphicsMouseEvent *event)
{
itemBeingCreated->resize(/* etc */) // basically how far you drag it from its origin, that's how big it'll be
}

Now I am trying to add undo/redo capability with QUndoStack and QUndoCommand. So now my mousePressEvent does this


MyScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
undoStack->push(new AddNewItem(/* etc */)); // "AddNewItem" is a QUndoCommand
}

But I don't understand how I can access the item created by "AddNewItem" in order to resize it in MyScene::onMouseMove. Should I just implement a "QGraphicsItem *AddNewItem::getCreatedItem()", or will that "break" the command pattern and lead to problems?

ChrisW67
8th March 2012, 01:35
Why did you discard the code you already had that kept track of the pointer to the new item?

Personally though, I'd wait until the mouse release event to determine:

That the added item is big enough to be worth adding. This avoids accidental short click-drag-release creating hard to see/use items.
That the user has not cancelled the creation, e.g. by pressing escape, if you allow that during the create event.
And the final size of the added item is known.

wayfaerer
8th March 2012, 02:31
I should have clarified that AddNewItem both creates the item (and pointer) and adds it to the scene. Thus, the code that kept track of the pointer is now inside of AddNewItem::redo(). Of course, the pointer is useless there, and goes out of scope after AddNewItem::redo().

Are you suggesting that I should create a null pointer to the item and pass it to AddNewItem's constructor, and have AddNewItem::redo() create the item and assign it to the previously null pointer?

ChrisW67
8th March 2012, 03:36
No, create the item and keep the pointer. Construct the AddNewItem object with the pointer, i.e. give AddNewItem's constructor and argument, and add it to the stack.

Edit: Ignore that. I see where you are going.

Consider moving the item creation to the end of the user's creation click-n-drag and then you don't have the issue.

wayfaerer
8th March 2012, 04:19
Thanks, I understand now.

I had a closer look at the Undo Framework example, and their AddCommand's redo and undo methods just added/removed the item from the scene, whereas in my case, redo and undo actually created and deleted the item (AddNewItem's constructor stored all of the necessary info to re-create the item after it was deleted). So I'll do what you suggested, and change the redo and undo functions.