--- /dev/null
+#ifndef MBDebug_HeaderFile\r
+#define MBDebug_HeaderFile\r
+\r
+//---------------------------------------------------------------\r
+// Usage of the logging facilities:\r
+//\r
+// (1) At the beginning of each class file to be debugged, there\r
+// should be a static string variable defined with the name\r
+// of the class. Then, include the "MBDebug.h" header file.\r
+//\r
+// //---------------------------------------------------------\r
+// #define USE_DEBUG\r
+// //#define MB_IGNORE_QT\r
+// //#define MB_FULL_DUMP\r
+// #define MBCLASSNAME "ClassName"\r
+// #include "MBDebug.h"\r
+// // <-- insert includes for addtional debug headers here!\r
+// //---------------------------------------------------------\r
+//\r
+// (2) At the beginning of each class method, call the DBG_FUN\r
+// macro.\r
+//\r
+// int ClassName::MyMethod(int x)\r
+// {\r
+// DBG_FUN();\r
+// ...\r
+// }\r
+//\r
+// NOTE: For static methods, call the DBG_FUNC() macro!!\r
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\r
+// This debugging/logging class is a "header-only" solution and\r
+// does NOT require any additional implementation (.cpp) file!\r
+//---------------------------------------------------------------\r
+\r
+#include <iostream>\r
+#include <string>\r
+#include <locale>\r
+#include <codecvt>\r
+#include <list>\r
+#include <map>\r
+#include <set>\r
+#include <vector>\r
+#include <mutex>\r
+#include <thread>\r
+#ifndef MB_IGNORE_QT\r
+# include <QString>\r
+# include <QStringList>\r
+#endif\r
+\r
+static std::mutex mtx;\r
+\r
+//---------------------------------------------------------------\r
+// Set the debug flags dependent on the preprocessor definitions\r
+//---------------------------------------------------------------\r
+#ifdef USE_DEBUG\r
+# define MBS_DEBUG_FLAG MBDebug::DF_DEBUG\r
+#else\r
+# define MBS_DEBUG_FLAG 0\r
+#endif /*DEBUG*/ \r
+\r
+#define MBS_DBG_FLAGS (MBS_DEBUG_FLAG)\r
+\r
+\r
+//---------------------------------------------------------------\r
+// Define the global debug macros\r
+//---------------------------------------------------------------\r
+#define DLOG MBDebug::LogPrint()\r
+#define RETURN(var) { RET(var); return (var); }\r
+\r
+#ifdef USE_DEBUG\r
+\r
+# define DBG_FUN() MBDebug _dbg(MBCLASSNAME, __FUNCTION__, MBS_DBG_FLAGS, (void*)this)\r
+# define DBG_FUNC() MBDebug _dbg(MBCLASSNAME, __FUNCTION__, MBS_DBG_FLAGS)\r
+# define DBG_FUNB(blk) MBDebug _dbg(MBCLASSNAME, blk, MBS_DBG_FLAGS)\r
+# define MSGEL(txt) MBDebug::LogPrint() << ":" << txt << std::endl\r
+# define PRINT(txt) MBDebug::LogPrint() << txt\r
+# define SHOW2(var,typ) do { PRINT(std::this_thread::get_id()); DumpVar(#var,(typ)(var)); } while (0)\r
+# define SHOW(var) do { PRINT(std::this_thread::get_id()); DumpVar(#var,var); } while (0)\r
+# define ARG(var) do { PRINT(std::this_thread::get_id() << ":in:"); DumpVar(#var,var); } while (0)\r
+# define ARG2(var,typ) do { PRINT(std::this_thread::get_id() << ":in:"); DumpVar(#var,(typ)(var)); } while (0)\r
+# define RET(var) do { PRINT(std::this_thread::get_id() << ":out:"); DumpVar(#var,var); } while (0)\r
+# define MSG(txt) MBDebug::LogPrint() << std::this_thread::get_id() << ":" << txt\r
+\r
+#else /*!USE_DEBUG*/ \r
+\r
+# define DBG_FUN()\r
+# define DBG_FUNC()\r
+# define DBG_FUNB(blk)\r
+# define MSGEL(txt)\r
+# define PRINT(txt)\r
+# define SHOW2(var,typ)\r
+# define SHOW(var)\r
+# define ARG(var)\r
+# define ARG2(var,typ)\r
+# define RET(var)\r
+# define MSG(txt)\r
+\r
+#endif /*USE_DEBUG*/ \r
+\r
+\r
+//---------------------------------------------------------------\r
+// Declare the debugging and profiling class\r
+//---------------------------------------------------------------\r
+class MBDebug\r
+{\r
+public:\r
+ enum {\r
+ DF_NONE = 0x00, // no debug\r
+ DF_DEBUG = 0x01 // debug a function\r
+ };\r
+\r
+ MBDebug(const char* aClassName, const char* aFuncName, const short aFlag, void* aThis=NULL)\r
+ :mClassName(aClassName),mFuncName(aFuncName),mThis(aThis),mFlags((unsigned char)aFlag)\r
+ {\r
+ if (mFlags & (DF_DEBUG))\r
+ {\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ std::cout << std::this_thread::get_id() << ":{ENTER: " << mClassName + "::" + mFuncName;\r
+ if (mThis) std::cout << "(this=" << mThis << ")";\r
+ std::cout << std::endl;\r
+ }\r
+ }\r
+ virtual ~MBDebug()\r
+ {\r
+ if (mFlags & (DF_DEBUG))\r
+ {\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ std::cout << std::this_thread::get_id() << ":}LEAVE: " << mClassName << "::" << mFuncName << std::endl;\r
+ }\r
+ }\r
+\r
+ // Log file output management\r
+ static std::ostream& LogPrint() { return std::cout; }\r
+\r
+private:\r
+ std::string mClassName; // Name of class to be debugged\r
+ std::string mFuncName; // Name of function to be debugged\r
+ void* mThis; // The "this" pointer to the class being debugged\r
+ unsigned char mFlags; // Debug mode flags\r
+};\r
+\r
+\r
+\r
+#define YesNo(b) (b ? "Yes" : "No")\r
+\r
+\r
+\r
+inline std::string w2s(std::wstring ws)\r
+{\r
+ using convert_typeX = std::codecvt_utf8<wchar_t>;\r
+ std::wstring_convert<convert_typeX, wchar_t> converterX;\r
+ return(converterX.to_bytes(ws));\r
+}\r
+\r
+// Primitive types\r
+inline void DumpVar(const char *szName, char value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[chr]: " << szName << "='" << value << "'" << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, bool value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[bool]: " << szName << "=" << (value ? "true" : "false") << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, short value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[shrt]: " << szName << "=" << value << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, int value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[int]: " << szName << "=" << value << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, long value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[long]: " << szName << "=" << value << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, double value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[dbl]: " << szName << "=" << value << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, unsigned char value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[byte]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, unsigned short value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[word]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, unsigned int value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[uint]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, unsigned long value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[dword]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, const char* value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[str]: " << szName << "=\"" << (value ? value : "") << "\"" << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, const std::string &value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[Str]: " << szName << "=\"" << value << "\"" << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, const std::wstring &value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[WStr]: " << szName << "=\"" << w2s(value) << "\"" << std::endl;\r
+}\r
+\r
+#ifndef MB_IGNORE_QT\r
+inline void DumpVar(const char *szName, const QString &value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[QStr]: " << szName << "=\"" << value.toStdString() << "\"" << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, const QStringList &value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[QStrLst]: " << szName << "=[len=" << value.length() << "] {";\r
+ bool first = true;\r
+ QStringList::const_iterator it = value.constBegin();\r
+ for ( ; it != value.constEnd(); ++it)\r
+ {\r
+ DLOG << (first ? "" : ",") << "\"" << (*it).toStdString() << "\"";\r
+ first = false;\r
+ }\r
+ DLOG << "}" << std::endl;\r
+}\r
+#endif\r
+\r
+inline void DumpVar(const char *szName, const void* value)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[ptr]: " << szName << "=" << value << std::endl;\r
+}\r
+\r
+\r
+// Collection of primitive types\r
+inline void DumpVar(const char *szName, const std::set<int> &values)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[intSet]: " << szName << "={" << values.size() << "}[";\r
+ bool bFirst = true;\r
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {\r
+ DLOG << (bFirst ? "" : ",") << *it;\r
+ bFirst = false;\r
+ }\r
+ DLOG << "]" << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, const std::vector<int> &values)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[intVect]: " << szName << "={" << values.size() << "}[";\r
+ bool bFirst = true;\r
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {\r
+ DLOG << (bFirst ? "" : ",") << *it;\r
+ bFirst = false;\r
+ }\r
+ DLOG << "]" << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, const std::list<bool>& values)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[boolList]: " << szName << "={" << values.size() << "}[";\r
+ bool bFirst = true;\r
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {\r
+ DLOG << (bFirst ? "" : ",") << (*it ? "Y" : "N");\r
+ bFirst = false;\r
+ }\r
+ DLOG << "]" << std::endl;\r
+}\r
+\r
+inline void DumpVar(const char *szName, const std::list<std::string> &values)\r
+{\r
+ std::lock_guard<std::mutex> lck(mtx);\r
+ DLOG << "[strLst]: " << szName << "={" << values.size() << "}[";\r
+ bool bFirst = true;\r
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {\r
+ DLOG << (bFirst ? "\"" : ", \"") << *it << "\"";\r
+ bFirst = false;\r
+ }\r
+ DLOG << "]" << std::endl;\r
+}\r
+\r
+#endif // MBDebug_HeaderFile\r
+\r
#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SALOME_Exception)
+
//#define NOTIFY_BY_EVENT
class ObserverEvent : public QEvent
Saves document
\param theFileName - name of file
*/
-bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
+bool SalomeApp_Study::saveDocumentAs( const QString& theFileName, bool isBackup/*=false*/ )
{
+ bool wasSaved = isSaved();
+ bool wasModified = isModified();
+ std::string oldName = (studyDS() ? studyDS()->Name() : "");
+ std::string oldURL = (studyDS() ? studyDS()->URL() : "");
bool store = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", false );
- if ( store )
+ if ( store && !isBackup )
SalomeApp_VisualState( (SalomeApp_Application*)application() ).storeState();
ModelList list; dataModels( list );
if ( LightApp_DataModel* aModel =
dynamic_cast<LightApp_DataModel*>( it.next() ) ) {
listOfFiles.clear();
- aModel->saveAs( theFileName, this, listOfFiles );
+ aModel->saveAs( theFileName, this, listOfFiles, isBackup );
if ( !listOfFiles.isEmpty() )
saveModuleData(aModel->module()->name(), 0, // 0 means persistence file
listOfFiles);
bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false );
bool isAscii = resMgr->booleanValue( "Study", "ascii_file", false );
bool res = studyDS()->SaveAs( theFileName.toUtf8().data(), isMultiFile, isAscii )
- && CAM_Study::saveDocumentAs( theFileName );
+ && CAM_Study::saveDocumentAs( theFileName, isBackup );
res = res && saveStudyData(theFileName, 0); // 0 means persistence file
- if ( res )
+ if ( res && !isBackup)
emit saved( this );
+ if (isBackup)
+ {
+ // Restore the isSaved and isModified flag after having done backup
+ setIsSaved(wasSaved);
+ setIsModified(wasModified);
+ // If the document hasn't been saved before, reset here its name and URL
+ if (studyDS())
+ {
+ studyDS()->URL(oldURL);
+ studyDS()->Name(oldName);
+ }
+ }
+
return res;
}