Reimplemented array resizing

This commit is contained in:
Aruki 2018-07-09 06:53:56 -06:00
parent 641cf81dd8
commit a90f1d0441
11 changed files with 320 additions and 328 deletions

View File

@ -199,7 +199,8 @@ HEADERS += \
CGeneratePropertyNamesDialog.h \
CProgressBarNotifier.h \
Widgets/CCheckableTreeWidgetItem.h \
Widgets/CCheckableTreeWidget.h
Widgets/CCheckableTreeWidget.h \
Undo/IEditPropertyCommand.h
# Source Files
SOURCES += \
@ -237,8 +238,6 @@ SOURCES += \
PropertyEdit/CPropertyDelegate.cpp \
PropertyEdit/CPropertyView.cpp \
WorldEditor/CInstancesModel.cpp \
Undo/CEditScriptPropertyCommand.cpp \
Undo/CResizeScriptArrayCommand.cpp \
WorldEditor/WEditorProperties.cpp \
Undo/CChangeLayerCommand.cpp \
WorldEditor/CTemplateEditDialog.cpp \
@ -275,7 +274,8 @@ SOURCES += \
ResourceBrowser/CVirtualDirectoryModel.cpp \
ResourceBrowser/CVirtualDirectoryTreeView.cpp \
CPropertyNameValidator.cpp \
CGeneratePropertyNamesDialog.cpp
CGeneratePropertyNamesDialog.cpp \
Undo/IEditPropertyCommand.cpp
# UI Files
FORMS += \

View File

@ -365,7 +365,7 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
if (Type != EPropertyTypeNew::Array)
{
// TODO: support this for non script object properties
pCommand = new CEditScriptPropertyCommand(mpEditor, mpModel->GetScriptObject(), pProp);
pCommand = new CEditScriptPropertyCommand(mpEditor, rkIndex, mpModel);
pCommand->SaveOldData();
// Handle sub-properties of flags and animation sets
@ -478,18 +478,22 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
// Array
else
{
//FIXME
/*
pCommand = new CResizeScriptArrayCommand(mpEditor, rkIndex, mpModel);
pCommand->SaveOldData();
WIntegralSpinBox* pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
CArrayProperty* pArray = static_cast<CArrayProperty*>(pProp);
int OldCount = pArray->ArrayCount(pData);
int NewCount = pSpinBox->value();
if (pArray->Count() != NewCount)
if (OldCount != NewCount)
{
CResizeScriptArrayCommand *pCmd = new CResizeScriptArrayCommand(pProp, mpEditor, mpModel, NewCount);
mpEditor->UndoStack()->push(pCmd);
mpModel->ArrayAboutToBeResized(rkIndex, NewCount);
pArray->Resize(pData, NewCount);
mpModel->ArrayResized(rkIndex, OldCount);
}
*/
pCommand->SaveNewData();
}
}

View File

@ -13,13 +13,25 @@ CPropertyModel::CPropertyModel(QObject *pParent /*= 0*/)
, mpPropertyData(nullptr)
, mBoldModifiedProperties(true)
, mShowNameValidity(false)
, mFirstUnusedID(-1)
{
}
int CPropertyModel::RecursiveBuildArrays(IPropertyNew* pProperty, int ParentID)
{
int MyID = mProperties.size();
mProperties << SProperty();
// Insert into an unused slot if one exists. Otherwise, append to the end of the array.
int MyID = -1;
if (mFirstUnusedID >= 0)
{
MyID = mFirstUnusedID;
mFirstUnusedID = mProperties[MyID].ParentID; // on unused slots ParentID stores the ID of the next unused slot
}
else
{
MyID = mProperties.size();
mProperties << SProperty();
}
mProperties[MyID].pProperty = pProperty;
mProperties[MyID].ParentID = ParentID;
@ -70,6 +82,7 @@ void CPropertyModel::ConfigureIntrinsic(CGameProject* pProject, IPropertyNew* pR
mProperties.clear();
mPropertyToIDMap.clear();
mFirstUnusedID = -1;
if (pRootProperty)
RecursiveBuildArrays(pRootProperty, -1);
@ -532,37 +545,80 @@ void CPropertyModel::NotifyPropertyModified(const QModelIndex& rkIndex)
void CPropertyModel::ArrayAboutToBeResized(const QModelIndex& rkIndex, u32 NewSize)
{
//FIXME
/*QModelIndex Index = rkIndex.sibling(rkIndex.row(), 0);
CArrayProperty *pArray = static_cast<CArrayProperty*>(PropertyForIndex(Index, false));
QModelIndex Index = rkIndex.sibling(rkIndex.row(), 0);
IPropertyNew* pProperty = PropertyForIndex(Index, false);
CArrayProperty* pArray = TPropCast<CArrayProperty>(pProperty);
ASSERT(pArray);
if (pArray && pArray->Type() == eArrayProperty)
void* pArrayData = DataPointerForIndex(Index);
u32 OldSize = pArray->ArrayCount(pArrayData);
if (NewSize != OldSize)
{
u32 OldSize = pArray->Count();
if (NewSize != OldSize)
{
if (NewSize > OldSize)
beginInsertRows(Index, OldSize, NewSize - 1);
else
beginRemoveRows(Index, NewSize, OldSize - 1);
}
}*/
if (NewSize > OldSize)
beginInsertRows(Index, OldSize, NewSize - 1);
else
beginRemoveRows(Index, NewSize, OldSize - 1);
}
}
void CPropertyModel::ArrayResized(const QModelIndex& rkIndex, u32 OldSize)
{
//FIXME
/*CArrayProperty *pArray = static_cast<CArrayProperty*>(PropertyForIndex(rkIndex, false));
u32 NewSize = pArray->Count();
QModelIndex Index = rkIndex.sibling(rkIndex.row(), 0);
IPropertyNew* pProperty = PropertyForIndex(Index, false);
CArrayProperty* pArray = TPropCast<CArrayProperty>(pProperty);
ASSERT(pArray);
void* pArrayData = DataPointerForIndex(Index);
u32 NewSize = pArray->ArrayCount(pArrayData);
if (NewSize != OldSize)
{
if (pArray->Count() > OldSize)
int ID = Index.internalId();
if (NewSize > OldSize)
{
// add new elements
void* pOldData = mpPropertyData;
for (u32 ElementIdx = OldSize; ElementIdx < NewSize; ElementIdx++)
{
mpPropertyData = pArray->ItemPointer(pArrayData, ElementIdx);
int NewChildID = RecursiveBuildArrays( pArray->ItemArchetype(), ID );
mProperties[ID].ChildIDs.push_back(NewChildID);
}
mpPropertyData = pOldData;
endInsertRows();
}
else
{
// remove old elements
for (u32 ElementIdx = NewSize; ElementIdx < OldSize; ElementIdx++)
{
int ChildID = mProperties[ID].ChildIDs[ElementIdx];
ClearSlot(ChildID);
}
mProperties[ID].ChildIDs.resize(NewSize);
endRemoveRows();
}*/
}
}
}
void CPropertyModel::ClearSlot(int ID)
{
for (int ChildIdx = 0; ChildIdx < mProperties[ID].ChildIDs.size(); ChildIdx++)
{
ClearSlot(mProperties[ID].ChildIDs[ChildIdx]);
}
mProperties[ID].ChildIDs.clear();
mProperties[ID].Index = QModelIndex();
mProperties[ID].ParentID = mFirstUnusedID;
mProperties[ID].pProperty = nullptr;
mFirstUnusedID = ID;
}
void CPropertyModel::SetShowPropertyNameValidity(bool Enable)

View File

@ -18,6 +18,7 @@ class CPropertyModel : public QAbstractItemModel
};
QVector<SProperty> mProperties;
QMap<IPropertyNew*, int> mPropertyToIDMap;
int mFirstUnusedID;
CGameProject* mpProject;
CScriptObject* mpObject; // may be null
@ -49,6 +50,7 @@ public:
void ArrayAboutToBeResized(const QModelIndex& rkIndex, u32 NewSize);
void ArrayResized(const QModelIndex& rkIndex, u32 OldSize);
void ResizeArray(const QModelIndex& rkIndex, u32 NewSize);
void ClearSlot(int ID);
void SetShowPropertyNameValidity(bool Enable);

View File

@ -1,56 +0,0 @@
#include "CEditScriptPropertyCommand.h"
#include "EUndoCommand.h"
/*CEditScriptPropertyCommand::CEditScriptPropertyCommand(IProperty *pProp, CWorldEditor *pEditor, IPropertyValue *pOldValue, bool IsDone, const QString& rkCommandName /*= "Edit Property")
: IUndoCommand(rkCommandName)
, mpProp(pProp)
, mpEditor(pEditor)
, mCommandEnded(IsDone)
{
mpOldValue = pOldValue;
mpNewValue = pProp->RawValue()->Clone();
}
CEditScriptPropertyCommand::~CEditScriptPropertyCommand()
{
delete mpOldValue;
delete mpNewValue;
}
int CEditScriptPropertyCommand::id() const
{
return eEditScriptPropertyCmd;
}
bool CEditScriptPropertyCommand::mergeWith(const QUndoCommand *pkOther)
{
if (!mCommandEnded && pkOther->id() == eEditScriptPropertyCmd)
{
const CEditScriptPropertyCommand *pkCmd = static_cast<const CEditScriptPropertyCommand*>(pkOther);
if (pkCmd->mpProp == mpProp)
{
mpNewValue->Copy(pkCmd->mpNewValue);
mCommandEnded = pkCmd->mCommandEnded;
return true;
}
}
return false;
}
void CEditScriptPropertyCommand::undo()
{
IProperty *pProp = *mpProp;
pProp->RawValue()->Copy(mpOldValue);
mpEditor->OnPropertyModified(pProp);
mCommandEnded = true;
}
void CEditScriptPropertyCommand::redo()
{
IProperty *pProp = *mpProp;
pProp->RawValue()->Copy(mpNewValue);
mpEditor->OnPropertyModified(pProp);
}
*/

View File

@ -1,167 +1,29 @@
#ifndef CEDITSCRIPTPROPERTYCOMMAND_H
#define CEDITSCRIPTPROPERTYCOMMAND_H
#include "IUndoCommand.h"
#include "IEditPropertyCommand.h"
#include "ObjReferences.h"
#include "EUndoCommand.h"
#include "Editor/PropertyEdit/CPropertyModel.h"
#include "Editor/WorldEditor/CWorldEditor.h"
class IEditPropertyCommand : public IUndoCommand
{
std::vector<char> mOldData;
std::vector<char> mNewData;
protected:
IPropertyNew* mpProperty;
bool mCommandEnded;
bool mSavedOldData;
bool mSavedNewData;
/** Save the current state of the object properties to the given data buffer */
void SaveObjectStateToArray(std::vector<char>& rVector)
{
CVectorOutStream MemStream(&rVector, IOUtil::kSystemEndianness);
CBasicBinaryWriter Writer(&MemStream, CSerialVersion(IArchive::skCurrentArchiveVersion, 0, mpProperty->Game()));
std::vector<void*> DataPointers;
GetObjectDataPointers(DataPointers);
for (int PtrIdx = 0; PtrIdx < DataPointers.size(); PtrIdx++)
{
void* pData = DataPointers[PtrIdx];
mpProperty->SerializeValue(pData, Writer);
}
}
/** Restore the state of the object properties from the given data buffer */
void RestoreObjectStateFromArray(std::vector<char>& rArray)
{
CBasicBinaryReader Reader(rArray.data(), rArray.size(), CSerialVersion(IArchive::skCurrentArchiveVersion, 0, mpProperty->Game()));
std::vector<void*> DataPointers;
GetObjectDataPointers(DataPointers);
for (int PtrIdx = 0; PtrIdx < DataPointers.size(); PtrIdx++)
{
void* pData = DataPointers[PtrIdx];
mpProperty->SerializeValue(pData, Reader);
}
}
public:
IEditPropertyCommand(IPropertyNew* pProperty, const QString& rkCommandName = "Edit Property")
: IUndoCommand(rkCommandName)
, mpProperty(pProperty)
, mSavedOldData(false)
, mSavedNewData(false)
{}
void SaveOldData()
{
SaveObjectStateToArray(mOldData);
mSavedOldData = true;
}
void SaveNewData()
{
SaveObjectStateToArray(mNewData);
mSavedNewData = true;
}
bool IsNewDataDifferent()
{
if (mOldData.size() != mNewData.size()) return false;
return memcmp(mOldData.data(), mNewData.data(), mNewData.size()) != 0;
}
void SetEditComplete(bool IsComplete)
{
mCommandEnded = IsComplete;
}
/** Interface */
virtual void GetObjectDataPointers(std::vector<void*>& rOutPointers) const = 0;
/** IUndoCommand/QUndoCommand interface */
int id() const
{
return eEditScriptPropertyCmd;
}
bool mergeWith(const QUndoCommand *pkOther)
{
if (!mCommandEnded)
{
const IEditPropertyCommand* pkCmd = dynamic_cast<const IEditPropertyCommand*>(pkOther);
if (pkCmd && pkCmd->mpProperty == mpProperty)
{
std::vector<void*> MyPointers;
GetObjectDataPointers(MyPointers);
std::vector<void*> TheirPointers;
pkCmd->GetObjectDataPointers(TheirPointers);
if (TheirPointers.size() == MyPointers.size())
{
for (int PtrIdx = 0; PtrIdx < MyPointers.size(); PtrIdx++)
{
if (MyPointers[PtrIdx] != TheirPointers[PtrIdx])
return false;
}
// Match
mNewData = pkCmd->mNewData;
mCommandEnded = pkCmd->mCommandEnded;
return true;
}
}
}
return false;
}
void undo()
{
ASSERT(mSavedOldData && mSavedNewData);
RestoreObjectStateFromArray(mOldData);
mCommandEnded = true;
}
void redo()
{
ASSERT(mSavedOldData && mSavedNewData);
RestoreObjectStateFromArray(mNewData);
}
bool AffectsCleanState() const
{
return true;
}
};
class CEditScriptPropertyCommand : public IEditPropertyCommand
{
std::vector<CInstancePtr> mInstances;
CWorldEditor* mpEditor;
public:
CEditScriptPropertyCommand(CWorldEditor* pEditor, CScriptObject* pInstance, IPropertyNew* pProperty, const QString& rkCommandName = "Edit Property")
: IEditPropertyCommand(pProperty, rkCommandName)
CEditScriptPropertyCommand(CWorldEditor* pEditor, const QModelIndex& rkIndex, CPropertyModel* pInModel, const QString& rkCommandName = "Edit Property")
: IEditPropertyCommand(rkIndex, pInModel, rkCommandName)
, mpEditor(pEditor)
{
mInstances.push_back( CInstancePtr(pInstance) );
mInstances.push_back( CInstancePtr(pInModel->GetScriptObject()) );
}
virtual void GetObjectDataPointers(std::vector<void*>& rOutPointers) const override
{
rOutPointers.resize(mInstances.size());
for (int InstanceIdx = 0; InstanceIdx < mInstances.size(); InstanceIdx++)
{
rOutPointers[InstanceIdx] = mInstances[InstanceIdx]->PropertyData();
}
//@todo support multiple objects
rOutPointers[0] = mpModel->DataPointerForIndex(mIndex);
}
virtual void undo() override

View File

@ -1,72 +0,0 @@
#include "CResizeScriptArrayCommand.h"
/*
CResizeScriptArrayCommand::CResizeScriptArrayCommand(IPropertyNew *pProp, CWorldEditor *pEditor, CPropertyModel *pModel, int NewSize)
: IUndoCommand("Edit Property")
, mpEditor(pEditor)
, mpArray(pProp)
, mpModel(pModel)
, mOldSize(static_cast<CArrayProperty*>(pProp)->Count())
, mNewSize(NewSize)
{
mNewSizeLarger = mNewSize > mOldSize;
if (!mNewSizeLarger)
{
CArrayProperty *pArray = static_cast<CArrayProperty*>(pProp);
for (int iSub = mNewSize; iSub < mOldSize; iSub++)
{
mDeletedProperties << pArray->PropertyByIndex(iSub)->Clone(nullptr);
}
}
}
CResizeScriptArrayCommand::~CResizeScriptArrayCommand()
{
foreach (IPropertyNew *pProp, mDeletedProperties)
delete pProp;
}
void CResizeScriptArrayCommand::undo()
{
if (mNewSize != mOldSize)
{
// Update parents
CArrayProperty *pArray = static_cast<CArrayProperty*>(*mpArray);
foreach (IProperty *pProp, mDeletedProperties)
pProp->SetParent(pArray);
// Resize array
QModelIndex Index = mpModel->IndexForProperty(pArray);
mpModel->ArrayAboutToBeResized(Index, (u32) mOldSize);
pArray->Resize(mOldSize);
if (!mNewSizeLarger)
{
int NumNewElements = mOldSize - mNewSize;
for (int iSub = 0; iSub < NumNewElements; iSub++)
{
u32 Idx = iSub + mNewSize;
pArray->PropertyByIndex(Idx)->Copy(mDeletedProperties[iSub]);
}
}
mpModel->ArrayResized(Index, (u32) mNewSize);
}
}
void CResizeScriptArrayCommand::redo()
{
// Whether we're increasing or decreasing in size, there's no need to restore deleted properties on redo.
if (mNewSize != mOldSize)
{
CArrayProperty *pArray = static_cast<CArrayProperty*>(*mpArray);
QModelIndex Index = mpModel->IndexForProperty(pArray);
mpModel->ArrayAboutToBeResized(Index, (u32) mNewSize);
pArray->Resize(mNewSize);
mpModel->ArrayResized(Index, (u32) mOldSize);
}
}
*/

View File

@ -1,31 +1,50 @@
#ifndef CRESIZESCRIPTARRAYCOMMAND_H
#define CRESIZESCRIPTARRAYCOMMAND_H
#include "IUndoCommand.h"
#include "ObjReferences.h"
#include "Editor/PropertyEdit/CPropertyModel.h"
#include "Editor/WorldEditor/CWorldEditor.h"
#include <QUndoCommand>
#include "CEditScriptPropertyCommand.h"
// todo: make this more general... it shouldn't be relying on a CPropertyModel pointer
//FIXME
/*class CResizeScriptArrayCommand : public IUndoCommand
class CResizeScriptArrayCommand : public CEditScriptPropertyCommand
{
CWorldEditor* mpEditor;
IPropertyNew* mpArray;
QVector<IPropertyNew*> mDeletedProperties;
CPropertyModel *mpModel;
int mOldSize;
int mNewSize;
bool mNewSizeLarger;
public:
CResizeScriptArrayCommand(IPropertyNew *pProp, CWorldEditor *pEditor, CPropertyModel *pModel, int NewSize);
~CResizeScriptArrayCommand();
void undo();
void redo();
bool AffectsCleanState() const { return true; }
};*/
CResizeScriptArrayCommand(CWorldEditor* pEditor, const QModelIndex& rkIndex, CPropertyModel* pInModel, const QString& rkCommandName = "Resize Array")
: CEditScriptPropertyCommand(pEditor, rkIndex, pInModel, rkCommandName)
{}
bool mergeWith(const QUndoCommand *pkOther)
{
return false;
}
// Note in some cases undo/redo may be called when the change has already been applied outside of the undo command
// This is why we need to check the array's actual current size instead of assuming it will match one of the arrays
void undo()
{
// unpleasant cast, but easiest/fastest way to access the sizes
int NewSize = *((int*)mOldData.data());
int OldSize = CurrentArrayCount();
mpModel->ArrayAboutToBeResized(mIndex, NewSize);
CEditScriptPropertyCommand::undo();
mpModel->ArrayResized(mIndex, OldSize);
}
void redo()
{
// unpleasant cast, but easiest/fastest way to access the sizes
int NewSize = *((int*)mNewData.data());
int OldSize = CurrentArrayCount();
mpModel->ArrayAboutToBeResized(mIndex, NewSize);
CEditScriptPropertyCommand::redo();
mpModel->ArrayResized(mIndex, OldSize);
}
int CurrentArrayCount()
{
void* pData = mpModel->DataPointerForIndex(mIndex);
CArrayProperty* pArray = TPropCast<CArrayProperty>(mpProperty);
return pArray->ArrayCount(pData);
}
};
#endif // CRESIZESCRIPTARRAYCOMMAND_H

View File

@ -8,7 +8,7 @@ enum EUndoCommand
eTranslateNodeCmd,
eRotateNodeCmd,
eScaleNodeCmd,
eEditScriptPropertyCmd
eEditPropertyCmd
};
#endif // EUNDOCOMMAND

View File

@ -0,0 +1,127 @@
#include "IEditPropertyCommand.h"
/** Save the current state of the object properties to the given data buffer */
void IEditPropertyCommand::SaveObjectStateToArray(std::vector<char>& rVector)
{
CVectorOutStream MemStream(&rVector, IOUtil::kSystemEndianness);
CBasicBinaryWriter Writer(&MemStream, CSerialVersion(IArchive::skCurrentArchiveVersion, 0, mpProperty->Game()));
std::vector<void*> DataPointers;
GetObjectDataPointers(DataPointers);
for (int PtrIdx = 0; PtrIdx < DataPointers.size(); PtrIdx++)
{
void* pData = DataPointers[PtrIdx];
mpProperty->SerializeValue(pData, Writer);
}
}
/** Restore the state of the object properties from the given data buffer */
void IEditPropertyCommand::RestoreObjectStateFromArray(std::vector<char>& rArray)
{
CBasicBinaryReader Reader(rArray.data(), rArray.size(), CSerialVersion(IArchive::skCurrentArchiveVersion, 0, mpProperty->Game()));
std::vector<void*> DataPointers;
GetObjectDataPointers(DataPointers);
for (int PtrIdx = 0; PtrIdx < DataPointers.size(); PtrIdx++)
{
void* pData = DataPointers[PtrIdx];
mpProperty->SerializeValue(pData, Reader);
}
}
IEditPropertyCommand::IEditPropertyCommand(
const QModelIndex& rkInIndex,
CPropertyModel* pInModel,
const QString& rkCommandName /*= "Edit Property"*/
)
: IUndoCommand(rkCommandName)
, mIndex(rkInIndex)
, mpModel(pInModel)
, mSavedOldData(false)
, mSavedNewData(false)
{
mpProperty = mpModel->PropertyForIndex(rkInIndex, true);
ASSERT(mpModel && mpProperty);
}
void IEditPropertyCommand::SaveOldData()
{
SaveObjectStateToArray(mOldData);
mSavedOldData = true;
}
void IEditPropertyCommand::SaveNewData()
{
SaveObjectStateToArray(mNewData);
mSavedNewData = true;
}
bool IEditPropertyCommand::IsNewDataDifferent()
{
if (mOldData.size() != mNewData.size()) return true;
return memcmp(mOldData.data(), mNewData.data(), mNewData.size()) != 0;
}
void IEditPropertyCommand::SetEditComplete(bool IsComplete)
{
mCommandEnded = IsComplete;
}
/** IUndoCommand/QUndoCommand interface */
int IEditPropertyCommand::id() const
{
return eEditPropertyCmd;
}
bool IEditPropertyCommand::mergeWith(const QUndoCommand *pkOther)
{
if (!mCommandEnded)
{
const IEditPropertyCommand* pkCmd = dynamic_cast<const IEditPropertyCommand*>(pkOther);
if (pkCmd && pkCmd->mIndex == mIndex && pkCmd->mpProperty == mpProperty)
{
std::vector<void*> MyPointers;
GetObjectDataPointers(MyPointers);
std::vector<void*> TheirPointers;
pkCmd->GetObjectDataPointers(TheirPointers);
if (TheirPointers.size() == MyPointers.size())
{
for (int PtrIdx = 0; PtrIdx < MyPointers.size(); PtrIdx++)
{
if (MyPointers[PtrIdx] != TheirPointers[PtrIdx])
return false;
}
// Match
mNewData = pkCmd->mNewData;
mCommandEnded = pkCmd->mCommandEnded;
return true;
}
}
}
return false;
}
void IEditPropertyCommand::undo()
{
ASSERT(mSavedOldData && mSavedNewData);
RestoreObjectStateFromArray(mOldData);
mCommandEnded = true;
}
void IEditPropertyCommand::redo()
{
ASSERT(mSavedOldData && mSavedNewData);
RestoreObjectStateFromArray(mNewData);
}
bool IEditPropertyCommand::AffectsCleanState() const
{
return true;
}

View File

@ -0,0 +1,50 @@
#ifndef IEDITPROPERTYCOMMAND_H
#define IEDITPROPERTYCOMMAND_H
#include "IUndoCommand.h"
#include "EUndoCommand.h"
#include "Editor/PropertyEdit/CPropertyModel.h"
class IEditPropertyCommand : public IUndoCommand
{
protected:
std::vector<char> mOldData;
std::vector<char> mNewData;
QModelIndex mIndex;
CPropertyModel* mpModel;
IPropertyNew* mpProperty;
bool mCommandEnded;
bool mSavedOldData;
bool mSavedNewData;
/** Save the current state of the object properties to the given data buffer */
void SaveObjectStateToArray(std::vector<char>& rVector);
/** Restore the state of the object properties from the given data buffer */
void RestoreObjectStateFromArray(std::vector<char>& rArray);
public:
IEditPropertyCommand(
const QModelIndex& rkInIndex,
CPropertyModel* pInModel,
const QString& rkCommandName = "Edit Property"
);
void SaveOldData();
void SaveNewData();
bool IsNewDataDifferent();
void SetEditComplete(bool IsComplete);
/** Interface */
virtual void GetObjectDataPointers(std::vector<void*>& rOutPointers) const = 0;
/** IUndoCommand/QUndoCommand interface */
int id() const;
bool mergeWith(const QUndoCommand *pkOther);
void undo();
void redo();
bool AffectsCleanState() const;
};
#endif // IEDITPROPERTYCOMMAND_H