App: add Property::isSame() API

To compare if two property contains the same content. The default
implementation in Property uses the persistense interface to save both
properties to string and compares the content. This may not work at the
moment if the property saves content in separate file or in binary.

Various properties have cheaper implementation to direct compare their
internal values.
This commit is contained in:
Zheng, Lei
2020-01-01 18:26:39 +08:00
committed by Chris Hennes
parent 875452c020
commit 54c484df9b
9 changed files with 133 additions and 6 deletions

View File

@@ -276,6 +276,17 @@ void Property::setStatus(Status pos, bool on) {
bits.set(pos,on);
setStatusValue(bits.to_ulong());
}
bool Property::isSame(const Property &other) const {
if(other.getTypeId() != getTypeId() || getMemSize() != other.getMemSize())
return false;
Base::StringWriter writer,writer2;
Save(writer);
other.Save(writer2);
return writer.getString() == writer2.getString();
}
//**************************************************************************
//**************************************************************************
// PropertyListsBase

View File

@@ -236,6 +236,9 @@ public:
/// Called before a child property changing value
virtual void aboutToSetChildValue(Property &) {}
/// Compare if this property has the same content as the given one
virtual bool isSame(const Property &other) const;
friend class PropertyContainer;
friend struct PropertyData;
friend class DynamicProperty;
@@ -492,6 +495,11 @@ public:
const_reference operator[] (int idx) const {return _lValueList[idx];}
virtual bool isSame(const Property &other) const override {
return this->getTypeId() == other.getTypeId()
&& this->getValue() == static_cast<decltype(this)>(&other)->getValue();
}
virtual void setPyObject(PyObject *value) override {
try {
setValue(getPyValue(value));

View File

@@ -103,6 +103,13 @@ public:
virtual void Paste(const Property &from);
virtual unsigned int getMemSize (void) const;
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& _BaseFileName == static_cast<decltype(this)>(&other)->_BaseFileName
&& _OriginalName == static_cast<decltype(this)>(&other)->_OriginalName
&& _cValue == static_cast<decltype(this)>(&other)->_cValue;
}
/** get a temp file name in the transient path of the document.
* Using this file for new Version of the file and set
* this file with setValue() is the fastest way to change

View File

@@ -108,6 +108,11 @@ public:
return Base::Unit();
}
virtual bool isSame(const Property &other) const override {
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
}
private:
Base::Vector3d _cVec;
};
@@ -278,6 +283,11 @@ public:
return sizeof(Base::Matrix4D);
}
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
}
private:
Base::Matrix4D _cMat;
};
@@ -345,6 +355,11 @@ public:
return sizeof(Base::Placement);
}
virtual bool isSame(const Property &other) const override {
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
}
static const Placement Null;
private:

View File

@@ -84,6 +84,27 @@ void PropertyLinkBase::hasSetValue() {
Property::hasSetValue();
}
bool PropertyLinkBase::isSame(const Property &other) const
{
if(other.isDerivedFrom(PropertyLinkBase::getClassTypeId())
|| getScope() != static_cast<const PropertyLinkBase*>(&other)->getScope())
return false;
static std::vector<App::DocumentObject*> ret;
static std::vector<std::string> subs;
static std::vector<App::DocumentObject*> ret2;
static std::vector<std::string> subs2;
ret.clear();
subs.clear();
ret2.clear();
subs2.clear();
getLinks(ret,true,&subs,false);
static_cast<const PropertyLinkBase *>(&other)->getLinks(ret2,true,&subs2,true);
return ret==ret2 && subs==subs2;
}
void PropertyLinkBase::unregisterElementReference() {
}

View File

@@ -93,8 +93,8 @@ public:
* Retrieve what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and
* all Childs or to all objects within the Glocal scope.
*/
LinkScope getScope() {return _pcScope;};
LinkScope getScope() const {return _pcScope;};
protected:
LinkScope _pcScope = LinkScope::Local;
};
@@ -288,6 +288,8 @@ public:
}
//@}
virtual bool isSame(const Property &other) const override;
/** Enable/disable temporary holding external object without throwing exception
*
* Warning, non-PropertyXLink related property does not have internal

View File

@@ -207,7 +207,7 @@ void PropertyPath::setValue(const char * Path)
hasSetValue();
}
boost::filesystem::path PropertyPath::getValue() const
const boost::filesystem::path &PropertyPath::getValue(void) const
{
return _cValue;
}

View File

@@ -81,6 +81,11 @@ public:
virtual void setPathValue(const App::ObjectIdentifier & path, const boost::any & value);
virtual const boost::any getPathValue(const App::ObjectIdentifier & /*path*/) const { return _lValue; }
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
}
protected:
long _lValue;
};
@@ -107,7 +112,7 @@ public:
/** This method returns a string representation of the property
*/
boost::filesystem::path getValue(void) const;
const boost::filesystem::path &getValue(void) const;
virtual const char* getEditorName(void) const { return "Gui::PropertyEditor::PropertyPathItem"; }
@@ -122,6 +127,11 @@ public:
virtual unsigned int getMemSize (void) const;
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
}
protected:
boost::filesystem::path _cValue;
};
@@ -217,6 +227,11 @@ public:
virtual const boost::any getPathValue(const App::ObjectIdentifier & /*path*/) const;
virtual bool getPyPathValue(const ObjectIdentifier &path, Py::Object &r) const;
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getEnum() == static_cast<decltype(this)>(&other)->getEnum();
}
private:
Enumeration _enum;
std::string _editorTypeName;
@@ -391,6 +406,10 @@ public:
virtual void Paste(const Property &from);
virtual unsigned int getMemSize (void) const;
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getValues() == static_cast<decltype(this)>(&other)->getValues();
}
private:
std::set<long> _lValueSet;
};
@@ -444,7 +463,11 @@ public:
virtual void Paste(const Property &from);
virtual unsigned int getMemSize (void) const;
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getValues() == static_cast<decltype(this)>(&other)->getValues();
}
private:
std::map<std::string,std::string> _lValueList;
@@ -495,6 +518,11 @@ public:
void setPathValue(const App::ObjectIdentifier &path, const boost::any &value);
const boost::any getPathValue(const App::ObjectIdentifier &path) const;
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
}
protected:
double _dValue;
};
@@ -679,6 +707,11 @@ public:
void setPathValue(const App::ObjectIdentifier &path, const boost::any &value);
const boost::any getPathValue(const App::ObjectIdentifier &path) const;
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getStrValue() == static_cast<decltype(this)>(&other)->getStrValue();
}
protected:
std::string _cValue;
};
@@ -722,6 +755,11 @@ public:
virtual void Paste(const Property &from);
virtual unsigned int getMemSize (void) const;
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& _uuid.getValue() == static_cast<decltype(this)>(&other)->_uuid.getValue();
}
private:
Base::Uuid _uuid;
};
@@ -738,6 +776,11 @@ public:
virtual ~PropertyFont();
virtual const char* getEditorName(void) const
{ return "Gui::PropertyEditor::PropertyFontItem"; }
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
}
};
class AppExport PropertyStringList: public PropertyListsT<std::string>
@@ -819,6 +862,11 @@ public:
void setPathValue(const App::ObjectIdentifier &path, const boost::any &value);
const boost::any getPathValue(const App::ObjectIdentifier &path) const;
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
}
private:
bool _lValue;
};
@@ -892,7 +940,11 @@ public:
virtual void Paste(const Property &from);
virtual unsigned int getMemSize (void) const{return sizeof(Color);}
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
}
private:
Color _cCol;
@@ -979,6 +1031,11 @@ public:
virtual void Paste(const Property &from);
virtual unsigned int getMemSize (void) const{return sizeof(_cMat);}
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
}
private:
Material _cMat;

View File

@@ -71,6 +71,12 @@ public:
virtual void setPathValue(const App::ObjectIdentifier &path, const boost::any &value);
virtual const boost::any getPathValue(const App::ObjectIdentifier &path) const;
virtual bool isSame(const Property &other) const {
return getTypeId() == other.getTypeId()
&& getValue() == static_cast<decltype(this)>(&other)->getValue()
&& _Unit == static_cast<decltype(this)>(&other)->_Unit;
}
protected:
Base::Quantity createQuantityFromPy(PyObject *value);
Base::Unit _Unit;