#include <ConstructionPlugin_Plane.h>
#include <ConstructionPlugin_Point.h>
+#include <Events_InfoMessage.h>
+
+#include <PartSetPlugin_Part.h>
+
+#include <sstream>
+
// Obtain all features to be exported to get the list of selected results.
-static void collectFeatures(AttributeSelectionListPtr theSelected,
+static void collectFeatures(DocumentPtr theDocument,
+ AttributeSelectionListPtr theSelected,
std::list<FeaturePtr>& theExport);
// Obtain all constuction elements of the document.
static void collectConstructions(DocumentPtr theDocument, std::list<FeaturePtr>& theExport);
+// Check features could be exported. The following features cannot be exported:
+// * non-construction result (Part) when exporting the PartSet;
+// * features, which refer to objects from another document.
+// Returns true if all features can be exported.
+static bool verifyExport(const std::list<FeaturePtr>& theFeatures,
+ std::list<FeaturePtr>& theExternalReferences,
+ std::list<FeaturePtr>& theExportedParts);
ExchangePlugin_ExportPart::ExchangePlugin_ExportPart()
AttributeStringPtr aFilePathAttr = string(FILE_PATH_ID());
std::string aFilename = aFilePathAttr->value();
if (aFilename.empty()) {
- setError("File path is empty.");
+ setError("File name is empty.");
return;
}
std::list<FeaturePtr> aFeaturesToExport;
- SessionPtr aSession = ModelAPI_Session::get();
+ DocumentPtr anExportDoc = document();
+ DocumentPtr aPartSetDoc = ModelAPI_Session::get()->moduleDocument();
AttributeSelectionListPtr aSelected = selectionList(SELECTION_LIST_ID());
- DocumentPtr anExportDoc;
- if (aSelected && aSelected->size() == 0 &&
- aSession->activeDocument() == aSession->moduleDocument()) {
+ if (aSelected && aSelected->size() == 0 && anExportDoc == aPartSetDoc) {
// no result is selected, thus have to export all features of the current document,
// but the document is a PartSet; and it is forbidden to copy results of Parts,
// thus copy construction elements only
- collectConstructions(aSession->moduleDocument(), aFeaturesToExport);
+ collectConstructions(anExportDoc, aFeaturesToExport);
}
else
- collectFeatures(aSelected, aFeaturesToExport);
+ collectFeatures(anExportDoc, aSelected, aFeaturesToExport);
+
+ if (aFeaturesToExport.empty()) {
+ Events_InfoMessage(getKind(), "Selected features cannot be exported from the document.").send();
+ return;
+ }
+
+ // remove 'ExportPart' feature if any
+ if (aFeaturesToExport.back()->getKind() == ExchangePlugin_ExportPart::ID())
+ aFeaturesToExport.pop_back();
+
+ std::list<FeaturePtr> anExternalLinks, aReferredParts;
+ if (!verifyExport(aFeaturesToExport, anExternalLinks, aReferredParts)) {
+ if (!anExternalLinks.empty()) {
+ // collect names of features as a string
+ std::ostringstream aListOfFeatures;
+ for (std::list<FeaturePtr>::iterator anIt = anExternalLinks.begin();
+ anIt != anExternalLinks.end(); ++anIt) {
+ if (anIt != anExternalLinks.begin())
+ aListOfFeatures << ", ";
+ aListOfFeatures << "'" << (*anIt)->name() << "'";
+ }
+
+ std::string aMessage = "The selected results were created using external references "
+ "outside of this Part from features %1. "
+ "Please, remove these references or select another "
+ "sub-set of results to be able to export.";
+ Events_InfoMessage(getKind(), aMessage).arg(aListOfFeatures.str()).send();
+ }
+ if (!aReferredParts.empty()) {
+ // collect names of parts as a string
+ std::ostringstream aListOfParts;
+ for (std::list<FeaturePtr>::iterator anIt = aReferredParts.begin();
+ anIt != aReferredParts.end(); ++anIt) {
+ if (anIt != aReferredParts.begin())
+ aListOfParts << ", ";
+ aListOfParts << "'" << (*anIt)->name() << "'";
+ }
+
+ std::string aMessage = "The selected results were created using references "
+ "to results of Parts %1. Please, remove these references "
+ "or select another sub-set of results to be able to export.";
+ Events_InfoMessage(getKind(), aMessage).arg(aListOfParts.str()).send();
+ }
+ // should not export anything
+ aFeaturesToExport.clear();
+ }
if (!aFeaturesToExport.empty()) {
- // remove 'ExportPart' feature is any
- if (aFeaturesToExport.back()->getKind() == ExchangePlugin_ExportPart::ID())
- aFeaturesToExport.pop_back();
// save the document
- if (!aSession->activeDocument()->save(aFilename.c_str(), aFeaturesToExport))
+ if (!anExportDoc->save(aFilename.c_str(), aFeaturesToExport))
setError("Cannot save the document.");
}
}
// ================================ Auxiliary functions ===================================
-static void allReferencedFeatures(std::set<FeaturePtr>& theFeatures)
+static void allReferencedFeatures(const std::set<FeaturePtr>& theFeatures,
+ std::set<FeaturePtr>& theReferencedFeatures)
{
std::set<FeaturePtr> aReferences;
- for (std::set<FeaturePtr>::iterator anIt = theFeatures.begin();
+ for (std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin();
anIt != theFeatures.end(); ++anIt) {
+ theReferencedFeatures.insert(*anIt);
+
std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
(*anIt)->data()->referencesToObjects(aRefs);
for (std::list<ObjectPtr>::iterator anObjIt = aRIt->second.begin();
anObjIt != aRIt->second.end(); ++anObjIt) {
FeaturePtr aFeature = ModelAPI_Feature::feature(*anObjIt);
- if (aFeature)
+ if (aFeature && theReferencedFeatures.find(aFeature) == theReferencedFeatures.end())
aReferences.insert(aFeature);
}
}
}
- if (!aReferences.empty()) {
- allReferencedFeatures(aReferences);
- theFeatures.insert(aReferences.begin(), aReferences.end());
- }
+ if (!aReferences.empty())
+ allReferencedFeatures(aReferences, theReferencedFeatures);
+}
+
+static bool isCoordinate(FeaturePtr theFeature)
+{
+ return !theFeature->isInHistory() &&
+ (theFeature->getKind() == ConstructionPlugin_Point::ID() ||
+ theFeature->getKind() == ConstructionPlugin_Axis::ID() ||
+ theFeature->getKind() == ConstructionPlugin_Plane::ID());
}
-void collectFeatures(AttributeSelectionListPtr theSelected, std::list<FeaturePtr>& theExport)
+void collectFeatures(DocumentPtr theDocument,
+ AttributeSelectionListPtr theSelected,
+ std::list<FeaturePtr>& theExport)
{
- theExport = ModelAPI_Session::get()->activeDocument()->allFeatures();
+ theExport = theDocument->allFeatures();
if (!theSelected || theSelected->size() == 0) {
// nothing is selected, return all features of the document
aFeaturesToExport.insert(aCurrentFeature);
}
// recursively collect all features used for the selected results
- allReferencedFeatures(aFeaturesToExport);
+ allReferencedFeatures(aFeaturesToExport, aFeaturesToExport);
// remove the features which are not affect the selected results
std::list<FeaturePtr>::iterator anIt = theExport.begin();
ResultPtr aCurResult = aCurFeature->lastResult();
bool isApplicable =
- (!aCurResult || aCurResult->groupName() == ModelAPI_ResultConstruction::group());
-
- if (isApplicable && !aCurFeature->isInHistory()) {
- isApplicable = aCurFeature->getKind() != ConstructionPlugin_Point::ID() &&
- aCurFeature->getKind() != ConstructionPlugin_Axis::ID() &&
- aCurFeature->getKind() != ConstructionPlugin_Plane::ID();
- }
+ (!aCurResult || aCurResult->groupName() == ModelAPI_ResultConstruction::group()) &&
+ !isCoordinate(aCurFeature);
if (isApplicable)
++anIt;
}
}
}
+
+bool verifyExport(const std::list<FeaturePtr>& theFeatures,
+ std::list<FeaturePtr>& theExternalReferences,
+ std::list<FeaturePtr>& theExportedParts)
+{
+ for (std::list<FeaturePtr>::const_iterator anIt = theFeatures.begin();
+ anIt != theFeatures.end(); ++anIt) {
+ // full part should not be exported
+ if ((*anIt)->getKind() == PartSetPlugin_Part::ID())
+ theExportedParts.push_back(*anIt);
+
+ DocumentPtr aDoc = (*anIt)->document();
+
+ std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
+ (*anIt)->data()->referencesToObjects(aRefs);
+ std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRIt = aRefs.begin();
+ for (; aRIt != aRefs.end(); ++aRIt) {
+ for (std::list<ObjectPtr>::iterator anObjIt = aRIt->second.begin();
+ anObjIt != aRIt->second.end(); ++anObjIt) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(*anObjIt);
+ if (aFeature) {
+ // feature refers to external entity,
+ // which is neither the Origin nor coordinate axis or plane
+ if (aFeature->document() != aDoc && !isCoordinate(aFeature))
+ theExternalReferences.push_back(*anIt);
+ // feature refers to result of a part
+ if (aFeature->getKind() == PartSetPlugin_Part::ID())
+ theExportedParts.push_back(*anIt);
+ }
+ }
+ }
+ }
+
+ return theExternalReferences.empty() && theExportedParts.empty();
+}