]> SALOME platform Git repositories - modules/shaper.git/blob - src/ExchangePlugin/ExchangePlugin_ExportPart.cpp
Salome HOME
cc4af14c6ac7e97874ce8c6a1a5d6c27fb28975b
[modules/shaper.git] / src / ExchangePlugin / ExchangePlugin_ExportPart.cpp
1 // Copyright (C) 2014-2019  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <ExchangePlugin_ExportPart.h>
21
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>
27
28 #include <ConstructionPlugin_Axis.h>
29 #include <ConstructionPlugin_Plane.h>
30 #include <ConstructionPlugin_Point.h>
31
32 #include <Events_InfoMessage.h>
33
34 #include <PartSetPlugin_Part.h>
35
36 #include <sstream>
37
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);
51
52
53 ExchangePlugin_ExportPart::ExchangePlugin_ExportPart()
54 {
55 }
56
57 void ExchangePlugin_ExportPart::initAttributes()
58 {
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());
64 }
65
66 void ExchangePlugin_ExportPart::execute()
67 {
68   AttributeStringPtr aFilePathAttr = string(FILE_PATH_ID());
69   std::string aFilename = aFilePathAttr->value();
70   if (aFilename.empty()) {
71     setError("File name is empty.");
72     return;
73   }
74
75   std::list<FeaturePtr> aFeaturesToExport;
76
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);
85   }
86   else
87     collectFeatures(anExportDoc, aSelected, aFeaturesToExport);
88
89   if (aFeaturesToExport.empty()) {
90     Events_InfoMessage(getKind(), "Selected features cannot be exported from the document.").send();
91     return;
92   }
93
94   // remove 'ExportPart' feature if any
95   if (aFeaturesToExport.back()->getKind() == ExchangePlugin_ExportPart::ID())
96     aFeaturesToExport.pop_back();
97
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() << "'";
108       }
109
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();
115     }
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() << "'";
124       }
125
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();
130     }
131     // should not export anything
132     aFeaturesToExport.clear();
133   }
134
135   if (!aFeaturesToExport.empty()) {
136     // save the document
137     if (!anExportDoc->save(aFilename.c_str(), aFeaturesToExport))
138       setError("Cannot save the document.");
139   }
140 }
141
142
143 // ================================     Auxiliary functions     ===================================
144
145 static void allReferencedFeatures(const std::set<FeaturePtr>& theFeatures,
146                                   std::set<FeaturePtr>& theReferencedFeatures)
147 {
148   std::set<FeaturePtr> aReferences;
149   for (std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin();
150        anIt != theFeatures.end(); ++anIt) {
151     theReferencedFeatures.insert(*anIt);
152
153     std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
154     (*anIt)->data()->referencesToObjects(aRefs);
155
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);
163       }
164     }
165   }
166
167   if (!aReferences.empty())
168     allReferencedFeatures(aReferences, theReferencedFeatures);
169 }
170
171 static bool isCoordinate(FeaturePtr theFeature)
172 {
173   return !theFeature->isInHistory() &&
174           (theFeature->getKind() == ConstructionPlugin_Point::ID() ||
175            theFeature->getKind() == ConstructionPlugin_Axis::ID() ||
176            theFeature->getKind() == ConstructionPlugin_Plane::ID());
177 }
178
179 void collectFeatures(DocumentPtr theDocument,
180                      AttributeSelectionListPtr theSelected,
181                      std::list<FeaturePtr>& theExport)
182 {
183   theExport = theDocument->allFeatures();
184
185   if (!theSelected || theSelected->size() == 0) {
186     // nothing is selected, return all features of the document
187     return;
188   }
189
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());
195     if (aCurrentFeature)
196       aFeaturesToExport.insert(aCurrentFeature);
197   }
198   // recursively collect all features used for the selected results
199   allReferencedFeatures(aFeaturesToExport, aFeaturesToExport);
200
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);
207     }
208     else
209       ++anIt;
210   }
211 }
212
213 void collectConstructions(DocumentPtr theDocument, std::list<FeaturePtr>& theExport)
214 {
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();
221
222     bool isApplicable =
223         (!aCurResult || aCurResult->groupName() == ModelAPI_ResultConstruction::group()) &&
224         !isCoordinate(aCurFeature);
225
226     if (isApplicable)
227       ++anIt;
228     else {
229       std::list<FeaturePtr>::iterator aRemoveIt = anIt++;
230       theExport.erase(aRemoveIt);
231     }
232   }
233 }
234
235 bool verifyExport(const std::list<FeaturePtr>& theFeatures,
236                   std::list<FeaturePtr>& theExternalReferences,
237                   std::list<FeaturePtr>& theExportedParts)
238 {
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);
244
245     DocumentPtr aDoc = (*anIt)->document();
246
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);
254         if (aFeature) {
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);
262         }
263       }
264     }
265   }
266
267   return theExternalReferences.empty() && theExportedParts.empty();
268 }