13 #include <Poco/Delegate.h> 14 #include <Poco/Path.h> 15 #include <Poco/TemporaryFile.h> 16 #include <Poco/Zip/Compress.h> 17 #include <Poco/Zip/Decompress.h> 31 #include <itkObjectFactoryBase.h> 39 #include "itksys/SystemTools.hxx" 55 std::string returnValue = Poco::Path::temp() +
"SceneIOTemp" + uidGen.
GetUID();
56 std::string uniquename = returnValue + Poco::Path::separator();
61 bool existsNot = tempdir.createDirectory();
64 MITK_ERROR <<
"Warning: Directory already exitsts: " << uniquename <<
" (choosing another)";
66 "SceneIOTempDirectory" + uidGen.
GetUID();
67 uniquename = returnValue + Poco::Path::separator();
69 if (!tempdir2.createDirectory())
71 MITK_ERROR <<
"Warning: Second directory also already exitsts: " << uniquename;
75 catch (std::exception &e)
77 MITK_ERROR <<
"Could not create temporary directory " << uniquename <<
":" << e.what();
86 bool clearStorageFirst)
100 MITK_ERROR <<
"No filename given. Not possible to load scene.";
105 std::ifstream file(filename.c_str(), std::ios::binary);
108 MITK_ERROR <<
"Cannot open '" << filename <<
"' for reading";
116 MITK_ERROR <<
"Could not create temporary directory. Cannot open scene files.";
123 unzipper.EError += Poco::Delegate<SceneIO, std::pair<const Poco::Zip::ZipLocalFileHeader, const std::string>>(
125 unzipper.EOk += Poco::Delegate<SceneIO, std::pair<const Poco::Zip::ZipLocalFileHeader, const Poco::Path>>(
127 unzipper.decompressAllFiles();
128 unzipper.EError -= Poco::Delegate<SceneIO, std::pair<const Poco::Zip::ZipLocalFileHeader, const std::string>>(
130 unzipper.EOk -= Poco::Delegate<SceneIO, std::pair<const Poco::Zip::ZipLocalFileHeader, const Poco::Path>>(
136 <<
"'. Will attempt to read whatever could be unzipped.";
149 deleteDir.remove(
true);
162 bool clearStorageFirst)
168 if (storage.IsNull())
173 if (clearStorageFirst)
177 storage->Remove(storage->GetAll());
181 MITK_ERROR <<
"DataStorage cannot be cleared properly.";
186 if (indexfilename.empty())
188 MITK_ERROR <<
"No filename given. Not possible to load scene.";
193 std::string tempfilename;
194 std::string workingDir;
195 itksys::SystemTools::SplitProgramPath(indexfilename, workingDir, tempfilename);
199 TiXmlDocument document(indexfilename);
200 if (!document.LoadFile())
203 <<
"index.xml\nTinyXML reports: " << document.ErrorDesc() << std::endl;
208 if (!reader->LoadScene(document, workingDir, storage))
210 MITK_ERROR <<
"There were errors while loading scene file " << indexfilename <<
". Your data may be corrupted";
219 const std::string &filename)
223 MITK_ERROR <<
"No set of nodes given. Not possible to save scene.";
228 MITK_ERROR <<
"No data storage given. Not possible to save scene.";
233 if (filename.empty())
235 MITK_ERROR <<
"No filename given. Not possible to save scene.";
247 TiXmlDocument document;
248 auto *decl =
new TiXmlDeclaration(
252 document.LinkEndChild(decl);
254 auto *version =
new TiXmlElement(
"Version");
255 version->SetAttribute(
"Writer", __FILE__);
256 version->SetAttribute(
"Revision",
"$Revision: 17055 $");
257 version->SetAttribute(
"FileVersion", 1);
258 document.LinkEndChild(version);
262 if (sceneNodes.IsNull())
264 MITK_WARN <<
"Saving empty scene to " << filename;
268 if (sceneNodes->size() == 0)
270 MITK_WARN <<
"Saving empty scene to " << filename;
273 MITK_INFO <<
"Storing scene with " << sceneNodes->size() <<
" objects to " << filename;
278 MITK_ERROR <<
"Could not create temporary directory. Cannot create scene files.";
285 typedef std::map<DataNode *, std::string> UIDMapType;
286 typedef std::map<DataNode *, std::list<std::string>> SourcesMapType;
289 SourcesMapType sourceUIDs;
293 for (
auto iter = sceneNodes->begin(); iter != sceneNodes->end(); ++iter)
295 DataNode *node = iter->GetPointer();
300 DataStorage::SetOfObjects::ConstPointer sourceObjects = storage->
GetSources(node);
301 for (
auto sourceIter = sourceObjects->begin();
302 sourceIter != sourceObjects->end();
305 if (std::find(sceneNodes->begin(), sceneNodes->end(), *sourceIter) == sceneNodes->end())
309 if (nodeUIDs[*sourceIter].empty())
311 nodeUIDs[*sourceIter] = nodeUIDGen.
GetUID();
315 sourceUIDs[node].push_back(nodeUIDs[*sourceIter]);
318 if (nodeUIDs[node].empty())
320 nodeUIDs[node] = nodeUIDGen.
GetUID();
325 for (
auto iter = sceneNodes->begin(); iter != sceneNodes->end(); ++iter)
327 DataNode *node = iter->GetPointer();
331 auto *nodeElement =
new TiXmlElement(
"node");
332 std::string filenameHint(node->
GetName());
333 filenameHint = itksys::SystemTools::MakeCindentifier(
334 filenameHint.c_str());
337 auto searchUIDIter = nodeUIDs.find(node);
338 if (searchUIDIter != nodeUIDs.end())
341 nodeElement->SetAttribute(
"UID", searchUIDIter->second.c_str());
344 auto searchSourcesIter = sourceUIDs.find(node);
345 if (searchSourcesIter != sourceUIDs.end())
348 for (
auto sourceUIDIter = searchSourcesIter->second.begin();
349 sourceUIDIter != searchSourcesIter->second.end();
352 auto *uidElement =
new TiXmlElement(
"source");
353 uidElement->SetAttribute(
"UID", sourceUIDIter->c_str());
354 nodeElement->LinkEndChild(uidElement);
363 TiXmlElement *dataElement(
SaveBaseData(data, filenameHint, error));
371 if (propertyList && !propertyList->
IsEmpty())
373 TiXmlElement *baseDataPropertiesElement(
375 dataElement->LinkEndChild(baseDataPropertiesElement);
378 nodeElement->LinkEndChild(dataElement);
383 for (
auto renderWindowName : propertyListKeys)
386 if (propertyList && !propertyList->
IsEmpty())
388 TiXmlElement *renderWindowPropertiesElement(
390 renderWindowPropertiesElement->SetAttribute(
"renderwindow", renderWindowName);
391 nodeElement->LinkEndChild(renderWindowPropertiesElement);
397 if (propertyList && !propertyList->
IsEmpty())
399 TiXmlElement *propertiesElement(
401 nodeElement->LinkEndChild(propertiesElement);
403 document.LinkEndChild(nodeElement);
407 MITK_WARN <<
"Ignoring nullptr node during scene serialization.";
414 std::string defaultLocale_WorkingDirectory = Poco::Path::transcode(
m_WorkingDirectory );
416 if (!document.SaveFile(defaultLocale_WorkingDirectory + Poco::Path::separator() +
"index.xml"))
418 MITK_ERROR <<
"Could not write scene to " << defaultLocale_WorkingDirectory << Poco::Path::separator() <<
"index.xml" 419 <<
"\nTinyXML reports '" << document.ErrorDesc() <<
"'";
427 if (deleteFile.exists())
433 std::ofstream file(filename.c_str(), std::ios::binary | std::ios::out);
436 MITK_ERROR <<
"Could not open a zip file for writing: '" << filename <<
"'";
441 Poco::Zip::Compress zipper(file,
true);
443 zipper.addRecursive(tmpdir);
449 deleteDir.remove(
true);
457 catch (std::exception &e)
465 catch (std::exception &e)
467 MITK_ERROR <<
"Caught exception during saving temporary files to disk. Error description: '" << e.what() <<
"'";
482 auto *element =
new TiXmlElement(
"data");
483 element->SetAttribute(
"type", data->GetNameOfClass());
486 std::string serializername(data->GetNameOfClass());
487 serializername +=
"Serializer";
489 std::list<itk::LightObject::Pointer> thingsThatCanSerializeThis =
490 itk::ObjectFactoryBase::CreateAllInstance(serializername.c_str());
491 if (thingsThatCanSerializeThis.size() < 1)
493 MITK_ERROR <<
"No serializer found for " << data->GetNameOfClass() <<
". Skipping object";
496 for (
auto iter = thingsThatCanSerializeThis.begin();
497 iter != thingsThatCanSerializeThis.end();
500 if (
auto *serializer = dynamic_cast<BaseDataSerializer *>(iter->GetPointer()))
502 serializer->SetData(data);
503 serializer->SetFilenameHint(filenamehint);
504 std::string defaultLocale_WorkingDirectory = Poco::Path::transcode(
m_WorkingDirectory );
505 serializer->SetWorkingDirectory(defaultLocale_WorkingDirectory);
508 std::string writtenfilename = serializer->Serialize();
509 element->SetAttribute(
"file", writtenfilename);
512 catch (std::exception &e)
514 MITK_ERROR <<
"Serializer " << serializer->GetNameOfClass() <<
" failed: " << e.what();
525 assert(propertyList);
528 auto *element =
new TiXmlElement(
"properties");
533 serializer->SetPropertyList(propertyList);
534 serializer->SetFilenameHint(filenamehint);
535 std::string defaultLocale_WorkingDirectory = Poco::Path::transcode(
m_WorkingDirectory );
536 serializer->SetWorkingDirectory(defaultLocale_WorkingDirectory);
539 std::string writtenfilename = serializer->Serialize();
540 element->SetAttribute(
"file", writtenfilename);
542 if (failedProperties.IsNotNull())
548 catch (std::exception &e)
550 MITK_ERROR <<
"Serializer " << serializer->GetNameOfClass() <<
" failed: " << e.what();
567 std::pair<const Poco::Zip::ZipLocalFileHeader, const std::string> &
info)
570 MITK_ERROR <<
"Error while unzipping: " << info.second;
574 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)
static char GetDirectorySeparator()
std::string m_WorkingDirectory
Data management class that handles 'was created by' relations.
TiXmlElement * SaveBaseData(BaseData *data, const std::string &filenamehint, bool &error)
std::vector< MapOfPropertyLists::key_type > PropertyListKeyNames
Base of all data objects.
TiXmlElement * SavePropertyList(PropertyList *propertyList, const std::string &filenamehint)
virtual SetOfObjects::ConstPointer GetSources(const 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).
Key-value list holding instances of BaseProperty.
virtual DataStorage::Pointer LoadSceneUnzipped(const std::string &indexfilename, DataStorage *storage=nullptr, bool clearStorageFirst=false)
Load a scene of objects from directory.
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,...)
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.
unsigned int m_UnzipErrors
std::string GetOptionDirectory()
Return directory of/for option files.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
Convenience class to temporarily change the current locale.
PropertyList::Pointer m_FailedProperties
FailedBaseDataListType::Pointer m_FailedNodes
PropertyListKeyNames GetPropertyListNames() const
The "names" used for (renderer-specific) PropertyLists in GetPropertyList(string).
mitk::PropertyList * GetPropertyList(const mitk::BaseRenderer *renderer=nullptr) const
Get the PropertyList of the renderer. If renderer is nullptr, the BaseRenderer-independent PropertyLi...
void AddStepsToDo(unsigned int steps)
Adds steps to totalSteps.
virtual DataStorage::Pointer LoadScene(const std::string &filename, DataStorage *storage=nullptr, bool clearStorageFirst=false)
Load a scene of objects from file.
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.
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...