// GUI includes
#include <LightApp_Study.h>
+#include <LightApp_Module.h>
+#include <LightApp_Application.h>
+#include <LightApp_DataModel.h>
#include <CAM_DataObject.h>
+#include <SUIT_Tools.h>
+#include <SUIT_Session.h>
+#include <SUIT_ResourceMgr.h>
+
+// KERNEL
+#include <utilities.h>
// Qt includes
#include <QFile>
+#include <QFileInfo>
#include <QTextStream>
+#include <QDomNode>
+
+// ParaView include
+#include <pqApplicationCore.h>
+#include <pqServer.h>
+#include <pqFixPathsInStateFilesBehavior.h>
+
+const QString PVGUI_DataModel::RESTORE_FLAG_FILE = "do_restore_paravis_references.par";
+
+/*!
+ * XML processing functions to handle the PV state file.
+ */
+namespace {
+
+ void processElements(QDomNode& thePropertyNode, QStringList& theFileNames,
+ const QString& theNewPath, bool theRestore)
+ {
+ QDomNode aElementNode = thePropertyNode.firstChild();
+ while (aElementNode.isElement()) {
+ QDomElement aElement = aElementNode.toElement();
+ if (aElement.tagName() == "Element") {
+ QString aIndex = aElement.attribute("index");
+ if (aIndex == "0") {
+ QString aValue = aElement.attribute("value");
+ if (!aValue.isNull()) {
+ if (theNewPath.isEmpty()) {
+ QFileInfo aFInfo(aValue);
+ if (aFInfo.exists()) {
+ theFileNames<<aValue;
+ aElement.setAttribute("value", aFInfo.fileName());
+ }
+ break;
+ } else {
+ if (theRestore)
+ aElement.setAttribute("value", QString(theNewPath) + aValue);
+ }
+ }
+ }
+ }
+ aElementNode = aElementNode.nextSibling();
+ }
+ }
+
+ void processProperties(QDomNode& theProxyNode, QStringList& theFileNames,
+ const QString& theNewPath, bool theRestore)
+ {
+ QDomNode aPropertyNode = theProxyNode.firstChild();
+ while (aPropertyNode.isElement()) {
+ QDomElement aProperty = aPropertyNode.toElement();
+ QString aName = aProperty.attribute("name");
+ if ((aName == "FileName") || (aName == "FileNameInfo") || (aName == "FileNames")) {
+ processElements(aPropertyNode, theFileNames, theNewPath, theRestore);
+ }
+ aPropertyNode = aPropertyNode.nextSibling();
+ }
+ }
+
+
+ void processProxies(QDomNode& theNode, QStringList& theFileNames,
+ const QString& theNewPath, bool theRestore)
+ {
+ QDomNode aProxyNode = theNode.firstChild();
+ while (aProxyNode.isElement()) {
+ QDomElement aProxy = aProxyNode.toElement();
+ if (aProxy.tagName() == "Proxy") {
+ QString aGroup = aProxy.attribute("group");
+ if (aGroup == "sources") {
+ processProperties(aProxyNode, theFileNames, theNewPath, theRestore);
+ }
+ }
+ aProxyNode = aProxyNode.nextSibling();
+ }
+ }
+
+ bool processAllFilesInState(const QString& aFileName, QStringList& theFileNames,
+ const QString& theNewPath, bool theRestore)
+ {
+ QFile aFile(aFileName);
+ if (!aFile.open(QFile::ReadOnly)) {
+ MESSAGE("Can't open state file "<<aFileName.toStdString());
+ return false;
+ }
+ QDomDocument aDoc;
+ bool aRes = aDoc.setContent(&aFile);
+ aFile.close();
+
+ if (!aRes) {
+ MESSAGE("File "<<aFileName.toStdString()<<" is not XML document");
+ return false;
+ }
+
+ QDomElement aRoot = aDoc.documentElement();
+ if ( aRoot.isNull() ) {
+ MESSAGE( "Invalid XML root" );
+ return false;
+ }
+
+ QDomNode aNode = aRoot.firstChild();
+ while (aRes && !aNode.isNull() ) {
+ aRes = aNode.isElement();
+ if ( aRes ) {
+ QDomElement aSection = aNode.toElement();
+ if (aSection.tagName() == "ServerManagerState") {
+ processProxies(aNode, theFileNames, theNewPath, theRestore);
+ }
+ }
+ aNode = aNode.nextSibling();
+ }
+ if (!aFile.open(QFile::WriteOnly | QFile::Truncate)) {
+ MESSAGE("Can't open state file "<<aFileName.toStdString()<<" for writing");
+ return false;
+ }
+ QTextStream out(&aFile);
+ aDoc.save(out, 2);
+ aFile.close();
+
+ return true;
+ }
+}
+
PVGUI_DataModel::PVGUI_DataModel( PVGUI_Module* theModule ):
- LightApp_DataModel(theModule)
+ LightApp_DataModel(theModule),
+ myStudyURL("")
{}
PVGUI_DataModel::~PVGUI_DataModel()
{}
+bool PVGUI_DataModel::create( CAM_Study* theStudy) {
+ bool res = LightApp_DataModel::create(theStudy);
+ publishComponent(theStudy);
+ return res;
+}
+
+void PVGUI_DataModel::publishComponent( CAM_Study* theStudy ) {
+ LightApp_Study* study = dynamic_cast<LightApp_Study*>( theStudy );
+ CAM_ModuleObject *aModelRoot = dynamic_cast<CAM_ModuleObject*>( root());
+ if( study && aModelRoot == NULL ) {
+ aModelRoot = createModuleObject( theStudy->root() );
+ aModelRoot->setDataModel( this );
+ setRoot(aModelRoot);
+ }
+}
+
bool PVGUI_DataModel::dumpPython( const QString& path, CAM_Study* std,
bool isMultiFile, QStringList& listOfFiles)
{
return true;
}
-/*-----------------------------------------------------------------------------------------*/
-bool PVGUI_DataModel::open( const QString& theName, CAM_Study* theStudy, QStringList theList) {
- bool res = LightApp_DataModel::open(theName, theStudy, theList);
+/*!
+ \brief Open data model (read ParaView pipeline state from the files).
+ \param theName study file path
+ \param theStudy study pointer
+ \param theList list of the (temporary) files with data
+ \return operation status (\c true on success and \c false on error)
+*/
+bool PVGUI_DataModel::open( const QString& theName, CAM_Study* theStudy, QStringList theList)
+{
+ bool ret = false;
+ LightApp_Study* aDoc = dynamic_cast<LightApp_Study*>( theStudy );
+ if ( !aDoc )
+ return false;
+
+ LightApp_DataModel::open( theName, aDoc, theList );
publishComponent(theStudy);
- return res;
+
+ // The first list item contains path to a temporary
+ // directory, where the persistent files was placed
+ if ( theList.count() > 0 ) {
+ QString aTmpDir ( theList[0] );
+
+ if ( theList.size() >= 2 ) {
+ myStudyURL = theName;
+ QString aFullPath = SUIT_Tools::addSlash( aTmpDir ) + theList[1];
+// std::cout << "open: tmp dir is" << aFullPath.toStdString() << std::endl;
+ PVGUI_Module * mod = dynamic_cast<PVGUI_Module *>(getModule());
+ if (mod)
+ {
+ bool doRestore = false;
+ QStringList srcFilesEmpty;
+ createAndCheckRestoreFlag(aTmpDir, srcFilesEmpty, /*out*/doRestore);
+ if(doRestore)
+ {
+ // Update state file so that it points to new dir:
+ processAllFilesInState(aFullPath, srcFilesEmpty, aTmpDir.toStdString().c_str(), true);
+ }
+
+ pqFixPathsInStateFilesBehavior::blockDialog(true);
+ mod->loadParaviewState(aFullPath);
+ pqFixPathsInStateFilesBehavior::blockDialog(false);
+ ret = true;
+ }
+ ret = true;
+ }
+ }
+
+ return ret;
}
-/*-----------------------------------------------------------------------------------------*/
-bool PVGUI_DataModel::create( CAM_Study* theStudy) {
- bool res = LightApp_DataModel::create(theStudy);
- publishComponent(theStudy);
- return res;
+/*!
+ * Create an empty file indicating whether source files in the pipeline should be restored.
+ */
+bool PVGUI_DataModel::createAndCheckRestoreFlag(const QString& tmpdir, QStringList& listOfFiles, bool & alreadyThere)
+{
+ QString aFullPath = SUIT_Tools::addSlash( tmpdir ) + RESTORE_FLAG_FILE;
+ QFile f(aFullPath);
+ if (f.exists())
+ {
+ alreadyThere = true;
+ return true;
+ }
+ else
+ {
+ bool ret = f.open(QFile::WriteOnly);
+ if (ret)
+ {
+ f.close();
+ listOfFiles << RESTORE_FLAG_FILE;
+ }
+ return ret;
+ }
}
-/*-----------------------------------------------------------------------------------------*/
-void PVGUI_DataModel::publishComponent( CAM_Study* theStudy ) {
- LightApp_Study* study = dynamic_cast<LightApp_Study*>( theStudy );
- CAM_ModuleObject *aModelRoot = dynamic_cast<CAM_ModuleObject*>( root());
- if( study && aModelRoot == NULL ) {
- aModelRoot = createModuleObject( theStudy->root() );
- aModelRoot->setDataModel( this );
- setRoot(aModelRoot);
+
+
+/*!
+ \brief Save data model (write ParaView pipeline to the files).
+ \param listOfFiles returning list of the (temporary) files with saved data
+ \return operation status (\c true on success and \c false on error)
+*/
+bool PVGUI_DataModel::save( QStringList& theListOfFiles)
+{
+ bool isMultiFile = false; // TODO: decide, how to access this parameter
+ bool ret = false;
+
+ LightApp_DataModel::save( theListOfFiles );
+
+ LightApp_Study* study = dynamic_cast<LightApp_Study*>( getModule()->getApp()->activeStudy() );
+ QString aTmpDir = study->GetTmpDir( myStudyURL.toLatin1(), isMultiFile ).c_str();
+// std::cout << "save: tmp dir is" << aTmpDir.toStdString() << std::endl;
+
+ QString aFileName = SUIT_Tools::file( myStudyURL, false ) + "_PARAVIS.pvsm";
+ QString aFullPath = aTmpDir + aFileName;
+
+ PVGUI_Module * mod = dynamic_cast<PVGUI_Module *>(getModule());
+ QStringList srcFiles;
+ if (mod)
+ {
+ // Create ParaView state file:
+ mod->saveParaviewState(aFullPath.toStdString().c_str());
+
+ // add this to the list to be saved:
+ theListOfFiles << aTmpDir;
+ theListOfFiles << aFileName;
+
+ // Potentially save referenced files:
+ SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
+ int aSavingType = aResourceMgr->integerValue( "PARAVIS", "savestate_type", 0 );
+
+ bool unused;
+ bool isBuiltIn = false;
+ pqServer* aServer;
+ QString nullS;
+
+ switch (aSavingType) {
+ case 0: // Save referenced files when they are accessible
+ createAndCheckRestoreFlag(aTmpDir, theListOfFiles ,unused);
+ processAllFilesInState(aFullPath, srcFiles, nullS, false);
+ break;
+ case 1: // Save referenced files only if this is the builtin server
+ aServer = pqApplicationCore::instance()->getActiveServer();
+ if (aServer)
+ isBuiltIn != aServer->isRemote();
+ if(isBuiltIn)
+ {
+ createAndCheckRestoreFlag(aTmpDir, theListOfFiles, unused);
+ processAllFilesInState(aFullPath, srcFiles, nullS, false);
+ }
+ break;
+ case 2: // Do not save referenced file
+ break;
+ default:
+ break;
+ }
+
+ ret = true;
+ }
+ // Copying valid source files to the temp directory and adding them to the list
+ foreach(QString fName, srcFiles)
+ {
+ QFile fSrc(fName);
+ if (fSrc.exists())
+ {
+ QFileInfo inf(fSrc);
+ QString newPth(SUIT_Tools::addSlash( aTmpDir ) + inf.fileName());
+ if (fSrc.copy(newPth))
+ {
+ theListOfFiles << inf.fileName();
+ }
+ }
}
+
+ return ret;
+}
+
+/*!
+ \brief Save data model (write ParaView pipeline state to the files).
+ \param url study file path
+ \param study study pointer
+ \param listOfFiles returning list of the (temporary) files with saved data
+ \return operation status (\c true on success and \c false on error)
+*/
+bool PVGUI_DataModel::saveAs( const QString& url, CAM_Study* study, QStringList& theListOfFiles)
+{
+ myStudyURL = url;
+ return save( theListOfFiles );
}