diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 30816239d5..a82c23c3c1 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -102,6 +102,7 @@ #include "OriginFeature.h" #include "OriginGroupExtension.h" #include "OriginGroupExtensionPy.h" +#include "StringHasherPy.h" #include "Part.h" #include "PartPy.h" #include "Placement.h" @@ -277,6 +278,7 @@ void Application::setupPythonTypes() Base::Interpreter().addType(&Base::PlacementPy::Type, pAppModule, "Placement"); Base::Interpreter().addType(&Base::RotationPy::Type, pAppModule, "Rotation"); Base::Interpreter().addType(&Base::AxisPy::Type, pAppModule, "Axis"); + Base::Interpreter().addType(&App::StringHasherPy::Type, pAppModule, "StringHasher"); // Note: Create an own module 'Base' which should provide the python // binding classes from the base module. At a later stage we should @@ -1904,6 +1906,9 @@ void Application::initTypes() Data::ComplexGeoData ::init(); Data::Segment ::init(); + App::StringID ::init(); + App::StringHasher ::init(); + // Properties App ::Property ::init(); App ::PropertyContainer ::init(); diff --git a/src/App/CMakeLists.txt b/src/App/CMakeLists.txt index 7ebe15135e..8691b6a21b 100644 --- a/src/App/CMakeLists.txt +++ b/src/App/CMakeLists.txt @@ -87,6 +87,8 @@ else() ) endif() +generate_from_xml(StringIDPy) +generate_from_xml(StringHasherPy) generate_from_xml(DocumentPy) generate_from_xml(DocumentObjectPy) generate_from_xml(ExtensionPy) @@ -109,6 +111,8 @@ generate_from_py(FreeCADInit InitScript.h) generate_from_py(FreeCADTest TestScript.h) SET(FreeCADApp_XML_SRCS + StringIDPy.xml + StringHasherPy.xml ExtensionPy.xml ExtensionContainerPy.xml DocumentObjectExtensionPy.xml @@ -131,7 +135,11 @@ SOURCE_GROUP("XML" FILES ${FreeCADApp_XML_SRCS}) # The document stuff SET(Document_CPP_SRCS Annotation.cpp + StringHasher.cpp + StringHasherPyImp.cpp + StringIDPyImp.cpp Document.cpp + DocumentParams.cpp DocumentObject.cpp Extension.cpp ExtensionPyImp.cpp @@ -178,7 +186,9 @@ SET(Document_CPP_SRCS SET(Document_HPP_SRCS Annotation.h + StringHasher.h Document.h + DocumentParams.h DocumentObject.h Extension.h ExtensionContainer.h diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 33884763f1..c256be5631 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -65,6 +65,7 @@ recompute path. Also, it enables more complicated dependencies beyond trees. #include #include +#include #include #ifdef USE_OLD_DAG @@ -107,6 +108,7 @@ recompute path. Also, it enables more complicated dependencies beyond trees. #include "MergeDocuments.h" #include "Origin.h" #include "OriginGroupExtension.h" +#include "StringHasher.h" #include "Transactions.h" #ifdef _MSC_VER @@ -117,7 +119,6 @@ recompute path. Also, it enables more complicated dependencies beyond trees. #include #include - FC_LOG_LEVEL_INIT("App", true, true, true) using Base::Console; @@ -152,8 +153,10 @@ typedef std::vector Path; namespace App { +typedef boost::bimap HasherMap; + static bool _IsRestoring; -static bool _IsRelabeling; + // Pimpl class struct DocumentP { @@ -179,6 +182,7 @@ struct DocumentP unsigned int UndoMemSize; unsigned int UndoMaxStackSize; std::string programVersion; + mutable HasherMap hashers; #ifdef USE_OLD_DAG DependencyList DepList; std::map VertexObjectList; @@ -187,10 +191,15 @@ struct DocumentP std::multimap > _RecomputeLog; + StringHasherRef Hasher; + // restored files std::set files; DocumentP() { +#ifdef FC_NO_RANDOM_ID + lastObjectId = 10; +#else static std::random_device _RD; static std::mt19937 _RGEN(_RD()); static std::uniform_int_distribution<> _RDIST(0,5000); @@ -198,6 +207,8 @@ struct DocumentP // copying shape from other document. It is probably better to randomize // on each object ID. lastObjectId = _RDIST(_RGEN); +#endif + Hasher.reset(new StringHasher); activeObject = nullptr; activeUndoTransaction = nullptr; iTransactionMode = 0; @@ -1470,7 +1481,6 @@ void Document::onChanged(const Property* prop) // the Name property is a label for display purposes if (prop == &Label) { - Base::FlagToggler<> flag(_IsRelabeling); App::GetApplication().signalRelabelDocument(*this); } else if(prop == &ShowHidden) { App::GetApplication().signalShowHidden(*this); @@ -1505,6 +1515,12 @@ void Document::onChanged(const Property* prop) // recursive call of onChanged() this->Uid.setValue(id); } + } else if(prop == &UseHasher) { + for(auto obj : d->objectArray) { + auto geofeature = dynamic_cast(obj); + if(geofeature && geofeature->getPropertyOfGeometry()) + geofeature->enforceRecompute(); + } } } @@ -1512,8 +1528,8 @@ void Document::onBeforeChangeProperty(const TransactionalObject *Who, const Prop { if(Who->isDerivedFrom(App::DocumentObject::getClassTypeId())) signalBeforeChangeObject(*static_cast(Who), *What); - if(!d->rollback && !_IsRelabeling) { - _checkTransaction(nullptr,What,__LINE__); + if(!d->rollback) { + _checkTransaction(nullptr, What, __LINE__); if (d->activeUndoTransaction) d->activeUndoTransaction->addObjectChange(Who,What); } @@ -1548,10 +1564,8 @@ Document::Document(const char *name) Console().Log("+App::Document: %p\n",this); #endif std::string CreationDateString = Base::TimeInfo::currentDateTimeString(); - std::string Author = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetASCII("prefAuthor",""); - std::string AuthorComp = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetASCII("prefCompany",""); + std::string Author = DocumentParams::getprefAuthor(); + std::string AuthorComp = DocumentParams::getprefCompany(); ADD_PROPERTY_TYPE(Label,("Unnamed"),0,Prop_None,"The name of the document"); ADD_PROPERTY_TYPE(FileName,(""),0,PropertyType(Prop_Transient|Prop_ReadOnly),"The path to the file where the document is saved to"); ADD_PROPERTY_TYPE(CreatedBy,(Author.c_str()),0,Prop_None,"The creator of the document"); @@ -1572,8 +1586,7 @@ Document::Document(const char *name) ADD_PROPERTY_TYPE(LicenseURL,("http://creativecommons.org/licenses/by/3.0/"),0,Prop_None,"URL to the license text/contract"); // license stuff - int licenseId = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetInt("prefLicenseType",0); + int licenseId = DocumentParams::getprefLicenseType(); std::string license; std::string licenseUrl; switch (licenseId) { @@ -1618,13 +1631,17 @@ Document::Document(const char *name) break; } - licenseUrl = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetASCII("prefLicenseUrl", licenseUrl.c_str()); + if(DocumentParams::getprefLicenseUrl().empty()) + licenseUrl = DocumentParams::getprefLicenseUrl(); ADD_PROPERTY_TYPE(License,(license.c_str()),0,Prop_None,"License string of the Item"); ADD_PROPERTY_TYPE(LicenseURL,(licenseUrl.c_str()),0,Prop_None,"URL to the license text/contract"); ADD_PROPERTY_TYPE(ShowHidden,(false), 0,PropertyType(Prop_None), "Whether to show hidden object items in the tree view"); + ADD_PROPERTY_TYPE(UseHasher,(true), 0,PropertyType(Prop_Hidden), + "Whether to use hasher on topological naming"); + if(!DocumentParams::getUseHasher()) + UseHasher.setValue(false); // this creates and sets 'TransientDir' in onChanged() ADD_PROPERTY_TYPE(TransientDir,(""),0,PropertyType(Prop_Transient|Prop_ReadOnly), @@ -1694,11 +1711,27 @@ std::string Document::getTransientDirectoryName(const std::string& uuid, const s void Document::Save (Base::Writer &writer) const { + d->hashers.clear(); + addStringHasher(d->Hasher); + writer.Stream() << "" << endl; + << "\" FileVersion=\"" << writer.getFileVersion() + << "\" Uid=\"" << Uid.getValueStr() + << "\" StringHasher=\"1\">\n"; + + writer.incInd(); + + // NOTE: DO NOT save the main string hasher as separate file, because it is + // required by many objects, which assume the string hasher is fully + // restored. + d->Hasher->setPersistenceFileName(0); + + d->Hasher->Save(writer); + + writer.decInd(); PropertyContainer::Save(writer); @@ -1710,7 +1743,12 @@ void Document::Save (Base::Writer &writer) const void Document::Restore(Base::XMLReader &reader) { int i,Cnt; + d->hashers.clear(); d->touchedObjs.clear(); + addStringHasher(d->Hasher); + + Base::ReaderContext rctx(getName()); + setStatus(Document::PartialDoc,false); reader.readElement("Document"); @@ -1727,6 +1765,11 @@ void Document::Restore(Base::XMLReader &reader) reader.FileVersion = 0; } + if (reader.hasAttribute("StringHasher")) { + Base::ReaderContext rctx("StringHasher"); + d->Hasher->Restore(reader); + } else + d->Hasher->clear(); // When this document was created the FileName and Label properties // were set to the absolute path or file name, respectively. To save // the document to the file it was loaded from or to show the file name @@ -1769,6 +1812,7 @@ void Document::Restore(Base::XMLReader &reader) for (i=0 ;isetStatus(ObjectStatus::Restore, true); @@ -1791,6 +1835,36 @@ void Document::Restore(Base::XMLReader &reader) reader.readEndElement("Document"); } +std::pair Document::addStringHasher(const StringHasherRef & hasher) const { + if (!hasher) + return std::make_pair(false, 0); + auto ret = d->hashers.left.insert(HasherMap::left_map::value_type(hasher,(int)d->hashers.size())); + if (ret.second) + hasher->clearMarks(); + return std::make_pair(ret.second,ret.first->second); +} + +StringHasherRef Document::getHasher() const { + return d->Hasher; +} + +StringHasherRef Document::getStringHasher(int idx) const { + StringHasherRef hasher; + if(idx<0) { + if(UseHasher.getValue()) + return d->Hasher; + return hasher; + } + + auto it = d->hashers.right.find(idx); + if(it == d->hashers.right.end()) { + hasher = new StringHasher; + d->hashers.right.insert(HasherMap::right_map::value_type(idx,hasher)); + }else + hasher = it->second; + return hasher; +} + struct DocExportStatus { Document::ExportStatus status; std::set objs; @@ -1827,6 +1901,7 @@ Document::ExportStatus Document::isExporting(const App::DocumentObject *obj) con void Document::exportObjects(const std::vector& obj, std::ostream& out) { DocumentExporting exporting(obj); + d->hashers.clear(); if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { for(auto o : obj) { @@ -1863,6 +1938,7 @@ void Document::exportObjects(const std::vector& obj, std:: // write additional files writer.writeFiles(); + d->hashers.clear(); } #define FC_ATTR_DEPENDENCIES "Dependencies" @@ -2166,14 +2242,16 @@ Document::readObjects(Base::XMLReader& reader) void Document::addRecomputeObject(DocumentObject *obj) { if(testStatus(Status::Restoring) && obj) { + setStatus(Status::RecomputeOnRestore, true); d->touchedObjs.insert(obj); - obj->touch(); + obj->enforceRecompute(); } } std::vector Document::importObjects(Base::XMLReader& reader) { + d->hashers.clear(); Base::FlagToggler<> flag(_IsRestoring,false); Base::ObjectStatusLocker restoreBit(Status::Restoring, this); Base::ObjectStatusLocker restoreBit2(Status::Importing, this); @@ -2192,6 +2270,7 @@ Document::importObjects(Base::XMLReader& reader) reader.FileVersion = 0; } + Base::ReaderContext rctx(getName()); std::vector objs = readObjects(reader); for(auto o : objs) { if(o && o->getNameInDocument()) { @@ -2224,7 +2303,7 @@ Document::importObjects(Base::XMLReader& reader) if(o && o->getNameInDocument()) o->setStatus(App::ObjImporting,false); } - + d->hashers.clear(); return objs; } @@ -2237,6 +2316,8 @@ unsigned int Document::getMemSize (void) const for (it = d->objectArray.begin(); it != d->objectArray.end(); ++it) size += (*it)->getMemSize(); + size += d->Hasher->getMemSize(); + // size of the document properties... size += PropertyContainer::getMemSize(); diff --git a/src/App/Document.h b/src/App/Document.h index 337de4e857..2dae41c852 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -23,13 +23,22 @@ #ifndef APP_DOCUMENT_H #define APP_DOCUMENT_H +#include +#include +#include +#include +#include + #include "PropertyContainer.h" #include "PropertyLinks.h" #include "PropertyStandard.h" +#include #include #include +class QByteArray; + namespace Base { class Writer; } @@ -43,6 +52,8 @@ namespace App class DocumentPy; // the python document class class Application; class Transaction; + class StringHasher; + typedef Base::Reference StringHasherRef; } namespace App @@ -68,6 +79,7 @@ public: RestoreError = 10, LinkStampChanged = 11, // Indicates during restore time if any linked document's time stamp has changed IgnoreErrorOnRecompute = 12, // Don't report errors if the recompute failed + RecomputeOnRestore = 13, // Mark pending recompute on restore for migration purpose }; /** @name Properties */ @@ -109,6 +121,8 @@ public: PropertyString TipName; /// Whether to show hidden items in TreeView PropertyBool ShowHidden; + /// Whether to use hasher on topological naming + PropertyBool UseHasher; //@} /** @name Signals of the document */ @@ -473,6 +487,38 @@ public: (const App::DocumentObject* from, const App::DocumentObject* to) const; //@} + /** Called by property during properly save its containing StringHasher + * + * @param hasher: the input hasher + * @return Returns a pair. Boolean member indicate if the + * StringHasher has been saved before. The Integer is the hasher index. + * + * The StringHasher object is designed to be shared among multiple objects. + * So, we must not save duplicate copies of the same hasher. And must be + * able to restore with the same sharing relationship. This function returns + * whether the hasher has been saved before by other objects, and the index + * of the hasher. If the hasher has not been saved before, the object must + * save the hasher by calling StringHasher::Save + */ + std::pair addStringHasher(const StringHasherRef & hasher) const; + + /** Called by property to restore its containing StringHasher + * + * @param index: the index previously returned by calling addStringHasher() + * during save. Or if is negative, then return document's own string hasher + * if UseHasher is True + * + * @return Return the resulting string hasher. + * + * The caller is responsible to restore the hasher itself if it is the first + * owner of the hasher, i.e. return addStringHasher() returns true during + * save + */ + StringHasherRef getStringHasher(int index=-1) const; + + /// Return the document's own hasher regardless of UseHasher + StringHasherRef getHasher() const; + /** Return the links to a given object * * @param links: holds the links found diff --git a/src/App/DocumentParams.cpp b/src/App/DocumentParams.cpp new file mode 100644 index 0000000000..affa18975f --- /dev/null +++ b/src/App/DocumentParams.cpp @@ -0,0 +1,1081 @@ +/**************************************************************************** + * Copyright (c) 2022 Zheng Lei (realthunder) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ****************************************************************************/ + +#include "PreCompiled.h" + + +/*[[[cog +import DocumentParams +DocumentParams.define() +]]]*/ + +// Auto generated code (Tools/params_utils.py:162) +#include +#include +#include +#include "DocumentParams.h" +using namespace App; + +// Auto generated code (Tools/params_utils.py:171) +namespace { +class DocumentParamsP: public ParameterGrp::ObserverType { +public: + ParameterGrp::handle handle; + std::unordered_map funcs; + + // Auto generated code (Tools/params_utils.py:181) + boost::signals2::signal signalParamChanged; + void signalAll() + { + signalParamChanged("prefAuthor"); + signalParamChanged("prefSetAuthorOnSave"); + signalParamChanged("prefCompany"); + signalParamChanged("prefLicenseType"); + signalParamChanged("prefLicenseUrl"); + signalParamChanged("CompressionLevel"); + signalParamChanged("CheckExtension"); + signalParamChanged("ForceXML"); + signalParamChanged("SplitXML"); + signalParamChanged("PreferBinary"); + signalParamChanged("AutoRemoveFile"); + signalParamChanged("BackupPolicy"); + signalParamChanged("CreateBackupFiles"); + signalParamChanged("UseFCBakExtension"); + signalParamChanged("SaveBackupDateFormat"); + signalParamChanged("CountBackupFiles"); + signalParamChanged("OptimizeRecompute"); + signalParamChanged("CanAbortRecompute"); + signalParamChanged("UseHasher"); + signalParamChanged("ViewObjectTransaction"); + signalParamChanged("WarnRecomputeOnRestore"); + signalParamChanged("NoPartialLoading"); + signalParamChanged("ThumbnailNoBackground"); + signalParamChanged("ThumbnailSampleSize"); + signalParamChanged("DuplicateLabels"); + signalParamChanged("TransactionOnRecompute"); + signalParamChanged("RelativeStringID"); + signalParamChanged("EnableMaterialEdit"); + + // Auto generated code (Tools/params_utils.py:190) + } + std::string prefAuthor; + bool prefSetAuthorOnSave; + std::string prefCompany; + long prefLicenseType; + std::string prefLicenseUrl; + long CompressionLevel; + bool CheckExtension; + long ForceXML; + bool SplitXML; + bool PreferBinary; + bool AutoRemoveFile; + bool BackupPolicy; + bool CreateBackupFiles; + bool UseFCBakExtension; + std::string SaveBackupDateFormat; + long CountBackupFiles; + bool OptimizeRecompute; + bool CanAbortRecompute; + bool UseHasher; + bool ViewObjectTransaction; + bool WarnRecomputeOnRestore; + bool NoPartialLoading; + bool ThumbnailNoBackground; + long ThumbnailSampleSize; + bool DuplicateLabels; + bool TransactionOnRecompute; + bool RelativeStringID; + bool EnableMaterialEdit; + + // Auto generated code (Tools/params_utils.py:199) + DocumentParamsP() { + handle = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document"); + handle->Attach(this); + + prefAuthor = handle->GetASCII("prefAuthor", ""); + funcs["prefAuthor"] = &DocumentParamsP::updateprefAuthor; + prefSetAuthorOnSave = handle->GetBool("prefSetAuthorOnSave", false); + funcs["prefSetAuthorOnSave"] = &DocumentParamsP::updateprefSetAuthorOnSave; + prefCompany = handle->GetASCII("prefCompany", ""); + funcs["prefCompany"] = &DocumentParamsP::updateprefCompany; + prefLicenseType = handle->GetInt("prefLicenseType", 0); + funcs["prefLicenseType"] = &DocumentParamsP::updateprefLicenseType; + prefLicenseUrl = handle->GetASCII("prefLicenseUrl", ""); + funcs["prefLicenseUrl"] = &DocumentParamsP::updateprefLicenseUrl; + CompressionLevel = handle->GetInt("CompressionLevel", 3); + funcs["CompressionLevel"] = &DocumentParamsP::updateCompressionLevel; + CheckExtension = handle->GetBool("CheckExtension", true); + funcs["CheckExtension"] = &DocumentParamsP::updateCheckExtension; + ForceXML = handle->GetInt("ForceXML", 3); + funcs["ForceXML"] = &DocumentParamsP::updateForceXML; + SplitXML = handle->GetBool("SplitXML", true); + funcs["SplitXML"] = &DocumentParamsP::updateSplitXML; + PreferBinary = handle->GetBool("PreferBinary", false); + funcs["PreferBinary"] = &DocumentParamsP::updatePreferBinary; + AutoRemoveFile = handle->GetBool("AutoRemoveFile", true); + funcs["AutoRemoveFile"] = &DocumentParamsP::updateAutoRemoveFile; + BackupPolicy = handle->GetBool("BackupPolicy", true); + funcs["BackupPolicy"] = &DocumentParamsP::updateBackupPolicy; + CreateBackupFiles = handle->GetBool("CreateBackupFiles", true); + funcs["CreateBackupFiles"] = &DocumentParamsP::updateCreateBackupFiles; + UseFCBakExtension = handle->GetBool("UseFCBakExtension", false); + funcs["UseFCBakExtension"] = &DocumentParamsP::updateUseFCBakExtension; + SaveBackupDateFormat = handle->GetASCII("SaveBackupDateFormat", "%Y%m%d-%H%M%S"); + funcs["SaveBackupDateFormat"] = &DocumentParamsP::updateSaveBackupDateFormat; + CountBackupFiles = handle->GetInt("CountBackupFiles", 1); + funcs["CountBackupFiles"] = &DocumentParamsP::updateCountBackupFiles; + OptimizeRecompute = handle->GetBool("OptimizeRecompute", true); + funcs["OptimizeRecompute"] = &DocumentParamsP::updateOptimizeRecompute; + CanAbortRecompute = handle->GetBool("CanAbortRecompute", true); + funcs["CanAbortRecompute"] = &DocumentParamsP::updateCanAbortRecompute; + UseHasher = handle->GetBool("UseHasher", true); + funcs["UseHasher"] = &DocumentParamsP::updateUseHasher; + ViewObjectTransaction = handle->GetBool("ViewObjectTransaction", false); + funcs["ViewObjectTransaction"] = &DocumentParamsP::updateViewObjectTransaction; + WarnRecomputeOnRestore = handle->GetBool("WarnRecomputeOnRestore", true); + funcs["WarnRecomputeOnRestore"] = &DocumentParamsP::updateWarnRecomputeOnRestore; + NoPartialLoading = handle->GetBool("NoPartialLoading", false); + funcs["NoPartialLoading"] = &DocumentParamsP::updateNoPartialLoading; + ThumbnailNoBackground = handle->GetBool("ThumbnailNoBackground", false); + funcs["ThumbnailNoBackground"] = &DocumentParamsP::updateThumbnailNoBackground; + ThumbnailSampleSize = handle->GetInt("ThumbnailSampleSize", 0); + funcs["ThumbnailSampleSize"] = &DocumentParamsP::updateThumbnailSampleSize; + DuplicateLabels = handle->GetBool("DuplicateLabels", false); + funcs["DuplicateLabels"] = &DocumentParamsP::updateDuplicateLabels; + TransactionOnRecompute = handle->GetBool("TransactionOnRecompute", false); + funcs["TransactionOnRecompute"] = &DocumentParamsP::updateTransactionOnRecompute; + RelativeStringID = handle->GetBool("RelativeStringID", true); + funcs["RelativeStringID"] = &DocumentParamsP::updateRelativeStringID; + EnableMaterialEdit = handle->GetBool("EnableMaterialEdit", true); + funcs["EnableMaterialEdit"] = &DocumentParamsP::updateEnableMaterialEdit; + } + + // Auto generated code (Tools/params_utils.py:213) + ~DocumentParamsP() { + } + + // Auto generated code (Tools/params_utils.py:218) + void OnChange(Base::Subject &, const char* sReason) { + if(!sReason) + return; + auto it = funcs.find(sReason); + if(it == funcs.end()) + return; + it->second(this); + signalParamChanged(sReason); + } + + + // Auto generated code (Tools/params_utils.py:234) + static void updateprefAuthor(DocumentParamsP *self) { + self->prefAuthor = self->handle->GetASCII("prefAuthor", ""); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateprefSetAuthorOnSave(DocumentParamsP *self) { + self->prefSetAuthorOnSave = self->handle->GetBool("prefSetAuthorOnSave", false); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateprefCompany(DocumentParamsP *self) { + self->prefCompany = self->handle->GetASCII("prefCompany", ""); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateprefLicenseType(DocumentParamsP *self) { + self->prefLicenseType = self->handle->GetInt("prefLicenseType", 0); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateprefLicenseUrl(DocumentParamsP *self) { + self->prefLicenseUrl = self->handle->GetASCII("prefLicenseUrl", ""); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateCompressionLevel(DocumentParamsP *self) { + self->CompressionLevel = self->handle->GetInt("CompressionLevel", 3); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateCheckExtension(DocumentParamsP *self) { + self->CheckExtension = self->handle->GetBool("CheckExtension", true); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateForceXML(DocumentParamsP *self) { + self->ForceXML = self->handle->GetInt("ForceXML", 3); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateSplitXML(DocumentParamsP *self) { + self->SplitXML = self->handle->GetBool("SplitXML", true); + } + // Auto generated code (Tools/params_utils.py:234) + static void updatePreferBinary(DocumentParamsP *self) { + self->PreferBinary = self->handle->GetBool("PreferBinary", false); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateAutoRemoveFile(DocumentParamsP *self) { + self->AutoRemoveFile = self->handle->GetBool("AutoRemoveFile", true); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateBackupPolicy(DocumentParamsP *self) { + self->BackupPolicy = self->handle->GetBool("BackupPolicy", true); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateCreateBackupFiles(DocumentParamsP *self) { + self->CreateBackupFiles = self->handle->GetBool("CreateBackupFiles", true); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateUseFCBakExtension(DocumentParamsP *self) { + self->UseFCBakExtension = self->handle->GetBool("UseFCBakExtension", false); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateSaveBackupDateFormat(DocumentParamsP *self) { + self->SaveBackupDateFormat = self->handle->GetASCII("SaveBackupDateFormat", "%Y%m%d-%H%M%S"); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateCountBackupFiles(DocumentParamsP *self) { + self->CountBackupFiles = self->handle->GetInt("CountBackupFiles", 1); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateOptimizeRecompute(DocumentParamsP *self) { + self->OptimizeRecompute = self->handle->GetBool("OptimizeRecompute", true); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateCanAbortRecompute(DocumentParamsP *self) { + self->CanAbortRecompute = self->handle->GetBool("CanAbortRecompute", true); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateUseHasher(DocumentParamsP *self) { + self->UseHasher = self->handle->GetBool("UseHasher", true); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateViewObjectTransaction(DocumentParamsP *self) { + self->ViewObjectTransaction = self->handle->GetBool("ViewObjectTransaction", false); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateWarnRecomputeOnRestore(DocumentParamsP *self) { + self->WarnRecomputeOnRestore = self->handle->GetBool("WarnRecomputeOnRestore", true); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateNoPartialLoading(DocumentParamsP *self) { + self->NoPartialLoading = self->handle->GetBool("NoPartialLoading", false); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateThumbnailNoBackground(DocumentParamsP *self) { + self->ThumbnailNoBackground = self->handle->GetBool("ThumbnailNoBackground", false); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateThumbnailSampleSize(DocumentParamsP *self) { + self->ThumbnailSampleSize = self->handle->GetInt("ThumbnailSampleSize", 0); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateDuplicateLabels(DocumentParamsP *self) { + self->DuplicateLabels = self->handle->GetBool("DuplicateLabels", false); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateTransactionOnRecompute(DocumentParamsP *self) { + self->TransactionOnRecompute = self->handle->GetBool("TransactionOnRecompute", false); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateRelativeStringID(DocumentParamsP *self) { + self->RelativeStringID = self->handle->GetBool("RelativeStringID", true); + } + // Auto generated code (Tools/params_utils.py:234) + static void updateEnableMaterialEdit(DocumentParamsP *self) { + self->EnableMaterialEdit = self->handle->GetBool("EnableMaterialEdit", true); + } +}; + +// Auto generated code (Tools/params_utils.py:252) +DocumentParamsP *instance() { + static DocumentParamsP *inst = new DocumentParamsP; + return inst; +} + +} // Anonymous namespace + +// Auto generated code (Tools/params_utils.py:261) +ParameterGrp::handle DocumentParams::getHandle() { + return instance()->handle; +} + +// Auto generated code (Tools/params_utils.py:269) +boost::signals2::signal & +DocumentParams::signalParamChanged() { + return instance()->signalParamChanged; +} + +// Auto generated code (Tools/params_utils.py:276) +void signalAll() { + instance()->signalAll(); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docprefAuthor() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const std::string & DocumentParams::getprefAuthor() { + return instance()->prefAuthor; +} + +// Auto generated code (Tools/params_utils.py:296) +const std::string & DocumentParams::defaultprefAuthor() { + const static std::string def = ""; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setprefAuthor(const std::string &v) { + instance()->handle->SetASCII("prefAuthor",v); + instance()->prefAuthor = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeprefAuthor() { + instance()->handle->RemoveASCII("prefAuthor"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docprefSetAuthorOnSave() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getprefSetAuthorOnSave() { + return instance()->prefSetAuthorOnSave; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultprefSetAuthorOnSave() { + const static bool def = false; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setprefSetAuthorOnSave(const bool &v) { + instance()->handle->SetBool("prefSetAuthorOnSave",v); + instance()->prefSetAuthorOnSave = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeprefSetAuthorOnSave() { + instance()->handle->RemoveBool("prefSetAuthorOnSave"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docprefCompany() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const std::string & DocumentParams::getprefCompany() { + return instance()->prefCompany; +} + +// Auto generated code (Tools/params_utils.py:296) +const std::string & DocumentParams::defaultprefCompany() { + const static std::string def = ""; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setprefCompany(const std::string &v) { + instance()->handle->SetASCII("prefCompany",v); + instance()->prefCompany = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeprefCompany() { + instance()->handle->RemoveASCII("prefCompany"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docprefLicenseType() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const long & DocumentParams::getprefLicenseType() { + return instance()->prefLicenseType; +} + +// Auto generated code (Tools/params_utils.py:296) +const long & DocumentParams::defaultprefLicenseType() { + const static long def = 0; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setprefLicenseType(const long &v) { + instance()->handle->SetInt("prefLicenseType",v); + instance()->prefLicenseType = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeprefLicenseType() { + instance()->handle->RemoveInt("prefLicenseType"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docprefLicenseUrl() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const std::string & DocumentParams::getprefLicenseUrl() { + return instance()->prefLicenseUrl; +} + +// Auto generated code (Tools/params_utils.py:296) +const std::string & DocumentParams::defaultprefLicenseUrl() { + const static std::string def = ""; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setprefLicenseUrl(const std::string &v) { + instance()->handle->SetASCII("prefLicenseUrl",v); + instance()->prefLicenseUrl = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeprefLicenseUrl() { + instance()->handle->RemoveASCII("prefLicenseUrl"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docCompressionLevel() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const long & DocumentParams::getCompressionLevel() { + return instance()->CompressionLevel; +} + +// Auto generated code (Tools/params_utils.py:296) +const long & DocumentParams::defaultCompressionLevel() { + const static long def = 3; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setCompressionLevel(const long &v) { + instance()->handle->SetInt("CompressionLevel",v); + instance()->CompressionLevel = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeCompressionLevel() { + instance()->handle->RemoveInt("CompressionLevel"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docCheckExtension() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getCheckExtension() { + return instance()->CheckExtension; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultCheckExtension() { + const static bool def = true; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setCheckExtension(const bool &v) { + instance()->handle->SetBool("CheckExtension",v); + instance()->CheckExtension = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeCheckExtension() { + instance()->handle->RemoveBool("CheckExtension"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docForceXML() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const long & DocumentParams::getForceXML() { + return instance()->ForceXML; +} + +// Auto generated code (Tools/params_utils.py:296) +const long & DocumentParams::defaultForceXML() { + const static long def = 3; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setForceXML(const long &v) { + instance()->handle->SetInt("ForceXML",v); + instance()->ForceXML = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeForceXML() { + instance()->handle->RemoveInt("ForceXML"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docSplitXML() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getSplitXML() { + return instance()->SplitXML; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultSplitXML() { + const static bool def = true; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setSplitXML(const bool &v) { + instance()->handle->SetBool("SplitXML",v); + instance()->SplitXML = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeSplitXML() { + instance()->handle->RemoveBool("SplitXML"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docPreferBinary() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getPreferBinary() { + return instance()->PreferBinary; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultPreferBinary() { + const static bool def = false; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setPreferBinary(const bool &v) { + instance()->handle->SetBool("PreferBinary",v); + instance()->PreferBinary = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removePreferBinary() { + instance()->handle->RemoveBool("PreferBinary"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docAutoRemoveFile() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getAutoRemoveFile() { + return instance()->AutoRemoveFile; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultAutoRemoveFile() { + const static bool def = true; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setAutoRemoveFile(const bool &v) { + instance()->handle->SetBool("AutoRemoveFile",v); + instance()->AutoRemoveFile = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeAutoRemoveFile() { + instance()->handle->RemoveBool("AutoRemoveFile"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docBackupPolicy() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getBackupPolicy() { + return instance()->BackupPolicy; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultBackupPolicy() { + const static bool def = true; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setBackupPolicy(const bool &v) { + instance()->handle->SetBool("BackupPolicy",v); + instance()->BackupPolicy = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeBackupPolicy() { + instance()->handle->RemoveBool("BackupPolicy"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docCreateBackupFiles() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getCreateBackupFiles() { + return instance()->CreateBackupFiles; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultCreateBackupFiles() { + const static bool def = true; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setCreateBackupFiles(const bool &v) { + instance()->handle->SetBool("CreateBackupFiles",v); + instance()->CreateBackupFiles = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeCreateBackupFiles() { + instance()->handle->RemoveBool("CreateBackupFiles"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docUseFCBakExtension() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getUseFCBakExtension() { + return instance()->UseFCBakExtension; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultUseFCBakExtension() { + const static bool def = false; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setUseFCBakExtension(const bool &v) { + instance()->handle->SetBool("UseFCBakExtension",v); + instance()->UseFCBakExtension = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeUseFCBakExtension() { + instance()->handle->RemoveBool("UseFCBakExtension"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docSaveBackupDateFormat() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const std::string & DocumentParams::getSaveBackupDateFormat() { + return instance()->SaveBackupDateFormat; +} + +// Auto generated code (Tools/params_utils.py:296) +const std::string & DocumentParams::defaultSaveBackupDateFormat() { + const static std::string def = "%Y%m%d-%H%M%S"; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setSaveBackupDateFormat(const std::string &v) { + instance()->handle->SetASCII("SaveBackupDateFormat",v); + instance()->SaveBackupDateFormat = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeSaveBackupDateFormat() { + instance()->handle->RemoveASCII("SaveBackupDateFormat"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docCountBackupFiles() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const long & DocumentParams::getCountBackupFiles() { + return instance()->CountBackupFiles; +} + +// Auto generated code (Tools/params_utils.py:296) +const long & DocumentParams::defaultCountBackupFiles() { + const static long def = 1; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setCountBackupFiles(const long &v) { + instance()->handle->SetInt("CountBackupFiles",v); + instance()->CountBackupFiles = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeCountBackupFiles() { + instance()->handle->RemoveInt("CountBackupFiles"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docOptimizeRecompute() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getOptimizeRecompute() { + return instance()->OptimizeRecompute; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultOptimizeRecompute() { + const static bool def = true; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setOptimizeRecompute(const bool &v) { + instance()->handle->SetBool("OptimizeRecompute",v); + instance()->OptimizeRecompute = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeOptimizeRecompute() { + instance()->handle->RemoveBool("OptimizeRecompute"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docCanAbortRecompute() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getCanAbortRecompute() { + return instance()->CanAbortRecompute; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultCanAbortRecompute() { + const static bool def = true; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setCanAbortRecompute(const bool &v) { + instance()->handle->SetBool("CanAbortRecompute",v); + instance()->CanAbortRecompute = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeCanAbortRecompute() { + instance()->handle->RemoveBool("CanAbortRecompute"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docUseHasher() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getUseHasher() { + return instance()->UseHasher; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultUseHasher() { + const static bool def = true; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setUseHasher(const bool &v) { + instance()->handle->SetBool("UseHasher",v); + instance()->UseHasher = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeUseHasher() { + instance()->handle->RemoveBool("UseHasher"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docViewObjectTransaction() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getViewObjectTransaction() { + return instance()->ViewObjectTransaction; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultViewObjectTransaction() { + const static bool def = false; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setViewObjectTransaction(const bool &v) { + instance()->handle->SetBool("ViewObjectTransaction",v); + instance()->ViewObjectTransaction = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeViewObjectTransaction() { + instance()->handle->RemoveBool("ViewObjectTransaction"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docWarnRecomputeOnRestore() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getWarnRecomputeOnRestore() { + return instance()->WarnRecomputeOnRestore; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultWarnRecomputeOnRestore() { + const static bool def = true; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setWarnRecomputeOnRestore(const bool &v) { + instance()->handle->SetBool("WarnRecomputeOnRestore",v); + instance()->WarnRecomputeOnRestore = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeWarnRecomputeOnRestore() { + instance()->handle->RemoveBool("WarnRecomputeOnRestore"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docNoPartialLoading() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getNoPartialLoading() { + return instance()->NoPartialLoading; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultNoPartialLoading() { + const static bool def = false; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setNoPartialLoading(const bool &v) { + instance()->handle->SetBool("NoPartialLoading",v); + instance()->NoPartialLoading = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeNoPartialLoading() { + instance()->handle->RemoveBool("NoPartialLoading"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docThumbnailNoBackground() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getThumbnailNoBackground() { + return instance()->ThumbnailNoBackground; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultThumbnailNoBackground() { + const static bool def = false; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setThumbnailNoBackground(const bool &v) { + instance()->handle->SetBool("ThumbnailNoBackground",v); + instance()->ThumbnailNoBackground = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeThumbnailNoBackground() { + instance()->handle->RemoveBool("ThumbnailNoBackground"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docThumbnailSampleSize() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const long & DocumentParams::getThumbnailSampleSize() { + return instance()->ThumbnailSampleSize; +} + +// Auto generated code (Tools/params_utils.py:296) +const long & DocumentParams::defaultThumbnailSampleSize() { + const static long def = 0; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setThumbnailSampleSize(const long &v) { + instance()->handle->SetInt("ThumbnailSampleSize",v); + instance()->ThumbnailSampleSize = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeThumbnailSampleSize() { + instance()->handle->RemoveInt("ThumbnailSampleSize"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docDuplicateLabels() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getDuplicateLabels() { + return instance()->DuplicateLabels; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultDuplicateLabels() { + const static bool def = false; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setDuplicateLabels(const bool &v) { + instance()->handle->SetBool("DuplicateLabels",v); + instance()->DuplicateLabels = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeDuplicateLabels() { + instance()->handle->RemoveBool("DuplicateLabels"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docTransactionOnRecompute() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getTransactionOnRecompute() { + return instance()->TransactionOnRecompute; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultTransactionOnRecompute() { + const static bool def = false; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setTransactionOnRecompute(const bool &v) { + instance()->handle->SetBool("TransactionOnRecompute",v); + instance()->TransactionOnRecompute = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeTransactionOnRecompute() { + instance()->handle->RemoveBool("TransactionOnRecompute"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docRelativeStringID() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getRelativeStringID() { + return instance()->RelativeStringID; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultRelativeStringID() { + const static bool def = true; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setRelativeStringID(const bool &v) { + instance()->handle->SetBool("RelativeStringID",v); + instance()->RelativeStringID = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeRelativeStringID() { + instance()->handle->RemoveBool("RelativeStringID"); +} + +// Auto generated code (Tools/params_utils.py:284) +const char *DocumentParams::docEnableMaterialEdit() { + return ""; +} + +// Auto generated code (Tools/params_utils.py:290) +const bool & DocumentParams::getEnableMaterialEdit() { + return instance()->EnableMaterialEdit; +} + +// Auto generated code (Tools/params_utils.py:296) +const bool & DocumentParams::defaultEnableMaterialEdit() { + const static bool def = true; + return def; +} + +// Auto generated code (Tools/params_utils.py:303) +void DocumentParams::setEnableMaterialEdit(const bool &v) { + instance()->handle->SetBool("EnableMaterialEdit",v); + instance()->EnableMaterialEdit = v; +} + +// Auto generated code (Tools/params_utils.py:310) +void DocumentParams::removeEnableMaterialEdit() { + instance()->handle->RemoveBool("EnableMaterialEdit"); +} +//[[[end]]] diff --git a/src/App/DocumentParams.h b/src/App/DocumentParams.h new file mode 100644 index 0000000000..aada778757 --- /dev/null +++ b/src/App/DocumentParams.h @@ -0,0 +1,359 @@ +/**************************************************************************** + * Copyright (c) 2022 Zheng Lei (realthunder) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ****************************************************************************/ + +#ifndef DOCUMENT_PARAMS_H +#define DOCUMENT_PARAMS_H + +/*[[[cog +import DocumentParams +DocumentParams.declare() +]]]*/ + +// Auto generated code (Tools/params_utils.py:68) +#include +#include + +// Auto generated code (Tools/params_utils.py:74) +namespace App { +/** Convenient class to obtain App::Document related parameters + + * The parameters are under group "User parameter:BaseApp/Preferences/Document" + * + * This class is auto generated by App/DocumentParams.py. Modify that file + * instead of this one, if you want to add any parameter. You need + * to install Cog Python package for code generation: + * @code + * pip install cogapp + * @endcode + * + * Once modified, you can regenerate the header and the source file, + * @code + * python3 -m cogapp -r App/DocumentParams.h App/DocumentParams.cpp + * @endcode + * + * You can add a new parameter by adding lines in App/DocumentParams.py. Available + * parameter types are 'Int, UInt, String, Bool, Float'. For example, to add + * a new Int type parameter, + * @code + * ParamInt(parameter_name, default_value, documentation, on_change=False) + * @endcode + * + * If there is special handling on parameter change, pass in on_change=True. + * And you need to provide a function implementation in App/DocumentParams.cpp with + * the following signature. + * @code + * void DocumentParams:onChanged() + * @endcode + */ +class AppExport DocumentParams { +public: + static ParameterGrp::handle getHandle(); + + static boost::signals2::signal &signalParamChanged(); + static void signalAll(); + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter prefAuthor + static const std::string & getprefAuthor(); + static const std::string & defaultprefAuthor(); + static void removeprefAuthor(); + static void setprefAuthor(const std::string &v); + static const char *docprefAuthor(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter prefSetAuthorOnSave + static const bool & getprefSetAuthorOnSave(); + static const bool & defaultprefSetAuthorOnSave(); + static void removeprefSetAuthorOnSave(); + static void setprefSetAuthorOnSave(const bool &v); + static const char *docprefSetAuthorOnSave(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter prefCompany + static const std::string & getprefCompany(); + static const std::string & defaultprefCompany(); + static void removeprefCompany(); + static void setprefCompany(const std::string &v); + static const char *docprefCompany(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter prefLicenseType + static const long & getprefLicenseType(); + static const long & defaultprefLicenseType(); + static void removeprefLicenseType(); + static void setprefLicenseType(const long &v); + static const char *docprefLicenseType(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter prefLicenseUrl + static const std::string & getprefLicenseUrl(); + static const std::string & defaultprefLicenseUrl(); + static void removeprefLicenseUrl(); + static void setprefLicenseUrl(const std::string &v); + static const char *docprefLicenseUrl(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter CompressionLevel + static const long & getCompressionLevel(); + static const long & defaultCompressionLevel(); + static void removeCompressionLevel(); + static void setCompressionLevel(const long &v); + static const char *docCompressionLevel(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter CheckExtension + static const bool & getCheckExtension(); + static const bool & defaultCheckExtension(); + static void removeCheckExtension(); + static void setCheckExtension(const bool &v); + static const char *docCheckExtension(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter ForceXML + static const long & getForceXML(); + static const long & defaultForceXML(); + static void removeForceXML(); + static void setForceXML(const long &v); + static const char *docForceXML(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter SplitXML + static const bool & getSplitXML(); + static const bool & defaultSplitXML(); + static void removeSplitXML(); + static void setSplitXML(const bool &v); + static const char *docSplitXML(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter PreferBinary + static const bool & getPreferBinary(); + static const bool & defaultPreferBinary(); + static void removePreferBinary(); + static void setPreferBinary(const bool &v); + static const char *docPreferBinary(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter AutoRemoveFile + static const bool & getAutoRemoveFile(); + static const bool & defaultAutoRemoveFile(); + static void removeAutoRemoveFile(); + static void setAutoRemoveFile(const bool &v); + static const char *docAutoRemoveFile(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter BackupPolicy + static const bool & getBackupPolicy(); + static const bool & defaultBackupPolicy(); + static void removeBackupPolicy(); + static void setBackupPolicy(const bool &v); + static const char *docBackupPolicy(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter CreateBackupFiles + static const bool & getCreateBackupFiles(); + static const bool & defaultCreateBackupFiles(); + static void removeCreateBackupFiles(); + static void setCreateBackupFiles(const bool &v); + static const char *docCreateBackupFiles(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter UseFCBakExtension + static const bool & getUseFCBakExtension(); + static const bool & defaultUseFCBakExtension(); + static void removeUseFCBakExtension(); + static void setUseFCBakExtension(const bool &v); + static const char *docUseFCBakExtension(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter SaveBackupDateFormat + static const std::string & getSaveBackupDateFormat(); + static const std::string & defaultSaveBackupDateFormat(); + static void removeSaveBackupDateFormat(); + static void setSaveBackupDateFormat(const std::string &v); + static const char *docSaveBackupDateFormat(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter CountBackupFiles + static const long & getCountBackupFiles(); + static const long & defaultCountBackupFiles(); + static void removeCountBackupFiles(); + static void setCountBackupFiles(const long &v); + static const char *docCountBackupFiles(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter OptimizeRecompute + static const bool & getOptimizeRecompute(); + static const bool & defaultOptimizeRecompute(); + static void removeOptimizeRecompute(); + static void setOptimizeRecompute(const bool &v); + static const char *docOptimizeRecompute(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter CanAbortRecompute + static const bool & getCanAbortRecompute(); + static const bool & defaultCanAbortRecompute(); + static void removeCanAbortRecompute(); + static void setCanAbortRecompute(const bool &v); + static const char *docCanAbortRecompute(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter UseHasher + static const bool & getUseHasher(); + static const bool & defaultUseHasher(); + static void removeUseHasher(); + static void setUseHasher(const bool &v); + static const char *docUseHasher(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter ViewObjectTransaction + static const bool & getViewObjectTransaction(); + static const bool & defaultViewObjectTransaction(); + static void removeViewObjectTransaction(); + static void setViewObjectTransaction(const bool &v); + static const char *docViewObjectTransaction(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter WarnRecomputeOnRestore + static const bool & getWarnRecomputeOnRestore(); + static const bool & defaultWarnRecomputeOnRestore(); + static void removeWarnRecomputeOnRestore(); + static void setWarnRecomputeOnRestore(const bool &v); + static const char *docWarnRecomputeOnRestore(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter NoPartialLoading + static const bool & getNoPartialLoading(); + static const bool & defaultNoPartialLoading(); + static void removeNoPartialLoading(); + static void setNoPartialLoading(const bool &v); + static const char *docNoPartialLoading(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter ThumbnailNoBackground + static const bool & getThumbnailNoBackground(); + static const bool & defaultThumbnailNoBackground(); + static void removeThumbnailNoBackground(); + static void setThumbnailNoBackground(const bool &v); + static const char *docThumbnailNoBackground(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter ThumbnailSampleSize + static const long & getThumbnailSampleSize(); + static const long & defaultThumbnailSampleSize(); + static void removeThumbnailSampleSize(); + static void setThumbnailSampleSize(const long &v); + static const char *docThumbnailSampleSize(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter DuplicateLabels + static const bool & getDuplicateLabels(); + static const bool & defaultDuplicateLabels(); + static void removeDuplicateLabels(); + static void setDuplicateLabels(const bool &v); + static const char *docDuplicateLabels(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter TransactionOnRecompute + static const bool & getTransactionOnRecompute(); + static const bool & defaultTransactionOnRecompute(); + static void removeTransactionOnRecompute(); + static void setTransactionOnRecompute(const bool &v); + static const char *docTransactionOnRecompute(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter RelativeStringID + static const bool & getRelativeStringID(); + static const bool & defaultRelativeStringID(); + static void removeRelativeStringID(); + static void setRelativeStringID(const bool &v); + static const char *docRelativeStringID(); + //@} + + // Auto generated code (Tools/params_utils.py:118) + //@{ + /// Accessor for parameter EnableMaterialEdit + static const bool & getEnableMaterialEdit(); + static const bool & defaultEnableMaterialEdit(); + static void removeEnableMaterialEdit(); + static void setEnableMaterialEdit(const bool &v); + static const char *docEnableMaterialEdit(); + //@} + +// Auto generated code (Tools/params_utils.py:146) +}; // class DocumentParams +} // namespace App +//[[[end]]] + +#endif // DOCUMENT_PARAMS_H diff --git a/src/App/StringHasher.cpp b/src/App/StringHasher.cpp new file mode 100644 index 0000000000..596c47bb97 --- /dev/null +++ b/src/App/StringHasher.cpp @@ -0,0 +1,646 @@ +/**************************************************************************** + * Copyright (c) 2022 Zheng Lei (realthunder) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ****************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +FC_LOG_LEVEL_INIT("App",true,true) + +namespace bio = boost::iostreams; +using namespace App; + +/////////////////////////////////////////////////////////// + +struct StringIDHasher { + std::size_t operator()(const StringID *sid) const { + if (!sid) + return 0; + return qHash(sid->data(), qHash(sid->postfix())); + } + + bool operator()(const StringID *a, const StringID *b) const { + if (a == b) + return true; + if (!a || !b) + return false; + return a->data() == b->data() && a->postfix() == b->postfix(); + } +}; + +typedef boost::bimap< + boost::bimaps::unordered_set_of, + boost::bimaps::set_of > + HashMapBase; + +class StringHasher::HashMap: public HashMapBase +{ +public: + bool SaveAll = false; + int Threshold = 0; +}; + +/////////////////////////////////////////////////////////// + +TYPESYSTEM_SOURCE_ABSTRACT(App::StringID, Base::BaseClass) + +StringID::~StringID() +{ + if (_hasher) + _hasher->_hashes->right.erase(_id); +} + +PyObject *StringID::getPyObject() { + return new StringIDPy(this); +} + +PyObject *StringID::getPyObjectWithIndex(int index) { + auto res = new StringIDPy(this); + res->_index = index; + return res; +} + +std::string StringID::toString(int index) const { + std::ostringstream ss; + ss << '#' << std::hex << value(); + if (index) + ss << ':' << index; + return ss.str(); +} + +StringID::IndexID StringID::fromString(const char *name, bool eof, int size) { + IndexID res; + res.id = 0; + res.index = 0; + if (!name) { + res.id = -1; + return res; + } + if (size < 0) + size = std::strlen(name); + bio::stream iss(name, size); + char sep = 0; + char sep2 = 0; + iss >> sep >> std::hex >> res.id >> sep2 >> res.index; + if((eof && !iss.eof()) || sep!='#' || (sep2!=0 && sep2!=':')) { + res.id = -1; + return res; + } + return res; +} + +std::string StringID::dataToText(int index) const { + if(isHashed() || isBinary()) + return _data.toBase64().constData(); + + std::string res(_data.constData()); + if (index) + res += std::to_string(index); + if (_postfix.size()) + res += _postfix.constData(); + return res; +} + +void StringID::mark() const +{ + if (isMarked()) + return; + _flags.set(Marked); + for (auto & sid : _sids) + sid.deref().mark(); +} + +/////////////////////////////////////////////////////////// + +TYPESYSTEM_SOURCE(App::StringHasher, Base::Persistence) + +StringHasher::StringHasher() + :_hashes(new HashMap) +{} + +StringHasher::~StringHasher() { + clear(); +} + +void StringHasher::setSaveAll(bool enable) { + if (_hashes->SaveAll == enable) + return; + _hashes->SaveAll = enable; + compact(); +} + +void StringHasher::compact() +{ + if (_hashes->SaveAll) + return; + + std::deque pendings; + for (auto & v : _hashes->right) { + if (!v.second->isPersistent() && v.second->getRefCount() == 1) + pendings.emplace_back(v.second); + } + while(pendings.size()) { + StringIDRef sid = pendings.front(); + pendings.pop_front(); + if (!_hashes->right.erase(sid.value())) + continue; + sid._sid->_hasher = nullptr; + sid._sid->unref(); + for (auto & s : sid._sid->_sids) { + if (s._sid->_hasher == this + && !s._sid->isPersistent() + && s._sid->getRefCount() == 2) + pendings.push_back(s); + } + } +} + +bool StringHasher::getSaveAll() const { + return _hashes->SaveAll; +} + +void StringHasher::setThreshold(int threshold) { + _hashes->Threshold = threshold; +} + +int StringHasher::getThreshold() const { + return _hashes->Threshold; +} + +long StringHasher::lastID() const { + if(_hashes->right.empty()) + return 0; + auto it = _hashes->right.end(); + --it; + return it->first; +} + +StringIDRef StringHasher::getID(const char *text, int len, bool hashable) { + if(len<0) len = strlen(text); + return getID(QByteArray::fromRawData(text,len),false,hashable); +} + +StringIDRef StringHasher::getID(const QByteArray &data, bool binary, bool hashable, bool nocopy) +{ + bool hashed = hashable && _hashes->Threshold>0 + && (int)data.size()>_hashes->Threshold; + + StringID d; + if(hashed) { + QCryptographicHash hasher(QCryptographicHash::Sha1); + hasher.addData(data); + d._data = hasher.result(); + } else + d._data = data; + + auto it = _hashes->left.find(&d); + if(it!=_hashes->left.end()) + return StringIDRef(it->first); + + if(!hashed && !nocopy) { + // if not hashed, make a deep copy of the data + d._data = QByteArray(data.constData(), data.size()); + } + + StringIDRef sid(new StringID(lastID()+1,d._data,binary,hashed)); + return StringIDRef(insert(sid)); +} + +StringIDRef StringHasher::getID(long id, int index) const { + if(id<=0) + return StringIDRef(); + auto it = _hashes->right.find(id); + if(it == _hashes->right.end()) + return StringIDRef(); + StringIDRef res(it->second); + res._index = index; + return res; +} + +void StringHasher::setPersistenceFileName(const char *filename) const { + if(!filename) + filename = ""; + _filename = filename; +} + +const std::string &StringHasher::getPersistenceFileName() const { + return _filename; +} + +void StringHasher::Save(Base::Writer &writer) const { + + size_t count; + if (_hashes->SaveAll) + count = _hashes->size(); + else { + count = 0; + for (auto & v : _hashes->right) { + if (v.second->isMarked() || v.second->isPersistent()) + ++count; + } + } + + writer.Stream() << writer.ind() + << "SaveAll + << "\" threshold=\"" << _hashes->Threshold << "\""; + + if(!count) { + writer.Stream() << " count=\"0\">\n"; + return; + } + + writer.Stream() << " count=\"0\" new=\"1\"/>\n"; + + writer.Stream() << writer.ind() << "\n"; + return; + } + + writer.Stream() << " count=\"" << count << "\">\n"; + saveStream(writer.beginCharStream(false) << '\n'); + writer.endCharStream() << '\n'; + writer.Stream() << writer.ind() << "\n"; +} + +void StringHasher::SaveDocFile (Base::Writer &writer) const { + std::size_t count = _hashes->SaveAll?this->size():this->count(); + writer.Stream() << count << '\n'; + saveStream(writer.Stream()); +} + +void StringHasher::saveStream(std::ostream &s) const { + Base::OutputStream str(s,false); + boost::io::ios_flags_saver ifs(s); + s << std::hex; + + bool allowRealtive = DocumentParams::getRelativeStringID(); + long anchor = 0; + const StringID *last = nullptr; + long lastid = 0; + bool relative = false; + + for(auto &v : _hashes->right) { + auto & d = *v.second; + long id = d._id; + if (!_hashes->SaveAll && !d.isMarked() && !d.isPersistent()) + continue; + + if (!allowRealtive) + s << id; + else { + // We use relative coding to save space. But in order to have some + // minimum protection against corruption, write an absolute value every + // once a while. + relative = (id - anchor) < 1000; + if (relative) + s << '-' << id - lastid; + else { + anchor = id; + s << id; + } + lastid = id; + } + + int offset = d.isPostfixEncoded() ? 1 : 0; + + StringID::IndexID prefixid; + prefixid.id = 0; + prefixid.index = 0; + if (d.isPrefixID()) { + assert(d._sids.size() > offset); + prefixid.id = d._sids[offset].value(); + } + else if (d.isPrefixIDIndex()) { + prefixid = StringID::fromString(d._data); + assert(d._sids.size() > offset && d._sids[offset].value() == prefixid.id); + } + + auto flags = d._flags; + flags.reset(StringID::Marked); + s << '.' << flags.to_ulong(); + + int i = 0; + if (!relative) { + for (; i_sids.size(); ++i) { + long m = last->_sids[i].value(); + long n = d._sids[i].value(); + if (n < m) + s << ".-" << m-n; + else + s << '.' << n-m; + } + } + for (; i> marker; + std::size_t count; + _hashes->clear(); + if (marker == "StringTableStart") { + reader >> ver >> count; + if (ver != "v1") + FC_WARN("Unknown string table format"); + restoreStreamNew(reader, count); + return; + } + reader >> count; + restoreStream(reader,count); +} + +void StringHasher::restoreStreamNew(std::istream &s, std::size_t count) { + Base::InputStream str(s,false); + _hashes->clear(); + std::string content; + boost::io::ios_flags_saver ifs(s); + s >> std::hex; + std::vector tokens; + long lastid = 0; + const StringID * last = nullptr; + + std::string tmp; + + for(uint32_t i=0;i> tmp)) + FC_THROWM(Base::RuntimeError, "Invalid string table"); + + tokens.clear(); + boost::split(tokens, tmp, boost::is_any_of(".")); + if (tokens.size() < 2) + FC_THROWM(Base::RuntimeError, "Invalid string table"); + + long id; + bool relative = false; + if (tokens[0][0] == '-') { + relative = true; + id = lastid + strtol(tokens[0].c_str()+1, nullptr, 16); + } else + id = strtol(tokens[0].c_str(), nullptr, 16); + + lastid = id; + + unsigned long flag = strtol(tokens[1].c_str(), nullptr, 16); + StringIDRef sid(new StringID(id,QByteArray(),flag)); + + StringID & d = *sid._sid; + d._sids.reserve(tokens.size()-2); + + int j = 2; + if (relative && last) { + for (;j<(int)tokens.size() && j-2_sids.size(); ++j) { + long m = last->_sids[j-2].value(); + long n; + if (tokens[j][0] == '-') + n = -strtol(&tokens[j][1], nullptr, 16); + else + n = strtol(&tokens[j][0], nullptr, 16); + StringIDRef sid = getID(m + n); + if (!sid) + FC_THROWM(Base::RuntimeError, "Invalid string id reference"); + d._sids.push_back(sid); + } + } + for (;j<(int)tokens.size(); ++j) { + long n = strtol(&tokens[j][0], nullptr, 16) ; + StringIDRef sid = getID(relative ? id - n : n); + if (!sid) + FC_THROWM(Base::RuntimeError, "Invalid string id reference"); + d._sids.push_back(sid); + } + + if (!d.isPostfixed()) { + str >> content; + if(d.isHashed() || d.isBinary()) + d._data = QByteArray::fromBase64(content.c_str()); + else + d._data = content.c_str(); + } else { + int offset = 0; + if (d.isPostfixEncoded()) { + offset = 1; + if (d._sids.empty()) + FC_THROWM(Base::RuntimeError, "Missing string postfix"); + d._postfix = d._sids[0]._sid->_data; + } + if (d.isIndexed()) { + if (d._sids.size() <= offset) + FC_THROWM(Base::RuntimeError, "Missing string prefix"); + d._data = d._sids[offset]._sid->_data; + } + else if (d.isPrefixID() || d.isPrefixIDIndex()) { + if (d._sids.size() <= offset) + FC_THROWM(Base::RuntimeError, "Missing string prefix id"); + int index = 0; + if (d.isPrefixIDIndex()) { + if (!(s >> index)) + FC_THROWM(Base::RuntimeError, "Missing string prefix index"); + } + d._data = d._sids[offset]._sid->toString(index).c_str(); + } else { + s >> content; + d._data = content.c_str(); + } + if (!d.isPostfixEncoded()) { + s >> content; + d._postfix = content.c_str(); + } + } + + last = insert(sid); + } +} + +StringID * StringHasher::insert(const StringIDRef & sid) +{ + assert(sid && sid._sid->_hasher == nullptr); + auto & d = *sid._sid; + d._hasher = this; + d.ref(); + auto res = _hashes->right.insert(_hashes->right.end(), + HashMap::right_map::value_type(sid.value(),&d)); + if (res->second != &d) { + d._hasher = nullptr; + d.unref(); + } + return res->second; +} + +void StringHasher::restoreStream(std::istream &s, std::size_t count) { + Base::InputStream str(s,false); + _hashes->clear(); + std::string content; + for(uint32_t i=0;i> id >> type >> content; + StringIDRef sid = new StringID(id,QByteArray(),type); + if(sid.isHashed() || sid.isBinary()) { + sid._sid->_data = QByteArray::fromBase64(content.c_str()); + } else + sid._sid->_data = QByteArray(content.c_str()); + insert(sid); + } +} + +void StringHasher::clear() { + for (auto & v : _hashes->right) { + v.second->_hasher = nullptr; + v.second->unref(); + } + _hashes->clear(); +} + +size_t StringHasher::size() const { + return _hashes->size(); +} + +size_t StringHasher::count() const { + size_t count = 0; + for(auto &v : _hashes->right) + if(v.second->getRefCount()>1) + ++count; + return count; +} + +void StringHasher::Restore(Base::XMLReader &reader) { + clear(); + reader.readElement("StringHasher"); + _hashes->SaveAll = reader.getAttributeAsInteger("saveall")?true:false; + _hashes->Threshold = reader.getAttributeAsInteger("threshold"); + + bool newtag = false; + if (reader.getAttributeAsInteger("new","0") > 0) { + reader.readElement("StringHasher2"); + newtag = true; + } + + if(reader.hasAttribute("file")) { + const char *file = reader.getAttribute("file"); + if(*file) + reader.addFile(file,this); + return; + } + + std::size_t count = reader.getAttributeAsUnsigned("count"); + if (newtag) { + restoreStreamNew(reader.beginCharStream(false),count); + reader.readEndElement("StringHasher2"); + return; + } + else if(count && reader.FileVersion > 1) + restoreStream(reader.beginCharStream(false),count); + else { + for(std::size_t i=0;iSaveAll?size():count()) * 10; +} + +PyObject *StringHasher::getPyObject() { + return new StringHasherPy(this); +} + +std::map StringHasher::getIDMap() const { + std::map ret; + for(auto &v : _hashes->right) + ret.emplace_hint(ret.end(), v.first, StringIDRef(v.second)); + return ret; +} + +void StringHasher::clearMarks() const +{ + for (auto & v : _hashes->right) + v.second->_flags.reset(StringID::Marked); +} diff --git a/src/App/StringHasher.h b/src/App/StringHasher.h new file mode 100644 index 0000000000..ca5b41670a --- /dev/null +++ b/src/App/StringHasher.h @@ -0,0 +1,481 @@ +/**************************************************************************** + * Copyright (c) 2022 Zheng Lei (realthunder) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ****************************************************************************/ + +#ifndef APP_STRINGID_H +#define APP_STRINGID_H + +#include +#include + +#include +#include + +#include +#include +#include + +namespace App { + +class StringHasher; +class StringID; +class StringIDRef; +typedef Base::Reference StringHasherRef; + +class AppExport StringID: public Base::BaseClass, public Base::Handled { + TYPESYSTEM_HEADER_WITH_OVERRIDE(); +public: + enum Flag { + Binary, + Hashed, + PostfixEncoded, + Postfixed, + Indexed, + PrefixID, + PrefixIDIndex, + Persistent, + Marked, + }; + StringID(long id, const QByteArray &data, bool binary, bool hashed) + :_id(id),_data(data) + { + if(binary) _flags.set(Binary); + if(hashed) _flags.set(Hashed); + } + + StringID(long id, const QByteArray &data, uint8_t flags) + :_id(id),_data(data),_flags(flags) + {} + + StringID() + :_id(0),_flags(0) + {} + + virtual ~StringID(); + + long value() const {return _id;} + const QVector &relatedIDs() const {return _sids;} + + bool isBinary() const {return _flags.test(Binary);} + bool isHashed() const {return _flags.test(Hashed);} + bool isPostfixed() const {return _flags.test(Postfixed);} + bool isPostfixEncoded() const {return _flags.test(PostfixEncoded);} + bool isIndexed() const {return _flags.test(Indexed);} + bool isPrefixID() const {return _flags.test(PrefixID);} + bool isPrefixIDIndex() const {return _flags.test(PrefixIDIndex);} + bool isMarked() const {return _flags.test(Marked);} + bool isPersistent() const {return _flags.test(Persistent);} + + bool isFromSameHasher(const StringHasherRef & hasher) const + { + return this->_hasher == hasher; + } + + StringHasherRef getHasher() const + { + return StringHasherRef(_hasher); + } + + const QByteArray data() const {return _data;} + const QByteArray postfix() const {return _postfix;} + + virtual PyObject *getPyObject() override; + PyObject *getPyObjectWithIndex(int index); + + std::string toString(int index) const; + + struct IndexID { + long id; + int index; + + explicit operator bool() const { + return id > 0; + } + + friend std::ostream & operator << (std::ostream &s, const IndexID & id) { + s << id.id; + if (id.index) + s << ':' << id.index; + return s; + } + }; + static IndexID fromString(const char *name, bool eof=true, int size = -1); + + static IndexID fromString(const QByteArray &bytes, bool eof=true) { + return fromString(bytes.constData(), eof, bytes.size()); + } + + std::string dataToText(int index) const; + + void toBytes(QByteArray &bytes, int index) const { + if (_postfix.size()) + bytes = _data + _postfix; + else if (index) + bytes = _data + QByteArray::number(index); + else + bytes = _data; + } + + void mark() const; + + void setPersistent(bool enable) + { + _flags.set(Persistent, enable); + } + + bool operator<(const StringID &other) const { + return compare(other) < 0; + } + + int compare(const StringID &other) const { + if (_hasher < other._hasher) + return -1; + if (_hasher > other._hasher) + return 1; + if (_id < other._id) + return -1; + if (_id > other._id) + return 1; + return 0; + } + + friend class StringHasher; + +private: + long _id; + QByteArray _data; + QByteArray _postfix; + StringHasher *_hasher = nullptr; + mutable std::bitset<32> _flags; + mutable QVector _sids; +}; + +////////////////////////////////////////////////////////////////////////// + +class StringIDRef +{ +public: + StringIDRef() + :_sid(0), _index(0) + {} + + StringIDRef(StringID* p, int index=0) + : _sid(p), _index(index) + { + if (_sid) + _sid->ref(); + } + + StringIDRef(const StringIDRef & other) + : _sid(other._sid) + , _index(other._index) + { + if (_sid) + _sid->ref(); + } + + StringIDRef(StringIDRef && other) + : _sid(other._sid) + , _index(other._index) + { + other._sid = nullptr; + } + + StringIDRef(const StringIDRef & other, int index) + : _sid(other._sid) + , _index(index) + { + if (_sid) + _sid->ref(); + } + + ~StringIDRef() + { + if (_sid) + _sid->unref(); + } + + void reset(const StringIDRef & p = StringIDRef()) { + *this = p; + } + + void reset(const StringIDRef &p, int index) { + *this = p; + this->_index = index; + } + + void swap(StringIDRef &p) { + if(*this != p) { + auto tmp = p; + p = *this; + *this = tmp; + } + } + + StringIDRef & operator=(StringID* p) { + if (_sid == p) + return *this; + if (_sid) + _sid->unref(); + _sid = p; + if (_sid) + _sid->ref(); + this->_index = 0; + return *this; + } + + StringIDRef & operator=(const StringIDRef & p) { + if (_sid != p._sid) { + if (_sid) + _sid->unref(); + _sid = p._sid; + if (_sid) + _sid->ref(); + } + this->_index = p._index; + return *this; + } + + StringIDRef & operator=(StringIDRef && p) { + if (_sid != p._sid) { + if (_sid) + _sid->unref(); + _sid = p._sid; + p._sid = nullptr; + } + this->_index = p._index; + return *this; + } + + bool operator<(const StringIDRef & p) const { + if (!_sid) + return true; + if (!p._sid) + return false; + int res = _sid->compare(*p._sid); + if (res < 0) + return true; + if (res > 0) + return false; + return _index < p._index; + } + + bool operator==(const StringIDRef & p) const { + return _sid == p._sid && _index == p._index; + } + + bool operator!=(const StringIDRef & p) const { + return _sid != p._sid || _index != p._index; + } + + explicit operator bool() const { + return _sid != nullptr; + } + + int getRefCount(void) const { + if (_sid) + return _sid->getRefCount(); + return 0; + } + + std::string toString() const { + if (_sid) + return _sid->toString(_index); + return std::string(); + } + + std::string dataToText() const { + if (_sid) + return _sid->dataToText(_index); + return std::string(); + } + + const char * constData() const { + if (_sid) { + assert(_index == 0); + assert(_sid->postfix().isEmpty()); + return _sid->data().constData(); + } + return ""; + } + + const StringID & deref() const { + return *_sid; + } + + long value() const { + if (_sid) + return _sid->value(); + return 0; + } + + QVector relatedIDs() const { + if (_sid) + return _sid->relatedIDs(); + return QVector(); + } + + bool isBinary() const { + if (_sid) + return _sid->isBinary(); + return false; + } + + bool isHashed() const { + if (_sid) + return _sid->isHashed(); + return false; + } + + void toBytes(QByteArray &bytes) const { + if (_sid) + _sid->toBytes(bytes, _index); + } + + PyObject *getPyObject(void) { + if (_sid) + return _sid->getPyObjectWithIndex(_index); + Py_INCREF(Py_None); + return Py_None; + } + + void mark() const { + if (_sid) + _sid->mark(); + } + + bool isMarked() const { + return _sid && _sid->isMarked(); + } + + bool isFromSameHasher(const StringHasherRef & hasher) const + { + return _sid && _sid->isFromSameHasher(hasher); + } + + StringHasherRef getHasher() const + { + if (_sid) + return _sid->getHasher(); + return StringHasherRef(); + } + + void setPersistent(bool enable) + { + if (_sid) + _sid->setPersistent(enable); + } + + friend class StringHasher; + +private: + StringID *_sid; + int _index; +}; + +/// A String table to map string from/to a unique integer +class AppExport StringHasher: public Base::Persistence, public Base::Handled { + + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + +public: + StringHasher(); + virtual ~StringHasher(); + + virtual unsigned int getMemSize (void) const override; + virtual void Save (Base::Writer &/*writer*/) const override; + virtual void Restore(Base::XMLReader &/*reader*/) override; + virtual void SaveDocFile (Base::Writer &/*writer*/) const override; + virtual void RestoreDocFile (Base::Reader &/*reader*/) override; + void setPersistenceFileName(const char *name) const; + const std::string &getPersistenceFileName() const; + + /** Maps an arbitrary string to an integer + * + * The function maps an arbitrary text string to a unique integer ID, which + * is returned as a shared pointer to reference count the ID so that it is + * possible to prune any unused strings. + * + * If the string is longer than the threshold setting of this StringHasher, + * it will be sha1 hashed before storing, and the original content of the + * string is discarded. + * + * The purpose of function is to provide a short form of a stable string + * identification. + */ + StringIDRef getID(const char *text, int len=-1, bool hashable=false); + + /** Map text or binary data to an integer */ + StringIDRef getID(const QByteArray & data, bool binary, bool hashable=true, bool nocopy=false); + + /** Obtain the reference counted StringID object from numerical id + * + * This function exists because the stored string may be one way hashed, + * and the original text is not persistent. The caller use this function to + * retrieve the reference count ID object after restore + */ + StringIDRef getID(long id, int index = 0) const; + + StringIDRef getID(const StringID::IndexID &id) const { + return getID(id.id, id.index); + } + + std::map getIDMap() const; + + /// Clear all string hashes + void clear(); + + /// Size of the hash table + size_t size() const; + + /// Return the number of hashes that are used by others + size_t count() const; + + virtual PyObject *getPyObject(void) override; + + void setSaveAll(bool enable); + bool getSaveAll() const; + + void setThreshold(int threshold); + int getThreshold() const; + + void clearMarks() const; + + void compact(); + + class HashMap; + friend class StringID; + +protected: + StringID * insert(const StringIDRef & sid); + long lastID() const; + void saveStream(std::ostream &s) const; + void restoreStream(std::istream &s, std::size_t count); + void restoreStreamNew(std::istream &s, std::size_t count); + +private: + std::unique_ptr _hashes; + mutable std::string _filename; +}; + +} + +#endif diff --git a/src/App/StringHasherPy.xml b/src/App/StringHasherPy.xml new file mode 100644 index 0000000000..60a2f0f461 --- /dev/null +++ b/src/App/StringHasherPy.xml @@ -0,0 +1,70 @@ + + + + + + This is the StringHasher class + This is the StringHasher class + + + + +getID(txt|id, base64=False) -> StringID + +If the input is text, return a StringID object that is unique within this hasher. This +StringID object is reference counted. The hasher may only save hash ID's that are used. + +If the input is an integer, then the hasher will try to find the StringID object stored +with the same integer value. + +base64: indicate if the input 'txt' is base64 encoded binary data + + + + + + Check if two hasher are the same + + + + + Return count of used hashes + + + + + + Return the size of the hashes + + + + + + Whether to save all string hashes regardless of its use count + + + + + + Data length exceed this threshold will be hashed before storing + + + + + + Return the entire string table as Int->String dictionary + + + + + diff --git a/src/App/StringHasherPyImp.cpp b/src/App/StringHasherPyImp.cpp new file mode 100644 index 0000000000..712966a6c2 --- /dev/null +++ b/src/App/StringHasherPyImp.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** + * Copyright (c) 2018 Zheng Lei (realthunder) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ****************************************************************************/ + +#include "PreCompiled.h" + +#include "StringHasher.h" + +#include "StringHasherPy.h" +#include "StringHasherPy.cpp" + +using namespace App; + +// returns a string which represent the object e.g. when printed in python +std::string StringHasherPy::representation(void) const +{ + std::ostringstream str; + str << ""; + return str.str(); +} + +PyObject *StringHasherPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +{ + return new StringHasherPy(new StringHasher); +} + +// constructor method +int StringHasherPy::PyInit(PyObject* , PyObject* ) +{ + return 0; +} + + +PyObject* StringHasherPy::isSame(PyObject *args) +{ + PyObject *other; + if (!PyArg_ParseTuple(args, "O!", &StringHasherPy::Type, &other)){ // convert args: Python->C + return Py::new_reference_to(Py::False()); + } + auto otherHasher = static_cast(other)->getStringHasherPtr(); + return Py::new_reference_to(Py::Boolean(getStringHasherPtr() == otherHasher)); +} + +PyObject* StringHasherPy::getID(PyObject *args) +{ + long id = -1; + int index = 0; + PyObject *value = 0; + PyObject *base64 = Py_False; + if (!PyArg_ParseTuple(args, "l|i",&id,&index)) { + PyErr_Clear(); + if (!PyArg_ParseTuple(args, "O|O",&value,&base64)) + return NULL; // NULL triggers exception + } + if(id>0) { + PY_TRY { + auto sid = getStringHasherPtr()->getID(id, index); + if(!sid) Py_Return; + return sid.getPyObject(); + }PY_CATCH; + } + std::string txt; +#if PY_MAJOR_VERSION >= 3 + if (PyUnicode_Check(value)) { + txt = PyUnicode_AsUTF8(value); + } +#else + if (PyUnicode_Check(value)) { + PyObject* unicode = PyUnicode_AsLatin1String(value); + txt = PyString_AsString(unicode); + Py_DECREF(unicode); + } + else if (PyString_Check(value)) { + txt = PyString_AsString(value); + } +#endif + else + throw Py::TypeError("expect argument of type string"); + PY_TRY { + QByteArray data; + StringIDRef sid; + if(PyObject_IsTrue(base64)) { + data = QByteArray::fromBase64(QByteArray::fromRawData(txt.c_str(),txt.size())); + sid = getStringHasherPtr()->getID(data,true); + }else + sid = getStringHasherPtr()->getID(txt.c_str(),txt.size()); + return sid.getPyObject(); + }PY_CATCH; +} + +Py::Int StringHasherPy::getCount(void) const { + return Py::Int((long)getStringHasherPtr()->count()); +} + +Py::Int StringHasherPy::getSize(void) const { + return Py::Int((long)getStringHasherPtr()->size()); +} + +Py::Boolean StringHasherPy::getSaveAll(void) const { + return Py::Boolean(getStringHasherPtr()->getSaveAll()); +} + +void StringHasherPy::setSaveAll(Py::Boolean value) { + getStringHasherPtr()->setSaveAll(value); +} + +Py::Int StringHasherPy::getThreshold(void) const { + return Py::Int((long)getStringHasherPtr()->getThreshold()); +} + +void StringHasherPy::setThreshold(Py::Int value) { + getStringHasherPtr()->setThreshold(value); +} + +Py::Dict StringHasherPy::getTable() const { + Py::Dict dict; + for(auto &v : getStringHasherPtr()->getIDMap()) + dict.setItem(Py::Int(v.first),Py::String(v.second.dataToText())); + return dict; +} + +PyObject *StringHasherPy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int StringHasherPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} + + diff --git a/src/App/StringIDPy.xml b/src/App/StringIDPy.xml new file mode 100644 index 0000000000..2ef9a0005b --- /dev/null +++ b/src/App/StringIDPy.xml @@ -0,0 +1,58 @@ + + + + + + This is the StringID class + This is the StringID class + + + + Check if two StringIDs are the same + + + + + Return the integer value of this ID + + + + + + Return the data associated with this ID + + + + + + Check if the data is binary, + + + + + + Check if the data is hash, if so 'Data' returns a base64 encoded string of the raw hash + + + + + + Geometry index. Only meaningful for geometry element name + + + + private: + friend class StringID; + int _index = 0; + + + diff --git a/src/App/StringIDPyImp.cpp b/src/App/StringIDPyImp.cpp new file mode 100644 index 0000000000..b1d6d9e87b --- /dev/null +++ b/src/App/StringIDPyImp.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** + * Copyright (c) 2018 Zheng Lei (realthunder) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ****************************************************************************/ + +#include "PreCompiled.h" + +#include "StringHasher.h" + +#include "StringIDPy.h" +#include "StringIDPy.cpp" + +using namespace App; + +// returns a string which represent the object e.g. when printed in python +std::string StringIDPy::representation(void) const +{ + return getStringIDPtr()->toString(_index); +} + +PyObject* StringIDPy::isSame(PyObject *args) +{ + PyObject *other; + if (!PyArg_ParseTuple(args, "O!", &StringIDPy::Type, &other)) { // convert args: Python->C + return Py::new_reference_to(Py::False()); + } + auto otherPy = static_cast(other); + return Py::new_reference_to(Py::Boolean( + otherPy->getStringIDPtr() == this->getStringIDPtr() + && otherPy->_index == this->_index)); +} + +Py::Int StringIDPy::getValue(void) const { + return Py::Int(getStringIDPtr()->value()); +} + +Py::String StringIDPy::getData(void) const { + return Py::String(getStringIDPtr()->dataToText(this->_index)); +} + +Py::Boolean StringIDPy::getIsBinary(void) const { + return Py::Boolean(getStringIDPtr()->isBinary()); +} + +Py::Boolean StringIDPy::getIsHashed(void) const { + return Py::Boolean(getStringIDPtr()->isHashed()); +} + +Py::Int StringIDPy::getIndex(void) const { + return Py::Int(this->_index); +} + +void StringIDPy::setIndex(Py::Int index) { + this->_index = index; +} + +PyObject *StringIDPy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int StringIDPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} + +