1 // Copyright (C) 2014-2019 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include <ExchangePlugin_ExportPart.h>
22 #include <ModelAPI_AttributeSelectionList.h>
23 #include <ModelAPI_AttributeString.h>
24 #include <ModelAPI_ResultConstruction.h>
25 #include <ModelAPI_Session.h>
26 #include <ModelAPI_Validator.h>
28 #include <ConstructionPlugin_Axis.h>
29 #include <ConstructionPlugin_Plane.h>
30 #include <ConstructionPlugin_Point.h>
32 #include <Events_InfoMessage.h>
34 #include <PartSetPlugin_Part.h>
38 // Obtain all features to be exported to get the list of selected results.
39 static void collectFeatures(DocumentPtr theDocument,
40 AttributeSelectionListPtr theSelected,
41 std::list<FeaturePtr>& theExport);
42 // Obtain all constuction elements of the document.
43 static void collectConstructions(DocumentPtr theDocument, std::list<FeaturePtr>& theExport);
44 // Check features could be exported. The following features cannot be exported:
45 // * non-construction result (Part) when exporting the PartSet;
46 // * features, which refer to objects from another document.
47 // Returns true if all features can be exported.
48 static bool verifyExport(const std::list<FeaturePtr>& theFeatures,
49 std::list<FeaturePtr>& theExternalReferences,
50 std::list<FeaturePtr>& theExportedParts);
53 ExchangePlugin_ExportPart::ExchangePlugin_ExportPart()
57 void ExchangePlugin_ExportPart::initAttributes()
59 data()->addAttribute(FILE_PATH_ID(), ModelAPI_AttributeString::typeId());
60 data()->addAttribute(FILE_FORMAT_ID(), ModelAPI_AttributeString::typeId());
61 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FILE_FORMAT_ID());
62 data()->addAttribute(SELECTION_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
63 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SELECTION_LIST_ID());
66 void ExchangePlugin_ExportPart::execute()
68 AttributeStringPtr aFilePathAttr = string(FILE_PATH_ID());
69 std::string aFilename = aFilePathAttr->value();
70 if (aFilename.empty()) {
71 setError("File name is empty.");
75 std::list<FeaturePtr> aFeaturesToExport;
77 DocumentPtr anExportDoc = document();
78 DocumentPtr aPartSetDoc = ModelAPI_Session::get()->moduleDocument();
79 AttributeSelectionListPtr aSelected = selectionList(SELECTION_LIST_ID());
80 if (aSelected && aSelected->size() == 0 && anExportDoc == aPartSetDoc) {
81 // no result is selected, thus have to export all features of the current document,
82 // but the document is a PartSet; and it is forbidden to copy results of Parts,
83 // thus copy construction elements only
84 collectConstructions(anExportDoc, aFeaturesToExport);
87 collectFeatures(anExportDoc, aSelected, aFeaturesToExport);
89 if (aFeaturesToExport.empty()) {
90 Events_InfoMessage(getKind(), "Selected features cannot be exported from the document.").send();
94 // remove 'ExportPart' feature if any
95 if (aFeaturesToExport.back()->getKind() == ExchangePlugin_ExportPart::ID())
96 aFeaturesToExport.pop_back();
98 std::list<FeaturePtr> anExternalLinks, aReferredParts;
99 if (!verifyExport(aFeaturesToExport, anExternalLinks, aReferredParts)) {
100 if (!anExternalLinks.empty()) {
101 // collect names of features as a string
102 std::ostringstream aListOfFeatures;
103 for (std::list<FeaturePtr>::iterator anIt = anExternalLinks.begin();
104 anIt != anExternalLinks.end(); ++anIt) {
105 if (anIt != anExternalLinks.begin())
106 aListOfFeatures << ", ";
107 aListOfFeatures << "'" << (*anIt)->name() << "'";
110 std::string aMessage = "The selected results were created using external references "
111 "outside of this Part from features %1. "
112 "Please, remove these references or select another "
113 "sub-set of results to be able to export.";
114 Events_InfoMessage(getKind(), aMessage).arg(aListOfFeatures.str()).send();
116 if (!aReferredParts.empty()) {
117 // collect names of parts as a string
118 std::ostringstream aListOfParts;
119 for (std::list<FeaturePtr>::iterator anIt = aReferredParts.begin();
120 anIt != aReferredParts.end(); ++anIt) {
121 if (anIt != aReferredParts.begin())
122 aListOfParts << ", ";
123 aListOfParts << "'" << (*anIt)->name() << "'";
126 std::string aMessage = "The selected results were created using references "
127 "to results of Parts %1. Please, remove these references "
128 "or select another sub-set of results to be able to export.";
129 Events_InfoMessage(getKind(), aMessage).arg(aListOfParts.str()).send();
131 // should not export anything
132 aFeaturesToExport.clear();
135 if (!aFeaturesToExport.empty()) {
137 if (!anExportDoc->save(aFilename.c_str(), aFeaturesToExport))
138 setError("Cannot save the document.");
143 // ================================ Auxiliary functions ===================================
145 static void allReferencedFeatures(const std::set<FeaturePtr>& theFeatures,
146 std::set<FeaturePtr>& theReferencedFeatures)
148 std::set<FeaturePtr> aReferences;
149 for (std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin();
150 anIt != theFeatures.end(); ++anIt) {
151 theReferencedFeatures.insert(*anIt);
153 std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
154 (*anIt)->data()->referencesToObjects(aRefs);
156 for (std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRIt = aRefs.begin();
157 aRIt != aRefs.end(); ++aRIt) {
158 for (std::list<ObjectPtr>::iterator anObjIt = aRIt->second.begin();
159 anObjIt != aRIt->second.end(); ++anObjIt) {
160 FeaturePtr aFeature = ModelAPI_Feature::feature(*anObjIt);
161 if (aFeature && theReferencedFeatures.find(aFeature) == theReferencedFeatures.end())
162 aReferences.insert(aFeature);
167 if (!aReferences.empty())
168 allReferencedFeatures(aReferences, theReferencedFeatures);
171 static bool isCoordinate(FeaturePtr theFeature)
173 return !theFeature->isInHistory() &&
174 (theFeature->getKind() == ConstructionPlugin_Point::ID() ||
175 theFeature->getKind() == ConstructionPlugin_Axis::ID() ||
176 theFeature->getKind() == ConstructionPlugin_Plane::ID());
179 void collectFeatures(DocumentPtr theDocument,
180 AttributeSelectionListPtr theSelected,
181 std::list<FeaturePtr>& theExport)
183 theExport = theDocument->allFeatures();
185 if (!theSelected || theSelected->size() == 0) {
186 // nothing is selected, return all features of the document
190 // collect initial list of features basing on the selected results
191 std::set<FeaturePtr> aFeaturesToExport;
192 for (int anIndex = 0, aSize = theSelected->size(); anIndex < aSize; ++anIndex) {
193 AttributeSelectionPtr aCurrent = theSelected->value(anIndex);
194 FeaturePtr aCurrentFeature = ModelAPI_Feature::feature(aCurrent->context());
196 aFeaturesToExport.insert(aCurrentFeature);
198 // recursively collect all features used for the selected results
199 allReferencedFeatures(aFeaturesToExport, aFeaturesToExport);
201 // remove the features which are not affect the selected results
202 std::list<FeaturePtr>::iterator anIt = theExport.begin();
203 while (anIt != theExport.end()) {
204 if (aFeaturesToExport.find(*anIt) == aFeaturesToExport.end()) {
205 std::list<FeaturePtr>::iterator aRemoveIt = anIt++;
206 theExport.erase(aRemoveIt);
213 void collectConstructions(DocumentPtr theDocument, std::list<FeaturePtr>& theExport)
215 theExport = theDocument->allFeatures();
216 // keep constructions only
217 std::list<FeaturePtr>::iterator anIt = theExport.begin();
218 while (anIt != theExport.end()) {
219 FeaturePtr aCurFeature = *anIt;
220 ResultPtr aCurResult = aCurFeature->lastResult();
223 (!aCurResult || aCurResult->groupName() == ModelAPI_ResultConstruction::group()) &&
224 !isCoordinate(aCurFeature);
229 std::list<FeaturePtr>::iterator aRemoveIt = anIt++;
230 theExport.erase(aRemoveIt);
235 bool verifyExport(const std::list<FeaturePtr>& theFeatures,
236 std::list<FeaturePtr>& theExternalReferences,
237 std::list<FeaturePtr>& theExportedParts)
239 for (std::list<FeaturePtr>::const_iterator anIt = theFeatures.begin();
240 anIt != theFeatures.end(); ++anIt) {
241 // full part should not be exported
242 if ((*anIt)->getKind() == PartSetPlugin_Part::ID())
243 theExportedParts.push_back(*anIt);
245 DocumentPtr aDoc = (*anIt)->document();
247 std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
248 (*anIt)->data()->referencesToObjects(aRefs);
249 std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRIt = aRefs.begin();
250 for (; aRIt != aRefs.end(); ++aRIt) {
251 for (std::list<ObjectPtr>::iterator anObjIt = aRIt->second.begin();
252 anObjIt != aRIt->second.end(); ++anObjIt) {
253 FeaturePtr aFeature = ModelAPI_Feature::feature(*anObjIt);
255 // feature refers to external entity,
256 // which is neither the Origin nor coordinate axis or plane
257 if (aFeature->document() != aDoc && !isCoordinate(aFeature))
258 theExternalReferences.push_back(*anIt);
259 // feature refers to result of a part
260 if (aFeature->getKind() == PartSetPlugin_Part::ID())
261 theExportedParts.push_back(*anIt);
267 return theExternalReferences.empty() && theExportedParts.empty();