1 // Copyright (C) 2010-2022 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Adrien Bruneton (CEA)
23 #include "PVGUI_DataModel.h"
24 #include "PVGUI_Module.h"
27 #include <LightApp_Study.h>
28 #include <LightApp_Module.h>
29 #include <LightApp_Application.h>
30 #include <LightApp_DataModel.h>
31 #include <CAM_DataObject.h>
32 #include <SUIT_Tools.h>
33 #include <SUIT_Session.h>
34 #include <SUIT_ResourceMgr.h>
37 #include <utilities.h>
42 #include <QTextStream>
46 #include <pqApplicationCore.h>
48 #include <vtkOutputWindow.h>
50 const QString PVGUI_DataModel::RESTORE_FLAG_FILE = "do_restore_paravis_references.par";
53 * XML processing functions to handle the PV state file.
57 QStringList multiFormats()
59 static QStringList formats;
60 if ( formats.isEmpty() )
61 formats << "vtm" << "lata" << "pvd";
64 void warning( const QString& message )
66 vtkOutputWindow* vtkWindow = vtkOutputWindow::GetInstance();
69 vtkWindow->DisplayWarningText( qPrintable( message ) );
73 void processElements(QDomNode& thePropertyNode, QStringList& theFileNames,
74 const QString& theNewPath, bool theRestore)
76 QDomElement aProperty = thePropertyNode.toElement();
77 int aNbElements = aProperty.attribute("number_of_elements").toInt();
78 if ( aNbElements > 1 )
79 warning( QString("You save data file with number of entities > 1 (%1); some data may be lost!").arg(aNbElements) );
80 QDomNode aElementNode = thePropertyNode.firstChild();
81 while (aElementNode.isElement()) {
82 QDomElement aElement = aElementNode.toElement();
83 if (aElement.tagName() == "Element") {
84 QString aIndex = aElement.attribute("index");
86 QString aValue = aElement.attribute("value");
87 if (!aValue.isNull()) {
88 if (theNewPath.isEmpty()) {
89 QFileInfo aFInfo(aValue);
90 if (aFInfo.exists()) {
91 QString ext = aFInfo.suffix();
92 if ( multiFormats().contains(aFInfo.suffix()) )
93 warning( QString("You save data in multiple file format (%1); some data may be not saved!").arg(ext) );
95 aElement.setAttribute("value", aFInfo.fileName());
100 aElement.setAttribute("value", QString(theNewPath) + aValue);
105 aElementNode = aElementNode.nextSibling();
109 void processProperties(QDomNode& theProxyNode, QStringList& theFileNames,
110 const QString& theNewPath, bool theRestore)
112 QDomNode aPropertyNode = theProxyNode.firstChild();
113 while (aPropertyNode.isElement()) {
114 QDomElement aProperty = aPropertyNode.toElement();
115 QString aName = aProperty.attribute("name");
116 if ((aName == "FileName") || (aName == "FileNameInfo") || (aName == "FileNames")) {
117 processElements(aPropertyNode, theFileNames, theNewPath, theRestore);
119 aPropertyNode = aPropertyNode.nextSibling();
124 void processProxies(QDomNode& theNode, QStringList& theFileNames,
125 const QString& theNewPath, bool theRestore)
127 QDomNode aProxyNode = theNode.firstChild();
128 while (aProxyNode.isElement()) {
129 QDomElement aProxy = aProxyNode.toElement();
130 if (aProxy.tagName() == "Proxy") {
131 QString aGroup = aProxy.attribute("group");
132 if (aGroup == "sources") {
133 processProperties(aProxyNode, theFileNames, theNewPath, theRestore);
136 aProxyNode = aProxyNode.nextSibling();
140 bool processAllFilesInState(const QString& aFileName, QStringList& theFileNames,
141 const QString& theNewPath, bool theRestore)
143 QFile aFile(aFileName);
144 if (!aFile.open(QFile::ReadOnly)) {
145 MESSAGE("Can't open state file "<<aFileName.toStdString());
149 bool aRes = aDoc.setContent(&aFile);
153 MESSAGE("File "<<aFileName.toStdString()<<" is not XML document");
157 QDomElement aRoot = aDoc.documentElement();
158 if ( aRoot.isNull() ) {
159 MESSAGE( "Invalid XML root" );
163 QDomNode aNode = aRoot.firstChild();
164 while (aRes && !aNode.isNull() ) {
165 aRes = aNode.isElement();
167 QDomElement aSection = aNode.toElement();
168 if (aSection.tagName() == "ServerManagerState") {
169 processProxies(aNode, theFileNames, theNewPath, theRestore);
172 aNode = aNode.nextSibling();
174 if (!aFile.open(QFile::WriteOnly | QFile::Truncate)) {
175 MESSAGE("Can't open state file "<<aFileName.toStdString()<<" for writing");
178 QTextStream out(&aFile);
187 PVGUI_DataModel::PVGUI_DataModel( PVGUI_Module* theModule ):
188 LightApp_DataModel(theModule),
192 PVGUI_DataModel::~PVGUI_DataModel()
195 bool PVGUI_DataModel::create( CAM_Study* theStudy) {
196 bool res = LightApp_DataModel::create(theStudy);
197 publishComponent(theStudy);
201 void PVGUI_DataModel::publishComponent( CAM_Study* theStudy ) {
202 LightApp_Study* study = dynamic_cast<LightApp_Study*>( theStudy );
203 CAM_ModuleObject *aModelRoot = dynamic_cast<CAM_ModuleObject*>( root());
204 if( study && aModelRoot == NULL ) {
205 aModelRoot = createModuleObject( theStudy->root() );
206 aModelRoot->setDataModel( this );
211 bool PVGUI_DataModel::dumpPython( const QString& path, CAM_Study* std,
212 bool isMultiFile, QStringList& listOfFiles)
215 LightApp_Study* study = dynamic_cast<LightApp_Study*>( std );
219 std::string aTmpDir = study->GetTmpDir( path.toLatin1().constData(), isMultiFile );
220 std::string aFile = aTmpDir + "paravis_dump.tmp";
222 listOfFiles.append(aTmpDir.c_str());
223 listOfFiles.append("paravis_dump.tmp");
225 QFile file(aFile.c_str());
226 if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
229 PVGUI_Module * mod = (PVGUI_Module *) getModule();
230 QString trace(mod->getTraceString());
235 abuffer.push_back(QString("def RebuildData():"));
236 QStringList lst(trace.split("\n"));
237 foreach(QString elem, lst)
239 QString s = " " + elem;
240 abuffer.push_back(s);
242 abuffer.push_back(QString(" pass"));
243 trace = abuffer.join("\n");
245 QTextStream out(&file);
246 out << trace.toStdString().c_str() << "\n";
254 \brief Open data model (read ParaView pipeline state from the files).
255 \param theName study file path
256 \param theStudy study pointer
257 \param theList list of the (temporary) files with data
258 \return operation status (\c true on success and \c false on error)
260 bool PVGUI_DataModel::open( const QString& theName, CAM_Study* theStudy, QStringList theList)
263 LightApp_Study* aDoc = dynamic_cast<LightApp_Study*>( theStudy );
267 LightApp_DataModel::open( theName, aDoc, theList );
268 publishComponent(theStudy);
270 // The first list item contains path to a temporary
271 // directory, where the persistent files was placed
272 if ( theList.count() > 0 ) {
273 QString aTmpDir ( theList[0] );
275 if ( theList.size() >= 2 ) {
276 myStudyURL = theName;
277 QString aFullPath = SUIT_Tools::addSlash( aTmpDir ) + theList[1];
278 // std::cout << "open: tmp dir is" << aFullPath.toStdString() << std::endl;
279 PVGUI_Module * mod = dynamic_cast<PVGUI_Module *>(getModule());
282 bool doRestore = false;
283 QStringList srcFilesEmpty;
284 createAndCheckRestoreFlag(aTmpDir, srcFilesEmpty, /*out*/doRestore);
287 // Update state file so that it points to new dir:
288 processAllFilesInState(aFullPath, srcFilesEmpty, aTmpDir.toStdString().c_str(), true);
291 mod->loadParaviewState(aFullPath);
302 * Create an empty file indicating whether source files in the pipeline should be restored.
304 bool PVGUI_DataModel::createAndCheckRestoreFlag(const QString& tmpdir, QStringList& listOfFiles, bool & alreadyThere)
306 QString aFullPath = SUIT_Tools::addSlash( tmpdir ) + RESTORE_FLAG_FILE;
315 bool ret = f.open(QFile::WriteOnly);
319 listOfFiles << RESTORE_FLAG_FILE;
327 \brief Save data model (write ParaView pipeline to the files).
328 \param theListOfFiles returning list of the (temporary) files with saved data
329 \return operation status (\c true on success and \c false on error)
331 bool PVGUI_DataModel::save( QStringList& theListOfFiles)
333 bool isMultiFile = false; // TODO: decide, how to access this parameter
336 LightApp_DataModel::save( theListOfFiles );
338 LightApp_Study* study = dynamic_cast<LightApp_Study*>( getModule()->getApp()->activeStudy() );
339 QString aTmpDir = study->GetTmpDir( myStudyURL.toLatin1(), isMultiFile ).c_str();
340 // std::cout << "save: tmp dir is" << aTmpDir.toStdString() << std::endl;
342 QString aFileName = SUIT_Tools::file( myStudyURL, false ) + "_PARAVIS.pvsm";
343 QString aFullPath = aTmpDir + aFileName;
345 PVGUI_Module * mod = dynamic_cast<PVGUI_Module *>(getModule());
346 QStringList srcFiles;
349 // Create ParaView state file:
350 mod->saveParaviewState(aFullPath.toStdString().c_str());
352 // add this to the list to be saved:
353 theListOfFiles << aTmpDir;
354 theListOfFiles << aFileName;
356 // Potentially save referenced files:
357 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
358 int aSavingType = aResourceMgr->integerValue( "PARAVIS", "savestate_type", 0 );
361 bool isBuiltIn = false;
365 switch (aSavingType) {
366 case 0: // Save referenced files when they are accessible
367 createAndCheckRestoreFlag(aTmpDir, theListOfFiles ,unused);
368 processAllFilesInState(aFullPath, srcFiles, nullS, false);
370 case 1: // Save referenced files only if this is the builtin server
371 aServer = pqApplicationCore::instance()->getActiveServer();
373 isBuiltIn = !aServer->isRemote();
376 createAndCheckRestoreFlag(aTmpDir, theListOfFiles, unused);
377 processAllFilesInState(aFullPath, srcFiles, nullS, false);
380 case 2: // Do not save referenced file
388 // Copying valid source files to the temp directory and adding them to the list
389 foreach(QString fName, srcFiles)
395 QString newPth(SUIT_Tools::addSlash( aTmpDir ) + inf.fileName());
396 if (fSrc.copy(newPth))
398 theListOfFiles << inf.fileName();
407 \brief Save data model (write ParaView pipeline state to the files).
408 \param url study file path
409 \param study study pointer
410 \param theListOfFiles returning list of the (temporary) files with saved data
411 \return operation status (\c true on success and \c false on error)
413 bool PVGUI_DataModel::saveAs( const QString& url, CAM_Study* /*study*/, QStringList& theListOfFiles)
416 return save( theListOfFiles );