From bd6237624152554b0820e73673b4dbb16a4ee546 Mon Sep 17 00:00:00 2001 From: mpv Date: Thu, 15 May 2014 09:04:31 +0400 Subject: [PATCH] Implementation of open/save documents functionality --- src/Model/Model_Application.cpp | 18 +++ src/Model/Model_Application.h | 9 ++ src/Model/Model_AttributeDocRef.cpp | 6 + src/Model/Model_Document.cpp | 202 +++++++++++++++++----------- src/XGUI/XGUI_Workshop.cpp | 2 +- 5 files changed, 161 insertions(+), 76 deletions(-) diff --git a/src/Model/Model_Application.cpp b/src/Model/Model_Application.cpp index 166b4e1a1..df32ef977 100644 --- a/src/Model/Model_Application.cpp +++ b/src/Model/Model_Application.cpp @@ -26,6 +26,12 @@ const boost::shared_ptr& Model_Application::getDocument(string t boost::shared_ptr aNew(new Model_Document(theDocID)); myDocs[theDocID] = aNew; + // load it if it must be loaded by demand + if (myLoadedByDemand.find(theDocID) != myLoadedByDemand.end() && !myPath.empty()) { + aNew->load(myPath.c_str()); + myLoadedByDemand.erase(theDocID); // done, don't do it anymore + } + return myDocs[theDocID]; } @@ -40,6 +46,18 @@ bool Model_Application::hasDocument(std::string theDocID) return myDocs.find(theDocID) != myDocs.end(); } +//======================================================================= +void Model_Application::setLoadPath(std::string thePath) +{ + myPath = thePath; +} + +//======================================================================= +void Model_Application::setLoadByDemand(std::string theID) +{ + myLoadedByDemand.insert(theID); +} + //======================================================================= Model_Application::Model_Application() { diff --git a/src/Model/Model_Application.h b/src/Model/Model_Application.h index ddd3155bd..9281f9ce6 100644 --- a/src/Model/Model_Application.h +++ b/src/Model/Model_Application.h @@ -36,6 +36,11 @@ public: //! Deletes the document from the application MODEL_EXPORT void deleteDocument(std::string theDocID); + //! Set path for the loaded by demand documents + void setLoadPath(std::string thePath); + //! Defines that specified document must be loaded by demand + void setLoadByDemand(std::string theID); + public: // Redefined OCAF methods //! Return name of resource (i.e. "Standard") @@ -51,6 +56,10 @@ public: private: /// Map from string identifiers to created documents of an application std::map > myDocs; + /// Path for the loaded by demand documents + std::string myPath; + /// Path for the loaded by demand documents + std::set myLoadedByDemand; }; #endif diff --git a/src/Model/Model_AttributeDocRef.cpp b/src/Model/Model_AttributeDocRef.cpp index 93c8af713..dfb307f4d 100644 --- a/src/Model/Model_AttributeDocRef.cpp +++ b/src/Model/Model_AttributeDocRef.cpp @@ -36,5 +36,11 @@ Model_AttributeDocRef::Model_AttributeDocRef(TDF_Label& theLabel) if (!theLabel.FindAttribute(TDataStd_Comment::GetID(), myComment)) { // create attribute: not initialized by value yet, just empty string myComment = TDataStd_Comment::Set(theLabel, ""); + } else { // document was already referenced: try to set it as loaded by demand + Handle(Model_Application) anApp = Model_Application::getApplication(); + string anID(TCollection_AsciiString(myComment->Get()).ToCString()); + if (!anApp->hasDocument(anID)) { + anApp->setLoadByDemand(anID); + } } } diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index 8c305effa..9d8c2c12a 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -18,6 +19,12 @@ #include +#ifdef WIN32 +# define _separator_ '\\' +#else +# define _separator_ '/' +#endif + static const int UNDO_LIMIT = 10; // number of possible undo operations static const int TAG_GENERAL = 1; // general properties tag @@ -26,83 +33,125 @@ static const int TAG_HISTORY = 3; // tag of the history sub-tree (python dump) using namespace std; +/// Returns the file name of this document by the nameof directory and identifuer of a document +static TCollection_ExtendedString DocFileName(const char* theFileName, const string& theID) +{ + TCollection_ExtendedString aPath ((const Standard_CString)theFileName); + aPath += _separator_; + aPath += theID.c_str(); + aPath += ".cbf"; // standard binary file extension + return aPath; +} + bool Model_Document::load(const char* theFileName) { - bool myIsError = Standard_False; - /* - TCollection_ExtendedString aPath ((const Standard_CString)theFileName); - PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1; - try - { - Handle(TDocStd_Document) aDoc = this; - aStatus = Model_Application::GetApplication()->Open(aPath, aDoc); - } - catch (Standard_Failure) - {} - myIsError = aStatus != PCDM_RS_OK; - if (myIsError) - { - switch (aStatus) - { - case PCDM_RS_UnknownDocument: cout<<"OCAFApp_Appl_RUnknownDocument"<rootDocument().get()) { + anApp->setLoadPath(theFileName); + } + TCollection_ExtendedString aPath (DocFileName(theFileName, myID)); + PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1; + try + { + aStatus = anApp->Open(aPath, myDoc); + } + catch (Standard_Failure) + { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + Events_Error::send(string("Exception in opening of document: ") + aFail->GetMessageString()); + return false; + } + bool isError = aStatus != PCDM_RS_OK; + if (isError) + { + switch (aStatus) + { + case PCDM_RS_UnknownDocument: + Events_Error::send(string("Can not open document: PCDM_RS_UnknownDocument")); break; + case PCDM_RS_AlreadyRetrieved: + Events_Error::send(string("Can not open document: PCDM_RS_AlreadyRetrieved")); break; + case PCDM_RS_AlreadyRetrievedAndModified: + Events_Error::send(string("Can not open document: PCDM_RS_AlreadyRetrievedAndModified")); break; + case PCDM_RS_NoDriver: + Events_Error::send(string("Can not open document: PCDM_RS_NoDriver")); break; + case PCDM_RS_UnknownFileDriver: + Events_Error::send(string("Can not open document: PCDM_RS_UnknownFileDriver")); break; + case PCDM_RS_OpenError: + Events_Error::send(string("Can not open document: PCDM_RS_OpenError")); break; + case PCDM_RS_NoVersion: + Events_Error::send(string("Can not open document: PCDM_RS_NoVersion")); break; + case PCDM_RS_NoModel: + Events_Error::send(string("Can not open document: PCDM_RS_NoModel")); break; + case PCDM_RS_NoDocument: + Events_Error::send(string("Can not open document: PCDM_RS_NoDocument")); break; + case PCDM_RS_FormatFailure: + Events_Error::send(string("Can not open document: PCDM_RS_FormatFailure")); break; + case PCDM_RS_TypeNotFoundInSchema: + Events_Error::send(string("Can not open document: PCDM_RS_TypeNotFoundInSchema")); break; + case PCDM_RS_UnrecognizedFileFormat: + Events_Error::send(string("Can not open document: PCDM_RS_UnrecognizedFileFormat")); break; + case PCDM_RS_MakeFailure: + Events_Error::send(string("Can not open document: PCDM_RS_MakeFailure")); break; + case PCDM_RS_PermissionDenied: + Events_Error::send(string("Can not open document: PCDM_RS_PermissionDenied")); break; + case PCDM_RS_DriverFailure: + Events_Error::send(string("Can not open document: PCDM_RS_DriverFailure")); break; + default: + Events_Error::send(string("Can not open document: unknown error")); break; + } + } + if (!isError) { + myDoc->SetUndoLimit(UNDO_LIMIT); + synchronizeFeatures(); + } + return !isError; } bool Model_Document::save(const char* theFileName) { - bool myIsError = true; - /* - TCollection_ExtendedString aPath ((const Standard_CString)theFileName); - PCDM_StoreStatus aStatus; - try { - Handle(TDocStd_Document) aDoc = this; - aStatus = Model_Application::GetApplication()->SaveAs (aDoc, aPath); - } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - cout<<"OCAFApp_Engine:save Error: "<GetMessageString()<rootDocument().get()) { +#ifdef WIN32 + CreateDirectory(theFileName, NULL); +#else + mkdir(theFileName, 0x1ff); +#endif + } + // filename in the dir is id of document inside of the given directory + TCollection_ExtendedString aPath(DocFileName(theFileName, myID)); + PCDM_StoreStatus aStatus; + try { + aStatus = Model_Application::getApplication()->SaveAs(myDoc, aPath); + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + Events_Error::send(string("Exception in saving of document: ") + aFail->GetMessageString()); + return false; + } + bool isDone = aStatus == PCDM_SS_OK || aStatus == PCDM_SS_No_Obj; + if (!isDone) + { + switch (aStatus) + { + case PCDM_SS_DriverFailure: + Events_Error::send(string("Can not save document: PCDM_SS_DriverFailure")); + break; + case PCDM_SS_WriteFailure: + Events_Error::send(string("Can not save document: PCDM_SS_WriteFailure")); + break; + case PCDM_SS_Failure: + default: + Events_Error::send(string("Can not save document: PCDM_SS_Failure")); + break; + } + } + myTransactionsAfterSave = 0; + if (isDone) { // save also sub-documents if any + set::iterator aSubIter = mySubs.begin(); + for(; aSubIter != mySubs.end() && isDone; aSubIter++) + isDone = subDocument(*aSubIter)->save(theFileName); + } + return isDone; } void Model_Document::close() @@ -344,6 +393,8 @@ Model_Document::Model_Document(const std::string theID) { myDoc->SetUndoLimit(UNDO_LIMIT); myTransactionsAfterSave = 0; + // to have something in the document and avoid empty doc open/save problem + TDataStd_Integer::Set(myDoc->Main().Father(), 0); } TDF_Label Model_Document::groupLabel(const string theGroup) @@ -458,10 +509,6 @@ void Model_Document::synchronizeFeatures() aFeature->setDoc(aThis); aFeature->setData(aData); aFeature->initAttributes(); - // event: model is updated - static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_CREATED); - Model_FeatureUpdatedMessage aMsg(aFeature, anEvent); - Events_Loop::loop()->send(aMsg); if (aFIter == aFeatures.end()) { aFeatures.push_back(aFeature); @@ -470,6 +517,11 @@ void Model_Document::synchronizeFeatures() aFIter++; aFeatures.insert(aFIter, aFeature); } + // event: model is updated + static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_CREATED); + Model_FeatureUpdatedMessage aMsg(aFeature, anEvent); + Events_Loop::loop()->send(aMsg); + // feature for this label is added, so go to the next label aFLabIter.Next(); } else { // nothing is changed, both iterators are incremented diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 577e6deca..aeb505f9d 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -421,7 +421,7 @@ void XGUI_Workshop::onOpen() } //show file dialog, check if readable and open - myCurrentFile = QFileDialog::getOpenFileName(mainWindow()); + myCurrentFile = QFileDialog::getExistingDirectory(mainWindow()); if(myCurrentFile.isEmpty()) return; QFileInfo aFileInfo(myCurrentFile); -- 2.39.2