From 5ef8898eadf504376d917cedd3c3c696d1c4af34 Mon Sep 17 00:00:00 2001 From: mpv Date: Thu, 17 Jul 2014 15:47:31 +0400 Subject: [PATCH] Optimize document functionality and debug undo/redo synchronization --- src/Model/Model_Document.cpp | 324 ++++++++++---------------- src/Model/Model_Document.h | 15 +- src/ModelAPI/CMakeLists.txt | 3 +- src/ModelAPI/ModelAPI_Feature.cpp | 50 ++++ src/ModelAPI/ModelAPI_Feature.h | 13 +- src/PartSet/PartSet_Module.cpp | 6 +- src/SketchPlugin/SketchPlugin_Arc.cpp | 2 +- 7 files changed, 194 insertions(+), 219 deletions(-) create mode 100644 src/ModelAPI/ModelAPI_Feature.cpp diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index c08c85160..f63dbbb25 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -20,9 +20,8 @@ #include #include #include -#include - -#include +#include +#include #include #ifndef WIN32 @@ -358,13 +357,13 @@ FeaturePtr Model_Document::addFeature(std::string theID) if (aFeature) { TDF_Label aFeatureLab; if (!aFeature->isAction()) {// do not add action to the data model - TDF_Label aFeaturesLab = aDocToAdd->groupLabel(ModelAPI_Feature::group()); + TDF_Label aFeaturesLab = aDocToAdd->featuresLabel(); aFeatureLab = aFeaturesLab.NewChild(); aDocToAdd->initData(aFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS); // keep the feature ID to restore document later correctly TDataStd_Comment::Set(aFeatureLab, aFeature->getKind().c_str()); aDocToAdd->setUniqueName(aFeature); - aDocToAdd->myObjs[ModelAPI_Feature::group()].push_back(aFeature); + aDocToAdd->myObjs.Bind(aFeatureLab, aFeature); // store feature in the history of features array if (aFeature->isInHistory()) { AddToRefArray(aFeaturesLab, aFeatureLab); @@ -414,20 +413,14 @@ void Model_Document::removeFeature(FeaturePtr theFeature) { boost::shared_ptr aData = boost::static_pointer_cast(theFeature->data()); TDF_Label aFeatureLabel = aData->label().Father(); - // remove feature from the myObjects list - std::vector& aVec = myObjs[ModelAPI_Feature::group()]; - std::vector::iterator anIter = aVec.begin(); - while(anIter != aVec.end()) { - if (*anIter == theFeature) { - anIter = aVec.erase(anIter); - } else { - anIter++; - } - } + if (myObjs.IsBound(aFeatureLabel)) + myObjs.UnBind(aFeatureLabel); + else return; // not found feature => do not remove + // erase all attributes under the label of feature aFeatureLabel.ForgetAllAttributes(); // remove it from the references array - RemoveFromRefArray(groupLabel(ModelAPI_Feature::group()), aData->label()); + RemoveFromRefArray(featuresLabel(), aData->label()); // event: feature is deleted ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group()); @@ -443,43 +436,21 @@ void Model_Document::removeFeature(FeaturePtr theFeature) } } -/// returns the object group name by the object label -static std::string groupName(TDF_Label theObjectLabel) { - TDF_Label aGroupLab = theObjectLabel.Father(); - Handle(TDataStd_Comment) aComment; - if (aGroupLab.FindAttribute(TDataStd_Comment::GetID(), aComment)) - return std::string(TCollection_AsciiString(aComment->Get()).ToCString()); - return ""; // not found -} - FeaturePtr Model_Document::feature(TDF_Label& theLabel) { - // iterate all features, may be optimized later by keeping labels-map - std::vector& aVec = myObjs[ModelAPI_Feature::group()]; - std::vector::iterator aFIter = aVec.begin(); - for(; aFIter != aVec.end(); aFIter++) { - boost::shared_ptr aData = - boost::dynamic_pointer_cast((*aFIter)->data()); - if (aData->label().IsEqual(theLabel)) - return boost::dynamic_pointer_cast(*aFIter); - } + if (myObjs.IsBound(theLabel)) + return myObjs.Find(theLabel); return FeaturePtr(); // not found } ObjectPtr Model_Document::object(TDF_Label theLabel) { - // iterate all features, may be optimized later by keeping labels-map - std::vector& aVec = myObjs[ModelAPI_Feature::group()]; - std::vector::iterator aFIter = aVec.begin(); - for(; aFIter != aVec.end(); aFIter++) { - boost::shared_ptr aData = - boost::dynamic_pointer_cast((*aFIter)->data()); - if (aData->label().IsEqual(theLabel)) - return *aFIter; - std::list >& aResults = - boost::dynamic_pointer_cast(*aFIter)->results(); - std::list >::iterator aRIter = aResults.begin(); - for(; aRIter != aResults.end(); aRIter++) { + TDF_Label aFeatureLabel = theLabel.Father().Father(); + FeaturePtr aFeature = feature(aFeatureLabel); + if (aFeature) { + const std::list >& aResults = aFeature->results(); + std::list >::const_iterator aRIter = aResults.cbegin(); + for(; aRIter != aResults.cend(); aRIter++) { boost::shared_ptr aResData = boost::dynamic_pointer_cast((*aRIter)->data()); if (aResData->label().IsEqual(theLabel)) @@ -500,39 +471,30 @@ boost::shared_ptr Model_Document::subDocument(std::string the ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex) { if (theGroupID == ModelAPI_Feature::group()) { - // features may be not in history but in the myObjs, so, iterate all + Handle(TDataStd_ReferenceArray) aRefs; + if (!featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) + return ObjectPtr(); + if (aRefs->Lower() > theIndex || aRefs->Upper() < theIndex) + return ObjectPtr(); + TDF_Label aFeatureLabel = aRefs->Value(theIndex); + return feature(aFeatureLabel); + } else { + // comment must be in any feature: it is kind int anIndex = 0; - std::map >::iterator aFind = - myObjs.find(ModelAPI_Feature::group()); - if (aFind != myObjs.end()) { - std::vector::iterator aFIter = aFind->second.begin(); - for(; aFIter != aFind->second.end(); aFIter++) { - if ((*aFIter)->isInHistory()) { - if (theIndex == anIndex) - return *aFIter; + TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID()); + for(; aLabIter.More(); aLabIter.Next()) { + TDF_Label aFLabel = aLabIter.Value()->Label(); + FeaturePtr aFeature = feature(aFLabel); + const std::list >& aResults = aFeature->results(); + std::list >::const_iterator aRIter = aResults.begin(); + for(; aRIter != aResults.cend(); aRIter++) { + if ((*aRIter)->isInHistory() && (*aRIter)->groupName() == theGroupID) { + if (anIndex == theIndex) + return *aRIter; anIndex++; } } } - } else { - // iterate all features in order to find the needed result - std::map >::iterator aFind = - myObjs.find(ModelAPI_Feature::group()); - if (aFind != myObjs.end()) { - std::vector::iterator aFIter = aFind->second.begin(); - for(int anIndex = 0; aFIter != aFind->second.end(); aFIter++) { - const std::list >& aResults = - boost::dynamic_pointer_cast(*aFIter)->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for(; aRIter != aResults.cend(); aRIter++) { - if ((*aRIter)->isInHistory() && (*aRIter)->groupName() == theGroupID) { - if (anIndex == theIndex) - return *aRIter; - anIndex++; - } - } - } - } } // not found return ObjectPtr(); @@ -542,31 +504,20 @@ int Model_Document::size(const std::string& theGroupID) { int aResult = 0; if (theGroupID == ModelAPI_Feature::group()) { - // features may be not in history but in the myObjs, so, iterate all - std::map >::iterator aFind = - myObjs.find(ModelAPI_Feature::group()); - if (aFind != myObjs.end()) { - std::vector::iterator aFIter = aFind->second.begin(); - for(; aFIter != aFind->second.end(); aFIter++) { - if ((*aFIter)->isInHistory()) { - aResult++; - } - } - } + Handle(TDataStd_ReferenceArray) aRefs; + if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) + return aRefs->Length(); } else { - // iterate all features in order to find the needed result - std::map >::iterator aFind = - myObjs.find(ModelAPI_Feature::group()); - if (aFind != myObjs.end()) { - std::vector::iterator aFIter = aFind->second.begin(); - for(; aFIter != aFind->second.end(); aFIter++) { - const std::list >& aResults = - boost::dynamic_pointer_cast(*aFIter)->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for(; aRIter != aResults.cend(); aRIter++) { - if ((*aRIter)->isInHistory() && (*aRIter)->groupName() == theGroupID) { - aResult++; - } + // comment must be in any feature: it is kind + TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID()); + for(; aLabIter.More(); aLabIter.Next()) { + TDF_Label aFLabel = aLabIter.Value()->Label(); + FeaturePtr aFeature = feature(aFLabel); + const std::list >& aResults = aFeature->results(); + std::list >::const_iterator aRIter = aResults.begin(); + for(; aRIter != aResults.cend(); aRIter++) { + if ((*aRIter)->isInHistory() && (*aRIter)->groupName() == theGroupID) { + aResult++; } } } @@ -589,32 +540,19 @@ Model_Document::Model_Document(const std::string theID) myDoc->CommitCommand(); } -TDF_Label Model_Document::groupLabel(const std::string theGroup) +TDF_Label Model_Document::featuresLabel() { - // searching for existing - TCollection_ExtendedString aGroup(theGroup.c_str()); - TDF_ChildIDIterator aGroupIter(myDoc->Main().FindChild(TAG_OBJECTS), TDataStd_Comment::GetID()); - for(; aGroupIter.More(); aGroupIter.Next()) { - Handle(TDataStd_Comment) aName = Handle(TDataStd_Comment)::DownCast(aGroupIter.Value()); - if (aName->Get() == aGroup) - return aGroupIter.Value()->Label(); - } - // create a new - TDF_Label aNew = myDoc->Main().FindChild(TAG_OBJECTS).NewChild(); - TDataStd_Comment::Set(aNew, aGroup); - return aNew; + return myDoc->Main().FindChild(TAG_OBJECTS); } void Model_Document::setUniqueName(FeaturePtr theFeature) { std::string aName; // result // first count all objects of such kind to start with index = count + 1 - int a, aNumObjects = 0; - int aSize = myObjs.find(ModelAPI_Feature::group()) == myObjs.end() ? - 0 : myObjs[ModelAPI_Feature::group()].size(); - for(a = 0; a < aSize; a++) { - if (boost::dynamic_pointer_cast(myObjs[ModelAPI_Feature::group()][a])-> - getKind() == theFeature->getKind()) + int aNumObjects = 0; + NCollection_DataMap::Iterator aFIter(myObjs); + for(; aFIter.More(); aFIter.Next()) { + if (aFIter.Value()->getKind() == theFeature->getKind()) aNumObjects++; } // generate candidate name @@ -622,9 +560,8 @@ void Model_Document::setUniqueName(FeaturePtr theFeature) aNameStream<getKind()<<"_"<(myObjs[ModelAPI_Feature::group()][a]); + for(aFIter.Initialize(myObjs); aFIter.More(); ) { + FeaturePtr aFeature = aFIter.Value(); bool isSameName = aFeature->isInHistory() && aFeature->data()->name() == aName; if (!isSameName) { // check also results to avoid same results names (actual for Parts) const std::list >& aResults = aFeature->results(); @@ -639,8 +576,8 @@ void Model_Document::setUniqueName(FeaturePtr theFeature) aNameStream<getKind()<<"_"<data()->setName(aName); } @@ -661,73 +598,59 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated) { boost::shared_ptr aThis = Model_Application::getApplication()->getDocument(myID); - // update all objects: iterate from the end: as they appeared in the list - std::map >::reverse_iterator aGroupIter = myObjs.rbegin(); - for(; aGroupIter != myObjs.rend(); aGroupIter++) { - std::vector::iterator anObjIter = aGroupIter->second.begin(); - // and in parallel iterate labels of features+ - const std::string& aGroupName = aGroupIter->first; - TDF_ChildIDIterator aLabIter(groupLabel(aGroupName), TDataStd_Comment::GetID()); - while(anObjIter != aGroupIter->second.end() || aLabIter.More()) { - static const int INFINITE_TAG = INT_MAX; // no label means that it exists somwhere in infinite - int aFeatureTag = INFINITE_TAG; - if (anObjIter != aGroupIter->second.end()) { // existing tag for feature - boost::shared_ptr aData = - boost::dynamic_pointer_cast((*anObjIter)->data()); - aFeatureTag = aData->label().Tag(); + // update all objects by checking are they of labels or not + std::set aCheckedFeatures; + TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID()); + for(; aLabIter.More(); aLabIter.Next()) { + TDF_Label aFeatureLabel = aLabIter.Value()->Label(); + if (!myObjs.IsBound(aFeatureLabel)) { // a new feature is inserted + // create a feature + FeaturePtr aNewObj = ModelAPI_PluginManager::get()->createFeature( + TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get()) + .ToCString()); + // this must be before "setData" to redo the sketch line correctly + myObjs.Bind(aFeatureLabel, aNewObj); + aCheckedFeatures.insert(aNewObj); + initData(aNewObj, aFeatureLabel, TAG_FEATURE_ARGUMENTS); + aNewObj->execute(); // to restore results list + + // event: model is updated + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); + ModelAPI_EventCreator::get()->sendUpdated(aNewObj, anEvent); + // feature for this label is added, so go to the next label + } else { // nothing is changed, both iterators are incremented + aCheckedFeatures.insert(myObjs.Find(aFeatureLabel)); + if (theMarkUpdated) { + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + ModelAPI_EventCreator::get()->sendUpdated(myObjs.Find(aFeatureLabel), anEvent); } - int aDSTag = INFINITE_TAG; - if (aLabIter.More()) { // next label in DS is existing - aDSTag = aLabIter.Value()->Label().Tag(); + } + } + // check all features are checked: if not => it was removed + NCollection_DataMap::Iterator aFIter(myObjs); + while(aFIter.More()) { + if (aCheckedFeatures.find(aFIter.Value()) == aCheckedFeatures.end()) { + FeaturePtr aFeature = aFIter.Value(); + TDF_Label aLab = aFIter.Key(); + aFIter.Next(); + myObjs.UnBind(aLab); + // event: model is updated + if (aFeature->isInHistory()) { + ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group()); } - if (aDSTag > aFeatureTag) { // feature is removed - ObjectPtr anObj = *anObjIter; - anObjIter = aGroupIter->second.erase(anObjIter); - // event: model is updated - if (anObj->isInHistory()) { - ModelAPI_EventCreator::get()->sendDeleted(aThis, aGroupName); - } - // results of this feature must be redisplayed (hided) - static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); - const std::list >& aResults = boost::dynamic_pointer_cast(anObj)->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for(; aRIter != aResults.cend(); aRIter++) { - boost::shared_ptr aRes = *aRIter; - aRes->setData(boost::shared_ptr()); // deleted flag - ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP); - ModelAPI_EventCreator::get()->sendDeleted(aThis, aRes->groupName()); - } - } else if (aDSTag < aFeatureTag) { // a new feature is inserted - // create a feature - TDF_Label aLab = aLabIter.Value()->Label(); - ObjectPtr aNewObj = ModelAPI_PluginManager::get()->createFeature( - TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get()) - .ToCString()); - // this must be before "setData" to redo the sketch line correctly - if (anObjIter == aGroupIter->second.end()) { - aGroupIter->second.push_back(aNewObj); - anObjIter = aGroupIter->second.end(); - } else { - anObjIter++; - aGroupIter->second.insert(anObjIter, aNewObj); - } - initData(aNewObj, aLab, TAG_FEATURE_ARGUMENTS); - - // event: model is updated - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); - ModelAPI_EventCreator::get()->sendUpdated(aNewObj, anEvent); - // feature for this label is added, so go to the next label - aLabIter.Next(); - } else { // nothing is changed, both iterators are incremented - if (theMarkUpdated) { - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); - ModelAPI_EventCreator::get()->sendUpdated(*anObjIter, anEvent); - } - anObjIter++; - aLabIter.Next(); + // results of this feature must be redisplayed (hided) + static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); + const std::list >& aResults = aFeature->results(); + std::list >::const_iterator aRIter = aResults.begin(); + for(; aRIter != aResults.cend(); aRIter++) { + boost::shared_ptr aRes = *aRIter; + aRes->setData(boost::shared_ptr()); // deleted flag + ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP); + ModelAPI_EventCreator::get()->sendDeleted(aThis, aRes->groupName()); } - } + } else aFIter.Next(); } + // after all updates, sends a message that groups of features were created or updated boost::static_pointer_cast(Model_PluginManager::get())-> setCheckTransactions(false); @@ -748,8 +671,6 @@ void Model_Document::storeResult(boost::shared_ptr theFeatureData initData(theResult, boost::dynamic_pointer_cast(theFeatureData)-> label().Father().FindChild(TAG_FEATURE_RESULTS), theResultIndex); if (theResult->data()->name().empty()) { // if was not initialized, generate event and set a name - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); - ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent); theResult->data()->setName(theFeatureData->name()); } } @@ -805,21 +726,20 @@ boost::shared_ptr Model_Document::createPart( boost::shared_ptr Model_Document::feature( const boost::shared_ptr& theResult) { - // iterate all features in order to find the needed result - std::map >::iterator aFind = - myObjs.find(ModelAPI_Feature::group()); - if (aFind != myObjs.end()) { - std::vector::iterator aFIter = aFind->second.begin(); - for(; aFIter != aFind->second.end(); aFIter++) { - FeaturePtr aFeature = boost::dynamic_pointer_cast(*aFIter); - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for(; aRIter != aResults.cend(); aRIter++) { - if (*aRIter == theResult) { - return aFeature; - } - } - } + boost::shared_ptr aData = boost::dynamic_pointer_cast(theResult->data()); + if (aData) { + TDF_Label aFeatureLab = aData->label().Father().Father(); + return feature(aFeatureLab); } return FeaturePtr(); } + +Standard_Integer HashCode(const TDF_Label& theLab,const Standard_Integer theUpper) +{ + return TDF_LabelMapHasher::HashCode(theLab, theUpper); + +} +Standard_Boolean IsEqual(const TDF_Label& theLab1,const TDF_Label& theLab2) +{ + return TDF_LabelMapHasher::IsEqual(theLab1, theLab2); +} diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index 01171bf68..340ecd4cc 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -11,11 +11,17 @@ #include #include +#include +#include #include #include class Handle_Model_Document; +// for TDF_Label map usage +static Standard_Integer HashCode(const TDF_Label& theLab,const Standard_Integer theUpper); +static Standard_Boolean IsEqual(const TDF_Label& theLab1,const TDF_Label& theLab2); + /**\class Model_Document * \ingroup DataModel * \brief Document for internal data structure of any object storage. @@ -108,8 +114,8 @@ public: protected: - //! Returns (creates if needed) the group label - TDF_Label groupLabel(const std::string theGroup); + //! Returns (creates if needed) the features label + TDF_Label featuresLabel(); //! Initializes feature with a unique name in this group (unique name is generated as //! feature type + "_" + index @@ -145,8 +151,9 @@ private: int myTransactionsAfterSave; /// number of nested transactions performed (or -1 if not nested) int myNestedNum; - /// All objects managed by this document (not only in history of OB) - std::map > myObjs; + /// All features managed by this document (not only in history of OB) + /// For optimization mapped by labels + NCollection_DataMap myObjs; ///< set of identifiers of sub-documents of this document std::set mySubs; diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index 78d9901e6..a79ea6a88 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -24,10 +24,11 @@ SET(PROJECT_HEADERS ModelAPI_ResultBody.h ModelAPI_ResultConstruction.h ModelAPI_ResultPart.h - ModelAPI_ResultParameters.h + ModelAPI_ResultParameters.h ) SET(PROJECT_SOURCES + ModelAPI_Feature.cpp ModelAPI_PluginManager.cpp ) diff --git a/src/ModelAPI/ModelAPI_Feature.cpp b/src/ModelAPI/ModelAPI_Feature.cpp new file mode 100644 index 000000000..882e99aaa --- /dev/null +++ b/src/ModelAPI/ModelAPI_Feature.cpp @@ -0,0 +1,50 @@ +// File: ModelAPI_Feature.cpp +// Created: 17 Jul 2014 +// Author: Mikhail PONIKAROV + +#include "ModelAPI_Feature.h" +#include +#include +#include + +const std::list >& ModelAPI_Feature::results() +{ + return myResults; +} + +boost::shared_ptr ModelAPI_Feature::firstResult() +{ + return myResults.empty() ? boost::shared_ptr() : *(myResults.begin()); +} + +void ModelAPI_Feature::setResult(const boost::shared_ptr& theResult) +{ + if (firstResult() == theResult) { // just updated + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent); + return; + } + // created + while(!myResults.empty()) { // remove one by one with messages + boost::shared_ptr aRes = *(myResults.begin()); + myResults.erase(myResults.begin()); + ModelAPI_EventCreator::get()->sendDeleted(aRes->document(), aRes->groupName()); + } + myResults.push_back(theResult); + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); + ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent); +} + +boost::shared_ptr ModelAPI_Feature::documentToAdd() +{ + return ModelAPI_PluginManager::get()->currentDocument(); +} + +ModelAPI_Feature::~ModelAPI_Feature() +{ + while(!myResults.empty()) { // remove one by one with messages + boost::shared_ptr aRes = *(myResults.begin()); + myResults.erase(myResults.begin()); + ModelAPI_EventCreator::get()->sendDeleted(aRes->document(), aRes->groupName()); + } +} diff --git a/src/ModelAPI/ModelAPI_Feature.h b/src/ModelAPI/ModelAPI_Feature.h index 3770c06f0..2305044ed 100644 --- a/src/ModelAPI/ModelAPI_Feature.h +++ b/src/ModelAPI/ModelAPI_Feature.h @@ -43,13 +43,11 @@ public: virtual void execute() = 0; /// returns the current results of the feature - std::list >& results() {return myResults;} + MODELAPI_EXPORT const std::list >& results(); /// returns the first result in the list or NULL reference - boost::shared_ptr firstResult() - {return myResults.empty() ? boost::shared_ptr() : *(myResults.begin());} + MODELAPI_EXPORT boost::shared_ptr firstResult(); /// sets the alone result - void setResult(const boost::shared_ptr& theResult) - {myResults.clear(); myResults.push_back(theResult);} + MODELAPI_EXPORT void setResult(const boost::shared_ptr& theResult); /// Returns true if this feature must not be created: this is just an action /// that is not stored in the features history and data model (like "delete part"). @@ -57,11 +55,10 @@ public: /// Must return document where the new feature must be added to /// By default it is current document - virtual boost::shared_ptr documentToAdd() - {return ModelAPI_PluginManager::get()->currentDocument();} + MODELAPI_EXPORT virtual boost::shared_ptr documentToAdd(); /// To virtually destroy the fields of successors - virtual ~ModelAPI_Feature() {} + MODELAPI_EXPORT virtual ~ModelAPI_Feature(); }; //! Pointer on feature object diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index fc2ffb51b..c4f1b029e 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -306,9 +306,9 @@ void PartSet_Module::onStopSelection(const QFeatureList& theFeatures, const bool QResultList aResults; foreach(FeaturePtr aFeature, theFeatures) { if (aFeature->results().size() > 0) { - std::list& aResList = aFeature->results(); - std::list::iterator aIt; - for (aIt = aResList.begin(); aIt != aResList.end(); ++aIt) + const std::list& aResList = aFeature->results(); + std::list::const_iterator aIt; + for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) aResults.append(*aIt); } } diff --git a/src/SketchPlugin/SketchPlugin_Arc.cpp b/src/SketchPlugin/SketchPlugin_Arc.cpp index e5eb1f301..1445df99b 100644 --- a/src/SketchPlugin/SketchPlugin_Arc.cpp +++ b/src/SketchPlugin/SketchPlugin_Arc.cpp @@ -78,7 +78,7 @@ void SketchPlugin_Arc::execute() boost::shared_ptr aConstr = document()->createConstruction(data()); aConstr->setShape(aCompound); - results().push_back(aConstr); + setResult(aConstr); } } } -- 2.39.2