-void Model_Document::setUniqueName(FeaturePtr theFeature)
-{
- if (!theFeature->data()->name().empty())
- return; // not needed, name is already defined
- std::string aName; // result
- // first count all objects of such kind to start with index = count + 1
- int aNumObjects = 0;
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myObjs);
- for (; aFIter.More(); aFIter.Next()) {
- if (aFIter.Value()->getKind() == theFeature->getKind())
- aNumObjects++;
- }
- // generate candidate name
- std::stringstream aNameStream;
- aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
- aName = aNameStream.str();
- // check this is unique, if not, increase index by 1
- for (aFIter.Initialize(myObjs); aFIter.More();) {
- FeaturePtr aFeature = aFIter.Value();
- bool isSameName = aFeature->data()->name() == aName;
- if (!isSameName) { // check also results to avoid same results names (actual for Parts)
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- isSameName = (*aRIter)->data()->name() == aName;
- }
- }
- if (isSameName) {
- aNumObjects++;
- std::stringstream aNameStream;
- aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
- aName = aNameStream.str();
- // reinitialize iterator to make sure a new name is unique
- aFIter.Initialize(myObjs);
- } else
- aFIter.Next();
- }
- theFeature->data()->setName(aName);
-}
-
-void Model_Document::initData(ObjectPtr theObj, TDF_Label theLab, const int theTag)
-{
- std::shared_ptr<ModelAPI_Document> aThis = Model_Application::getApplication()->getDocument(
- myID);
- std::shared_ptr<Model_Data> aData(new Model_Data);
- aData->setLabel(theLab.FindChild(theTag));
- aData->setObject(theObj);
- theObj->setDoc(aThis);
- theObj->setData(aData);
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
- if (aFeature) {
- setUniqueName(aFeature); // must be before "initAttributes" because duplicate part uses name
- }
- theObj->initAttributes();
-}
-
-void Model_Document::synchronizeFeatures(
- const bool theMarkUpdated, const bool theUpdateReferences, const bool theFlush)
-{
- std::shared_ptr<ModelAPI_Document> aThis =
- Model_Application::getApplication()->getDocument(myID);
- // after all updates, sends a message that groups of features were created or updated
- Events_Loop* aLoop = Events_Loop::loop();
- static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- static Events_ID aCreateEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
- static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
- static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- static Events_ID aDeleteEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
- static Events_ID aToHideEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- aLoop->activateFlushes(false);
-
- // update all objects by checking are they on labels or not
- std::set<FeaturePtr> aNewFeatures, aKeptFeatures;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFeatureLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature;
- if (!myObjs.IsBound(aFeatureLabel)) { // a new feature is inserted
- // create a feature
- aFeature = std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get())->createFeature(
- TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get())
- .ToCString(), this);
- if (!aFeature) { // somethig is wrong, most probably, the opened document has invalid structure
- Events_Error::send("Invalid type of object in the document");
- aLabIter.Value()->Label().ForgetAllAttributes();
- continue;
- }
- // this must be before "setData" to redo the sketch line correctly
- myObjs.Bind(aFeatureLabel, aFeature);
- aNewFeatures.insert(aFeature);
- initData(aFeature, aFeatureLabel, TAG_FEATURE_ARGUMENTS);
-
- // event: model is updated
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, aCreateEvent);
- } else { // nothing is changed, both iterators are incremented
- aFeature = myObjs.Find(aFeatureLabel);
- aKeptFeatures.insert(aFeature);
- if (theMarkUpdated) {
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent);
- }
- }
- }
- // update results of the features (after features created because they may be connected, like sketch and sub elements)
- std::list<FeaturePtr> aComposites; // composites must be updated after their subs (issue 360)
- TDF_ChildIDIterator aLabIter2(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter2.More(); aLabIter2.Next()) {
- TDF_Label aFeatureLabel = aLabIter2.Value()->Label();
- if (myObjs.IsBound(aFeatureLabel)) { // a new feature is inserted
- FeaturePtr aFeature = myObjs.Find(aFeatureLabel);
- if (std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature).get())
- aComposites.push_back(aFeature);
- updateResults(aFeature);
- }
- }
- std::list<FeaturePtr>::iterator aComposite = aComposites.begin();
- for(; aComposite != aComposites.end(); aComposite++) {
- updateResults(*aComposite);
- }
-
- // check all features are checked: if not => it was removed
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myObjs);
- while (aFIter.More()) {
- if (aKeptFeatures.find(aFIter.Value()) == aKeptFeatures.end()
- && aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) {
- FeaturePtr aFeature = aFIter.Value();
- // event: model is updated
- //if (aFeature->isInHistory()) {
- ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group());
- //}
- // results of this feature must be redisplayed (hided)
- // redisplay also removed feature (used for sketch and AISObject)
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, aRedispEvent);
- aFeature->erase();
- // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter
- myObjs.UnBind(aFIter.Key());
- // reinitialize iterator because unbind may corrupt the previous order in the map
- aFIter.Initialize(myObjs);
- } else
- aFIter.Next();
- }
-
- if (theUpdateReferences) {
- synchronizeBackRefs();
- }
-
- myExecuteFeatures = false;
- aLoop->activateFlushes(true);
-
- if (theFlush) {
- aLoop->flush(aCreateEvent);
- aLoop->flush(aDeleteEvent);
- aLoop->flush(anUpdateEvent);
- aLoop->flush(aRedispEvent);
- aLoop->flush(aToHideEvent);
- }
- myExecuteFeatures = true;
-}
-
-void Model_Document::synchronizeBackRefs()
-{
- std::shared_ptr<ModelAPI_Document> aThis =
- Model_Application::getApplication()->getDocument(myID);
- // keeps the concealed flags of result to catch the change and create created/deleted events
- std::list<std::pair<ResultPtr, bool> > aConcealed;
- // first cycle: erase all data about back-references
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeatures(myObjs);
- for(; aFeatures.More(); aFeatures.Next()) {
- FeaturePtr aFeature = aFeatures.Value();
- std::shared_ptr<Model_Data> aFData =
- std::dynamic_pointer_cast<Model_Data>(aFeature->data());
- if (aFData) {
- aFData->eraseBackReferences();
- }
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- std::shared_ptr<Model_Data> aResData =
- std::dynamic_pointer_cast<Model_Data>((*aRIter)->data());
- if (aResData) {
- aConcealed.push_back(std::pair<ResultPtr, bool>(*aRIter, (*aRIter)->isConcealed()));
- aResData->eraseBackReferences();
- }
- }
- }
-
- // second cycle: set new back-references: only features may have reference, iterate only them
- ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
- for(aFeatures.Initialize(myObjs); aFeatures.More(); aFeatures.Next()) {
- FeaturePtr aFeature = aFeatures.Value();
- std::shared_ptr<Model_Data> aFData =
- std::dynamic_pointer_cast<Model_Data>(aFeature->data());
- if (aFData) {
- std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
- aFData->referencesToObjects(aRefs);
- std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator
- aRefsIter = aRefs.begin();
- for(; aRefsIter != aRefs.end(); aRefsIter++) {
- std::list<ObjectPtr>::iterator aRefTo = aRefsIter->second.begin();
- for(; aRefTo != aRefsIter->second.end(); aRefTo++) {
- if (*aRefTo) {
- std::shared_ptr<Model_Data> aRefData =
- std::dynamic_pointer_cast<Model_Data>((*aRefTo)->data());
- aRefData->addBackReference(aFeature, aRefsIter->first); // here the Concealed flag is updated
- }
- }
- }
- }
- }
- std::list<std::pair<ResultPtr, bool> >::iterator aCIter = aConcealed.begin();
- for(; aCIter != aConcealed.end(); aCIter++) {
- if (aCIter->first->isConcealed() != aCIter->second) { // somethign is changed => produce event
- if (aCIter->second) { // was concealed become not => creation event
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
- ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, anEvent);
- } else { // was not concealed become concealed => delete event
- ModelAPI_EventCreator::get()->sendDeleted(aThis, aCIter->first->groupName());
- // redisplay for the viewer (it must be disappeared also)
- static Events_ID EVENT_DISP =
- Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, EVENT_DISP);
- }
- }
- }
-}
-
-TDF_Label Model_Document::resultLabel(
- const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex)
-{
- const std::shared_ptr<Model_Data>& aData =
- std::dynamic_pointer_cast<Model_Data>(theFeatureData);
- return aData->label().Father().FindChild(TAG_FEATURE_RESULTS).FindChild(theResultIndex + 1);
-}
-
-void Model_Document::storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
- std::shared_ptr<ModelAPI_Result> theResult,
- const int theResultIndex)
-{
- std::shared_ptr<ModelAPI_Document> aThis =
- Model_Application::getApplication()->getDocument(myID);
- theResult->setDoc(aThis);
- initData(theResult, resultLabel(theFeatureData, theResultIndex), TAG_FEATURE_ARGUMENTS);
- if (theResult->data()->name().empty()) { // if was not initialized, generate event and set a name
- std::stringstream aNewName;
- aNewName<<theFeatureData->name();
- if (theResultIndex > 0) // if there are several results, add unique prefix starting from second
- aNewName<<"_"<<theResultIndex + 1;
- theResult->data()->setName(aNewName.str());
- }
-}
-