#include <TDF_ListIteratorOfLabelList.hxx>
#include <TDF_LabelMap.hxx>
#include <TDF_DeltaOnAddition.hxx>
+#include <TDataStd_UAttribute.hxx>
#include <TNaming_Builder.hxx>
#include <TNaming_SameShapeIterator.hxx>
#include <TNaming_Iterator.hxx>
// general sub-labels
/// where the reference to the current feature label is located (or no attribute if null feature)
static const int TAG_CURRENT_FEATURE = 1; ///< reference to the current feature
-static const int TAG_CURRENT_TRANSACTION = 2; ///< integer, index of the transaction
+/// integer, index of the transaction + GUID for auto recomutation blocking
+static const int TAG_CURRENT_TRANSACTION = 2;
static const int TAG_SELECTION_FEATURE = 3; ///< integer, tag of the selection feature label
static const int TAG_NODES_STATE = 4; ///< array, tag of the Object Browser nodes states
///< naming structures constructions selected from other document
subDoc(*aSubIter)->setExecuteFeatures(theFlag);
}
}
+
+void Model_Document::appendTransactionToPrevious()
+{
+ Transaction anAppended = myTransactions.back();
+ myTransactions.pop_back();
+ if (!myTransactions.empty()) { // if it is empty, just forget the appended
+ myTransactions.back().myOCAFNum += anAppended.myOCAFNum;
+ }
+ // propagate the same action to sub-documents
+ const std::set<int> aSubs = subDocuments();
+ for (std::set<int>::iterator aSubIter = aSubs.begin(); aSubIter != aSubs.end(); aSubIter++) {
+ subDoc(*aSubIter)->appendTransactionToPrevious();
+ }
+}
+
+/// GUID for keeping information about the auto-recomputation state
+static const Standard_GUID kAutoRecomputationID("8493fb74-0674-4912-a100-1cf46c7cfab3");
+
+void Model_Document::setAutoRecomutationState(const bool theState)
+{
+ if (theState)
+ generalLabel().FindChild(TAG_CURRENT_TRANSACTION).ForgetAttribute(kAutoRecomputationID);
+ else
+ TDataStd_UAttribute::Set(
+ generalLabel().FindChild(TAG_CURRENT_TRANSACTION), kAutoRecomputationID);
+}
+
+bool Model_Document::autoRecomutationState() const
+{
+ return !generalLabel().FindChild(TAG_CURRENT_TRANSACTION).IsAttribute(kAutoRecomputationID);
+}
/// returns true if theThis is later in the features trre and dependencies than theOther
bool isLaterByDep(FeaturePtr theThis, FeaturePtr theOther);
+ /// appends the latest transaction to the previous one (used for AutoUpdate enabling transaction)
+ void appendTransactionToPrevious();
+
+ /// Sets the automatic recomutation flag: true means enabled
+ void setAutoRecomutationState(const bool theState);
+ /// Returns the current automatic recomutation flag: true means enabled
+ bool autoRecomutationState() const;
+
friend class Model_Application;
friend class Model_Session;
friend class Model_Update;
myPluginsInfoLoaded = false;
myCheckTransactions = true;
myOperationAttachedToNext = false;
- myIsAutoUpdateBlocked = false;
ModelAPI_Session::setSession(std::shared_ptr<ModelAPI_Session>(this));
// register the configuration reading listener
Events_Loop* aLoop = Events_Loop::loop();
return ROOT_DOC->transactionID();
}
+bool Model_Session::isAutoUpdateBlocked()
+{
+ Handle(Model_Application) anApp = Model_Application::getApplication();
+ if (!anApp->hasRoot()) // when document is not yet created, do not create it by such simple call
+ return false;
+ return !ROOT_DOC->autoRecomutationState();
+}
+
void Model_Session::blockAutoUpdate(const bool theBlock)
{
- if (myIsAutoUpdateBlocked != theBlock) {
- myIsAutoUpdateBlocked = theBlock;
+ bool aCurrentState = isAutoUpdateBlocked();
+ if (aCurrentState != theBlock) {
+ // if there is no operation, start it to avoid modifications outside of transaction
+ bool isOperation = this->isOperation();
+ if (!isOperation)
+ startOperation("Auto update");
+ ROOT_DOC->setAutoRecomutationState(!theBlock);
static Events_Loop* aLoop = Events_Loop::loop();
if (theBlock) {
static const Events_ID kAutoOff = aLoop->eventByName(EVENT_AUTOMATIC_RECOMPUTATION_DISABLE);
std::shared_ptr<Events_Message> aMsg(new Events_Message(kAutoOff));
aLoop->send(aMsg);
} else {
+ // if there is no operation, start it to avoid modifications outside of transaction
+ bool isOperation = this->isOperation();
+ if (!isOperation)
+ startOperation("Auto update enabling");
static const Events_ID kAutoOn = aLoop->eventByName(EVENT_AUTOMATIC_RECOMPUTATION_ENABLE);
std::shared_ptr<Events_Message> aMsg(new Events_Message(kAutoOn));
aLoop->send(aMsg);
}
+ if (!isOperation) {
+ finishOperation();
+ // append this transaction to the previous one: ne don't need this separated operation in list
+ ROOT_DOC->appendTransactionToPrevious();
+ }
}
}
/// if true, generates error if document is updated outside of transaction
bool myCheckTransactions;
bool myOperationAttachedToNext; ///< the current operation must be committed twice, with nested
- bool myIsAutoUpdateBlocked; ///< the current state of the auto-update flag in the application
public:
//! Loads the OCAF document from the file.
/// Returns true if auto-update in the application is blocked
- MODEL_EXPORT virtual bool isAutoUpdateBlocked() const {
- return myIsAutoUpdateBlocked;
- }
+ MODEL_EXPORT virtual bool isAutoUpdateBlocked();
/// Set state of the auto-update of features result in the application
MODEL_EXPORT virtual void blockAutoUpdate(const bool theBlock);
virtual int transactionID() = 0;
/// Returns true if auto-update in the application is blocked
- virtual bool isAutoUpdateBlocked() const = 0;
+ virtual bool isAutoUpdateBlocked() = 0;
/// Set state of the auto-update of features result in the application
virtual void blockAutoUpdate(const bool theBlock) = 0;