X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Session.cpp;h=a68d98b0c847d6b6f8d45641e9db58d8093be330;hb=881cf7420dccf3c43837390efa9cded7b24836a2;hp=8dcd0a11b0e04e008fc17b0d4f906fb9058be13e;hpb=ce9008bdda3fa14d6fa6c61360541249ccf43ce0;p=modules%2Fshaper.git diff --git a/src/Model/Model_Session.cpp b/src/Model/Model_Session.cpp index 8dcd0a11b..a68d98b0c 100644 --- a/src/Model/Model_Session.cpp +++ b/src/Model/Model_Session.cpp @@ -9,26 +9,26 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include #include #include #include #include #include +#include #include #include #include #include -using namespace std; - static Model_Session* myImpl = new Model_Session(); // t oredirect all calls to the root document @@ -36,37 +36,44 @@ static Model_Session* myImpl = new Model_Session(); bool Model_Session::load(const char* theFileName) { - bool aRes = ROOT_DOC->load(theFileName); + bool aRes = ROOT_DOC->load(theFileName, "root", ROOT_DOC); return aRes; } bool Model_Session::save(const char* theFileName, std::list& theResults) { - return ROOT_DOC->save(theFileName, theResults); + return ROOT_DOC->save(theFileName, "root", theResults); } void Model_Session::closeAll() { - ROOT_DOC->close(true); Model_Application::getApplication()->deleteAllDocuments(); } -void Model_Session::startOperation(const std::string& theId) +void Model_Session::startOperation(const std::string& theId, const bool theAttachedToNested) { + myOperationAttachedToNext = theAttachedToNested; ROOT_DOC->startOperation(); ROOT_DOC->operationId(theId); static std::shared_ptr aStartedMsg (new Events_Message(Events_Loop::eventByName("StartOperation"))); Events_Loop::loop()->send(aStartedMsg); // remove all useless documents that has been closed: on start of operation undo/redo is cleared - std::list > aUsedDocs = allOpenedDocuments(); - Model_Application::getApplication()->removeUselessDocuments(aUsedDocs); + // MPV: this code is dangerous now because it may close the document that is activated right now + // but not in the list of the opened documents yet (create, delete, undo, activate Part) + // later this must be updated by correct usage of uniques IDs of documents, not names of results + //std::list > aUsedDocs = allOpenedDocuments(); + //Model_Application::getApplication()->removeUselessDocuments(aUsedDocs); } void Model_Session::finishOperation() { setCheckTransactions(false); ROOT_DOC->finishOperation(); + if (myOperationAttachedToNext) { // twice, with nested + ROOT_DOC->finishOperation(); + myOperationAttachedToNext = false; + } setCheckTransactions(true); } @@ -74,6 +81,10 @@ void Model_Session::abortOperation() { setCheckTransactions(false); ROOT_DOC->abortOperation(); + if (myOperationAttachedToNext) { // twice, with nested + ROOT_DOC->abortOperation(); + myOperationAttachedToNext = false; + } setCheckTransactions(true); // here the update mechanism may work after abort, so, supress the warnings about // modifications outside of the transactions @@ -131,10 +142,10 @@ std::list Model_Session::redoList() return ROOT_DOC->redoList(); } -FeaturePtr Model_Session::createFeature(string theFeatureID) +FeaturePtr Model_Session::createFeature(std::string theFeatureID, Model_Document* theDocOwner) { if (this != myImpl) { - return myImpl->createFeature(theFeatureID); + return myImpl->createFeature(theFeatureID, theDocOwner); } // load all information about plugins, features and attributes @@ -142,10 +153,10 @@ FeaturePtr Model_Session::createFeature(string theFeatureID) if (myPlugins.find(theFeatureID) != myPlugins.end()) { std::pair& aPlugin = myPlugins[theFeatureID]; // plugin and doc kind - if (!aPlugin.second.empty() && aPlugin.second != activeDocument()->kind()) { - Events_Error::send( - string("Feature '") + theFeatureID + "' can be created only in document '" - + aPlugin.second + "' by the XML definition"); + if (!aPlugin.second.empty() && aPlugin.second != theDocOwner->kind()) { + Events_InfoMessage("Model_Session", + "Feature '%1' can be created only in document '%2' by the XML definition") + .arg(theFeatureID).arg(aPlugin.second).send(); return FeaturePtr(); } myCurrentPluginName = aPlugin.first; @@ -156,16 +167,18 @@ FeaturePtr Model_Session::createFeature(string theFeatureID) if (myPluginObjs.find(myCurrentPluginName) != myPluginObjs.end()) { FeaturePtr aCreated = myPluginObjs[myCurrentPluginName]->createFeature(theFeatureID); if (!aCreated) { - Events_Error::send( - string("Can not initialize feature '") + theFeatureID + "' in plugin '" - + myCurrentPluginName + "'"); + Events_InfoMessage("Model_Session", + "Can not initialize feature '%1' in plugin '%2'") + .arg(theFeatureID).arg(myCurrentPluginName).send(); } return aCreated; } else { - Events_Error::send(string("Can not load plugin '") + myCurrentPluginName + "'"); + Events_InfoMessage("Model_Session", + "Can not load plugin '%1'").arg(myCurrentPluginName).send(); } } else { - Events_Error::send(string("Feature '") + theFeatureID + "' not found in any plugin"); + Events_InfoMessage("Model_Session", + "Feature '%1' not found in any plugin").arg(theFeatureID).send(); } return FeaturePtr(); // return nothing @@ -173,29 +186,30 @@ FeaturePtr Model_Session::createFeature(string theFeatureID) std::shared_ptr Model_Session::moduleDocument() { - bool aFirstCall = !Model_Application::getApplication()->hasDocument("root"); + Handle(Model_Application) anApp = Model_Application::getApplication(); + bool aFirstCall = !anApp->hasRoot(); if (aFirstCall) { + // to be sure that plugins are loaded, + // even before the first "createFeature" call (in unit tests) + LoadPluginsInfo(); // creation of the root document is always outside of the transaction, so, avoid checking it setCheckTransactions(false); - } - std::shared_ptr aDoc = std::shared_ptr( - Model_Application::getApplication()->getDocument("root")); - if (aFirstCall) { + anApp->createDocument(0); // 0 is a root ID // creation of the root document is always outside of the transaction, so, avoid checking it setCheckTransactions(true); } - return aDoc; + return anApp->rootDocument(); } -std::shared_ptr Model_Session::document(std::string theDocID) +std::shared_ptr Model_Session::document(int theDocID) { return std::shared_ptr( - Model_Application::getApplication()->getDocument(theDocID)); + Model_Application::getApplication()->document(theDocID)); } bool Model_Session::hasModuleDocument() { - return Model_Application::getApplication()->hasDocument("root"); + return Model_Application::getApplication()->hasRoot(); } std::shared_ptr Model_Session::activeDocument() @@ -205,18 +219,54 @@ std::shared_ptr Model_Session::activeDocument() return myCurrentDoc; } +/// makes the last feature in the document as the current +static void makeCurrentLast(std::shared_ptr theDoc) { + if (theDoc.get()) { + FeaturePtr aLast = std::dynamic_pointer_cast(theDoc)->lastFeature(); + // if last is nested into something else, make this something else as last: + // otherwise it will look like edition of sub-element, so, the main will be disabled + if (aLast.get()) { + CompositeFeaturePtr aMain = ModelAPI_Tools::compositeOwner(aLast); + while(aMain.get()) { + aLast = aMain; + aMain = ModelAPI_Tools::compositeOwner(aLast); + } + } + theDoc->setCurrentFeature(aLast, false); + } +} + void Model_Session::setActiveDocument( std::shared_ptr theDoc, bool theSendSignal) { if (myCurrentDoc != theDoc) { + if (myCurrentDoc.get()) + myCurrentDoc->setActive(false); + if (theDoc.get()) + theDoc->setActive(true); + + std::shared_ptr aPrevious = myCurrentDoc; myCurrentDoc = theDoc; if (theDoc.get() && theSendSignal) { + // this must be before the synchronisation call because features in PartSet lower than this + // part feature must be disabled and don't recomputed anymore (issue 1156, + // translation feature is failed on activation of Part 2) + if (isOperation()) { // do it only in transaction, not on opening of document + DocumentPtr aRoot = moduleDocument(); + if (myCurrentDoc != aRoot) { + FeaturePtr aPartFeat = ModelAPI_Tools::findPartFeature(aRoot, myCurrentDoc); + if (aPartFeat.get()) { + aRoot->setCurrentFeature(aPartFeat, false); + } + } + } // syncronize the document: it may be just opened or opened but removed before std::shared_ptr aDoc = std::dynamic_pointer_cast(theDoc); if (aDoc.get()) { bool aWasChecked = myCheckTransactions; setCheckTransactions(false); - aDoc->synchronizeFeatures(false, true, true); + TDF_LabelList anEmptyUpdated; + aDoc->objects()->synchronizeFeatures(anEmptyUpdated, true, true, true); if (aWasChecked) setCheckTransactions(true); } @@ -224,37 +274,49 @@ void Model_Session::setActiveDocument( new Events_Message(Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED))); Events_Loop::loop()->send(aMsg); } + // make the current state correct and synchronised in the module and sub-documents + if (isOperation()) { // do it only in transaction, not on opening of document + if (myCurrentDoc == moduleDocument()) { + // make the current feature the latest in root, in previous root current become also last + makeCurrentLast(aPrevious); + makeCurrentLast(myCurrentDoc); + } else { + // make the current feature the latest in sub, root current feature becomes this sub + makeCurrentLast(myCurrentDoc); + } + } } } std::list > Model_Session::allOpenedDocuments() { - list > aResult; + std::list > aResult; aResult.push_back(moduleDocument()); // add subs recursively - list >::iterator aDoc = aResult.begin(); + std::list >::iterator aDoc = aResult.begin(); for(; aDoc != aResult.end(); aDoc++) { DocumentPtr anAPIDoc = *aDoc; std::shared_ptr aDoc = std::dynamic_pointer_cast(anAPIDoc); if (aDoc) { - const std::set aSubs = aDoc->subDocuments(true); - std::set::const_iterator aSubIter = aSubs.cbegin(); + const std::set aSubs = aDoc->subDocuments(); + std::set::const_iterator aSubIter = aSubs.cbegin(); for(; aSubIter != aSubs.cend(); aSubIter++) { - if (!Model_Application::getApplication()->isLoadByDemand(*aSubIter)) { - aResult.push_back(Model_Application::getApplication()->getDocument(*aSubIter)); - } + aResult.push_back(Model_Application::getApplication()->document(*aSubIter)); } } } return aResult; } +bool Model_Session::isLoadByDemand(const std::string theDocID) +{ + return Model_Application::getApplication()->isLoadByDemand(theDocID); +} + std::shared_ptr Model_Session::copy( - std::shared_ptr theSource, std::string theID) + std::shared_ptr theSource, const int theDestID) { - // create a new document - std::shared_ptr aNew = std::dynamic_pointer_cast( - Model_Application::getApplication()->getDocument(theID)); + std::shared_ptr aNew = Model_Application::getApplication()->document(theDestID); // make a copy of all labels TDF_Label aSourceRoot = std::dynamic_pointer_cast(theSource)->document()->Main() .Father(); @@ -266,7 +328,8 @@ std::shared_ptr Model_Session::copy( aRT->SetRelocation(aSourceRoot, aTargetRoot); TDF_CopyTool::Copy(aDS, aRT); - aNew->synchronizeFeatures(false, true, true); + TDF_LabelList anEmptyUpdated; + aNew->objects()->synchronizeFeatures(anEmptyUpdated, true, true, true); return aNew; } @@ -274,10 +337,11 @@ Model_Session::Model_Session() { myPluginsInfoLoaded = false; myCheckTransactions = true; + myOperationAttachedToNext = false; ModelAPI_Session::setSession(std::shared_ptr(this)); // register the configuration reading listener Events_Loop* aLoop = Events_Loop::loop(); - static const Events_ID kFeatureEvent = + static const Events_ID kFeatureEvent = Events_Loop::eventByName(Config_FeatureMessage::MODEL_EVENT()); aLoop->registerListener(this, kFeatureEvent); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED), 0, true); @@ -288,38 +352,40 @@ Model_Session::Model_Session() void Model_Session::processEvent(const std::shared_ptr& theMessage) { - static const Events_ID kFeatureEvent = + static const Events_ID kFeatureEvent = Events_Loop::eventByName(Config_FeatureMessage::MODEL_EVENT()); static const Events_ID kValidatorEvent = Events_Loop::eventByName(EVENT_VALIDATOR_LOADED); if (theMessage->eventID() == kFeatureEvent) { - const std::shared_ptr aMsg = + const std::shared_ptr aMsg = std::dynamic_pointer_cast(theMessage); if (aMsg) { - // proccess the plugin info, load plugin + + // process the plugin info, load plugin if (myPlugins.find(aMsg->id()) == myPlugins.end()) { myPlugins[aMsg->id()] = std::pair( aMsg->pluginLibrary(), aMsg->documentKind()); } } else { - const std::shared_ptr aMsgAttr = + const std::shared_ptr aMsgAttr = std::dynamic_pointer_cast(theMessage); if (aMsgAttr) { + if (!aMsgAttr->isObligatory()) { validators()->registerNotObligatory(aMsgAttr->featureId(), aMsgAttr->attributeId()); } if(aMsgAttr->isConcealment()) { validators()->registerConcealment(aMsgAttr->featureId(), aMsgAttr->attributeId()); } - if (!aMsgAttr->caseId().empty()) { - validators()->registerCase(aMsgAttr->featureId(), aMsgAttr->attributeId(), - aMsgAttr->switchId(), aMsgAttr->caseId()); + const std::list >& aCases = aMsgAttr->getCases(); + if (!aCases.empty()) { + validators()->registerCase(aMsgAttr->featureId(), aMsgAttr->attributeId(), aCases); } } } // plugins information was started to load, so, it will be loaded myPluginsInfoLoaded = true; } else if (theMessage->eventID() == kValidatorEvent) { - std::shared_ptr aMsg = + std::shared_ptr aMsg = std::dynamic_pointer_cast(theMessage); if (aMsg) { if (aMsg->attributeId().empty()) { // feature validator @@ -331,16 +397,33 @@ void Model_Session::processEvent(const std::shared_ptr& theMessa } } else { // create/update/delete if (myCheckTransactions && !isOperation()) - Events_Error::send("Modification of data structure outside of the transaction"); + Events_InfoMessage("Model_Session", + "Modification of data structure outside of the transaction").send(); // if part is deleted, make the root as the current document (on undo of Parts creations) static const Events_ID kDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED); if (theMessage->eventID() == kDeletedEvent) { std::shared_ptr aDeleted = std::dynamic_pointer_cast(theMessage); - if (aDeleted && - aDeleted->groups().find(ModelAPI_ResultPart::group()) != aDeleted->groups().end()) + if (aDeleted && + aDeleted->groups().find(ModelAPI_ResultPart::group()) != aDeleted->groups().end()) { - setActiveDocument(moduleDocument()); + // check that the current feature of the session is still the active Part (even disabled) + bool aFound = false; + FeaturePtr aCurrentPart = moduleDocument()->currentFeature(true); + if (aCurrentPart.get()) { + const std::list >& aResList = aCurrentPart->results(); + std::list >::const_iterator aRes = aResList.begin(); + for(; !aFound && aRes != aResList.end(); aRes++) { + ResultPartPtr aPRes = std::dynamic_pointer_cast(*aRes); + if (aPRes.get() && aPRes->isActivated() && aPRes->partDoc() == activeDocument()) { + aFound = true; + + } + } + } + if (!aFound) { // if not, the part was removed, so activate the module document + setActiveDocument(moduleDocument()); + } } } } @@ -384,3 +467,27 @@ ModelAPI_ValidatorsFactory* Model_Session::validators() static Model_ValidatorsFactory* aFactory = new Model_ValidatorsFactory; return aFactory; } + +int Model_Session::transactionID() +{ + return ROOT_DOC->transactionID(); +} + +void Model_Session::forceLoadPlugin(const std::string& thePluginName) +{ + // load all information about plugins, features and attributes + LoadPluginsInfo(); + + // store name of current plugin for further restoring, + // because forceLoadPlugin may be called while loading another plugin + std::string aCurrentPluginName = myCurrentPluginName; + + myCurrentPluginName = thePluginName; + if (myPluginObjs.find(myCurrentPluginName) == myPluginObjs.end()) { + // load plugin library if not yet done + Config_ModuleReader::loadPlugin(myCurrentPluginName); + } + + // restore current plugin + myCurrentPluginName = aCurrentPluginName; +}