From: nds Date: Wed, 26 Aug 2015 18:38:55 +0000 (+0300) Subject: Providing Action class to have a common approach to start/finish/abort model transact... X-Git-Tag: V_1.4.0_beta4~233 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=f0f8fbdcadad2d5d42c443e70afc6251faea1469;p=modules%2Fshaper.git Providing Action class to have a common approach to start/finish/abort model transactions for such actions as Delete/Detach and others. An action instance is used for Delete operation of sketch sub-entities. --- diff --git a/src/ModuleBase/ModuleBase_Operation.cpp b/src/ModuleBase/ModuleBase_Operation.cpp index 4d54780f9..009502dcb 100644 --- a/src/ModuleBase/ModuleBase_Operation.cpp +++ b/src/ModuleBase/ModuleBase_Operation.cpp @@ -50,6 +50,26 @@ ModuleBase_Operation::~ModuleBase_Operation() delete myDescription; } +const QStringList& ModuleBase_Operation::grantedOperationIds() const +{ + return myGrantedIds; +} + +void ModuleBase_Operation::setGrantedOperationIds(const QStringList& theList) +{ + myGrantedIds = theList; +} + +void ModuleBase_Operation::addGrantedOperationId(const QString& theId) +{ + myGrantedIds.append(theId); +} + +void ModuleBase_Operation::removeGrantedOperationId(const QString& theId) +{ + myGrantedIds.removeAll(theId); +} + QString ModuleBase_Operation::id() const { return getDescription()->operationId(); @@ -65,39 +85,14 @@ bool ModuleBase_Operation::canBeCommitted() const return isValid(); } - void ModuleBase_Operation::start() { myIsModified = false; - /* - QString anId = getDescription()->operationId(); - if (myIsEditing) { - anId = anId.append(EditSuffix()); - } - ModelAPI_Session::get()->startOperation(anId.toStdString()); - - if (!myIsEditing) { - FeaturePtr aFeature = createFeature(); - // if the feature is not created, there is no sense to start the operation - if (aFeature.get() == NULL) { - // it is necessary to abor the operation in the session and emit the aborted signal - // in order to update commands status in the workshop, to be exact the feature action - // to be unchecked - abort(); - return; - } - } - /// Set current feature and remeber old current feature - if (myIsEditing) { - SessionPtr aMgr = ModelAPI_Session::get(); - DocumentPtr aDoc = aMgr->activeDocument(); - myCurrentFeature = aDoc->currentFeature(true); - aDoc->setCurrentFeature(feature(), false); - } + + ModelAPI_Session::get()->startOperation(id().toStdString()); startOperation(); emit started(); -*/ } void ModuleBase_Operation::postpone() @@ -114,75 +109,29 @@ void ModuleBase_Operation::resume() void ModuleBase_Operation::abort() { -/* // the viewer update should be blocked in order to avoid the features blinking before they are // hidden - std::shared_ptr aMsg = std::shared_ptr( - new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED))); - Events_Loop::loop()->send(aMsg); - - // the widgets of property panel should not process any events come from data mode - // after abort clicked. Some signal such as redisplay/create influence on content - // of the object browser and viewer context. Therefore it influence to the current - // selection and if the active widget listens it, the attribute value is errnoneous - // changed. - if (myPropertyPanel) - myPropertyPanel->cleanContent(); - - SessionPtr aMgr = ModelAPI_Session::get(); - if (myIsEditing) { - DocumentPtr aDoc = aMgr->activeDocument(); - bool aIsOp = aMgr->isOperation(); - if (!aIsOp) - aMgr->startOperation(); - aDoc->setCurrentFeature(myCurrentFeature, true); - if (!aIsOp) - aMgr->finishOperation(); - myCurrentFeature = FeaturePtr(); - } - abortOperation(); + //std::shared_ptr aMsg = std::shared_ptr( + // new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED))); + //Events_Loop::loop()->send(aMsg); - stopOperation(); - // is is necessary to deactivate current widgets before the model operation is aborted - // because abort removes the feature and activated filters should not check it - propertyPanel()->cleanContent(); + ModelAPI_Session::get()->abortOperation(); - aMgr->abortOperation(); emit stopped(); // the viewer update should be unblocked in order to avoid the features blinking before they are // hidden - aMsg = std::shared_ptr( - new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED))); - - Events_Loop::loop()->send(aMsg); + //aMsg = std::shared_ptr( + // new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED))); + //Events_Loop::loop()->send(aMsg); emit aborted(); -*/ } bool ModuleBase_Operation::commit() { -/* if (canBeCommitted()) { - // the widgets of property panel should not process any events come from data mode - // after commit clicked. Some signal such as redisplay/create influence on content - // of the object browser and viewer context. Therefore it influence to the current - // selection and if the active widget listens it, the attribute value is errnoneous - // changed. - if (myPropertyPanel) - myPropertyPanel->cleanContent(); - + if (canBeCommitted()) { SessionPtr aMgr = ModelAPI_Session::get(); - /// Set current feature and remeber old current feature - if (myIsEditing) { - DocumentPtr aDoc = aMgr->activeDocument(); - bool aIsOp = aMgr->isOperation(); - if (!aIsOp) - aMgr->startOperation(); - aDoc->setCurrentFeature(myCurrentFeature, true); - if (!aIsOp) - aMgr->finishOperation(); - myCurrentFeature = FeaturePtr(); - } + commitOperation(); aMgr->finishOperation(); @@ -193,7 +142,6 @@ bool ModuleBase_Operation::commit() afterCommitOperation(); return true; } -*/ return false; } @@ -209,5 +157,5 @@ void ModuleBase_Operation::setPropertyPanel(ModuleBase_IPropertyPanel* theProp) bool ModuleBase_Operation::isGranted(QString theId) const { - return false; + return myGrantedIds.contains(theId); } diff --git a/src/ModuleBase/ModuleBase_Operation.h b/src/ModuleBase/ModuleBase_Operation.h index 09b625778..01a351d1d 100644 --- a/src/ModuleBase/ModuleBase_Operation.h +++ b/src/ModuleBase/ModuleBase_Operation.h @@ -56,6 +56,21 @@ Q_OBJECT /// /returns the instance of the description class ModuleBase_OperationDescription* getDescription() const { return myDescription; } + /// Returns list of granted operation indices + const QStringList& grantedOperationIds() const; + + /// Sets list of operation indices, which can be started without the current operation stop + /// \param theList an ids + void setGrantedOperationIds(const QStringList& theList); + + /// Appends an operation index to be granted + /// \param theId an index + void addGrantedOperationId(const QString& theId); + + /// Removes an operation index from the granted + /// \param theId an index + void removeGrantedOperationId(const QString& theId); + /// Must return true if this operation can be launched as nested for any current operation /// and it is not necessary to check this operation on validity. By default /// the operation is not granted. @@ -168,6 +183,9 @@ private: /// Modified feature flag bool myIsModified; + /// List of operations IDs which are granted of the current operation + QStringList myGrantedIds; + /// Access to property panel ModuleBase_IPropertyPanel* myPropertyPanel; }; diff --git a/src/ModuleBase/ModuleBase_OperationAction.cpp b/src/ModuleBase/ModuleBase_OperationAction.cpp index cabc64c79..19dda8a73 100755 --- a/src/ModuleBase/ModuleBase_OperationAction.cpp +++ b/src/ModuleBase/ModuleBase_OperationAction.cpp @@ -17,3 +17,11 @@ ModuleBase_OperationAction::ModuleBase_OperationAction(const QString& theId, QOb ModuleBase_OperationAction::~ModuleBase_OperationAction() { } + +bool ModuleBase_OperationAction::commit() +{ + // the action is supposed to perform a single modification, so the operation returns modified state + setIsModified(true); + + return ModuleBase_Operation::commit(); +} diff --git a/src/ModuleBase/ModuleBase_OperationAction.h b/src/ModuleBase/ModuleBase_OperationAction.h index 4667840b0..3e9c283a9 100755 --- a/src/ModuleBase/ModuleBase_OperationAction.h +++ b/src/ModuleBase/ModuleBase_OperationAction.h @@ -17,13 +17,11 @@ /*! * \class ModuleBase_OperationAction * \ingroup GUI - * \brief Base class for all operations + * \brief Base class for action operations * - * Base class for all operations. If you perform an action it is reasonable to create - * operation intended for this. This is a base class for all operations which provides - * mechanism for correct starting operations, starting operations above already started - * ones, committing operations and so on. To create own operation it is reasonable to - * inherit it from this class and redefines virtual methods to provide own behavior + * This is an action-like operation, which modifies the structure of data through + * starting/comitting transactions in the document. This operations are single stepped, + * and have no filled property panel, like Delete/Detach. */ class MODULEBASE_EXPORT ModuleBase_OperationAction : public ModuleBase_Operation @@ -31,13 +29,17 @@ class MODULEBASE_EXPORT ModuleBase_OperationAction : public ModuleBase_Operation Q_OBJECT public: - /// Constructor /// \param theId the operation identifier /// \param theParent the QObject parent ModuleBase_OperationAction(const QString& theId = "", QObject* theParent = 0); /// Destructor virtual ~ModuleBase_OperationAction(); + + public slots: + /// Commits the operation. Change is modified state to true value. + /// \return the result of commit + virtual bool commit(); }; #endif diff --git a/src/ModuleBase/ModuleBase_OperationFeature.cpp b/src/ModuleBase/ModuleBase_OperationFeature.cpp index ff49f7145..2c00e3543 100755 --- a/src/ModuleBase/ModuleBase_OperationFeature.cpp +++ b/src/ModuleBase/ModuleBase_OperationFeature.cpp @@ -348,8 +348,3 @@ void ModuleBase_OperationFeature::setPropertyPanel(ModuleBase_IPropertyPanel* th theProp->activateNextWidget(NULL); } } - -bool ModuleBase_OperationFeature::isGranted(QString theId) const -{ - return myNestedFeatures.contains(theId); -} diff --git a/src/ModuleBase/ModuleBase_OperationFeature.h b/src/ModuleBase/ModuleBase_OperationFeature.h index cc937e1a4..dedbb6a16 100755 --- a/src/ModuleBase/ModuleBase_OperationFeature.h +++ b/src/ModuleBase/ModuleBase_OperationFeature.h @@ -58,31 +58,15 @@ Q_OBJECT /// Destructor virtual ~ModuleBase_OperationFeature(); - /** - * Must return true if this operation can be launched as nested for any current operation - * and it is not necessary to check this operation on validity. By default - * the operation is not granted. - * The method has to be redefined for granted operations. - */ - virtual bool isGranted(QString theId) const; - /// Returns True id the current operation is launched in editing mode bool isEditOperation() const { return myIsEditing; } - /// Returns list of nested features - QStringList nestedFeatures() const { return myNestedFeatures; } - - /// Sets list of nested features - void setNestedFeatures(const QStringList& theList) { myNestedFeatures = theList; } - /// Returns the operation feature /// \return the feature FeaturePtr feature() const; - /** - * Must return True if the operation's feature is valid. - * Since IOperation does not have any feature returns false. - */ + /// Must return True if the operation's feature is valid. + /// Since IOperation does not have any feature returns false. virtual bool isValid() const; /// Sets the operation feature @@ -154,9 +138,6 @@ signals: /// Editing feature flag bool myIsEditing; - /// List of nested operations IDs - QStringList myNestedFeatures; - /// List of pre-selected object QList myPreSelection; diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 54b88f25d..23741dfbd 100755 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -621,23 +622,26 @@ bool PartSet_Module::deleteObjects() if (aSketchObjects.size() == 0) return true; - // the active nested sketch operation should be aborted unconditionally - if (isNestedOp) - anOperation->abort(); - // 3. start operation QString aDescription = aWorkshop->contextMenuMgr()->action("DELETE_CMD")->text(); - aMgr->startOperation(aDescription.toStdString()); + ModuleBase_OperationAction* anAction = new ModuleBase_OperationAction(aDescription, this); + XGUI_OperationMgr* anOpMgr = aConnector->workshop()->operationMgr(); + // the active nested sketch operation should be aborted unconditionally + if (isSketchOp) + anOperation->addGrantedOperationId(anAction->id()); + if (!anOpMgr->canStartOperation(anAction->id())) + return true; // the objects are processed but can not be deleted + if (isSketchOp) + anOperation->removeGrantedOperationId(anAction->id()); + + anOpMgr->startOperation(anAction); // 4. delete features // sketch feature should be skipped, only sub-features can be removed // when sketch operation is active aWorkshop->deleteFeatures(aSketchObjects); // 5. stop operation - aWorkshop->displayer()->updateViewer(); - aMgr->finishOperation(); - XGUI_OperationMgr* anOpMgr = aConnector->workshop()->operationMgr(); - anOpMgr->updateApplyOfOperations(); + anOpMgr->commitOperation(); } else { bool isPartRemoved = false; // Delete part with help of PartSet plugin diff --git a/src/XGUI/XGUI_ActionsMgr.cpp b/src/XGUI/XGUI_ActionsMgr.cpp index 542e1b5e4..32f7e4af5 100644 --- a/src/XGUI/XGUI_ActionsMgr.cpp +++ b/src/XGUI/XGUI_ActionsMgr.cpp @@ -271,7 +271,7 @@ QAction* XGUI_ActionsMgr::operationStateAction(OperationStateActionId theId, QOb QAction* XGUI_ActionsMgr::action(const QString& theId) { - QAction* anAction; + QAction* anAction = 0; if(myActions.contains(theId)) { anAction = myActions.value(theId); } diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp index 52826dc65..259d3411d 100644 --- a/src/XGUI/XGUI_OperationMgr.cpp +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -117,9 +117,11 @@ bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation) connect(theOperation, SIGNAL(committed()), SLOT(onOperationCommitted())); connect(theOperation, SIGNAL(stopped()), SLOT(onOperationStopped())); connect(theOperation, SIGNAL(resumed()), SLOT(onOperationResumed())); - connect(theOperation, SIGNAL(triggered(bool)), SLOT(onOperationTriggered(bool))); - connect(theOperation, SIGNAL(activatedByPreselection()), - SIGNAL(operationActivatedByPreselection())); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + if (aFOperation) + connect(aFOperation, SIGNAL(activatedByPreselection()), + SIGNAL(operationActivatedByPreselection())); theOperation->start(); onValidateOperation(); @@ -273,7 +275,7 @@ bool XGUI_OperationMgr::canStartOperation(QString theId) if (aCurrentOp) { if (!aCurrentOp->isGranted(theId)) { if (canStopOperation()) { - if (myIsApplyEnabled) + if (myIsApplyEnabled && aCurrentOp->isModified()) aCurrentOp->commit(); else abortOperation(aCurrentOp); diff --git a/src/XGUI/XGUI_OperationMgr.h b/src/XGUI/XGUI_OperationMgr.h index 4c4514981..48b6a7ea2 100644 --- a/src/XGUI/XGUI_OperationMgr.h +++ b/src/XGUI/XGUI_OperationMgr.h @@ -159,10 +159,10 @@ public: // TEMPORARY, it should be protected and be performed automatically /// \param theOperation the sent operation. If it is NULL, all operations in the stack are sent. void updateApplyOfOperations(ModuleBase_Operation* theOperation = 0); -protected: // TEMPORARY /// Commits the current operatin if it is valid bool commitOperation(); +protected: // TEMPORARY /// Sets the current operation or NULL /// \param theOperation the started operation void resumeOperation(ModuleBase_Operation* theOperation); diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index fc0a66630..facd2e428 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -480,10 +480,10 @@ void XGUI_Workshop::setNestedFeatures(ModuleBase_Operation* theOperation) if (!aFOperation) return; - if (isSalomeMode()) - aFOperation->setNestedFeatures(mySalomeConnector->nestedActions(theOperation->id())); + if (isSalomeMode()) + aFOperation->setGrantedOperationIds(mySalomeConnector->nestedActions(theOperation->id())); else - aFOperation->setNestedFeatures(myActionsMgr->nestedCommands(theOperation->id())); + aFOperation->setGrantedOperationIds(myActionsMgr->nestedCommands(theOperation->id())); } void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) diff --git a/src/XGUI/XGUI_WorkshopListener.cpp b/src/XGUI/XGUI_WorkshopListener.cpp index be913ac98..fcc927c3e 100755 --- a/src/XGUI/XGUI_WorkshopListener.cpp +++ b/src/XGUI/XGUI_WorkshopListener.cpp @@ -65,6 +65,9 @@ XGUI_WorkshopListener::XGUI_WorkshopListener(ModuleBase_IWorkshop* theWorkshop) : myWorkshop(theWorkshop), myUpdatePrefs(false) { + XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr(); + connect(anOperationMgr, SIGNAL(nestedStateChanged(const std::string&, const bool)), + this, SLOT(onNestedStateChanged(const std::string&, const bool))); } //****************************************************** @@ -378,7 +381,8 @@ void XGUI_WorkshopListener::onNestedStateChanged(const std::string& theFeatureId anAcceptAllAction->setEnabled(theState); } else { AppElements_MainMenu* aMenuBar = aWorkshop->mainWindow()->menuObject(); - if (aMenuBar->feature(theFeatureId.c_str())->button()->additionalButtonWidget()) + AppElements_Command* aCommand = aMenuBar->feature(theFeatureId.c_str()); + if (aCommand && aCommand->button()->additionalButtonWidget()) anAcceptAllAction->setEnabled(theState); } } @@ -475,9 +479,6 @@ void XGUI_WorkshopListener::addFeature(const std::shared_ptractionsMgr()->addCommand(aCommand); aWorkshop->module()->actionCreated(aCommand); } - XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr(); - connect(anOperationMgr, SIGNAL(nestedStateChanged(const std::string&, const bool)), - this, SLOT(onNestedStateChanged(const std::string&, const bool))); }