From f6693f4e854d52637388d1e89511afef184d9e6f Mon Sep 17 00:00:00 2001 From: Ilia Ryabokon Date: Fri, 7 Sep 2012 19:36:50 +0300 Subject: [PATCH] Undo-redo stack for eraising operations and Sankore 834 --- src/adaptors/UBSvgSubsetAdaptor.cpp | 2 +- src/domain/UBGraphicsGroupContainerItem.cpp | 6 +- src/domain/UBGraphicsGroupContainerItem.h | 2 +- src/domain/UBGraphicsItemGroupUndoCommand.cpp | 4 +- src/domain/UBGraphicsItemUndoCommand.cpp | 66 ++++++++++++++++++- src/domain/UBGraphicsItemUndoCommand.h | 4 +- src/domain/UBGraphicsScene.cpp | 15 +++-- src/domain/UBGraphicsScene.h | 2 +- src/domain/UBItem.cpp | 6 ++ src/domain/UBItem.h | 1 + 10 files changed, 93 insertions(+), 15 deletions(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index f557ff8a..80f91e9d 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -1084,7 +1084,7 @@ QGraphicsItem *UBSvgSubsetAdaptor::UBSvgSubsetReader::readElementFromGroup() { QGraphicsItem *result = 0; - result = mScene->itemByUuid(QUuid(mXmlReader.attributes().value(aId).toString())); + result = mScene->itemForUuid(QUuid(mXmlReader.attributes().value(aId).toString())); mXmlReader.skipCurrentElement(); mXmlReader.readNext(); diff --git a/src/domain/UBGraphicsGroupContainerItem.cpp b/src/domain/UBGraphicsGroupContainerItem.cpp index 818eb88e..07b71ab3 100644 --- a/src/domain/UBGraphicsGroupContainerItem.cpp +++ b/src/domain/UBGraphicsGroupContainerItem.cpp @@ -125,6 +125,8 @@ void UBGraphicsGroupContainerItem::removeFromGroup(QGraphicsItem *item) pRemoveFromGroup(item); + item->setFlags(ItemIsSelectable | ItemIsFocusable); + } void UBGraphicsGroupContainerItem::deselectCurrentItem() @@ -219,7 +221,7 @@ void UBGraphicsGroupContainerItem::setUuid(const QUuid &pUuid) setData(UBGraphicsItemData::ItemUuid, QVariant(pUuid)); //store item uuid inside the QGraphicsItem to fast operations with Items on the scene } -void UBGraphicsGroupContainerItem::destroy() { +void UBGraphicsGroupContainerItem::destroy(bool canUndo) { foreach (QGraphicsItem *item, childItems()) { pRemoveFromGroup(item); @@ -227,7 +229,7 @@ void UBGraphicsGroupContainerItem::destroy() { item->setFlag(QGraphicsItem::ItemIsFocusable, true); } - remove(); + mDelegate->remove(canUndo); } void UBGraphicsGroupContainerItem::clearSource() diff --git a/src/domain/UBGraphicsGroupContainerItem.h b/src/domain/UBGraphicsGroupContainerItem.h index e8fa77eb..7207315d 100644 --- a/src/domain/UBGraphicsGroupContainerItem.h +++ b/src/domain/UBGraphicsGroupContainerItem.h @@ -37,7 +37,7 @@ public: } virtual void setUuid(const QUuid &pUuid); - void destroy(); + void destroy(bool canUndo = true); virtual void clearSource(); diff --git a/src/domain/UBGraphicsItemGroupUndoCommand.cpp b/src/domain/UBGraphicsItemGroupUndoCommand.cpp index 9b58dc1d..d087216f 100644 --- a/src/domain/UBGraphicsItemGroupUndoCommand.cpp +++ b/src/domain/UBGraphicsItemGroupUndoCommand.cpp @@ -22,7 +22,7 @@ UBGraphicsItemGroupUndoCommand::~UBGraphicsItemGroupUndoCommand() void UBGraphicsItemGroupUndoCommand::undo() { - mGroup->destroy(); + mGroup->destroy(false); foreach(QGraphicsItem *item, mItems) { item->setSelected(true); } @@ -41,7 +41,7 @@ void UBGraphicsItemGroupUndoCommand::redo() QList childItems = item->childItems(); UBGraphicsGroupContainerItem *currentGroup = dynamic_cast(item); if (currentGroup) { - currentGroup->destroy(); + currentGroup->destroy(false); } foreach (QGraphicsItem *chItem, childItems) { mGroup->addToGroup(chItem); diff --git a/src/domain/UBGraphicsItemUndoCommand.cpp b/src/domain/UBGraphicsItemUndoCommand.cpp index d9961fa0..64ea6091 100644 --- a/src/domain/UBGraphicsItemUndoCommand.cpp +++ b/src/domain/UBGraphicsItemUndoCommand.cpp @@ -27,10 +27,11 @@ #include "domain/UBGraphicsGroupContainerItem.h" UBGraphicsItemUndoCommand::UBGraphicsItemUndoCommand(UBGraphicsScene* pScene, const QSet& pRemovedItems, - const QSet& pAddedItems) + const QSet& pAddedItems, const QMultiMap &groupsMap) : mScene(pScene) - , mRemovedItems(pRemovedItems - pAddedItems) - , mAddedItems(pAddedItems - pRemovedItems) + , mRemovedItems(pRemovedItems - pAddedItems) + , mAddedItems(pAddedItems - pRemovedItems) + , mExcludedFromGroup(groupsMap) { mFirstRedo = true; @@ -110,6 +111,36 @@ void UBGraphicsItemUndoCommand::undo() } } + QMapIterator curMapElement(mExcludedFromGroup); + UBGraphicsGroupContainerItem *nextGroup = 0; + UBGraphicsGroupContainerItem *previousGroupItem; + bool groupChanged = false; + + while (curMapElement.hasNext()) { + curMapElement.next(); + + groupChanged = previousGroupItem != curMapElement.key(); + //trying to find the group on the scene; + if (!nextGroup || groupChanged) { + UBGraphicsGroupContainerItem *groupCandidate = curMapElement.key(); + if (groupCandidate) { + nextGroup = groupCandidate; + if(!mScene->items().contains(nextGroup)) { + mScene->addItem(nextGroup); + } + nextGroup->setVisible(true); + } + } + + QGraphicsItem *groupedItem = mScene->itemForUuid(curMapElement.value()); + if (groupedItem) { + nextGroup->addToGroup(groupedItem); + } + + previousGroupItem = curMapElement.key(); + UBGraphicsItem::Delegate(nextGroup)->update(); + } + // force refresh, QT is a bit lazy and take a lot of time (nb item ^2 ?) to trigger repaint mScene->update(mScene->sceneRect()); @@ -125,6 +156,35 @@ void UBGraphicsItemUndoCommand::redo() return; } + QMapIterator curMapElement(mExcludedFromGroup); + UBGraphicsGroupContainerItem *nextGroup = 0; + UBGraphicsGroupContainerItem *previousGroupItem; + bool groupChanged = false; + + while (curMapElement.hasNext()) { + curMapElement.next(); + + groupChanged = previousGroupItem != curMapElement.key(); + //trying to find the group on the scene; + if (!nextGroup || groupChanged) { + UBGraphicsGroupContainerItem *groupCandidate = curMapElement.key(); + if (groupCandidate) { + nextGroup = groupCandidate; + } + } + QGraphicsItem *groupedItem = mScene->itemForUuid(curMapElement.value()); + if (groupedItem) { + if (nextGroup->childItems().count() == 1) { + nextGroup->destroy(false); + break; + } + nextGroup->removeFromGroup(groupedItem); + } + + previousGroupItem = curMapElement.key(); + UBGraphicsItem::Delegate(nextGroup)->update(); + } + QSetIterator itRemoved(mRemovedItems); while (itRemoved.hasNext()) { diff --git a/src/domain/UBGraphicsItemUndoCommand.h b/src/domain/UBGraphicsItemUndoCommand.h index 78e7ec9a..be8fa9d4 100644 --- a/src/domain/UBGraphicsItemUndoCommand.h +++ b/src/domain/UBGraphicsItemUndoCommand.h @@ -18,6 +18,7 @@ #include #include "UBAbstractUndoCommand.h" +#include "UBGraphicsGroupContainerItem.h" class UBGraphicsScene; @@ -27,7 +28,7 @@ class UBGraphicsItemUndoCommand : public UBAbstractUndoCommand { public: UBGraphicsItemUndoCommand(UBGraphicsScene* pScene, const QSet& pRemovedItems, - const QSet& pAddedItems); + const QSet& pAddedItems, const QMultiMap &groupsMap = QMultiMap()); UBGraphicsItemUndoCommand(UBGraphicsScene* pScene, QGraphicsItem* pRemovedItem, QGraphicsItem* pAddedItem); @@ -47,6 +48,7 @@ class UBGraphicsItemUndoCommand : public UBAbstractUndoCommand UBGraphicsScene* mScene; QSet mRemovedItems; QSet mAddedItems; + QMultiMap mExcludedFromGroup; bool mFirstRedo; }; diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 0cdb2ae6..ecbcc424 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -1067,6 +1067,7 @@ UBItem* UBGraphicsScene::deepCopy() const void UBGraphicsScene::clearContent(clearCase pCase) { QSet removedItems; + QMultiMap groupsMap; switch (pCase) { case clearBackground : @@ -1106,8 +1107,13 @@ void UBGraphicsScene::clearContent(clearCase pCase) if(shouldDelete) { if (itemGroup) { itemGroup->removeFromGroup(item); + groupsMap.insert(itemGroup, UBGraphicsItem::getOwnUuid(item)); if (itemGroup->childItems().count() == 1) { - itemGroup->destroy(); + groupsMap.insert(itemGroup, UBGraphicsItem::getOwnUuid(itemGroup->childItems().first())); + QGraphicsItem *lastItem = itemGroup->childItems().first(); + bool isSelected = itemGroup->isSelected(); + itemGroup->destroy(false); + lastItem->setSelected(isSelected); } itemGroup->Delegate()->update(); } @@ -1123,7 +1129,7 @@ void UBGraphicsScene::clearContent(clearCase pCase) update(sceneRect()); if (enableUndoRedoStack) { //should be deleted after scene own undo stack implemented - UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, removedItems, QSet()); + UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, removedItems, QSet(), groupsMap); UBApplication::undoStack->push(uc); } @@ -1571,8 +1577,9 @@ void UBGraphicsScene::removeItem(QGraphicsItem* item) void UBGraphicsScene::removeItems(const QSet& items) { - foreach(QGraphicsItem* item, items) + foreach(QGraphicsItem* item, items) { UBCoreGraphicsScene::removeItem(item); + } mItemCount -= items.size(); @@ -1665,7 +1672,7 @@ QRectF UBGraphicsScene::normalizedSceneRect(qreal ratio) return normalizedRect; } -QGraphicsItem *UBGraphicsScene::itemByUuid(QUuid uuid) +QGraphicsItem *UBGraphicsScene::itemForUuid(QUuid uuid) { QGraphicsItem *result = 0; diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 0dedb9c1..3722d8be 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -174,7 +174,7 @@ class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem QRectF normalizedSceneRect(qreal ratio = -1.0); - QGraphicsItem *itemByUuid(QUuid uuid); + QGraphicsItem *itemForUuid(QUuid uuid); void moveTo(const QPointF& pPoint); void drawLineTo(const QPointF& pEndPoint, const qreal& pWidth, bool bLineStyle); diff --git a/src/domain/UBItem.cpp b/src/domain/UBItem.cpp index 10d3d6ce..e7083338 100644 --- a/src/domain/UBItem.cpp +++ b/src/domain/UBItem.cpp @@ -54,6 +54,12 @@ bool UBGraphicsItem::isRotatable(QGraphicsItem *item) return item->data(UBGraphicsItemData::ItemRotatable).toBool(); } +QUuid UBGraphicsItem::getOwnUuid(QGraphicsItem *item) +{ + QString idCandidate = item->data(UBGraphicsItemData::ItemUuid).toString(); + return idCandidate == QUuid().toString() ? QUuid() : QUuid(idCandidate); +} + UBGraphicsItemDelegate *UBGraphicsItem::Delegate(QGraphicsItem *pItem) { UBGraphicsItemDelegate *result = 0; diff --git a/src/domain/UBItem.h b/src/domain/UBItem.h index ca8a0f3b..2fe22ae8 100644 --- a/src/domain/UBItem.h +++ b/src/domain/UBItem.h @@ -107,6 +107,7 @@ public: static void assignZValue(QGraphicsItem*, qreal value); static bool isRotatable(QGraphicsItem *item); static bool isFlippable(QGraphicsItem *item); + static QUuid getOwnUuid(QGraphicsItem *item); static UBGraphicsItemDelegate *Delegate(QGraphicsItem *pItem); virtual UBGraphicsItemDelegate *Delegate() const = 0;