From 54c484df9b00f130cab56ff20cfa2fc69fe24a64 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Wed, 1 Jan 2020 18:26:39 +0800 Subject: [PATCH] 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. --- src/App/Property.cpp | 11 +++++++ src/App/Property.h | 8 +++++ src/App/PropertyFile.h | 7 ++++ src/App/PropertyGeo.h | 15 +++++++++ src/App/PropertyLinks.cpp | 21 ++++++++++++ src/App/PropertyLinks.h | 6 ++-- src/App/PropertyStandard.cpp | 2 +- src/App/PropertyStandard.h | 63 ++++++++++++++++++++++++++++++++++-- src/App/PropertyUnits.h | 6 ++++ 9 files changed, 133 insertions(+), 6 deletions(-) diff --git a/src/App/Property.cpp b/src/App/Property.cpp index 1c7bdce0d4..6bed9ef734 100644 --- a/src/App/Property.cpp +++ b/src/App/Property.cpp @@ -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 diff --git a/src/App/Property.h b/src/App/Property.h index 5c46f51662..f2ef4efeda 100644 --- a/src/App/Property.h +++ b/src/App/Property.h @@ -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(&other)->getValue(); + } + virtual void setPyObject(PyObject *value) override { try { setValue(getPyValue(value)); diff --git a/src/App/PropertyFile.h b/src/App/PropertyFile.h index 349bc2e7c5..9bc36df394 100644 --- a/src/App/PropertyFile.h +++ b/src/App/PropertyFile.h @@ -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(&other)->_BaseFileName + && _OriginalName == static_cast(&other)->_OriginalName + && _cValue == static_cast(&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 diff --git a/src/App/PropertyGeo.h b/src/App/PropertyGeo.h index f22be71507..4291fdb99b 100644 --- a/src/App/PropertyGeo.h +++ b/src/App/PropertyGeo.h @@ -108,6 +108,11 @@ public: return Base::Unit(); } + virtual bool isSame(const Property &other) const override { + return getTypeId() == other.getTypeId() + && getValue() == static_cast(&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(&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(&other)->getValue(); + } + static const Placement Null; private: diff --git a/src/App/PropertyLinks.cpp b/src/App/PropertyLinks.cpp index 5bdbb5286f..2b82781b6c 100644 --- a/src/App/PropertyLinks.cpp +++ b/src/App/PropertyLinks.cpp @@ -84,6 +84,27 @@ void PropertyLinkBase::hasSetValue() { Property::hasSetValue(); } +bool PropertyLinkBase::isSame(const Property &other) const +{ + if(other.isDerivedFrom(PropertyLinkBase::getClassTypeId()) + || getScope() != static_cast(&other)->getScope()) + return false; + + static std::vector ret; + static std::vector subs; + static std::vector ret2; + static std::vector subs2; + + ret.clear(); + subs.clear(); + ret2.clear(); + subs2.clear(); + getLinks(ret,true,&subs,false); + static_cast(&other)->getLinks(ret2,true,&subs2,true); + + return ret==ret2 && subs==subs2; +} + void PropertyLinkBase::unregisterElementReference() { } diff --git a/src/App/PropertyLinks.h b/src/App/PropertyLinks.h index 66c4d9bb80..5f527ba765 100644 --- a/src/App/PropertyLinks.h +++ b/src/App/PropertyLinks.h @@ -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 diff --git a/src/App/PropertyStandard.cpp b/src/App/PropertyStandard.cpp index 9898d94277..3344c9a29a 100644 --- a/src/App/PropertyStandard.cpp +++ b/src/App/PropertyStandard.cpp @@ -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; } diff --git a/src/App/PropertyStandard.h b/src/App/PropertyStandard.h index 49bc7509d3..2e5766e464 100644 --- a/src/App/PropertyStandard.h +++ b/src/App/PropertyStandard.h @@ -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(&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(&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(&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(&other)->getValues(); + } private: std::set _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(&other)->getValues(); + } private: std::map _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(&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(&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(&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(&other)->getValue(); + } }; class AppExport PropertyStringList: public PropertyListsT @@ -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(&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(&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(&other)->getValue(); + } private: Material _cMat; diff --git a/src/App/PropertyUnits.h b/src/App/PropertyUnits.h index fdc4b453f3..19b0cbb103 100644 --- a/src/App/PropertyUnits.h +++ b/src/App/PropertyUnits.h @@ -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(&other)->getValue() + && _Unit == static_cast(&other)->_Unit; + } + protected: Base::Quantity createQuantityFromPy(PyObject *value); Base::Unit _Unit;