Salome HOME
Task 5.1.7: To be able to export a part to a file and import it into an existing...
[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 // Obtain all features to be exported to get the list of selected results.
29 static void collectFeatures(AttributeSelectionListPtr theSelected,
30                             std::list<FeaturePtr>& theExport);
31 // Obtain all constuction elements of the document.
32 static void collectConstructions(DocumentPtr theDocument, std::list<FeaturePtr>& theExport);
33
34
35 ExchangePlugin_ExportPart::ExchangePlugin_ExportPart()
36 {
37 }
38
39 void ExchangePlugin_ExportPart::initAttributes()
40 {
41   data()->addAttribute(FILE_PATH_ID(), ModelAPI_AttributeString::typeId());
42   data()->addAttribute(FILE_FORMAT_ID(), ModelAPI_AttributeString::typeId());
43   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FILE_FORMAT_ID());
44   data()->addAttribute(SELECTION_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
45   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SELECTION_LIST_ID());
46 }
47
48 void ExchangePlugin_ExportPart::execute()
49 {
50   AttributeStringPtr aFilePathAttr = string(FILE_PATH_ID());
51   std::string aFilename = aFilePathAttr->value();
52   if (aFilename.empty()) {
53     setError("File path is empty.");
54     return;
55   }
56
57   std::list<FeaturePtr> aFeaturesToExport;
58
59   SessionPtr aSession = ModelAPI_Session::get();
60   AttributeSelectionListPtr aSelected = selectionList(SELECTION_LIST_ID());
61   DocumentPtr anExportDoc;
62   if (aSelected && aSelected->size() == 0 &&
63       aSession->activeDocument() == aSession->moduleDocument()) {
64     // no result is selected, thus have to export all features of the current document,
65     // but the document is a PartSet; and it is forbidden to copy results of Parts,
66     // thus copy construction elements only
67     collectConstructions(aSession->moduleDocument(), aFeaturesToExport);
68   }
69   else
70     collectFeatures(aSelected, aFeaturesToExport);
71
72   if (!aFeaturesToExport.empty()) {
73     // remove 'ExportPart' feature is any
74     if (aFeaturesToExport.back()->getKind() == ExchangePlugin_ExportPart::ID())
75       aFeaturesToExport.pop_back();
76     // save the document
77     if (!aSession->activeDocument()->save(aFilename.c_str(), aFeaturesToExport))
78       setError("Cannot save the document.");
79   }
80 }
81
82
83 // ================================     Auxiliary functions     ===================================
84
85 static void allReferencedFeatures(std::set<FeaturePtr>& theFeatures)
86 {
87   std::set<FeaturePtr> aReferences;
88   for (std::set<FeaturePtr>::iterator anIt = theFeatures.begin();
89        anIt != theFeatures.end(); ++anIt) {
90     std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
91     (*anIt)->data()->referencesToObjects(aRefs);
92
93     for (std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRIt = aRefs.begin();
94          aRIt != aRefs.end(); ++aRIt) {
95       for (std::list<ObjectPtr>::iterator anObjIt = aRIt->second.begin();
96            anObjIt != aRIt->second.end(); ++anObjIt) {
97         FeaturePtr aFeature = ModelAPI_Feature::feature(*anObjIt);
98         if (aFeature)
99           aReferences.insert(aFeature);
100       }
101     }
102   }
103
104   if (!aReferences.empty()) {
105     allReferencedFeatures(aReferences);
106     theFeatures.insert(aReferences.begin(), aReferences.end());
107   }
108 }
109
110 void collectFeatures(AttributeSelectionListPtr theSelected, std::list<FeaturePtr>& theExport)
111 {
112   theExport = ModelAPI_Session::get()->activeDocument()->allFeatures();
113
114   if (!theSelected || theSelected->size() == 0) {
115     // nothing is selected, return all features of the document
116     return;
117   }
118
119   // collect initial list of features basing on the selected results
120   std::set<FeaturePtr> aFeaturesToExport;
121   for (int anIndex = 0, aSize = theSelected->size(); anIndex < aSize; ++anIndex) {
122     AttributeSelectionPtr aCurrent = theSelected->value(anIndex);
123     FeaturePtr aCurrentFeature = ModelAPI_Feature::feature(aCurrent->context());
124     if (aCurrentFeature)
125       aFeaturesToExport.insert(aCurrentFeature);
126   }
127   // recursively collect all features used for the selected results
128   allReferencedFeatures(aFeaturesToExport);
129
130   // remove the features which are not affect the selected results
131   std::list<FeaturePtr>::iterator anIt = theExport.begin();
132   while (anIt != theExport.end()) {
133     if (aFeaturesToExport.find(*anIt) == aFeaturesToExport.end()) {
134       std::list<FeaturePtr>::iterator aRemoveIt = anIt++;
135       theExport.erase(aRemoveIt);
136     }
137     else
138       ++anIt;
139   }
140 }
141
142 void collectConstructions(DocumentPtr theDocument, std::list<FeaturePtr>& theExport)
143 {
144   theExport = theDocument->allFeatures();
145   // keep constructions only
146   std::list<FeaturePtr>::iterator anIt = theExport.begin();
147   while (anIt != theExport.end()) {
148     if ((*anIt)->lastResult()->groupName() == ModelAPI_ResultConstruction::group())
149       ++anIt;
150     else {
151       std::list<FeaturePtr>::iterator aRemoveIt = anIt++;
152       theExport.erase(aRemoveIt);
153     }
154   }
155 }