App: fix dynamic property undo/redo

Instead of enforce property type match when undo/redo, modify various
property Paste() to make it type safe.
This commit is contained in:
Zheng, Lei
2019-09-30 14:18:40 +08:00
committed by wmayer
parent 890bc90b0c
commit 41387fd991
6 changed files with 37 additions and 24 deletions

View File

@@ -147,17 +147,17 @@ void PropertyExpressionEngine::hasSetValue()
void PropertyExpressionEngine::Paste(const Property &from)
{
const PropertyExpressionEngine * fromee = static_cast<const PropertyExpressionEngine*>(&from);
const PropertyExpressionEngine &fromee = dynamic_cast<const PropertyExpressionEngine&>(from);
AtomicPropertyChange signaller(*this);
expressions.clear();
for(auto &e : fromee->expressions) {
for(auto &e : fromee.expressions) {
expressions[e.first] = ExpressionInfo(
boost::shared_ptr<Expression>(e.second.expression->copy()));
expressionChanged(e.first);
}
validator = fromee->validator;
validator = fromee.validator;
signaller.tryInvoke();
}

View File

@@ -292,7 +292,7 @@ void TransactionObject::applyNew(Document & /*Doc*/, TransactionalObject * /*pcO
{
}
void TransactionObject::applyChn(Document & /*Doc*/, TransactionalObject *pcObj, bool Forward)
void TransactionObject::applyChn(Document & /*Doc*/, TransactionalObject *pcObj, bool /* Forward */)
{
if (status == New || status == Chn) {
// Property change order is not preserved, as it is recursive in nature
@@ -333,17 +333,29 @@ void TransactionObject::applyChn(Document & /*Doc*/, TransactionalObject *pcObj,
prop->setStatusValue(data.property->getStatus());
}
}
// Because we now allow undo/redo dynamic property adding/removing,
// we have to enforce property type checking before calling Copy/Paste.
if(data.propertyType != prop->getTypeId()) {
FC_WARN("Cannot " << (Forward?"redo":"undo")
<< " change of property " << prop->getName()
<< " because of type change: "
<< data.propertyType.getName()
<< " -> " << prop->getTypeId().getName());
continue;
}
prop->Paste(*data.property);
// Many properties do not bother implement Copy() and accepts
// derived types just fine in Paste(). So we do not enforce type
// matching here. But instead, strengthen type checking in all
// Paste() implementation.
//
// if(data.propertyType != prop->getTypeId()) {
// FC_WARN("Cannot " << (Forward?"redo":"undo")
// << " change of property " << prop->getName()
// << " because of type change: "
// << data.propertyType.getName()
// << " -> " << prop->getTypeId().getName());
// continue;
// }
try {
prop->Paste(*data.property);
} catch (Base::Exception &e) {
e.ReportException();
FC_ERR("exception while restoring " << prop->getFullName() << ": " << e.what());
} catch (std::exception &e) {
FC_ERR("exception while restoring " << prop->getFullName() << ": " << e.what());
} catch (...)
{}
}
}
}

View File

@@ -63,7 +63,7 @@ App::Property *PropertyColumnWidths::Copy() const
void PropertyColumnWidths::Paste(const App::Property &from)
{
setValues(static_cast<const PropertyColumnWidths&>(from).getValues());
setValues(dynamic_cast<const PropertyColumnWidths&>(from).getValues());
}
void PropertyColumnWidths::setValues(const std::map<int,int> &values) {

View File

@@ -56,7 +56,7 @@ App::Property *PropertyRowHeights::Copy() const
void PropertyRowHeights::Paste(const Property &from)
{
setValues(static_cast<const PropertyRowHeights&>(from).getValues());
setValues(dynamic_cast<const PropertyRowHeights&>(from).getValues());
}
void PropertyRowHeights::setValues(const std::map<int,int> &values) {

View File

@@ -224,9 +224,9 @@ App::Property *PropertySheet::Copy(void) const
void PropertySheet::Paste(const Property &from)
{
AtomicPropertyChange signaller(*this);
const PropertySheet &froms = dynamic_cast<const PropertySheet&>(from);
const PropertySheet * froms = static_cast<const PropertySheet*>(&from);
AtomicPropertyChange signaller(*this);
std::map<CellAddress, Cell* >::iterator icurr = data.begin();
@@ -236,8 +236,8 @@ void PropertySheet::Paste(const Property &from)
++icurr;
}
std::map<CellAddress, Cell* >::const_iterator ifrom = froms->data.begin();
while (ifrom != froms->data.end()) {
std::map<CellAddress, Cell* >::const_iterator ifrom = froms.data.begin();
while (ifrom != froms.data.end()) {
std::map<CellAddress, Cell* >::iterator i = data.find(ifrom->first);
if (i != data.end()) {
@@ -269,7 +269,7 @@ void PropertySheet::Paste(const Property &from)
++icurr;
}
mergedCells = froms->mergedCells;
mergedCells = froms.mergedCells;
signaller.tryInvoke();
}

View File

@@ -1470,9 +1470,10 @@ Property *PropertySpreadsheetQuantity::Copy() const
void PropertySpreadsheetQuantity::Paste(const Property &from)
{
const auto &src = dynamic_cast<const PropertySpreadsheetQuantity&>(from);
aboutToSetValue();
_dValue = static_cast<const PropertySpreadsheetQuantity*>(&from)->_dValue;
_Unit = static_cast<const PropertySpreadsheetQuantity*>(&from)->_Unit;
_dValue = src._dValue;
_Unit = src._Unit;
hasSetValue();
}