From 9e396b8aa79134aac473c1dc2eb106833d594f47 Mon Sep 17 00:00:00 2001 From: mpv Date: Thu, 18 Sep 2014 18:30:01 +0400 Subject: [PATCH] Make automatic/manual rebuild property and connect the "Rebuild" button --- src/Config/CMakeLists.txt | 1 + src/Config/Config_Prop.cpp | 18 +++++++++ src/Config/Config_Prop.h | 6 +-- src/Model/Model_Application.cpp | 6 +++ src/Model/Model_Application.h | 2 + src/Model/Model_Data.cpp | 16 ++++++++ src/Model/Model_Data.h | 7 ++++ src/Model/Model_Document.h | 3 ++ src/Model/Model_Session.cpp | 21 +++++++++++ src/Model/Model_Session.h | 3 ++ src/Model/Model_Update.cpp | 63 ++++++++++++++++++++++++++------ src/Model/Model_Update.h | 11 ++++-- src/ModelAPI/ModelAPI_Data.h | 7 ++++ src/ModelAPI/ModelAPI_Document.h | 2 +- src/ModelAPI/ModelAPI_Session.h | 3 ++ src/XGUI/XGUI_Workshop.cpp | 9 +++++ src/XGUI/XGUI_Workshop.h | 1 + 17 files changed, 160 insertions(+), 19 deletions(-) create mode 100644 src/Config/Config_Prop.cpp diff --git a/src/Config/CMakeLists.txt b/src/Config/CMakeLists.txt index c40289ab9..1be2129ed 100644 --- a/src/Config/CMakeLists.txt +++ b/src/Config/CMakeLists.txt @@ -29,6 +29,7 @@ SET(PROJECT_SOURCES Config_PointerMessage.cpp Config_Common.cpp Config_ValidatorMessage.cpp + Config_Prop.cpp Config_PropManager.cpp ) diff --git a/src/Config/Config_Prop.cpp b/src/Config/Config_Prop.cpp new file mode 100644 index 000000000..7904021b6 --- /dev/null +++ b/src/Config/Config_Prop.cpp @@ -0,0 +1,18 @@ +// File: Config_Prop.cpp +// Created: 18 Sep 2014 +// Author: Mikhail PONIKAROV + + +#include "Config_Prop.h" +#include "Events_Loop.h" +#include "Events_Message.h" + +void Config_Prop::setValue(const std::string& theValue) +{ + if (theValue != myValue) { + myValue = theValue; + static const Events_ID aChangedEvent = Events_Loop::loop()->eventByName("PreferenceChanged"); + Events_Loop::loop()->send(boost::shared_ptr( + new Events_Message(aChangedEvent, this))); + } +} diff --git a/src/Config/Config_Prop.h b/src/Config/Config_Prop.h index f74137c3c..f4ea0138b 100644 --- a/src/Config/Config_Prop.h +++ b/src/Config/Config_Prop.h @@ -88,10 +88,8 @@ class Config_Prop { return myValue; } - void setValue(const std::string& theValue) - { - myValue = theValue; - } + + CONFIG_EXPORT void setValue(const std::string& theValue); bool operator==(const Config_Prop* theProp) const { diff --git a/src/Model/Model_Application.cpp b/src/Model/Model_Application.cpp index 797d00e19..23ecf05ae 100644 --- a/src/Model/Model_Application.cpp +++ b/src/Model/Model_Application.cpp @@ -61,6 +61,12 @@ void Model_Application::setLoadByDemand(std::string theID) myLoadedByDemand.insert(theID); } +//======================================================================= +bool Model_Application::isLoadByDemand(std::string theID) +{ + return myLoadedByDemand.find(theID) != myLoadedByDemand.end(); +} + //======================================================================= Model_Application::Model_Application() { diff --git a/src/Model/Model_Application.h b/src/Model/Model_Application.h index 09a1694c3..ae68024ee 100644 --- a/src/Model/Model_Application.h +++ b/src/Model/Model_Application.h @@ -41,6 +41,8 @@ class Model_Application : public TDocStd_Application void setLoadPath(std::string thePath); //! Defines that specified document must be loaded by demand void setLoadByDemand(std::string theID); + //! Returns true if specified document must be loaded by demand + bool isLoadByDemand(std::string theID); public: // Redefined OCAF methods diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index 2530dd567..26f537d68 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -20,6 +20,7 @@ #include #include +#include #include @@ -283,3 +284,18 @@ void Model_Data::erase() if (!myLab.IsNull()) myLab.ForgetAllAttributes(); } + +Standard_GUID kMustBeUpdatedGUID("baede74c-31a6-4416-9c4d-e48ce65f2005"); + +void Model_Data::mustBeUpdated(const bool theFlag) +{ + if (theFlag) + TDataStd_UAttribute::Set(myLab, kMustBeUpdatedGUID); + else + myLab.ForgetAttribute(kMustBeUpdatedGUID); +} + +bool Model_Data::mustBeUpdated() +{ + return myLab.IsAttribute(kMustBeUpdatedGUID) == Standard_True; +} diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index 94490d4aa..136e4504f 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -129,6 +129,13 @@ class Model_Data : public ModelAPI_Data } MODEL_EXPORT virtual void erase(); + + /// Makes feature must be updated later (on rebuild). Normally the Updater must call it + /// in case of not-automatic update to true + MODEL_EXPORT virtual void mustBeUpdated(const bool theFlag); + + /// Returns true if feature must be updated (re-executed) on rebuild + MODEL_EXPORT virtual bool mustBeUpdated(); }; #endif diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index e67556cc9..443d00c10 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -172,6 +172,9 @@ class Model_Document : public ModelAPI_Document //! Removes information that there is a reference to this object void objectIsNotReferenced(const ObjectPtr& theObject); + //! Returns all sub documents + const std::set& subDocuments() const {return mySubs;} + friend class Model_Application; friend class Model_Session; friend class Model_AttributeReference; diff --git a/src/Model/Model_Session.cpp b/src/Model/Model_Session.cpp index a6d12d8fb..d6503ee76 100644 --- a/src/Model/Model_Session.cpp +++ b/src/Model/Model_Session.cpp @@ -147,6 +147,27 @@ void Model_Session::setActiveDocument(boost::shared_ptr theDo } } +std::list > Model_Session::allOpenedDocuments() +{ + list > aResult; + aResult.push_back(moduleDocument()); + // add subs recursively + list >::iterator aDoc = aResult.begin(); + for(; aDoc != aResult.end(); aDoc++) { + DocumentPtr anAPIDoc = *aDoc; + boost::shared_ptr aDoc = boost::dynamic_pointer_cast(anAPIDoc); + if (aDoc) { + std::set::const_iterator aSubIter = aDoc->subDocuments().cbegin(); + for(; aSubIter != aDoc->subDocuments().cend(); aSubIter++) { + if (!Model_Application::getApplication()->isLoadByDemand(*aSubIter)) { + aResult.push_back(Model_Application::getApplication()->getDocument(*aSubIter)); + } + } + } + } + return aResult; +} + boost::shared_ptr Model_Session::copy( boost::shared_ptr theSource, std::string theID) { diff --git a/src/Model/Model_Session.h b/src/Model/Model_Session.h index dca8f220b..e691cea30 100644 --- a/src/Model/Model_Session.h +++ b/src/Model/Model_Session.h @@ -75,6 +75,9 @@ class Model_Session : public ModelAPI_Session, public Events_Listener /// Defines the current document that used for current work in the application MODEL_EXPORT virtual void setActiveDocument(boost::shared_ptr theDoc); + /// Returns all the opened documents of the session (without postponed) + MODEL_EXPORT virtual std::list > allOpenedDocuments(); + /// Registers the plugin that creates features. /// It is obligatory for each plugin to call this function on loading to be found by /// the plugin manager on call of the feature) diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index 848f38b80..70d977330 100644 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -16,34 +16,65 @@ #include #include #include +#include using namespace std; Model_Update MY_INSTANCE; /// the only one instance initialized on load of the library -Model_Update::Model_Update() +Model_Update::Model_Update() : isCreated(false) { + static const Events_ID kChangedEvent = Events_Loop::loop()->eventByName("PreferenceChanged"); + Events_Loop::loop()->registerListener(this, kChangedEvent); + static const Events_ID kRebuildEvent = Events_Loop::loop()->eventByName("Rebuild"); + Events_Loop::loop()->registerListener(this, kRebuildEvent); Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED)); Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + Config_PropManager::registerProp("Model update", "automatic_rebuild", "Rebuild automatically", + Config_Prop::Bool, "false"); + isAutomatic = Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true"; } void Model_Update::processEvent(const boost::shared_ptr& theMessage) { + static const Events_ID kChangedEvent = Events_Loop::loop()->eventByName("PreferenceChanged"); + static const Events_ID kRebuildEvent = Events_Loop::loop()->eventByName("Rebuild"); + bool isAutomaticChanged = false; + if (theMessage->eventID() == kChangedEvent) { // automatic and manual rebuild flag is changed + isAutomatic = + Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true"; + } else if (theMessage->eventID() == kRebuildEvent) { // the rebuild command + if (isAutomatic == false) { + isAutomaticChanged = true; + isAutomatic = true; + } + } + if (isExecuted) return; // nothing to do: it is executed now + // execute just created features anyway + isCreated = theMessage->eventID() == Events_Loop::eventByName(EVENT_OBJECT_CREATED); + //Events_LongOp::start(this); isExecuted = true; + list > aDocs; boost::shared_ptr aMsg = boost::dynamic_pointer_cast(theMessage); - myInitial = aMsg->objects(); + if (aMsg) myInitial = aMsg->objects(); + else { + myInitial.clear(); + // on change flag all documents must be updated + if (isAutomatic) { + aDocs = ModelAPI_Session::get()->allOpenedDocuments(); + } + } // collect all documents involved into the update - set > aDocs; set >::iterator aFIter = myInitial.begin(); for (; aFIter != myInitial.end(); aFIter++) { - aDocs.insert((*aFIter)->document()); + aDocs.push_back((*aFIter)->document()); } // iterate all features of features-documents to update them (including hidden) - set >::iterator aDIter = aDocs.begin(); + list >::iterator aDIter = aDocs.begin(); for (; aDIter != aDocs.end(); aDIter++) { int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group(), true); for (int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) { @@ -58,6 +89,8 @@ void Model_Update::processEvent(const boost::shared_ptr& theMess static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); Events_Loop::loop()->flush(EVENT_DISP); //Events_LongOp::end(this); + if (isAutomaticChanged) isAutomatic = false; + isCreated = false; isExecuted = false; } @@ -69,6 +102,7 @@ bool Model_Update::updateFeature(FeaturePtr theFeature) // check all features this feature depended on (recursive call of updateFeature) bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end(); if (theFeature) { // only real feature contains references to other objects + if (theFeature->data()->mustBeUpdated()) aMustbeUpdated = true; // references list > aRefs = theFeature->data()->attributes( ModelAPI_AttributeReference::type()); @@ -119,12 +153,19 @@ bool Model_Update::updateFeature(FeaturePtr theFeature) !theFeature->isPersistentResult()) { ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); if (aFactory->validate(theFeature)) { - try { - theFeature->execute(); - } catch(...) { - Events_Error::send( - "Feature " + theFeature->getKind() + " has failed during the execution"); - theFeature->eraseResults(); + if (isAutomatic || (isCreated && myInitial.find(theFeature) != myInitial.end()) || + !theFeature->isPersistentResult() /* execute quick, not persistent results */) { + try { + theFeature->execute(); + theFeature->data()->mustBeUpdated(false); + } catch(...) { + Events_Error::send( + "Feature " + theFeature->getKind() + " has failed during the execution"); + theFeature->eraseResults(); + } + } else { + theFeature->data()->mustBeUpdated(true); + aMustbeUpdated = false; } } else { theFeature->eraseResults(); diff --git a/src/Model/Model_Update.h b/src/Model/Model_Update.h index 5cfa02527..ff3e67660 100644 --- a/src/Model/Model_Update.h +++ b/src/Model/Model_Update.h @@ -20,12 +20,17 @@ class ModelAPI_Feature; */ class Model_Update : public Events_Listener { - ///< initial set of updated features that must be processed + /// initial set of updated features that must be processed std::set > myInitial; - ///< already updated and processed features and modificated feature flag + /// already updated and processed features and modificated feature flag std::map, bool> myUpdated; - ///< to know that all next updates are caused by this execution + /// to know that all next updates are caused by this execution bool isExecuted; + /// to know execute or not automatically all update + bool isAutomatic; + /// execute just created features for sure + bool isCreated; + public: /// Is called only once, on startup of the application Model_Update(); diff --git a/src/ModelAPI/ModelAPI_Data.h b/src/ModelAPI/ModelAPI_Data.h index 36838a6ef..e82a4c44a 100644 --- a/src/ModelAPI/ModelAPI_Data.h +++ b/src/ModelAPI/ModelAPI_Data.h @@ -91,6 +91,13 @@ class MODELAPI_EXPORT ModelAPI_Data { } + /// Makes feature must be updated later (on rebuild). Normally the Updater must call it + /// in case of not-automatic update to true + virtual void mustBeUpdated(const bool theFlag) = 0; + + /// Returns true if feature must be updated (re-executed) on rebuild + virtual bool mustBeUpdated() = 0; + protected: /// Objects are created for features automatically ModelAPI_Data() diff --git a/src/ModelAPI/ModelAPI_Document.h b/src/ModelAPI/ModelAPI_Document.h index cfd0eadf0..7f224da3e 100644 --- a/src/ModelAPI/ModelAPI_Document.h +++ b/src/ModelAPI/ModelAPI_Document.h @@ -55,7 +55,7 @@ public: //! \param theIndex zero-based index of feature in the group //! \param theHidden if it is true, it counts also the features that are not in tree virtual boost::shared_ptr - object(const std::string& theGroupID, const int theIndex, const bool theHidden = false) = 0; + object(const std::string& theGroupID, const int theIndex, const bool theHidden = false) = 0; //! Returns the number of objects in the group of objects //! If theHidden is true, it counts also the features that are not in tree diff --git a/src/ModelAPI/ModelAPI_Session.h b/src/ModelAPI/ModelAPI_Session.h index 54e807693..b5e4d5d3b 100644 --- a/src/ModelAPI/ModelAPI_Session.h +++ b/src/ModelAPI/ModelAPI_Session.h @@ -77,6 +77,9 @@ class MODELAPI_EXPORT ModelAPI_Session /// Defines the current document that used for current work in the application virtual void setActiveDocument(boost::shared_ptr theDoc) = 0; + /// Returns all the opened documents of the session (without postponed) + virtual std::list > allOpenedDocuments() = 0; + /// Copies the document to the new one with the given id virtual boost::shared_ptr copy(boost::shared_ptr theSource, std::string theID) = 0; diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 0f3fa139c..5ed671cc7 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -196,6 +196,7 @@ void XGUI_Workshop::initMenu() aCommand = aGroup->addFeature("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"), QIcon(":pictures/rebuild.png")); + aCommand->connectTo(this, SLOT(onRebuild())); aCommand = aGroup->addFeature("SAVEAS_CMD", tr("Save as..."), tr("Save the document into a file"), QIcon(":pictures/save.png")); @@ -750,6 +751,14 @@ void XGUI_Workshop::onRedo() updateCommandStatus(); } +//****************************************************** +void XGUI_Workshop::onRebuild() +{ + static const Events_ID aRebuildEvent = Events_Loop::loop()->eventByName("Rebuild"); + Events_Loop::loop()->send(boost::shared_ptr( + new Events_Message(aRebuildEvent, this))); +} + //****************************************************** void XGUI_Workshop::onPreferences() { diff --git a/src/XGUI/XGUI_Workshop.h b/src/XGUI/XGUI_Workshop.h index c2ca4a75c..dbb6cb60f 100644 --- a/src/XGUI/XGUI_Workshop.h +++ b/src/XGUI/XGUI_Workshop.h @@ -198,6 +198,7 @@ signals: void onExit(); void onUndo(); void onRedo(); + void onRebuild(); void onPreferences(); void showPropertyPanel(); -- 2.39.2