X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FExchangePlugin%2FExchangePlugin_ImportPart.cpp;h=e63d5ee9c0109b8265e43e291f243e405b21da8e;hb=8f43b985d2f7170b8dfa06abd3edc7d6cb0c2e1f;hp=9522e20bc53d88a457bc2a38bc86ab3fa8904a5f;hpb=3ee6dd7ba9733f4374c1cf370d7a0ee0847659d5;p=modules%2Fshaper.git diff --git a/src/ExchangePlugin/ExchangePlugin_ImportPart.cpp b/src/ExchangePlugin/ExchangePlugin_ImportPart.cpp index 9522e20bc..e63d5ee9c 100644 --- a/src/ExchangePlugin/ExchangePlugin_ImportPart.cpp +++ b/src/ExchangePlugin/ExchangePlugin_ImportPart.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2019 CEA/DEN, EDF R&D +// Copyright (C) 2014-2020 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -19,12 +19,26 @@ #include +#include #include +#include #include #include +#include #include +#include +#include + +static const std::string THE_NEW_PART_STR("New Part"); +static const std::string THE_PART_SET_STR("PartSet"); + +// Update names of imported features/results concurent with existing objects. +static void correntNonUniqueNames(DocumentPtr theDocument, std::list& theImported); +// Find the document according to its name or create the new one. +static DocumentPtr findDocument(DocumentPtr thePartSetDoc, const std::string& thePartName); + ExchangePlugin_ImportPart::ExchangePlugin_ImportPart() { } @@ -32,8 +46,11 @@ ExchangePlugin_ImportPart::ExchangePlugin_ImportPart() void ExchangePlugin_ImportPart::initAttributes() { data()->addAttribute(FILE_PATH_ID(), ModelAPI_AttributeString::typeId()); + data()->addAttribute(TARGET_PART_ID(), ModelAPI_AttributeInteger::typeId()); + data()->addAttribute(TARGET_PARTS_LIST_ID(), ModelAPI_AttributeStringArray::typeId()); } + void ExchangePlugin_ImportPart::execute() { AttributeStringPtr aFilePathAttr = string(FILE_PATH_ID()); @@ -43,22 +60,220 @@ void ExchangePlugin_ImportPart::execute() return; } - // load the file into the active document + // get the document where to import + AttributeStringArrayPtr aPartsAttr = stringArray(TARGET_PARTS_LIST_ID()); + AttributeIntegerPtr aTargetAttr = integer(TARGET_PART_ID()); SessionPtr aSession = ModelAPI_Session::get(); - DocumentPtr aDoc = document(); - bool isPartSet = aDoc == aSession->moduleDocument(); - bool isOk = aDoc->import(aFilename.c_str(), isPartSet); - if (!isOk && isPartSet) { - // there are features not appropriate for PartSet, - // create new part and load there - FeaturePtr aPartFeature = aDoc->addFeature(PartSetPlugin_Part::ID()); - ResultPartPtr aPartResult; + DocumentPtr aDoc = + findDocument(aSession->moduleDocument(), aPartsAttr->value(aTargetAttr->value())); + + // load the file into the document + std::list anImportedFeatures; + if (aDoc && aDoc->importPart(aFilename.c_str(), anImportedFeatures)) + correntNonUniqueNames(aDoc, anImportedFeatures); + else + setError("Cannot import the document."); +} + +void ExchangePlugin_ImportPart::attributeChanged(const std::string& theID) +{ + if (theID == FILE_PATH_ID()) { + AttributeStringPtr aFilePathAttr = string(FILE_PATH_ID()); + if (aFilePathAttr->value().empty()) + return; + + AttributeStringArrayPtr aPartsAttr = stringArray(TARGET_PARTS_LIST_ID()); + AttributeIntegerPtr aTargetAttr = integer(TARGET_PART_ID()); + + // update the list of target parts + SessionPtr aSession = ModelAPI_Session::get(); + DocumentPtr aDoc = document(); + bool isPartSet = aDoc == aSession->moduleDocument(); + if (isPartSet) { + std::list anAcceptedValues; + anAcceptedValues.push_back(THE_NEW_PART_STR); + + std::list anImportedFeatures; + if (aDoc->importPart(aFilePathAttr->value().c_str(), anImportedFeatures, isPartSet)) + anAcceptedValues.push_back(THE_PART_SET_STR); + + // append names of all parts + std::list aSubFeatures = aDoc->allFeatures(); + for (std::list::iterator aFIt = aSubFeatures.begin(); + aFIt != aSubFeatures.end(); ++aFIt) { + if ((*aFIt)->getKind() == PartSetPlugin_Part::ID()) + anAcceptedValues.push_back((*aFIt)->name()); + } + + if ((size_t)aPartsAttr->size() != anAcceptedValues.size()) + aTargetAttr->setValue(0); + + aPartsAttr->setSize((int)anAcceptedValues.size()); + std::list::iterator anIt = anAcceptedValues.begin(); + for (int anInd = 0; anIt != anAcceptedValues.end(); ++anIt, ++anInd) + aPartsAttr->setValue(anInd, *anIt); + } + else { + // keep only the name of the current part + if (aPartsAttr->size() == 0) { + FeaturePtr aPartFeature = ModelAPI_Tools::findPartFeature(aSession->moduleDocument(), aDoc); + + aPartsAttr->setSize(1); + aPartsAttr->setValue(0, aPartFeature->name()); + aTargetAttr->setValue(0); + } + } + } +} + + +// ================================ Auxiliary functions =================================== + +DocumentPtr findDocument(DocumentPtr thePartSetDoc, const std::string& thePartName) +{ + DocumentPtr aDoc; + if (thePartName == THE_PART_SET_STR) + aDoc = thePartSetDoc; + else { + FeaturePtr aPartFeature; + if (thePartName == THE_NEW_PART_STR) { + // create new part + aPartFeature = thePartSetDoc->addFeature(PartSetPlugin_Part::ID()); + if (aPartFeature) + aPartFeature->execute(); + } + else { + // find existing part by its name + std::list aSubFeatures = thePartSetDoc->allFeatures(); + for (std::list::iterator aFIt = aSubFeatures.begin(); + aFIt != aSubFeatures.end(); ++aFIt) { + if ((*aFIt)->getKind() == PartSetPlugin_Part::ID() && (*aFIt)->name() == thePartName) { + aPartFeature = *aFIt; + break; + } + } + } + if (aPartFeature) { - aPartFeature->execute(); - aPartResult = std::dynamic_pointer_cast(aPartFeature->lastResult()); + ResultPartPtr aPartResult = + std::dynamic_pointer_cast(aPartFeature->lastResult()); + if (aPartResult) + aDoc = aPartResult->partDoc(); + } + } + return aDoc; +} + +typedef std::map > > ObjectNameMap; + +bool splitName(std::string& theName, int& theIndex) +{ + size_t aLastUndercore = theName.find_last_of('_'); + bool isOk = aLastUndercore != std::string::npos; + if (isOk) { + char* isNumber; + std::string anIndexStr = theName.substr(aLastUndercore + 1); + theIndex = std::strtol(anIndexStr.c_str(), &isNumber, 10); + isOk = isNumber != 0; + if (isOk) + theName.erase(aLastUndercore); + } + return isOk; +} + +void addIndexedName(const ObjectPtr& theObject, ObjectNameMap& theIndexedNames) +{ + std::string aName = theObject->data()->name(); + std::string aGroup = theObject->groupName(); + int anIndex = 0; + bool isIndexed = splitName(aName, anIndex); + std::set& anIndices = theIndexedNames[aGroup][aName]; + if (isIndexed) + anIndices.insert(anIndex); +} + +// Collect names of features and results in the document before the import. +// The name of indexed feature/result will be split to the name and the index. For example , +// 'Point_1', 'Point_2' will be placed at the same key with the set of corrsponding indices: +// 'Point_1', 'Point_2' => {'Point', [1, 2]}. +// Thus, the new point should have index 3 and therefore the name 'Point_3'. +static void collectOldNames(DocumentPtr theDocument, std::list& theAvoided, + ObjectNameMap& theIndexedNames) +{ + std::list anAllFeatures = theDocument->allFeatures(); + std::list::iterator aFIt = anAllFeatures.begin(); + std::list::iterator anAvoidIt = theAvoided.begin(); + for (; aFIt != anAllFeatures.end(); ++aFIt) { + if (anAvoidIt != theAvoided.end() && *aFIt == *anAvoidIt) { + // skip this feature + ++anAvoidIt; + continue; + } + + // store name of feature + addIndexedName(*aFIt, theIndexedNames); + // store names of results + const std::list& aResults = (*aFIt)->results(); + for (std::list::const_iterator aRIt = aResults.begin(); + aRIt != aResults.end(); ++aRIt) + addIndexedName(*aRIt, theIndexedNames); + } +} + +static std::string uniqueName(const ObjectPtr& theObject, ObjectNameMap& theExistingNames) +{ + std::string aName = theObject->data()->name(); + std::string aGroup = theObject->groupName(); + int anIndex = 1; + splitName(aName, anIndex); + + ObjectNameMap::iterator aFoundGroup = theExistingNames.find(aGroup); + bool isUnique = aFoundGroup == theExistingNames.end(); + + std::map >::iterator aFound; + if (!isUnique) { + aFound = aFoundGroup->second.find(aName); + isUnique = aFound == aFoundGroup->second.end(); + } + + if (isUnique) { + // name is unique + aName = theObject->data()->name(); + addIndexedName(theObject, theExistingNames); + } + else { + // search the appropriate index + std::set::iterator aFoundIndex = aFound->second.find(anIndex); + for (; aFoundIndex != aFound->second.end(); ++aFoundIndex, ++anIndex) + if (anIndex != *aFoundIndex) + break; + // compose the new name + std::ostringstream aNewName; + aNewName << aName << "_" << anIndex; + aName = aNewName.str(); + // add new index + aFound->second.insert(anIndex); + } + + return aName; +} + +void correntNonUniqueNames(DocumentPtr theDocument, std::list& theImported) +{ + ObjectNameMap aNames; + collectOldNames(theDocument, theImported, aNames); + + for (std::list::iterator anIt = theImported.begin(); + anIt != theImported.end(); ++anIt) { + // update name of feature + std::string aNewName = uniqueName(*anIt, aNames); + (*anIt)->data()->setName(aNewName); + // update names of results + const std::list& aResults = (*anIt)->results(); + for (std::list::const_iterator aRIt = aResults.begin(); + aRIt != aResults.end(); ++aRIt) { + aNewName = uniqueName(*aRIt, aNames); + (*aRIt)->data()->setName(aNewName); } - isOk = aPartResult && aPartResult->partDoc()->import(aFilename.c_str()); } - if (!isOk) - setError("Cannot import the document."); }