#include <Model_ResultConstruction.h>
#include <Model_ResultBody.h>
#include <Model_ResultGroup.h>
+#include <Model_ResultParameter.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_CompositeFeature.h>
+
#include <Events_Loop.h>
#include <Events_Error.h>
return aPath;
}
+bool Model_Document::isRoot() const
+{
+ return this == Model_Session::get()->moduleDocument().get();
+}
+
bool Model_Document::load(const char* theFileName)
{
Handle(Model_Application) anApp = Model_Application::getApplication();
- if (this == Model_Session::get()->moduleDocument().get()) {
+ if (isRoot()) {
anApp->setLoadPath(theFileName);
}
TCollection_ExtendedString aPath(DocFileName(theFileName, myID));
std::dynamic_pointer_cast<Model_Session>(Model_Session::get());
aSession->setActiveDocument(anApp->getDocument(myID), false);
aSession->setCheckTransactions(false);
- synchronizeFeatures(false, true);
+ synchronizeFeatures(false, true, true);
aSession->setCheckTransactions(true);
aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false);
aSession->setActiveDocument(anApp->getDocument(myID), true);
{
// create a directory in the root document if it is not yet exist
Handle(Model_Application) anApp = Model_Application::getApplication();
- if (this == Model_Session::get()->moduleDocument().get()) {
+ if (isRoot()) {
#ifdef WIN32
CreateDirectory(theFileName, NULL);
#else
void Model_Document::close(const bool theForever)
{
std::shared_ptr<ModelAPI_Session> aPM = Model_Session::get();
- if (this != aPM->moduleDocument().get() && this == aPM->activeDocument().get()) {
+ if (!isRoot() && this == aPM->activeDocument().get()) {
aPM->setActiveDocument(aPM->moduleDocument());
- } else if (this == aPM->moduleDocument().get()) {
+ } else if (isRoot()) {
// erase the active document if root is closed
aPM->setActiveDocument(DocumentPtr());
}
// this must be here just after everything is finished but before real transaction stop
// to avoid messages about modifications outside of the transaction
// and to rebuild everything after all updates and creates
- if (Model_Session::get()->moduleDocument().get() == this) { // once for root document
+ if (isRoot()) { // once for root document
Events_Loop::loop()->autoFlush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
static std::shared_ptr<Events_Message> aFinishMsg
(new Events_Message(Events_Loop::eventByName("FinishOperation")));
if (!aResult && !myTransactions.empty() /* it can be for just created part document */)
aResult = myTransactions.rbegin()->myOCAFNum != 0;
- if (!aResult && Model_Session::get()->moduleDocument().get() == this) {
+ if (!aResult && isRoot()) {
// nothing inside in all documents, so remove this transaction from the transactions list
undoInternal(true, false);
myDoc->ClearRedos();
myDoc->Undo();
myDoc->ClearRedos();
}
- synchronizeFeatures(true, false); // references were not changed since transaction start
- // abort for all subs
+ // abort for all subs, flushes will be later, in the end of root abort
const std::set<std::string> aSubs = subDocuments(true);
std::set<std::string>::iterator aSubIter = aSubs.begin();
for (; aSubIter != aSubs.end(); aSubIter++)
subDoc(*aSubIter)->abortOperation();
+ // references may be changed because they are set in attributes on the fly
+ synchronizeFeatures(true, true, isRoot());
}
bool Model_Document::isOperation() const
for(int a = 0; a < aNumTransactions; a++)
myDoc->Undo();
- if (theSynchronize)
- synchronizeFeatures(true, true);
if (theWithSubs) {
// undo for all subs
const std::set<std::string> aSubs = subDocuments(true);
for (; aSubIter != aSubs.end(); aSubIter++)
subDoc(*aSubIter)->undoInternal(theWithSubs, theSynchronize);
}
+ // after redo of all sub-documents to avoid updates on not-modified data (issue 370)
+ if (theSynchronize)
+ synchronizeFeatures(true, true, isRoot());
}
void Model_Document::undo()
for(int a = 0; a < aNumRedos; a++)
myDoc->Redo();
- synchronizeFeatures(true, true);
// redo for all subs
const std::set<std::string> aSubs = subDocuments(true);
std::set<std::string>::iterator aSubIter = aSubs.begin();
for (; aSubIter != aSubs.end(); aSubIter++)
subDoc(*aSubIter)->redo();
+
+ // after redo of all sub-documents to avoid updates on not-modified data (issue 370)
+ synchronizeFeatures(true, true, isRoot());
}
std::list<std::string> Model_Document::undoList() const
{
TDF_Label anEmptyLab;
FeaturePtr anEmptyFeature;
- FeaturePtr aFeature = ModelAPI_Session::get()->createFeature(theID);
+ std::shared_ptr<Model_Session> aSession =
+ std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get());
+ FeaturePtr aFeature = aSession->createFeature(theID, this);
if (!aFeature)
return aFeature;
Model_Document* aDocToAdd;
- if (aFeature->documentToAdd().get()) { // use the customized document to add
- aDocToAdd = std::dynamic_pointer_cast<Model_Document>(aFeature->documentToAdd()).get();
+ if (!aFeature->documentToAdd().empty()) { // use the customized document to add
+ if (aFeature->documentToAdd() != kind()) { // the root document by default
+ aDocToAdd = std::dynamic_pointer_cast<Model_Document>(aSession->moduleDocument()).get();
+ } else {
+ aDocToAdd = this;
+ }
} else { // if customized is not presented, add to "this" document
aDocToAdd = this;
}
}
// event: feature is deleted
ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group());
+ // the redisplay signal should be flushed in order to erase the feature presentation in the viewer
+ Events_Loop::loop()->flush(EVENT_DISP);
}
}
theObj->initAttributes();
}
-void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool theUpdateReferences)
+void Model_Document::synchronizeFeatures(
+ const bool theMarkUpdated, const bool theUpdateReferences, const bool theFlush)
{
std::shared_ptr<ModelAPI_Document> aThis =
Model_Application::getApplication()->getDocument(myID);
FeaturePtr aFeature;
if (!myObjs.IsBound(aFeatureLabel)) { // a new feature is inserted
// create a feature
- aFeature = ModelAPI_Session::get()->createFeature(
+ aFeature = std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get())->createFeature(
TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get())
- .ToCString());
+ .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();
myExecuteFeatures = false;
aLoop->activateFlushes(true);
- aLoop->flush(aCreateEvent);
- aLoop->flush(aDeleteEvent);
- aLoop->flush(anUpdateEvent);
- aLoop->flush(aRedispEvent);
- aLoop->flush(aToHideEvent);
+ if (theFlush) {
+ aLoop->flush(aCreateEvent);
+ aLoop->flush(aDeleteEvent);
+ aLoop->flush(anUpdateEvent);
+ aLoop->flush(aRedispEvent);
+ aLoop->flush(aToHideEvent);
+ }
myExecuteFeatures = true;
}
return aResult;
}
+std::shared_ptr<ModelAPI_ResultParameter> Model_Document::createParameter(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+ TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+ TDataStd_Comment::Set(aLab, ModelAPI_ResultParameter::group().c_str());
+ ObjectPtr anOldObject = object(aLab);
+ std::shared_ptr<ModelAPI_ResultParameter> aResult;
+ if (anOldObject) {
+ aResult = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(anOldObject);
+ }
+ if (!aResult) {
+ aResult = std::shared_ptr<ModelAPI_ResultParameter>(new Model_ResultParameter);
+ storeResult(theFeatureData, aResult, theIndex);
+ }
+ return aResult;
+}
+
std::shared_ptr<ModelAPI_Feature> Model_Document::feature(
const std::shared_ptr<ModelAPI_Result>& theResult)
{