PDA

View Full Version : undo question with removeItem



mooreaa
13th July 2008, 11:14
Hello,

I am looking at the undo stack example and see that they implement undo on delete by saving the pointer to the object passed to the scene->removeItem( object )

In this case, obviously the destructor of the object isn't called.

WHEN is the destructor actually called?

Is there some hidden auto pointer or some kind of smart garbage collection? Or have I been neglecting the clean up process of all my QGraphicsItems?

In several places I've been calling removeItem() expecting them to be removed from the scene forever. Do I need to call delete on those objects manually?

caduel
13th July 2008, 13:02
In that example, the 'deletion' does not (really) delete.
It just 'moves' the QGraphicsItem from the scene to the Command.
That way, it is no longer visible, but the command can reinsert it for a redo.

Think of it like the deleting of files on KDE or windows: Hitting Delete usually does not really delete, but only move the files into the trashcan folder. It's about the same think that happens here.

It is possible to actually delete the item. But then you have to implement a different way of restoring it in case of a redo.
(E.g you could implement a method 'serialize' and 'unserialize' in your items that save the relevant data to a QByteArray.)

HTH

wysota
13th July 2008, 14:12
The item gets deleted when the command holding it gets deleted (because it is no longer needed or it is too deep in the stack).

mooreaa
14th July 2008, 01:01
Thank you, that makes sense. Though I am curious what is the mechenism used to determine if its the last instance of an object? Are these objects interally reference counted?

wysota
14th July 2008, 07:53
What objects are we talking about?

hayzel
22nd December 2014, 18:58
Digging out a very old thread, but I have exactly the same question with the original poster.
I have an application with QGraphicsScene/QGraphicsView model and use QUndoCommand extensively, for items in my scene.
I followed the UndoFramework example and used the myscene->removeItem/addItem procedures.
For example in a polygon item I have:


void saDeleteConcretePolygonCommand::undo()
{
m_scene->addItem(m_item);
}

void saDeleteConcretePolygonCommand::redo()
{
m_scene->removeItem(m_item);
}


m_item is a local pointer to the item manipulated. In Qt documentation is specifically says that when you use QGraphicsScene::removeItem, it is the responsibility of the caller to delete the m_item afterwards.
So what I am missing? When the m_item is destroyed or it stays in memory as leak?

Thank you in advnace

wysota
22nd December 2014, 19:06
You should destroy the item in the destructor of your command.

hayzel
22nd December 2014, 19:10
You should destroy the item in the destructor of your command.

So the Qt UndoFramework example is incomplete.

And how should I know in my destructor of QUndoCommand that the item is not already destroyed from my scene? Or just the command "delete m_item;" suffices?

d_stranz
22nd December 2014, 20:52
If the undo command goes out of scope while the item remains in the scene, then you can't delete the item in the undo command's destructor. If it doesn't cause a crash, it will almost certainly result in the object being removed from the scene. This scenario will occur if the undo action has been executed. So you probably need a flag that tells you whether or not you should delete the instance when the undo command destructor runs.

wysota
22nd December 2014, 22:42
So the Qt UndoFramework example is incomplete.
Why so?


And how should I know in my destructor of QUndoCommand that the item is not already destroyed from my scene?
Items don't destroy themselves "just like that". Unless you clear the scene (which implicitly deletes all the items in it) the item will remain alive.


Or just the command "delete m_item;" suffices?
No, you have to delete the item if the command is in a state where it makes sense that the item is deleted, e.g. if you have a "remove" command, you can delete the item if the command was not undone. For an "add" command that would be exactly the opposite way (delete the item if the last action executed on it was "undo"). For a "resize" command you would not delete the item at all (the item is valid after a redo as well as an undo) as the command does not "own" the item.