From d690edb4953cbca977d9c8fd5ebdb567811d9bb4 Mon Sep 17 00:00:00 2001 From: san Date: Tue, 15 Nov 2005 15:21:47 +0000 Subject: [PATCH] Debug from CATHARE GUI team: 1. Persistence problems in light configuration solved: - from now on, temporary files extracted from the study file are not removed until the study is closed or renamed; - "isSaved" status managed by the study, not by data models. 2. LightApp_Driver.h removed from LIB_MOC makefile variable to suppress warnings. --- src/LightApp/LightApp.h | 57 +- src/LightApp/LightApp_Driver.cxx | 1011 ++++++++++++++++-------------- src/LightApp/LightApp_Driver.h | 100 +-- src/LightApp/LightApp_Study.cxx | 71 ++- src/LightApp/Makefile.in | 1 - 5 files changed, 652 insertions(+), 588 deletions(-) diff --git a/src/LightApp/LightApp.h b/src/LightApp/LightApp.h index bfbe7e24a..1d0f5e196 100644 --- a/src/LightApp/LightApp.h +++ b/src/LightApp/LightApp.h @@ -1,28 +1,29 @@ -// File: LightApp.h -// Created: June, 2005 -// Author: OCC team -// Copyright (C) CEA 2005 - - -// The following ifdef block is the standard way of creating macros which make exporting -// from a DLL simpler. All files within this DLL are compiled with the LightApp_EXPORTS -// symbol defined on the command line. this symbol should not be defined on any project -// that uses this DLL. This way any other project whose source files include this file see -// LightApp_API functions as being imported from a DLL, wheras this DLL sees symbols -// defined with this macro as being exported. -#ifdef WNT - -#ifdef LIGHTAPP_EXPORTS -#define LIGHTAPP_EXPORT __declspec(dllexport) -#else -#define LIGHTAPP_EXPORT __declspec(dllimport) -#endif - -#else -#define LIGHTAPP_EXPORT -#endif //WNT - -#define APP_VERSION "0.1" - -#pragma warning ( disable:4251 ) -#pragma warning ( disable:4786 ) +// File: LightApp.h +// Created: June, 2005 +// Author: OCC team +// Copyright (C) CEA 2005 + + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the LightApp_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// LightApp_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. +#ifdef WNT + +#ifdef LIGHTAPP_EXPORTS +#define LIGHTAPP_EXPORT __declspec(dllexport) +#else +#define LIGHTAPP_EXPORT __declspec(dllimport) +#endif + +#pragma warning ( disable:4251 ) +#pragma warning ( disable:4786 ) +#pragma warning ( disable:4503 ) + +#else +#define LIGHTAPP_EXPORT +#endif //WNT + +#define APP_VERSION "0.1" diff --git a/src/LightApp/LightApp_Driver.cxx b/src/LightApp/LightApp_Driver.cxx index a37f4f5d2..a10d2be1e 100644 --- a/src/LightApp/LightApp_Driver.cxx +++ b/src/LightApp/LightApp_Driver.cxx @@ -1,486 +1,525 @@ -#include "LightApp_Driver.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#endif - -/*! Constructor.*/ -LightApp_Driver::LightApp_Driver() -{ -} - -/*! Destructor.*/ -LightApp_Driver::~LightApp_Driver() -{ -} - -using namespace std; - -//================================================================ -// Function : SaveDatasInFile -/*! Purpose : save in file 'theFileName' datas from this driver*/ -//================================================================ -bool LightApp_Driver::SaveDatasInFile( const char* theFileName, bool isMultiFile ) -{ - int aNbModules = 0; - std::map::const_iterator it; - for (it = myMap.begin(); it != myMap.end(); ++it) - aNbModules++; - - unsigned char** aBuffer = new unsigned char*[aNbModules]; - long* aBufferSize = new long[aNbModules]; - char** aModuleName = new char*[aNbModules]; - - if(aBuffer == NULL || aBufferSize == NULL || aModuleName == NULL) - return false; - - int aFileBufferSize = 4; //4 bytes for a number of the modules that will be written to the stream; - int i = 0; - for (it = myMap.begin(); it != myMap.end(); ++it) { - aModuleName[i] = const_cast(it->first.c_str());//(it->first); - aFileBufferSize += 4; //Add 4 bytes: a length of the module name - aFileBufferSize += strlen(aModuleName[i])+1; - std::string aName(aModuleName[i]); - PutFilesToStream(aName, aBuffer[i], aBufferSize[i], isMultiFile); - aFileBufferSize += 8; //Add 8 bytes: a length of the buffer - aFileBufferSize += aBufferSize[i]; - // Remove the files and tmp directory, created by the component storage procedure - if (!isMultiFile) - RemoveTemporaryFiles(aModuleName[i], true); - i++; - } - int n = i; - - unsigned char* aFileBuffer = new unsigned char[aFileBufferSize]; - if(aFileBuffer == NULL) - return false; - - int aCurrentPos = 0; - - //Initialize 4 bytes of the buffer by 0 - memset(aFileBuffer, 0, 4); - //Copy the number of modules that will be written to the stream - memcpy(aFileBuffer, &aNbModules, ((sizeof(int) > 4) ? 4 : sizeof(int))); - aCurrentPos += 4; - - int aBufferNameSize = 0; - for (i = 0; i < n; i++) { - aBufferNameSize = strlen(aModuleName[i])+1; - //Initialize 4 bytes of the buffer by 0 - memset((aFileBuffer + aCurrentPos), 0, 4); - //Copy the length of the module name to the buffer - memcpy((aFileBuffer + aCurrentPos), &aBufferNameSize, ((sizeof(int) > 4) ? 4 : sizeof(int))); - aCurrentPos += 4; - //Copy the module name to the buffer - memcpy((aFileBuffer + aCurrentPos), aModuleName[i], aBufferNameSize); - aCurrentPos += aBufferNameSize; - - //Initialize 8 bytes of the buffer by 0 - memset((aFileBuffer + aCurrentPos), 0, 8); - //Copy the length of the module buffer to the buffer - memcpy((aFileBuffer + aCurrentPos), (aBufferSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long))); - aCurrentPos += 8; - //Copy the module buffer to the buffer - memcpy((aFileBuffer + aCurrentPos), aBuffer[i], aBufferSize[i]); - aCurrentPos += aBufferSize[i]; - } - - ofstream aFile(theFileName); - aFile.write((char*)aFileBuffer, aFileBufferSize); - aFile.close(); - - delete[] aBuffer; - delete[] aBufferSize; - delete[] aModuleName; - delete[] aFileBuffer; - return true; -} - -//======================================================================= -// name : ReaDatasFromFile -/*! Purpose : filling current driver from file 'theFileName'*/ -//======================================================================= -bool LightApp_Driver::ReadDatasFromFile( const char* theFileName, bool isMultiFile ) -{ -#ifdef WNT - ifstream aFile(theFileName, ios::binary); -#else - ifstream aFile(theFileName); -#endif - - aFile.seekg(0, ios::end); - int aFileBufferSize = aFile.tellg(); - unsigned char* aFileBuffer = new unsigned char[aFileBufferSize]; - aFile.seekg(0, ios::beg); - aFile.read((char*)aFileBuffer, aFileBufferSize); - aFile.close(); - - int aNbModules = 0; - //Copy the number of files in the stream - memcpy(&aNbModules, aFileBuffer, sizeof(int)); - long aCurrentPos = 4; - int aModuleNameSize; - - for (int i = 0; i < aNbModules; i++) { - //Put a length of the module name to aModuleNameSize - memcpy(&aModuleNameSize, (aFileBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int))); - aCurrentPos += 4; - - char *aModuleName = new char[aModuleNameSize]; - //Put a module name to aModuleName - memcpy(aModuleName, (aFileBuffer + aCurrentPos), aModuleNameSize); - aCurrentPos += aModuleNameSize; - - //Put a length of the file buffer to aBufferSize - long aBufferSize; - memcpy(&aBufferSize, (aFileBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long))); - aCurrentPos += 8; - unsigned char *aBuffer = new unsigned char[aBufferSize]; - - //Put a buffer for current module to aBuffer - memcpy(aBuffer, (aFileBuffer + aCurrentPos), aBufferSize); - aCurrentPos += aBufferSize; - - // Put buffer to aListOfFiles and set to myMap - ListOfFiles aListOfFiles = PutStreamToFiles(aBuffer, aBufferSize, isMultiFile); - SetListOfFiles(aModuleName, aListOfFiles); - - delete[] aModuleName; - delete[] aBuffer; - } - delete[] aFileBuffer; - return true; -} - -//================================================================ -// Function : GetTmpDir -/*! Purpose : returns temp directory for path 'theURL'*/ -//================================================================ -std::string LightApp_Driver::GetTmpDir (const char* theURL, const bool isMultiFile) -{ - std::string anURLDir = GetDirFromPath(theURL); - std::string aTmpDir = isMultiFile ? anURLDir : GetTmpDir(); - - return aTmpDir; -} - -//================================================================ -// Function : GetListOfFiles -/*! Purpose : returns list of files for module with name 'theModuleName'*/ -//================================================================ -LightApp_Driver::ListOfFiles LightApp_Driver::GetListOfFiles( const char* theModuleName ) -{ - ListOfFiles aListOfFiles; - - std::string aName(theModuleName); - if (myMap.count(aName)) - aListOfFiles = myMap[aName]; - - return aListOfFiles; -} - -//================================================================ -// Function : SetListOfFiles -/*! Purpose : sets list of files for module with name 'theModuleName'*/ -//================================================================ -void LightApp_Driver::SetListOfFiles( const char* theModuleName, const ListOfFiles theListOfFiles ) -{ - std::string aName (theModuleName); - myMap[aName] = theListOfFiles; -} - -//============================================================================ -// function : PutFilesToStream -/*! Purpose : converts files which was created from module into a byte sequence unsigned char*/ -//============================================================================ -void LightApp_Driver::PutFilesToStream( const std::string& theModuleName, unsigned char*& theBuffer, - long& theBufferSize, bool theNamesOnly ) -{ - ListOfFiles aFiles = myMap[theModuleName]; - // aFiles must contain temporary directory name in its first item - // and names of files (relatively the temporary directory) in the others - - int i, aLength = aFiles.size() - 1; - if(aLength <= 0) { - theBufferSize = 0; - theBuffer = new unsigned char[theBufferSize]; - return; - } - //Get a temporary directory for saved a file - TCollection_AsciiString aTmpDir(const_cast(aFiles[0].c_str())); - - long aBufferSize = 0; - long aCurrentPos; - int aNbFiles = 0; - int* aFileNameSize= new int[aLength]; - long* aFileSize= new long[aLength]; - - //Determine the required size of the buffer - TCollection_AsciiString aFileName; - for (i = 0; i < aLength; i++) { - char* aFName = const_cast(aFiles[i+1].c_str()); - aFileName = aFName; - //Check if the file exists - if (!theNamesOnly) { // mpv 15.01.2003: if only file names must be stroed, then size of files is zero - TCollection_AsciiString aFullPath = aTmpDir + aFileName; - OSD_Path anOSDPath(aFullPath); - OSD_File anOSDFile(anOSDPath); - if(!anOSDFile.Exists()) continue; -#ifdef WNT - ifstream aFile(aFullPath.ToCString(), ios::binary); -#else - ifstream aFile(aFullPath.ToCString()); -#endif - aFile.seekg(0, ios::end); - aFileSize[i] = aFile.tellg(); - aBufferSize += aFileSize[i]; //Add a space to store the file - } - aFileNameSize[i] = strlen(aFName) + 1; - aBufferSize += aFileNameSize[i]; //Add a space to store the file name - aBufferSize += (theNamesOnly)?4:12; //Add 4 bytes: a length of the file name, - // 8 bytes: length of the file itself - aNbFiles++; - delete[] aFName; - } - - aBufferSize += 4; //4 bytes for a number of the files that will be written to the stream; - theBuffer = new unsigned char[aBufferSize]; - if(theBuffer == NULL) { - theBufferSize = 0; - theBuffer = 0; - return; - } - //Initialize 4 bytes of the buffer by 0 - memset(theBuffer, 0, 4); - //Copy the number of files that will be written to the stream - memcpy(theBuffer, &aNbFiles, ((sizeof(int) > 4) ? 4 : sizeof(int))); - - aCurrentPos = 4; - - for(i = 0; i < aLength; i++) { - ifstream *aFile; - if (!theNamesOnly) { // mpv 15.01.2003: we don't open any file if theNamesOnly = true - TCollection_AsciiString aName(const_cast(aFiles[i+1].c_str())); - TCollection_AsciiString aFullPath = aTmpDir + aName; - OSD_Path anOSDPath(aFullPath); - OSD_File anOSDFile(anOSDPath); - if(!anOSDFile.Exists()) continue; -#ifdef WNT - aFile = new ifstream(aFullPath.ToCString(), ios::binary); -#else - aFile = new ifstream(aFullPath.ToCString()); -#endif - } - //Initialize 4 bytes of the buffer by 0 - memset((theBuffer + aCurrentPos), 0, 4); - //Copy the length of the file name to the buffer - memcpy((theBuffer + aCurrentPos), (aFileNameSize + i), ((sizeof(int) > 4) ? 4 : sizeof(int))); - aCurrentPos += 4; - - //Copy the file name to the buffer - char* aFName = const_cast(aFiles[i+1].c_str()); - memcpy((theBuffer + aCurrentPos), aFName, aFileNameSize[i]); - aCurrentPos += aFileNameSize[i]; - - if (!theNamesOnly) { // mpv 15.01.2003: we don't copy file content to the buffer if !theNamesOnly - //Initialize 8 bytes of the buffer by 0 - memset((theBuffer + aCurrentPos), 0, 8); - //Copy the length of the file to the buffer - memcpy((theBuffer + aCurrentPos), (aFileSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long))); - aCurrentPos += 8; - - aFile->seekg(0, ios::beg); - aFile->read((char *)(theBuffer + aCurrentPos), aFileSize[i]); - aFile->close(); - delete(aFile); - aCurrentPos += aFileSize[i]; - } - } - delete[] aFileNameSize; - delete[] aFileSize; - - theBufferSize = aBufferSize; -} - -//============================================================================ -// function : PutStreamToFile -/*! Purpose : converts a byte sequence to files and return list of them*/ -//============================================================================ -LightApp_Driver::ListOfFiles LightApp_Driver::PutStreamToFiles( const unsigned char* theBuffer, - const long theBufferSize, bool theNamesOnly ) -{ - if(theBufferSize == 0 || theBuffer == 0) - return ListOfFiles(); - - // Create a temporary directory for the component's data files - std::string aDir = GetTmpDir(); - - //Get a temporary directory for saving a file - TCollection_AsciiString aTmpDir(const_cast(aDir.c_str())); - - long aFileSize, aCurrentPos = 4; - int i, aFileNameSize, aNbFiles = 0; - - //Copy the number of files in the stream - memcpy(&aNbFiles, theBuffer, sizeof(int)); - - const int n = aNbFiles + 1; - ListOfFiles aFiles(n); - aFiles[0] = aDir; - - for(i = 0; i < aNbFiles; i++) { - //Put a length of the file name to aFileNameSize - memcpy(&aFileNameSize, (theBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int))); - aCurrentPos += 4; - - char *aFileName = new char[aFileNameSize]; - //Put a file name to aFileName - memcpy(aFileName, (theBuffer + aCurrentPos), aFileNameSize); - aCurrentPos += aFileNameSize; - - //Put a length of the file to aFileSize - if (!theNamesOnly) { - memcpy(&aFileSize, (theBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long))); - aCurrentPos += 8; - - TCollection_AsciiString aFullPath = aTmpDir + aFileName; - ofstream aFile(aFullPath.ToCString()); - aFile.write((char *)(theBuffer+aCurrentPos), aFileSize); - aFile.close(); - aCurrentPos += aFileSize; - } - std::string aStrFileName(aFileName); - aFiles[i+1] = aStrFileName; - delete[] aFileName; - } - return aFiles; -} - -//============================================================================ -// function : RemoveTemporaryFiles -/*! Purpose : removes files which was created from module theModuleName if is true tmp directory is also deleted if it is empty*/ -//============================================================================ -void LightApp_Driver::RemoveTemporaryFiles( const char* theModuleName, const bool IsDirDeleted ) -{ - std::string aModuleName(theModuleName); - ListOfFiles aFiles = myMap[aModuleName]; - // aFiles must contain temporary directory name in its first item - // and names of files (relatively the temporary directory) in the others - - int i, aLength = aFiles.size() - 1; - if(aLength <= 0) { - return; - } - //Get a temporary directory for saved a file - TCollection_AsciiString aDirName(const_cast(aFiles[0].c_str())); - - for(i = 0; i < aLength; i++) { - TCollection_AsciiString aFile(aDirName); - aFile += const_cast(aFiles[i+1].c_str()); - OSD_Path anOSDPath(aFile); - OSD_File anOSDFile(anOSDPath); - if(!anOSDFile.Exists()) continue; - - OSD_Protection aProtection = anOSDFile.Protection(); - aProtection.SetUser(OSD_RW); - anOSDFile.SetProtection(aProtection); - - anOSDFile.Remove(); - } - - if(IsDirDeleted) { - OSD_Path aPath(aDirName); - OSD_Directory aDir(aPath); - OSD_FileIterator anIterator(aPath, '*'); - - if(aDir.Exists() && !anIterator.More()) aDir.Remove(); - } -} - -//============================================================================ -// function : ClearDriverContents -/*! Purpose : clear map of list files*/ -//============================================================================ -void LightApp_Driver::ClearDriverContents() -{ - myMap.clear(); -} - -//============================================================================ -// function : GetTempDir -/*! Purpose : return a temp directory to store created files like "/tmp/sub_dir/" */ -//============================================================================ -std::string LightApp_Driver::GetTmpDir() -{ - //Find a temporary directory to store a file - TCollection_AsciiString aTmpDir; - - char *Tmp_dir = getenv("SALOME_TMP_DIR"); - if(Tmp_dir != NULL) { - aTmpDir = TCollection_AsciiString(Tmp_dir); -#ifdef WIN32 - if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\'; -#else - if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/'; -#endif - } - else { -#ifdef WIN32 - aTmpDir = TCollection_AsciiString("C:\\"); -#else - aTmpDir = TCollection_AsciiString("/tmp/"); -#endif - } - - srand((unsigned int)time(NULL)); - int aRND = 999 + (int)(100000.0*rand()/(RAND_MAX+1.0)); //Get a random number to present a name of a sub directory - TCollection_AsciiString aSubDir(aRND); - if(aSubDir.Length() <= 1) aSubDir = TCollection_AsciiString("123409876"); - - aTmpDir += aSubDir; //Get RND sub directory - -#ifdef WIN32 - if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\'; -#else - if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/'; -#endif - - OSD_Path aPath(aTmpDir); - OSD_Directory aDir(aPath); - - for(aRND = 0; aDir.Exists(); aRND++) { - aTmpDir.Insert((aTmpDir.Length() - 1), TCollection_AsciiString(aRND)); //Build a unique directory name - aPath = OSD_Path(aTmpDir); - aDir = OSD_Directory(aPath); - } - - OSD_Protection aProtection(OSD_RW, OSD_RWX, OSD_RX, OSD_RX); - aDir.Build(aProtection); - - return aTmpDir.ToCString(); -} - -//============================================================================ -// function : GetDirFromPath -/*! Purpose : returns the dir by the path*/ -//============================================================================ -std::string LightApp_Driver::GetDirFromPath( const std::string& thePath ) { - if(thePath == "") - return ""; - OSD_Path aPath = OSD_Path(TCollection_AsciiString(const_cast(thePath.c_str()))); - TCollection_AsciiString aDirString(aPath.Trek()); - aDirString.ChangeAll('|','/'); - return aDirString.ToCString(); -} - +#include "LightApp_Driver.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef WIN32 +#include +#endif + +/*! Constructor.*/ +LightApp_Driver::LightApp_Driver() +{ +} + +/*! Destructor.*/ +LightApp_Driver::~LightApp_Driver() +{ +} + +using namespace std; + +//================================================================ +// Function : SaveDatasInFile +/*! Purpose : save in file 'theFileName' datas from this driver*/ +//================================================================ +bool LightApp_Driver::SaveDatasInFile( const char* theFileName, bool isMultiFile ) +{ + int aNbModules = 0; + std::map::const_iterator it; + for (it = myMap.begin(); it != myMap.end(); ++it) + aNbModules++; + + unsigned char** aBuffer = new unsigned char*[aNbModules]; + long* aBufferSize = new long[aNbModules]; + char** aModuleName = new char*[aNbModules]; + + if(aBuffer == NULL || aBufferSize == NULL || aModuleName == NULL) + return false; + + int aFileBufferSize = 4; //4 bytes for a number of the modules that will be written to the stream; + int i = 0; + for (it = myMap.begin(); it != myMap.end(); ++it) { + aModuleName[i] = const_cast(it->first.c_str());//(it->first); + aFileBufferSize += 4; //Add 4 bytes: a length of the module name + aFileBufferSize += strlen(aModuleName[i])+1; + std::string aName(aModuleName[i]); + PutFilesToStream(aName, aBuffer[i], aBufferSize[i], isMultiFile); + aFileBufferSize += 8; //Add 8 bytes: a length of the buffer + aFileBufferSize += aBufferSize[i]; + i++; + } + int n = i; + + unsigned char* aFileBuffer = new unsigned char[aFileBufferSize]; + if(aFileBuffer == NULL) + return false; + + myTmpDir = QDir::convertSeparators( QFileInfo( theFileName ).dirPath( true ) + "/" ).latin1() ; + + int aCurrentPos = 0; + + //Initialize 4 bytes of the buffer by 0 + memset(aFileBuffer, 0, 4); + //Copy the number of modules that will be written to the stream + memcpy(aFileBuffer, &aNbModules, ((sizeof(int) > 4) ? 4 : sizeof(int))); + aCurrentPos += 4; + + int aBufferNameSize = 0; + for (i = 0; i < n; i++) { + aBufferNameSize = strlen(aModuleName[i])+1; + //Initialize 4 bytes of the buffer by 0 + memset((aFileBuffer + aCurrentPos), 0, 4); + //Copy the length of the module name to the buffer + memcpy((aFileBuffer + aCurrentPos), &aBufferNameSize, ((sizeof(int) > 4) ? 4 : sizeof(int))); + aCurrentPos += 4; + //Copy the module name to the buffer + memcpy((aFileBuffer + aCurrentPos), aModuleName[i], aBufferNameSize); + aCurrentPos += aBufferNameSize; + + //Initialize 8 bytes of the buffer by 0 + memset((aFileBuffer + aCurrentPos), 0, 8); + //Copy the length of the module buffer to the buffer + memcpy((aFileBuffer + aCurrentPos), (aBufferSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long))); + aCurrentPos += 8; + //Copy the module buffer to the buffer + memcpy((aFileBuffer + aCurrentPos), aBuffer[i], aBufferSize[i]); + aCurrentPos += aBufferSize[i]; + } + +#ifdef WNT + ofstream aFile(theFileName, ios::out | ios::binary); +#else + ofstream aFile(theFileName); +#endif + aFile.write((char*)aFileBuffer, aFileBufferSize); + aFile.close(); + + delete[] aBuffer; + delete[] aBufferSize; + delete[] aModuleName; + delete[] aFileBuffer; + + return true; +} + +//======================================================================= +// name : ReaDatasFromFile +/*! Purpose : filling current driver from file 'theFileName'*/ +//======================================================================= +bool LightApp_Driver::ReadDatasFromFile( const char* theFileName, bool isMultiFile ) +{ +#ifdef WNT + ifstream aFile(theFileName, ios::binary); +#else + ifstream aFile(theFileName); +#endif + + myTmpDir = QDir::convertSeparators( QFileInfo( theFileName ).dirPath( true ) + "/" ).latin1() ; + + aFile.seekg(0, ios::end); + int aFileBufferSize = aFile.tellg(); + unsigned char* aFileBuffer = new unsigned char[aFileBufferSize]; + aFile.seekg(0, ios::beg); + aFile.read((char*)aFileBuffer, aFileBufferSize); + aFile.close(); + + int aNbModules = 0; + //Copy the number of files in the stream + memcpy(&aNbModules, aFileBuffer, sizeof(int)); + long aCurrentPos = 4; + int aModuleNameSize; + + for (int i = 0; i < aNbModules; i++) { + //Put a length of the module name to aModuleNameSize + memcpy(&aModuleNameSize, (aFileBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int))); + aCurrentPos += 4; + + char *aModuleName = new char[aModuleNameSize]; + //Put a module name to aModuleName + memcpy(aModuleName, (aFileBuffer + aCurrentPos), aModuleNameSize); + aCurrentPos += aModuleNameSize; + + //Put a length of the file buffer to aBufferSize + long aBufferSize; + memcpy(&aBufferSize, (aFileBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long))); + aCurrentPos += 8; + unsigned char *aBuffer = new unsigned char[aBufferSize]; + + //Put a buffer for current module to aBuffer + memcpy(aBuffer, (aFileBuffer + aCurrentPos), aBufferSize); + aCurrentPos += aBufferSize; + + // Put buffer to aListOfFiles and set to myMap + ListOfFiles aListOfFiles = PutStreamToFiles(aBuffer, aBufferSize, isMultiFile); + SetListOfFiles(aModuleName, aListOfFiles); + + delete[] aModuleName; + delete[] aBuffer; + } + + delete[] aFileBuffer; + + return true; +} + +//================================================================ +// Function : GetTmpDir +/*! Purpose : returns temp directory for path 'theURL'*/ +//================================================================ +std::string LightApp_Driver::GetTmpDir (const char* theURL, const bool isMultiFile) +{ + std::string anURLDir = GetDirFromPath(theURL); + std::string aTmpDir = isMultiFile ? anURLDir : GetTmpDir(); + + return aTmpDir; +} + +//================================================================ +// Function : GetListOfFiles +/*! Purpose : returns list of files for module with name 'theModuleName'*/ +//================================================================ +LightApp_Driver::ListOfFiles LightApp_Driver::GetListOfFiles( const char* theModuleName ) +{ + ListOfFiles aListOfFiles; + + std::string aName(theModuleName); + if (myMap.count(aName)) + aListOfFiles = myMap[aName]; + + return aListOfFiles; +} + +//================================================================ +// Function : SetListOfFiles +/*! Purpose : sets list of files for module with name 'theModuleName'*/ +//================================================================ +void LightApp_Driver::SetListOfFiles( const char* theModuleName, const ListOfFiles theListOfFiles ) +{ + std::string aName (theModuleName); + myMap[aName] = theListOfFiles; +} + +//============================================================================ +// function : PutFilesToStream +/*! Purpose : converts files which was created from module into a byte sequence unsigned char*/ +//============================================================================ +void LightApp_Driver::PutFilesToStream( const std::string& theModuleName, unsigned char*& theBuffer, + long& theBufferSize, bool theNamesOnly ) +{ + ListOfFiles aFiles = myMap[theModuleName]; + // aFiles must contain temporary directory name in its first item + // and names of files (relatively the temporary directory) in the others + + int i, aLength = aFiles.size() - 1; + if(aLength <= 0) { + theBufferSize = 0; + theBuffer = new unsigned char[theBufferSize]; + return; + } + //Get a temporary directory for saved a file + TCollection_AsciiString aTmpDir(const_cast(aFiles[0].c_str())); + + long aBufferSize = 0; + long aCurrentPos; + int aNbFiles = 0; + int* aFileNameSize= new int[aLength]; + long* aFileSize= new long[aLength]; + + //Determine the required size of the buffer + TCollection_AsciiString aFileName; + for (i = 0; i < aLength; i++) { + char* aFName = const_cast(aFiles[i+1].c_str()); + aFileName = aFName; + //Check if the file exists + if (!theNamesOnly) { // mpv 15.01.2003: if only file names must be stroed, then size of files is zero + TCollection_AsciiString aFullPath = aTmpDir + aFileName; + OSD_Path anOSDPath(aFullPath); + OSD_File anOSDFile(anOSDPath); + if(!anOSDFile.Exists()) continue; +#ifdef WNT + ifstream aFile(aFullPath.ToCString(), ios::binary); +#else + ifstream aFile(aFullPath.ToCString()); +#endif + aFile.seekg(0, ios::end); + aFileSize[i] = aFile.tellg(); + aBufferSize += aFileSize[i]; //Add a space to store the file + } + aFileNameSize[i] = strlen(aFName) + 1; + aBufferSize += aFileNameSize[i]; //Add a space to store the file name + aBufferSize += (theNamesOnly)?4:12; //Add 4 bytes: a length of the file name, + // 8 bytes: length of the file itself + aNbFiles++; + } + + aBufferSize += 4; //4 bytes for a number of the files that will be written to the stream; + theBuffer = new unsigned char[aBufferSize]; + if(theBuffer == NULL) { + theBufferSize = 0; + theBuffer = 0; + return; + } + //Initialize 4 bytes of the buffer by 0 + memset(theBuffer, 0, 4); + //Copy the number of files that will be written to the stream + memcpy(theBuffer, &aNbFiles, ((sizeof(int) > 4) ? 4 : sizeof(int))); + + aCurrentPos = 4; + + for(i = 0; i < aLength; i++) { + ifstream *aFile; + if (!theNamesOnly) { // mpv 15.01.2003: we don't open any file if theNamesOnly = true + TCollection_AsciiString aName(const_cast(aFiles[i+1].c_str())); + TCollection_AsciiString aFullPath = aTmpDir + aName; + OSD_Path anOSDPath(aFullPath); + OSD_File anOSDFile(anOSDPath); + if(!anOSDFile.Exists()) continue; +#ifdef WNT + aFile = new ifstream(aFullPath.ToCString(), ios::binary); +#else + aFile = new ifstream(aFullPath.ToCString()); +#endif + } + //Initialize 4 bytes of the buffer by 0 + memset((theBuffer + aCurrentPos), 0, 4); + //Copy the length of the file name to the buffer + memcpy((theBuffer + aCurrentPos), (aFileNameSize + i), ((sizeof(int) > 4) ? 4 : sizeof(int))); + aCurrentPos += 4; + + //Copy the file name to the buffer + char* aFName = const_cast(aFiles[i+1].c_str()); + memcpy((theBuffer + aCurrentPos), aFName, aFileNameSize[i]); + aCurrentPos += aFileNameSize[i]; + + if (!theNamesOnly) { // mpv 15.01.2003: we don't copy file content to the buffer if !theNamesOnly + //Initialize 8 bytes of the buffer by 0 + memset((theBuffer + aCurrentPos), 0, 8); + //Copy the length of the file to the buffer + memcpy((theBuffer + aCurrentPos), (aFileSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long))); + aCurrentPos += 8; + + aFile->seekg(0, ios::beg); + aFile->read((char *)(theBuffer + aCurrentPos), aFileSize[i]); + aFile->close(); + delete(aFile); + aCurrentPos += aFileSize[i]; + } + } + delete[] aFileNameSize; + delete[] aFileSize; + + theBufferSize = aBufferSize; +} + +//============================================================================ +// function : PutStreamToFile +/*! Purpose : converts a byte sequence to files and return list of them*/ +//============================================================================ +LightApp_Driver::ListOfFiles LightApp_Driver::PutStreamToFiles( const unsigned char* theBuffer, + const long theBufferSize, bool theNamesOnly ) +{ + if(theBufferSize == 0 || theBuffer == 0) + return ListOfFiles(); + + // Create a temporary directory for the component's data files + std::string aDir = GetTmpDir(); + + //Get a temporary directory for saving a file + TCollection_AsciiString aTmpDir(const_cast(aDir.c_str())); + + long aFileSize, aCurrentPos = 4; + int i, aFileNameSize, aNbFiles = 0; + + //Copy the number of files in the stream + memcpy(&aNbFiles, theBuffer, sizeof(int)); + + const int n = aNbFiles + 1; + ListOfFiles aFiles(n); + aFiles[0] = aDir; + + for(i = 0; i < aNbFiles; i++) { + //Put a length of the file name to aFileNameSize + memcpy(&aFileNameSize, (theBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int))); + aCurrentPos += 4; + + char *aFileName = new char[aFileNameSize]; + //Put a file name to aFileName + memcpy(aFileName, (theBuffer + aCurrentPos), aFileNameSize); + aCurrentPos += aFileNameSize; + + //Put a length of the file to aFileSize + if (!theNamesOnly) { + memcpy(&aFileSize, (theBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long))); + aCurrentPos += 8; + + TCollection_AsciiString aFullPath = aTmpDir + aFileName; + +#ifdef WNT + ofstream aFile(aFullPath.ToCString(), ios::out | ios::binary); +#else + ofstream aFile(aFullPath.ToCString()); +#endif + + aFile.write((char *)(theBuffer+aCurrentPos), aFileSize); + aFile.close(); + aCurrentPos += aFileSize; + } + std::string aStrFileName(aFileName); + aFiles[i+1] = aStrFileName; + delete[] aFileName; + } + return aFiles; +} + +//============================================================================ +// function : RemoveFiles +/*! Purpose : Remove files. First item in is a directory with slash at the end. + Other items are names of files. If is true, + then the directory is also deleted. +*/ +//============================================================================ +void LightApp_Driver::RemoveFiles( const ListOfFiles& theFiles, const bool IsDirDeleted) +{ + int i, aLength = theFiles.size() - 1; + if(aLength <= 0) { + return; + } + //Get a temporary directory for saved a file + TCollection_AsciiString aDirName(const_cast(theFiles[0].c_str())); + + for(i = 0; i < aLength; i++) { + TCollection_AsciiString aFile(aDirName); + aFile += const_cast(theFiles[i+1].c_str()); + OSD_Path anOSDPath(aFile); + OSD_File anOSDFile(anOSDPath); + if(!anOSDFile.Exists()) continue; + + anOSDFile.Remove(); + } + + if(IsDirDeleted) { + OSD_Path aPath(aDirName); + OSD_Directory aDir(aPath); + OSD_FileIterator anIterator(aPath, '*'); + + if(aDir.Exists() && !anIterator.More()) aDir.Remove(); + } +} + +//============================================================================ +// function : RemoveTemporaryFiles +/*! Purpose : removes files which was created from module theModuleName if + is true tmp directory is also deleted if it is empty*/ +//============================================================================ +void LightApp_Driver::RemoveTemporaryFiles( const char* theModuleName, const bool IsDirDeleted ) +{ + std::string aModuleName(theModuleName); + ListOfFiles aFiles = myMap[aModuleName]; + // aFiles must contain temporary directory name in its first item + // and names of files (relatively the temporary directory) in the others + RemoveFiles( aFiles, IsDirDeleted ); + +} + +//============================================================================ +// function : ClearDriverContents +/*! Purpose : clear map of list files*/ +//============================================================================ +void LightApp_Driver::ClearDriverContents() +{ + std::map::iterator it; + for ( it = myMap.begin(); it != myMap.end(); ++it ) + { + const char* aModuleName = const_cast(it->first.c_str()); + RemoveTemporaryFiles( aModuleName, false ); + } + myMap.clear(); +} + +//============================================================================ +// function : GetTempDir +/*! Purpose : return a temp directory to store created files like "/tmp/sub_dir/" */ +//============================================================================ +std::string LightApp_Driver::GetTmpDir() +{ + if ( myTmpDir.length() != 0 ) + return myTmpDir; + + //Find a temporary directory to store a file + TCollection_AsciiString aTmpDir; + + char *Tmp_dir = getenv("SALOME_TMP_DIR"); + if ( !Tmp_dir ) + Tmp_dir = getenv ( "TEMP" ); + if ( !Tmp_dir ) + Tmp_dir = getenv ( "TMP" ); + if ( Tmp_dir ) + { + aTmpDir = TCollection_AsciiString(Tmp_dir); +#ifdef WIN32 + if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\'; +#else + if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/'; +#endif + } + else + { +#ifdef WIN32 + aTmpDir = TCollection_AsciiString("C:\\"); +#else + aTmpDir = TCollection_AsciiString("/tmp/"); +#endif + } + + srand((unsigned int)time(NULL)); + int aRND = 999 + (int)(100000.0*rand()/(RAND_MAX+1.0)); //Get a random number to present a name of a sub directory + TCollection_AsciiString aSubDir(aRND); + if(aSubDir.Length() <= 1) aSubDir = TCollection_AsciiString("123409876"); + + aTmpDir += aSubDir; //Get RND sub directory + +#ifdef WIN32 + if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\'; +#else + if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/'; +#endif + + OSD_Path aPath(aTmpDir); + OSD_Directory aDir(aPath); + + for(aRND = 0; aDir.Exists(); aRND++) { + aTmpDir.Insert((aTmpDir.Length() - 1), TCollection_AsciiString(aRND)); //Build a unique directory name + aPath = OSD_Path(aTmpDir); + aDir = OSD_Directory(aPath); + } + + myTmpDir = aTmpDir.ToCString(); + + return aTmpDir.ToCString(); +} + +//============================================================================ +// function : GetDirFromPath +/*! Purpose : returns the dir by the path*/ +//============================================================================ +std::string LightApp_Driver::GetDirFromPath( const std::string& thePath ) { + if(thePath == "") + return ""; + OSD_Path aPath = OSD_Path(TCollection_AsciiString(const_cast(thePath.c_str()))); + TCollection_AsciiString aDirString(aPath.Trek()); + aDirString.ChangeAll('|','/'); + return aDirString.ToCString(); +} + diff --git a/src/LightApp/LightApp_Driver.h b/src/LightApp/LightApp_Driver.h index eb26e5633..1723a1a3d 100644 --- a/src/LightApp/LightApp_Driver.h +++ b/src/LightApp/LightApp_Driver.h @@ -1,49 +1,51 @@ -#ifndef LIGHTAPP_DRIVER_H -#define LIGHTAPP_DRIVER_H - -#include - -#include "string" -#include "vector" -#include "map" - -#ifdef WIN32 -#pragma warning( disable:4251 ) -#endif - -/*!Description : Driver can save to file and read from file list of files for light modules*/ - -class LIGHTAPP_EXPORT LightApp_Driver -{ -public: - LightApp_Driver(); - virtual ~LightApp_Driver(); - - - typedef std::vector ListOfFiles; - - bool SaveDatasInFile (const char* theFileName, bool isMultiFile ); - bool ReadDatasFromFile (const char* theFileName, bool isMultiFile ); - virtual std::string GetTmpDir (const char* theURL, const bool isMultiFile); - - ListOfFiles GetListOfFiles (const char* theModuleName); - virtual void SetListOfFiles (const char* theModuleName, const ListOfFiles theListOfFiles); - virtual void RemoveTemporaryFiles(const char* theModuleName, const bool IsDirDeleted); - - virtual void ClearDriverContents(); - -private: - void PutFilesToStream(const std::string& theModuleName, unsigned char*& theBuffer, - long& theBufferSize, bool theNamesOnly = false); - ListOfFiles PutStreamToFiles(const unsigned char* theBuffer, - const long theBufferSize, bool theNamesOnly = false); - - std::string GetTmpDir(); - std::string GetDirFromPath(const std::string& thePath); - -private: - typedef std::map MapOfListOfFiles; - MapOfListOfFiles myMap; -}; - -#endif +#ifndef LIGHTAPP_DRIVER_H +#define LIGHTAPP_DRIVER_H + +#include + +#include "string" +#include "vector" +#include "map" + +#ifdef WIN32 +#pragma warning( disable:4251 ) +#endif + +/*!Description : Driver can save to file and read from file list of files for light modules*/ + +class LIGHTAPP_EXPORT LightApp_Driver +{ +public: + LightApp_Driver(); + virtual ~LightApp_Driver(); + + + typedef std::vector ListOfFiles; + + bool SaveDatasInFile (const char* theFileName, bool isMultiFile ); + bool ReadDatasFromFile (const char* theFileName, bool isMultiFile ); + virtual std::string GetTmpDir (const char* theURL, const bool isMultiFile); + + ListOfFiles GetListOfFiles (const char* theModuleName); + virtual void SetListOfFiles (const char* theModuleName, const ListOfFiles theListOfFiles); + virtual void RemoveTemporaryFiles(const char* theModuleName, const bool IsDirDeleted); + void RemoveFiles( const ListOfFiles& theFiles, const bool IsDirDeleted); + + virtual void ClearDriverContents(); + +private: + void PutFilesToStream(const std::string& theModuleName, unsigned char*& theBuffer, + long& theBufferSize, bool theNamesOnly = false); + ListOfFiles PutStreamToFiles(const unsigned char* theBuffer, + const long theBufferSize, bool theNamesOnly = false); + + std::string GetTmpDir(); + std::string GetDirFromPath(const std::string& thePath); + +private: + typedef std::map MapOfListOfFiles; + MapOfListOfFiles myMap; + std::string myTmpDir; +}; + +#endif diff --git a/src/LightApp/LightApp_Study.cxx b/src/LightApp/LightApp_Study.cxx index e575e306d..f4c99a0b4 100644 --- a/src/LightApp/LightApp_Study.cxx +++ b/src/LightApp/LightApp_Study.cxx @@ -23,6 +23,7 @@ #include #include +#include #include /*! @@ -121,17 +122,52 @@ bool LightApp_Study::loadDocument( const QString& theStudyName ) //======================================================================= bool LightApp_Study::saveDocumentAs( const QString& theFileName ) { - ModelList list; dataModels( list ); + SUIT_ResourceMgr* resMgr = application()->resourceMgr(); + if( !resMgr ) + return false; + + ModelList list; + dataModels( list ); LightApp_DataModel* aModel = (LightApp_DataModel*)list.first(); - myDriver->ClearDriverContents(); QStringList listOfFiles; - for ( ; aModel; aModel = (LightApp_DataModel*)list.next() ) { + bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ); + for ( ; aModel; aModel = (LightApp_DataModel*)list.next() ) + { + std::vector anOldList = myDriver->GetListOfFiles( aModel->module()->name() ); listOfFiles.clear(); aModel->saveAs( theFileName, this, listOfFiles ); if ( !listOfFiles.isEmpty() ) saveModuleData(aModel->module()->name(), listOfFiles); + + // Remove files if necessary. File is removed if it was in the list of files before + // saving and it is not contained in the list after saving. This provides correct + // removing previous temporary files. These files are not removed before saving + // because they may be required for it. + + std::vector aNewList = myDriver->GetListOfFiles( aModel->module()->name() ); + + std::set aNewNames; + std::set toRemove; + int i, n; + for( i = 0, n = aNewList.size(); i < n; i++ ) + aNewNames.insert( aNewList[ i ] ); + for( i = 0, n = anOldList.size(); i < n; i++ ) + { + if ( i == 0 ) // directory is always inserted in list + toRemove.insert( anOldList[ i ] ); + else if ( aNewNames.find( anOldList[ i ] ) == aNewNames.end() ) + toRemove.insert( anOldList[ i ] ); + } + + std::vector toRemoveList( toRemove.size() ); + std::set::iterator anIter; + for( anIter = toRemove.begin(), i = 0; anIter != toRemove.end(); ++anIter, ++i ) + toRemoveList[ i ] = *anIter; + + + myDriver->RemoveFiles( toRemoveList, isMultiFile ); } bool res = saveStudyData(theFileName); @@ -175,6 +211,11 @@ bool LightApp_Study::saveDocument() //================================================================ void LightApp_Study::closeDocument(bool permanently) { + // Remove temporary files + ModelList aList; + dataModels( aList ); + myDriver->ClearDriverContents(); + // Inform everybody that this study is going to close when it's most safe to, // i.e. in the very beginning emit closed( this ); @@ -248,16 +289,7 @@ bool LightApp_Study::isModified() const //================================================================ bool LightApp_Study::isSaved() const { - bool isAllSaved = CAM_Study::isSaved(); - ModelList list; dataModels( list ); - - LightApp_DataModel* aModel = 0; - for ( QPtrListIterator it( list ); it.current() && isAllSaved; ++it ){ - aModel = dynamic_cast( it.current() ); - if ( aModel ) - isAllSaved = aModel->isSaved(); - } - return isAllSaved; + return CAM_Study::isSaved(); } //======================================================================= @@ -319,11 +351,6 @@ bool LightApp_Study::saveStudyData( const QString& theFileName ) bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ); bool aRes = myDriver->SaveDatasInFile(theFileName.latin1(), isMultiFile); - // clear map - std::vector aList(0); - for ( ModelListIterator it( list ); it.current(); ++it ) - myDriver->SetListOfFiles(it.current()->module()->name(), aList); - return aRes; } @@ -354,12 +381,7 @@ bool LightApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm QStringList listOfFiles; openModuleData(dm->module()->name(), listOfFiles); if (dm && dm->open(studyName, this, listOfFiles)) { - // Remove the files and temporary directory, created - // for this module by LightApp_Driver::OpenStudyData() - bool isMultiFile = false; // TODO: decide, how to access this parameter - RemoveTemporaryFiles( dm->module()->name(), isMultiFile ); - - // Something has been read -> create data model tree + // Something has been read -> create data model tree LightApp_DataModel* aDM = dynamic_cast( dm ); if ( aDM ) aDM->update(NULL, this); @@ -425,3 +447,4 @@ void LightApp_Study::components( QStringList& comp ) const comp.append( obj->entry() ); } } + diff --git a/src/LightApp/Makefile.in b/src/LightApp/Makefile.in index 2c0a57df8..092b071f7 100755 --- a/src/LightApp/Makefile.in +++ b/src/LightApp/Makefile.in @@ -80,7 +80,6 @@ LIB_MOC = LightApp_AboutDlg.h \ LightApp_Application.h \ LightApp_DataModel.h \ LightApp_Dialog.h \ - LightApp_Driver.h \ LightApp_GLSelector.h \ LightApp_OBSelector.h \ LightApp_OCCSelector.h \ -- 2.39.2