From 2eeb7eb916ca36bb522a2c65011d2bb8b0894fbc Mon Sep 17 00:00:00 2001 From: nds Date: Wed, 23 Apr 2014 16:14:07 +0400 Subject: [PATCH] refs #30 - Sketch base GUI: create, draw lines Creation of the operation manager to provide the operations stack. --- src/Model/Model_PluginManager.cpp | 4 +- src/ModuleBase/ModuleBase_Operation.cpp | 10 +++ src/ModuleBase/ModuleBase_Operation.h | 2 + src/PartSet/PartSet_Module.cpp | 50 +++++++++-- src/PartSet/PartSet_Module.h | 4 +- src/PartSet/PartSet_OperationSketch.cpp | 9 ++ src/PartSet/PartSet_OperationSketch.h | 2 + src/PartSet/PartSet_OperationSketchBase.cpp | 12 ++- src/PartSet/PartSet_OperationSketchBase.h | 7 +- src/XGUI/CMakeLists.txt | 3 + src/XGUI/XGUI_Displayer.cpp | 12 +++ src/XGUI/XGUI_Displayer.h | 2 + src/XGUI/XGUI_Module.h | 2 +- src/XGUI/XGUI_OperationMgr.cpp | 99 +++++++++++++++++++++ src/XGUI/XGUI_OperationMgr.h | 43 +++++++++ src/XGUI/XGUI_Workshop.cpp | 87 +++++++++++++----- src/XGUI/XGUI_Workshop.h | 15 ++-- 17 files changed, 320 insertions(+), 43 deletions(-) create mode 100644 src/XGUI/XGUI_OperationMgr.cpp create mode 100644 src/XGUI/XGUI_OperationMgr.h diff --git a/src/Model/Model_PluginManager.cpp b/src/Model/Model_PluginManager.cpp index eb279208a..75cc0430c 100644 --- a/src/Model/Model_PluginManager.cpp +++ b/src/Model/Model_PluginManager.cpp @@ -22,9 +22,9 @@ shared_ptr Model_PluginManager::createFeature(string theFeatur LoadPluginsInfo(); if (myPlugins.find(theFeatureID) != myPlugins.end()) { - if (myPluginObjs.find(myPlugins[theFeatureID]) == myPluginObjs.end()) { + myCurrentPluginName = myPlugins[theFeatureID]; + if (myPluginObjs.find(myCurrentPluginName) == myPluginObjs.end()) { // load plugin library if not yet done - myCurrentPluginName = myPlugins[theFeatureID]; loadLibrary(myCurrentPluginName); } if (myPluginObjs.find(myCurrentPluginName) != myPluginObjs.end()) { diff --git a/src/ModuleBase/ModuleBase_Operation.cpp b/src/ModuleBase/ModuleBase_Operation.cpp index e2e6891c4..672eb23f5 100644 --- a/src/ModuleBase/ModuleBase_Operation.cpp +++ b/src/ModuleBase/ModuleBase_Operation.cpp @@ -54,6 +54,16 @@ QString ModuleBase_Operation::operationId() const return myOperationId; } +/*! + * \brief Replied whether the operation should be commited after the start, or the operation itself + * do that. The default realization provides the check by the operation having the xml prepresentation + * @return the boolean value + */ +bool ModuleBase_Operation::isPerformedImmediately() const +{ + return xmlRepresentation().isEmpty(); +} + std::shared_ptr ModuleBase_Operation::feature() const { return myFeature; diff --git a/src/ModuleBase/ModuleBase_Operation.h b/src/ModuleBase/ModuleBase_Operation.h index a3c0c40c1..8d2390831 100644 --- a/src/ModuleBase/ModuleBase_Operation.h +++ b/src/ModuleBase/ModuleBase_Operation.h @@ -76,6 +76,8 @@ public: // Operation processing. virtual QString operationId() const; + virtual bool isPerformedImmediately() const; + std::shared_ptr feature() const; OperationState state() const; diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 7a32a90bb..bd136d50e 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -5,6 +5,9 @@ #include #include +#include +#include +#include #include #include @@ -29,6 +32,9 @@ extern "C" PARTSET_EXPORT XGUI_Module* createModule(XGUI_Workshop* theWshop) PartSet_Module::PartSet_Module(XGUI_Workshop* theWshop) { myWorkshop = theWshop; + XGUI_OperationMgr* anOperationMgr = myWorkshop->operationMgr(); + + connect(anOperationMgr, SIGNAL(beforeOperationStart()), this, SLOT(onBeforeOperationStart())); } PartSet_Module::~PartSet_Module() @@ -70,19 +76,19 @@ void PartSet_Module::onFeatureTriggered() else aPartSetOp = new ModuleBase_PropPanelOperation(aCmdId, this); - PartSet_OperationSketchBase* aPreviewOp = dynamic_cast(aPartSetOp); - if (aPreviewOp) - connect(aPreviewOp, SIGNAL(visualizePreview()), this, SLOT(onVisualizePreview())); - aPartSetOp->setXmlRepresentation(QString::fromStdString(aXmlCfg)); aPartSetOp->setDescription(QString::fromStdString(aDescription)); aMessage.setPointer(aPartSetOp); Event_Loop::loop()->send(aMessage); } -void PartSet_Module::onVisualizePreview() +/** + * Slot that is called by the operation requiring of preview display or erase + * \param isDisplay the display or erase state +*/ +void PartSet_Module::onVisualizePreview(bool isDisplay) { - ModuleBase_Operation* anOperation = myWorkshop->currentOperation(); + ModuleBase_Operation* anOperation = myWorkshop->operationMgr()->currentOperation(); if (!anOperation) return; @@ -90,5 +96,35 @@ void PartSet_Module::onVisualizePreview() if (!aPreviewOp) return; - myWorkshop->displayer()->Display(anOperation->feature(), aPreviewOp->preview()); + if (isDisplay) + myWorkshop->displayer()->Display(anOperation->feature(), aPreviewOp->preview()); + else + myWorkshop->displayer()->Erase(anOperation->feature(), aPreviewOp->preview()); +} + +void PartSet_Module::onBeforeOperationStart() +{ + ModuleBase_Operation* anOperation = myWorkshop->operationMgr()->currentOperation(); + + PartSet_OperationSketchBase* aPreviewOp = dynamic_cast(anOperation); + if (aPreviewOp) { + connect(anOperation, SIGNAL(stopped()), this, SLOT(onOperationStopped())); + connect(aPreviewOp, SIGNAL(visualizePreview(bool)), this, SLOT(onVisualizePreview(bool))); + connect(myWorkshop->mainWindow()->viewer(), SIGNAL(selectionChanged()), + aPreviewOp, SLOT(onViewSelectionChanged())); + } +} + +void PartSet_Module::onOperationStopped() +{ + ModuleBase_PropPanelOperation* anOperation = dynamic_cast(sender()); + if (!anOperation) + return; + + PartSet_OperationSketchBase* aPreviewOp = dynamic_cast(anOperation); + if (aPreviewOp) { + disconnect(aPreviewOp, SIGNAL(visualizePreview(bool)), this, SLOT(onVisualizePreview(bool))); + disconnect(myWorkshop->mainWindow()->viewer(), SIGNAL(selectionChanged()), + aPreviewOp, SLOT(onViewSelectionChanged())); + } } diff --git a/src/PartSet/PartSet_Module.h b/src/PartSet/PartSet_Module.h index b33d2ad7d..7530c2300 100644 --- a/src/PartSet/PartSet_Module.h +++ b/src/PartSet/PartSet_Module.h @@ -20,7 +20,9 @@ public: public slots: void onFeatureTriggered(); - void onVisualizePreview(); + void onBeforeOperationStart(); + void onOperationStopped(); + void onVisualizePreview(bool isDisplay); private: XGUI_Workshop* myWorkshop; diff --git a/src/PartSet/PartSet_OperationSketch.cpp b/src/PartSet/PartSet_OperationSketch.cpp index b5aa18747..3b4e5bd8d 100644 --- a/src/PartSet/PartSet_OperationSketch.cpp +++ b/src/PartSet/PartSet_OperationSketch.cpp @@ -20,3 +20,12 @@ PartSet_OperationSketch::PartSet_OperationSketch(const QString& theId, PartSet_OperationSketch::~PartSet_OperationSketch() { } + +/** + * The sketch can not be created immediately, firstly a plane should be set + * \return false value + */ +bool PartSet_OperationSketch::isPerformedImmediately() const +{ + return false; +} diff --git a/src/PartSet/PartSet_OperationSketch.h b/src/PartSet/PartSet_OperationSketch.h index 99cacfbb6..679f74afa 100644 --- a/src/PartSet/PartSet_OperationSketch.h +++ b/src/PartSet/PartSet_OperationSketch.h @@ -18,6 +18,8 @@ Q_OBJECT public: PartSet_OperationSketch(const QString& theId, QObject* theParent); virtual ~PartSet_OperationSketch(); + + virtual bool isPerformedImmediately() const; }; #endif diff --git a/src/PartSet/PartSet_OperationSketchBase.cpp b/src/PartSet/PartSet_OperationSketchBase.cpp index 0201255b8..9b34aa2eb 100644 --- a/src/PartSet/PartSet_OperationSketchBase.cpp +++ b/src/PartSet/PartSet_OperationSketchBase.cpp @@ -42,5 +42,15 @@ void PartSet_OperationSketchBase::startOperation() { ModuleBase_PropPanelOperation::startOperation(); - emit visualizePreview(); + emit visualizePreview(true); +} + +/*! + * Perform the operation stop and emit signal about visualization stop of the operation preview + */ +void PartSet_OperationSketchBase::stopOperation() +{ + ModuleBase_PropPanelOperation::stopOperation(); + + emit visualizePreview(false); } diff --git a/src/PartSet/PartSet_OperationSketchBase.h b/src/PartSet/PartSet_OperationSketchBase.h index ceb880264..de7c1ce03 100644 --- a/src/PartSet/PartSet_OperationSketchBase.h +++ b/src/PartSet/PartSet_OperationSketchBase.h @@ -24,10 +24,15 @@ public: const TopoDS_Shape& preview() const; signals: - void visualizePreview(); + /** + * The signal about preview visualization. + * \param isDisplay a state whether the preview should be displayed or erased + */ + void visualizePreview(bool isDisplay); protected: virtual void startOperation(); + virtual void stopOperation(); }; #endif diff --git a/src/XGUI/CMakeLists.txt b/src/XGUI/CMakeLists.txt index 309498380..becc47ee3 100644 --- a/src/XGUI/CMakeLists.txt +++ b/src/XGUI/CMakeLists.txt @@ -9,6 +9,7 @@ SET(PROJECT_HEADERS XGUI_MainMenu.h XGUI_MainWindow.h XGUI_MenuGroupPanel.h + XGUI_Module.h XGUI_Tools.h XGUI_Workbench.h XGUI_Workshop.h @@ -22,6 +23,7 @@ SET(PROJECT_HEADERS XGUI_DocumentDataModel.h XGUI_PartDataModel.h XGUI_ObjectsBrowser.h + XGUI_OperationMgr.h XGUI_DataTreeModel.h XGUI_SelectionMgr.h XGUI_SwitchWidget.h @@ -49,6 +51,7 @@ SET(PROJECT_SOURCES XGUI_DocumentDataModel.cpp XGUI_PartDataModel.cpp XGUI_ObjectsBrowser.cpp + XGUI_OperationMgr.cpp XGUI_SelectionMgr.cpp XGUI_SwitchWidget.cpp ) diff --git a/src/XGUI/XGUI_Displayer.cpp b/src/XGUI/XGUI_Displayer.cpp index 1df329170..79abb676f 100644 --- a/src/XGUI/XGUI_Displayer.cpp +++ b/src/XGUI/XGUI_Displayer.cpp @@ -45,3 +45,15 @@ void XGUI_Displayer::Display(std::shared_ptr theFeature, aContext->UpdateCurrentViewer(); } + +/*! + * Erase the feature and a shape. + * \param theFeature a feature instance + * \param theFeature a shape + */ +void XGUI_Displayer::Erase(std::shared_ptr theFeature, + const TopoDS_Shape& theShape) +{ + Handle(AIS_InteractiveContext) aContext = myViewer->AISContext(); + aContext->EraseAll(); +} diff --git a/src/XGUI/XGUI_Displayer.h b/src/XGUI/XGUI_Displayer.h index cf5dbbbd9..4c5333f45 100644 --- a/src/XGUI/XGUI_Displayer.h +++ b/src/XGUI/XGUI_Displayer.h @@ -24,6 +24,8 @@ public: void Display(std::shared_ptr theFeature, const TopoDS_Shape& theShape); + void Erase(std::shared_ptr theFeature, const TopoDS_Shape& theShape); + protected: XGUI_Viewer* myViewer; ///< the viewer }; diff --git a/src/XGUI/XGUI_Module.h b/src/XGUI/XGUI_Module.h index 374e057ea..347cc061a 100644 --- a/src/XGUI/XGUI_Module.h +++ b/src/XGUI/XGUI_Module.h @@ -22,4 +22,4 @@ typedef XGUI_Module* (*CREATE_FUNC)(XGUI_Workshop*); #define CREATE_MODULE "createModule" -#endif //XGUI_Module \ No newline at end of file +#endif //XGUI_Module diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp new file mode 100644 index 000000000..ae5aeb047 --- /dev/null +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -0,0 +1,99 @@ +#include "XGUI_OperationMgr.h" + +#include "ModuleBase_Operation.h" + +#include + +/*! + \brief Constructor + */ +XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent) +: QObject(theParent) +{ +} + +/*! + \brief Destructor + */ +XGUI_OperationMgr::~XGUI_OperationMgr() +{ +} + +/*! + \brief Returns the current operation or NULL + * \return the current operation + */ +ModuleBase_Operation* XGUI_OperationMgr::currentOperation() const +{ + return myOperations.count() > 0 ? myOperations.last() : 0; +} + +/*! + \brief Sets the current operation or NULL + * \return the current operation + */ +bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation) +{ + if (!canStartOperation(theOperation)) + return false; + + myOperations.append(theOperation); + emit beforeOperationStart(); + + connect(theOperation, SIGNAL(stopped()), this, SLOT(onOperationStopped())); + theOperation->start(); + + emit afterOperationStart(); + return true; +} + +bool XGUI_OperationMgr::canStartOperation(ModuleBase_Operation* theOperation) +{ + bool aCanStart = true; + ModuleBase_Operation* aCurrentOp = currentOperation(); + if (aCurrentOp && !theOperation->isGranted()) + { + int anAnswer = QMessageBox::question(0, tr("Operation launch"), + tr("Previous operation is not finished and will be aborted"), + QMessageBox::Ok, QMessageBox::Cancel); + if (anAnswer == QMessageBox::Ok) + aCurrentOp->abort(); + else + aCanStart = false; + } + return aCanStart; +} + +void XGUI_OperationMgr::commitCurrentOperation() +{ + ModuleBase_Operation* anOperation = currentOperation(); + if (!anOperation) + return; + + anOperation->commit(); +} + +void XGUI_OperationMgr::onOperationStopped() +{ + ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); + ModuleBase_Operation* anOperation = currentOperation(); + if (!aSenderOperation || !anOperation || aSenderOperation != anOperation ) + return; + + myOperations.removeAll(anOperation); + + // get last operation which can be resumed + ModuleBase_Operation* aResultOp = 0; + QListIterator anIt(myOperations); + anIt.toBack(); + while(anIt.hasPrevious()) + { + ModuleBase_Operation* anOp = anIt.previous(); + if (anOp) { + aResultOp = anOp; + break; + } + } + if (aResultOp) + startOperation(aResultOp); +} diff --git a/src/XGUI/XGUI_OperationMgr.h b/src/XGUI/XGUI_OperationMgr.h new file mode 100644 index 000000000..4fabac821 --- /dev/null +++ b/src/XGUI/XGUI_OperationMgr.h @@ -0,0 +1,43 @@ +#ifndef XGUI_OperationMgr_H +#define XGUI_OperationMgr_H + +#include "XGUI.h" + +#include + +#include +#include + +/**\class XGUI_OperationMgr + * \ingroup GUI + * \brief Operation manager. Servers to manupulate to the workshop operations. Contains a stack + * of started operations and uses the upper one as a current. + */ +class XGUI_EXPORT XGUI_OperationMgr : public QObject +{ + Q_OBJECT +public: + XGUI_OperationMgr(QObject* theParent); + virtual ~XGUI_OperationMgr(); + + ModuleBase_Operation* currentOperation() const; + bool startOperation(ModuleBase_Operation* theOperation); + + void commitCurrentOperation(); + +signals: + void beforeOperationStart(); + void afterOperationStart(); + +protected: + bool canStartOperation(ModuleBase_Operation* theOperation); + +protected slots: + void onOperationStopped(); + +private: + typedef QList Operations; + Operations myOperations; +}; + +#endif diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 891172028..f639e1adc 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -12,6 +12,7 @@ #include "XGUI_SelectionMgr.h" #include "XGUI_ObjectsBrowser.h" #include "XGUI_Displayer.h" +#include "XGUI_OperationMgr.h" #include #include @@ -43,12 +44,14 @@ XGUI_Workshop::XGUI_Workshop() : QObject(), - myCurrentOperation(NULL), myPartSetModule(NULL) { myMainWindow = new XGUI_MainWindow(); mySelector = new XGUI_SelectionMgr(this); myDisplayer = new XGUI_Displayer(myMainWindow->viewer()); + myOperationMgr = new XGUI_OperationMgr(this); + connect(myOperationMgr, SIGNAL(beforeOperationStart()), this, SLOT(onBeforeOperationStart())); + connect(myOperationMgr, SIGNAL(afterOperationStart()), this, SLOT(onAfterOperationStart())); } //****************************************************** @@ -150,15 +153,36 @@ void XGUI_Workshop::processEvent(const Event_Message* theMessage) const Config_PointerMessage* aPartSetMsg = dynamic_cast(theMessage); if (aPartSetMsg) { - ModuleBase_PropPanelOperation* aOperation = + ModuleBase_PropPanelOperation* anOperation = (ModuleBase_PropPanelOperation*)(aPartSetMsg->pointer()); - setCurrentOperation(aOperation); - if(aOperation->xmlRepresentation().isEmpty()) { //!< No need for property panel - myCurrentOperation->start(); - myCurrentOperation->commit(); - updateCommandStatus(); - } else { - fillPropertyPanel(aOperation); + + if (myOperationMgr->startOperation(anOperation)) + { + if (anOperation->isPerformedImmediately()) + { + myOperationMgr->commitCurrentOperation(); + updateCommandStatus(); + } + /*if(anOperation->xmlRepresentation().isEmpty()) { //!< No need for property panel + //connectToPropertyPanel(anOperation); + + anOperation->start(); + + if (anOperation->isPerformedImmediately()) { + anOperation->commit(); + updateCommandStatus(); + } + } else { + connectToPropertyPanel(anOperation); + QWidget* aPropWidget = myMainWindow->findChild(XGUI::PROP_PANEL_WDG); + qDeleteAll(aPropWidget->children()); + + anOperation->start(); + + XGUI_WidgetFactory aFactory = XGUI_WidgetFactory(anOperation); + aFactory.createWidget(aPropWidget); + myMainWindow->setPropertyPannelTitle(anOperation->description()); + }*/ } return; } @@ -170,6 +194,34 @@ void XGUI_Workshop::processEvent(const Event_Message* theMessage) } +void XGUI_Workshop::onBeforeOperationStart() +{ + ModuleBase_PropPanelOperation* aOperation = + (ModuleBase_PropPanelOperation*)(myOperationMgr->currentOperation()); + + if(aOperation->xmlRepresentation().isEmpty()) { //!< No need for property panel + //myPartSetModule->connectToPropertyPanel(aOperation); + } else { + connectToPropertyPanel(aOperation); + QWidget* aPropWidget = myMainWindow->findChild(XGUI::PROP_PANEL_WDG); + qDeleteAll(aPropWidget->children()); + } +} + +void XGUI_Workshop::onAfterOperationStart() +{ + ModuleBase_PropPanelOperation* aOperation = + (ModuleBase_PropPanelOperation*)(myOperationMgr->currentOperation()); + + if(aOperation->xmlRepresentation().isEmpty()) { //!< No need for property panel + } else { + XGUI_WidgetFactory aFactory = XGUI_WidgetFactory(aOperation); + QWidget* aPropWidget = myMainWindow->findChild(XGUI::PROP_PANEL_WDG); + aFactory.createWidget(aPropWidget); + myMainWindow->setPropertyPannelTitle(aOperation->description()); + } +} + /* * */ @@ -208,7 +260,7 @@ void XGUI_Workshop::addFeature(const Config_FeatureMessage* theMessage) /* * */ -void XGUI_Workshop::fillPropertyPanel(ModuleBase_PropPanelOperation* theOperation) +/*void XGUI_Workshop::fillPropertyPanel(ModuleBase_PropPanelOperation* theOperation) { connectToPropertyPanel(theOperation); QWidget* aPropWidget = myMainWindow->findChild(XGUI::PROP_PANEL_WDG); @@ -217,20 +269,7 @@ void XGUI_Workshop::fillPropertyPanel(ModuleBase_PropPanelOperation* theOperatio XGUI_WidgetFactory aFactory = XGUI_WidgetFactory(theOperation); aFactory.createWidget(aPropWidget); myMainWindow->setPropertyPannelTitle(theOperation->description()); -} - -void XGUI_Workshop::setCurrentOperation(ModuleBase_Operation* theOperation) -{ - //FIXME: Ask user about aborting of current operation? - if (myCurrentOperation) { - //TODO get isOperation from document - if (myCurrentOperation->isRunning()) - myCurrentOperation->abort(); - - myCurrentOperation->deleteLater(); - } - myCurrentOperation = theOperation; -} +}*/ /* * Makes a signal/slot connections between Property Panel diff --git a/src/XGUI/XGUI_Workshop.h b/src/XGUI/XGUI_Workshop.h index 50e0a44cc..4f62bf452 100644 --- a/src/XGUI/XGUI_Workshop.h +++ b/src/XGUI/XGUI_Workshop.h @@ -15,6 +15,7 @@ class XGUI_Module; class XGUI_Workbench; class XGUI_SelectionMgr; class XGUI_Displayer; +class XGUI_OperationMgr; class ModuleBase_Operation; class ModuleBase_PropPanelOperation; @@ -48,12 +49,12 @@ public: //! Returns displayer XGUI_Displayer* displayer() const { return myDisplayer; } + //! ! Returns operation manager. + XGUI_OperationMgr* operationMgr() const { return myOperationMgr; } + //! Creates and adds a new workbench (menu group) with the given name and returns it XGUI_Workbench* addWorkbench(const QString& theName); - //! Returns the current operation or NULL - ModuleBase_Operation* currentOperation() { return myCurrentOperation; } - //! Redefinition of Event_Listener method virtual void processEvent(const Event_Message* theMessage); @@ -71,9 +72,11 @@ public slots: protected: //Event-loop processing methods: void addFeature(const Config_FeatureMessage*); - void fillPropertyPanel(ModuleBase_PropPanelOperation* theOperation); void connectToPropertyPanel(ModuleBase_Operation* theOperation); - void setCurrentOperation(ModuleBase_Operation* theOperation); + +protected slots: + void onBeforeOperationStart(); + void onAfterOperationStart(); private: void initMenu(); @@ -87,7 +90,7 @@ private: XGUI_SelectionMgr* mySelector; XGUI_Displayer* myDisplayer; - ModuleBase_Operation* myCurrentOperation; + XGUI_OperationMgr* myOperationMgr; }; #endif -- 2.39.2