17 #include <Poco/Delegate.h>
18 #include <Poco/Path.h>
19 #include <Poco/TemporaryFile.h>
20 #include <Poco/Zip/Compress.h>
21 #include <Poco/Zip/Decompress.h>
35 #include <itkObjectFactoryBase.h>
43 #include "itksys/SystemTools.hxx"
59 std::string returnValue = Poco::Path::temp() +
"SceneIOTemp" + uidGen.
GetUID();
60 std::string uniquename = returnValue + Poco::Path::separator();
65 bool existsNot = tempdir.createDirectory();
68 MITK_ERROR <<
"Warning: Directory already exitsts: " << uniquename <<
" (choosing another)";
70 "SceneIOTempDirectory" + uidGen.
GetUID();
71 uniquename = returnValue + Poco::Path::separator();
73 if (!tempdir2.createDirectory())
75 MITK_ERROR <<
"Warning: Second directory also already exitsts: " << uniquename;
79 catch (std::exception &e)
81 MITK_ERROR <<
"Could not create temporary directory " << uniquename <<
":" << e.what();
90 bool clearStorageFirst)
101 if (clearStorageFirst)
105 storage->Remove(storage->GetAll());
109 MITK_ERROR <<
"DataStorage cannot be cleared properly.";
114 if (filename.empty())
116 MITK_ERROR <<
"No filename given. Not possible to load scene.";
121 std::ifstream file(filename.c_str(), std::ios::binary);
124 MITK_ERROR <<
"Cannot open '" << filename <<
"' for reading";
129 m_WorkingDirectory = CreateEmptyTempDirectory();
130 if (m_WorkingDirectory.empty())
132 MITK_ERROR <<
"Could not create temporary directory. Cannot open scene files.";
138 Poco::Zip::Decompress unzipper(file, Poco::Path(m_WorkingDirectory));
139 unzipper.EError += Poco::Delegate<SceneIO, std::pair<const Poco::Zip::ZipLocalFileHeader, const std::string>>(
141 unzipper.EOk += Poco::Delegate<SceneIO, std::pair<const Poco::Zip::ZipLocalFileHeader, const Poco::Path>>(
143 unzipper.decompressAllFiles();
144 unzipper.EError -= Poco::Delegate<SceneIO, std::pair<const Poco::Zip::ZipLocalFileHeader, const std::string>>(
146 unzipper.EOk -= Poco::Delegate<SceneIO, std::pair<const Poco::Zip::ZipLocalFileHeader, const Poco::Path>>(
151 MITK_ERROR <<
"There were " << m_UnzipErrors <<
" errors unzipping '" << filename
152 <<
"'. Will attempt to read whatever could be unzipped.";
158 if (!document.LoadFile())
161 <<
"index.xml\nTinyXML reports: " << document.ErrorDesc() << std::endl;
166 if (!reader->LoadScene(document, m_WorkingDirectory, storage))
168 MITK_ERROR <<
"There were errors while loading scene file " << filename <<
". Your data may be corrupted";
175 deleteDir.remove(
true);
179 MITK_ERROR <<
"Could not delete temporary directory " << m_WorkingDirectory;
192 MITK_ERROR <<
"No set of nodes given. Not possible to save scene.";
197 MITK_ERROR <<
"No data storage given. Not possible to save scene.";
202 if (filename.empty())
204 MITK_ERROR <<
"No filename given. Not possible to save scene.";
216 TiXmlDocument document;
217 TiXmlDeclaration *decl =
new TiXmlDeclaration(
221 document.LinkEndChild(decl);
223 TiXmlElement *version =
new TiXmlElement(
"Version");
224 version->SetAttribute(
"Writer", __FILE__);
225 version->SetAttribute(
"Revision",
"$Revision: 17055 $");
226 version->SetAttribute(
"FileVersion", 1);
227 document.LinkEndChild(version);
231 if (sceneNodes.IsNull())
237 if (sceneNodes->size() == 0)
242 MITK_INFO <<
"Storing scene with " << sceneNodes->size() <<
" objects to " <<
filename;
244 m_WorkingDirectory = CreateEmptyTempDirectory();
245 if (m_WorkingDirectory.empty())
247 MITK_ERROR <<
"Could not create temporary directory. Cannot create scene files.";
254 typedef std::map<DataNode *, std::string> UIDMapType;
255 typedef std::map<DataNode *, std::list<std::string>> SourcesMapType;
258 SourcesMapType sourceUIDs;
262 for (DataStorage::SetOfObjects::const_iterator iter = sceneNodes->begin(); iter != sceneNodes->end(); ++iter)
264 DataNode *node = iter->GetPointer();
270 for (mitk::DataStorage::SetOfObjects::const_iterator sourceIter = sourceObjects->begin();
271 sourceIter != sourceObjects->end();
274 if (std::find(sceneNodes->begin(), sceneNodes->end(), *sourceIter) == sceneNodes->end())
278 if (nodeUIDs[*sourceIter].empty())
280 nodeUIDs[*sourceIter] = nodeUIDGen.
GetUID();
284 sourceUIDs[node].push_back(nodeUIDs[*sourceIter]);
287 if (nodeUIDs[node].empty())
289 nodeUIDs[node] = nodeUIDGen.
GetUID();
294 for (DataStorage::SetOfObjects::const_iterator iter = sceneNodes->begin(); iter != sceneNodes->end(); ++iter)
296 DataNode *node = iter->GetPointer();
300 TiXmlElement *nodeElement =
new TiXmlElement(
"node");
301 std::string filenameHint(node->
GetName());
302 filenameHint = itksys::SystemTools::MakeCindentifier(
303 filenameHint.c_str());
306 UIDMapType::iterator searchUIDIter = nodeUIDs.find(node);
307 if (searchUIDIter != nodeUIDs.end())
310 nodeElement->SetAttribute(
"UID", searchUIDIter->second.c_str());
313 SourcesMapType::iterator searchSourcesIter = sourceUIDs.find(node);
314 if (searchSourcesIter != sourceUIDs.end())
317 for (std::list<std::string>::iterator sourceUIDIter = searchSourcesIter->second.begin();
318 sourceUIDIter != searchSourcesIter->second.end();
321 TiXmlElement *uidElement =
new TiXmlElement(
"source");
322 uidElement->SetAttribute(
"UID", sourceUIDIter->c_str());
323 nodeElement->LinkEndChild(uidElement);
332 TiXmlElement *dataElement(SaveBaseData(data, filenameHint, error));
335 m_FailedNodes->push_back(node);
340 if (propertyList && !propertyList->
IsEmpty())
342 TiXmlElement *baseDataPropertiesElement(
343 SavePropertyList(propertyList, filenameHint +
"-data"));
344 dataElement->LinkEndChild(baseDataPropertiesElement);
347 nodeElement->LinkEndChild(dataElement);
352 for (
auto renderWindowName : propertyListKeys)
355 if (propertyList && !propertyList->
IsEmpty())
357 TiXmlElement *renderWindowPropertiesElement(
358 SavePropertyList(propertyList, filenameHint +
"-" + renderWindowName));
359 renderWindowPropertiesElement->SetAttribute(
"renderwindow", renderWindowName);
360 nodeElement->LinkEndChild(renderWindowPropertiesElement);
366 if (propertyList && !propertyList->
IsEmpty())
368 TiXmlElement *propertiesElement(
369 SavePropertyList(propertyList, filenameHint +
"-node"));
370 nodeElement->LinkEndChild(propertiesElement);
372 document.LinkEndChild(nodeElement);
376 MITK_WARN <<
"Ignoring NULL node during scene serialization.";
383 if (!document.SaveFile(m_WorkingDirectory + Poco::Path::separator() +
"index.xml"))
385 MITK_ERROR <<
"Could not write scene to " << m_WorkingDirectory << Poco::Path::separator() <<
"index.xml"
386 <<
"\nTinyXML reports '" << document.ErrorDesc() <<
"'";
394 if (deleteFile.exists())
400 std::ofstream file(filename.c_str(), std::ios::binary | std::ios::out);
403 MITK_ERROR <<
"Could not open a zip file for writing: '" << filename <<
"'";
408 Poco::Zip::Compress zipper(file,
true);
409 Poco::Path tmpdir(m_WorkingDirectory);
410 zipper.addRecursive(tmpdir);
416 deleteDir.remove(
true);
420 MITK_ERROR <<
"Could not delete temporary directory " << m_WorkingDirectory;
424 catch (std::exception &e)
426 MITK_ERROR <<
"Could not create ZIP file from " << m_WorkingDirectory <<
"\nReason: " << e.what();
432 catch (std::exception &e)
434 MITK_ERROR <<
"Caught exception during saving temporary files to disk. Error description: '" << e.what() <<
"'";
449 TiXmlElement *element =
new TiXmlElement(
"data");
450 element->SetAttribute(
"type", data->GetNameOfClass());
453 std::string serializername(data->GetNameOfClass());
454 serializername +=
"Serializer";
456 std::list<itk::LightObject::Pointer> thingsThatCanSerializeThis =
457 itk::ObjectFactoryBase::CreateAllInstance(serializername.c_str());
458 if (thingsThatCanSerializeThis.size() < 1)
460 MITK_ERROR <<
"No serializer found for " << data->GetNameOfClass() <<
". Skipping object";
463 for (std::list<itk::LightObject::Pointer>::iterator iter = thingsThatCanSerializeThis.begin();
464 iter != thingsThatCanSerializeThis.end();
467 if (
BaseDataSerializer *serializer = dynamic_cast<BaseDataSerializer *>(iter->GetPointer()))
469 serializer->SetData(data);
470 serializer->SetFilenameHint(filenamehint);
471 serializer->SetWorkingDirectory(m_WorkingDirectory);
474 std::string writtenfilename = serializer->Serialize();
475 element->SetAttribute(
"file", writtenfilename);
478 catch (std::exception &e)
480 MITK_ERROR <<
"Serializer " << serializer->GetNameOfClass() <<
" failed: " << e.what();
491 assert(propertyList);
494 TiXmlElement *element =
new TiXmlElement(
"properties");
499 serializer->SetPropertyList(propertyList);
500 serializer->SetFilenameHint(filenamehint);
501 serializer->SetWorkingDirectory(m_WorkingDirectory);
504 std::string writtenfilename = serializer->Serialize();
505 element->SetAttribute(
"file", writtenfilename);
507 if (failedProperties.IsNotNull())
510 m_FailedProperties->ConcatenatePropertyList(failedProperties,
true);
513 catch (std::exception &e)
515 MITK_ERROR <<
"Serializer " << serializer->GetNameOfClass() <<
" failed: " << e.what();
523 return m_FailedNodes.GetPointer();
528 return m_FailedProperties;
532 std::pair<const Poco::Zip::ZipLocalFileHeader, const std::string> &
info)
535 MITK_ERROR <<
"Error while unzipping: " << info.second;
539 std::pair<const Poco::Zip::ZipLocalFileHeader, const Poco::Path> & )
void Progress(unsigned int steps=1)
Sets the current amount of progress to current progress + steps.
void OnUnzipError(const void *pSender, std::pair< const Poco::Zip::ZipLocalFileHeader, const std::string > &info)
mitk::PropertyList * GetPropertyList(const mitk::BaseRenderer *renderer=nullptr) const
Get the PropertyList of the renderer. If renderer is NULL, the BaseRenderer-independent PropertyList ...
static char GetDirectorySeparator()
Data management class that handles 'was created by' relations.
itk::SmartPointer< Self > Pointer
TiXmlElement * SaveBaseData(BaseData *data, const std::string &filenamehint, bool &error)
std::vector< MapOfPropertyLists::key_type > PropertyListKeyNames
Base of all data objects.
virtual DataStorage::Pointer LoadScene(const std::string &filename, DataStorage *storage=NULL, bool clearStorageFirst=false)
Load a scene of objects from file.
bool GetName(std::string &nodeName, const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="name") const
Convenience access method for accessing the name of an object (instance of StringProperty with proper...
Base class for objects that serialize BaseData types.
TiXmlElement * SavePropertyList(PropertyList *propertyList, const std::string &filenamehint)
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
Key-value list holding instances of BaseProperty.
virtual bool SaveScene(DataStorage::SetOfObjects::ConstPointer sceneNodes, const DataStorage *storage, const std::string &filename)
Save a scene of objects to file.
static ProgressBar * GetInstance()
static method to get the GUI dependent ProgressBar-instance so the methods for steps to do and progre...
static void info(const char *fmt,...)
itk::SmartPointer< const Self > ConstPointer
virtual SetOfObjects::ConstPointer GetSources(const mitk::DataNode *node, const NodePredicateBase *condition=nullptr, bool onlyDirectSources=true) const =0
returns a set of source objects for a given node that meet the given condition(s).
PropertyListKeyNames GetPropertyListNames() const
The "names" used for (renderer-specific) PropertyLists in GetPropertyList(string).
const FailedBaseDataListType * GetFailedNodes()
Get a list of nodes (BaseData containers) that failed to be read/written.
const PropertyList * GetFailedProperties()
Get a list of properties that failed to be read/written.
std::string GetOptionDirectory()
Return directory of/for option files.
Convenience class to temporarily change the current locale.
static const std::string filename
void AddStepsToDo(unsigned int steps)
Adds steps to totalSteps.
DataStorage::SetOfObjects FailedBaseDataListType
void OnUnzipOk(const void *pSender, std::pair< const Poco::Zip::ZipLocalFileHeader, const Poco::Path > &info)
static StandardFileLocations * GetInstance()
std::string CreateEmptyTempDirectory()
Class for nodes of the DataTree.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.