From: nds Date: Mon, 29 Jun 2015 06:18:52 +0000 (+0300) Subject: Separation of Workshop and events listener in order to make XGUI_Workshop is a child... X-Git-Tag: V_1.3.0~174 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=e688b089a4eab3d48ed762e18f9761da01bbaf81;p=modules%2Fshaper.git Separation of Workshop and events listener in order to make XGUI_Workshop is a child of ModuleBase_IWorkshop. --- diff --git a/src/XGUI/CMakeLists.txt b/src/XGUI/CMakeLists.txt index d570650ef..4da2ebeda 100644 --- a/src/XGUI/CMakeLists.txt +++ b/src/XGUI/CMakeLists.txt @@ -22,6 +22,7 @@ SET(PROJECT_HEADERS XGUI_Tools.h XGUI_ViewerProxy.h XGUI_Workshop.h + XGUI_WorkshopListener.h XGUI_HistoryMenu.h ) @@ -46,6 +47,7 @@ SET(PROJECT_SOURCES XGUI_Tools.cpp XGUI_ViewerProxy.cpp XGUI_Workshop.cpp + XGUI_WorkshopListener.cpp XGUI_HistoryMenu.cpp ) diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 0f6cd8c77..e0ca916c5 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -16,6 +16,8 @@ #include "XGUI_PropertyPanel.h" #include "XGUI_ContextMenuMgr.h" #include "XGUI_ModuleConnector.h" +#include "XGUI_WorkshopListener.h" + #include #include #include @@ -50,7 +52,6 @@ #include #include -#include #include #include #include @@ -95,8 +96,6 @@ #include #endif -//#define DEBUG_FEATURE_CREATED -//#define DEBUG_FEATURE_REDISPLAY //#define DEBUG_DELETE XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) @@ -107,9 +106,7 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) myPropertyPanel(0), myObjectBrowser(0), myDisplayer(0), - myUpdatePrefs(false), - myPartActivating(false), - myIsLoadingData(false) + myIsLoadingData(false) { myMainWindow = mySalomeConnector ? 0 : new AppElements_MainWindow(); @@ -139,7 +136,11 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) myActionsMgr, SLOT(updateOnViewSelection())); myModuleConnector = new XGUI_ModuleConnector(this); - myOperationMgr->setWorkshop(moduleConnector()); + + ModuleBase_IWorkshop* aWorkshop = moduleConnector(); + myOperationMgr->setWorkshop(aWorkshop); + + myEventsListener = new XGUI_WorkshopListener(aWorkshop); connect(myOperationMgr, SIGNAL(operationStarted(ModuleBase_Operation*)), SLOT(onOperationStarted(ModuleBase_Operation*))); @@ -154,6 +155,8 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) if (myMainWindow) connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit())); connect(this, SIGNAL(errorOccurred(const QString&)), myErrorDlg, SLOT(addError(const QString&))); + connect(myEventsListener, SIGNAL(errorOccurred(const QString&)), + myErrorDlg, SLOT(addError(const QString&))); //Config_PropManager::registerProp("Visualization", "object_default_color", "Object color", // Config_Prop::Color, "225,225,225"); @@ -183,19 +186,7 @@ void XGUI_Workshop::startApplication() Config_Prop::Directory, ""); //Initialize event listening - Events_Loop* aLoop = Events_Loop::loop(); - aLoop->registerListener(this, Events_Error::errorID()); //!< Listening application errors. - aLoop->registerListener(this, Events_Loop::eventByName(Config_FeatureMessage::GUI_EVENT())); - aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OPERATION_LAUNCHED)); - aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); - aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED)); - aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); - aLoop->registerListener(this, Events_LongOp::eventID()); - aLoop->registerListener(this, Events_Loop::eventByName(EVENT_PLUGIN_LOADED)); - aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SELFILTER_LOADED)); - - aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)); - aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)); + myEventsListener->initializeEventListening(); registerValidators(); @@ -343,107 +334,6 @@ AppElements_Workbench* XGUI_Workshop::addWorkbench(const QString& theName) return aMenuBar->addWorkbench(theName); } -//****************************************************** -void XGUI_Workshop::processEvent(const std::shared_ptr& theMessage) -{ - if (QApplication::instance()->thread() != QThread::currentThread()) { - #ifdef _DEBUG - std::cout << "XGUI_Workshop::processEvent: " << "Working in another thread." << std::endl; - #endif - SessionPtr aMgr = ModelAPI_Session::get(); - PostponeMessageQtEvent* aPostponeEvent = new PostponeMessageQtEvent(theMessage); - QApplication::postEvent(this, aPostponeEvent); - return; - } - - //A message to start feature creation received. - if (theMessage->eventID() == Events_Loop::loop()->eventByName(Config_FeatureMessage::GUI_EVENT())) { - std::shared_ptr aFeatureMsg = - std::dynamic_pointer_cast(theMessage); - if (!aFeatureMsg->isInternal()) { - addFeature(aFeatureMsg); - } - } - // Process creation of Part - else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) { - std::shared_ptr aUpdMsg = - std::dynamic_pointer_cast(theMessage); - onFeatureCreatedMsg(aUpdMsg); - if (myUpdatePrefs) { - if (mySalomeConnector) - mySalomeConnector->createPreferences(); - myUpdatePrefs = false; - } - } - else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_PLUGIN_LOADED)) { - myUpdatePrefs = true; - } - // Redisplay feature - else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)) { - std::shared_ptr aUpdMsg = - std::dynamic_pointer_cast(theMessage); - onFeatureRedisplayMsg(aUpdMsg); - } - //Update property panel on corresponding message. If there is no current operation (no - //property panel), or received message has different feature to the current - do nothing. - else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) { - std::shared_ptr anUpdateMsg = - std::dynamic_pointer_cast(theMessage); - onFeatureUpdatedMsg(anUpdateMsg); - } else if (theMessage->eventID() == Events_LongOp::eventID()) { - if (Events_LongOp::isPerformed()) { - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - } else { - QApplication::restoreOverrideCursor(); - } - } - //An operation passed by message. Start it, process and commit. - else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OPERATION_LAUNCHED)) { - std::shared_ptr aPartSetMsg = - std::dynamic_pointer_cast(theMessage); - //myPropertyPanel->cleanContent(); - ModuleBase_Operation* anOperation = (ModuleBase_Operation*) aPartSetMsg->pointer(); - - if (myOperationMgr->startOperation(anOperation)) { - myPropertyPanel->updateContentWidget(anOperation->feature()); - if (!anOperation->getDescription()->hasXmlRepresentation()) { - if (anOperation->commit()) - updateCommandStatus(); - } - } - } - else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_SELFILTER_LOADED)) { - std::shared_ptr aMsg = - std::dynamic_pointer_cast(theMessage); - if (aMsg) { - ModuleBase_FilterFactory* aFactory = moduleConnector()->selectionFilters(); - if (!aMsg->attributeId().empty()) { - aFactory->assignFilter(aMsg->selectionFilterId(), aMsg->featureId(), aMsg->attributeId(), - aMsg->parameters()); - } - } - } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)) { - // the viewer's update context will not happens until viewer updated is emitted - myDisplayer->enableUpdateViewer(false); - } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)) { - // the viewer's update context is unblocked, the viewer's update works - myDisplayer->enableUpdateViewer(true); - myDisplayer->updateViewer(); - } else { - //Show error dialog if error message received. - std::shared_ptr anAppError = std::dynamic_pointer_cast(theMessage); - if (anAppError) { - emit errorOccurred(QString::fromLatin1(anAppError->description())); - } - return; - } - if (!isSalomeMode()) { - SessionPtr aMgr = ModelAPI_Session::get(); - if (aMgr->isModified() != myMainWindow->isModifiedState()) - myMainWindow->setModifiedState(aMgr->isModified()); - } -} - //****************************************************** QMainWindow* XGUI_Workshop::desktop() const { @@ -458,79 +348,6 @@ void XGUI_Workshop::onStartWaiting() } } -//****************************************************** -void XGUI_Workshop::onFeatureUpdatedMsg(const std::shared_ptr& theMsg) -{ - std::set aFeatures = theMsg->objects(); - if (myOperationMgr->hasOperation()) { - FeaturePtr aCurrentFeature = myOperationMgr->currentOperation()->feature(); - std::set::const_iterator aIt; - for (aIt = aFeatures.begin(); aIt != aFeatures.end(); ++aIt) { - ObjectPtr aNewFeature = (*aIt); - if (aNewFeature == aCurrentFeature) { - myPropertyPanel->updateContentWidget(aCurrentFeature); - break; - } - } - } - myOperationMgr->onValidateOperation(); - //if (myObjectBrowser) - // myObjectBrowser->processEvent(theMsg); -} - -//****************************************************** -void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr& theMsg) -{ - std::set aObjects = theMsg->objects(); - std::set::const_iterator aIt; - -#ifdef DEBUG_FEATURE_REDISPLAY - QStringList anInfo; - for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { - anInfo.append(ModuleBase_Tools::objectInfo((*aIt))); - } - QString anInfoStr = anInfo.join(", "); - qDebug(QString("onFeatureRedisplayMsg: %1, %2").arg(aObjects.size()).arg(anInfoStr).toStdString().c_str()); -#endif - - for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { - ObjectPtr aObj = (*aIt); - - // Hide the object if it is invalid or concealed one - bool aHide = !aObj->data() || !aObj->data()->isValid() || - aObj->isDisabled() || (!aObj->isDisplayed()); - if (!aHide) { // check that this is not hidden result - ResultPtr aRes = std::dynamic_pointer_cast(aObj); - aHide = aRes && aRes->isConcealed(); - } - if (aHide) - myDisplayer->erase(aObj, false); - else { - // Redisplay the visible object or the object of the current operation - bool isVisibleObject = myDisplayer->isVisible(aObj); - #ifdef DEBUG_FEATURE_REDISPLAY - //QString anObjInfo = ModuleBase_Tools::objectInfo((aObj)); - //qDebug(QString("visible=%1 : display= %2").arg(isVisibleObject).arg(anObjInfo).toStdString().c_str()); - #endif - - if (isVisibleObject) { // redisplay visible object - //displayObject(aObj); // In order to update presentation - // in order to avoid the check whether the object can be redisplayed, the exact method - // of redisplay is called. This modification is made in order to have the line is updated - // by creation of a horizontal constraint on the line by preselection - myDisplayer->redisplay(aObj, false); - // Deactivate object of current operation from selection - deactivateActiveObject(aObj, false); - } else { // display object if the current operation has it - if (displayObject(aObj)) { - // Deactivate object of current operation from selection - deactivateActiveObject(aObj, false); - } - } - } - } - myDisplayer->updateViewer(); -} //****************************************************** void XGUI_Workshop::deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer) @@ -541,49 +358,6 @@ void XGUI_Workshop::deactivateActiveObject(const ObjectPtr& theObject, const boo } } -//****************************************************** -void XGUI_Workshop::onFeatureCreatedMsg(const std::shared_ptr& theMsg) -{ - std::set aObjects = theMsg->objects(); - std::set::const_iterator aIt; -#ifdef DEBUG_FEATURE_CREATED - QStringList anInfo; - for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { - anInfo.append(ModuleBase_Tools::objectInfo((*aIt))); - } - QString anInfoStr = anInfo.join(", "); - qDebug(QString("onFeatureCreatedMsg: %1, %2").arg(aObjects.size()).arg(anInfoStr).toStdString().c_str()); -#endif - - //bool aHasPart = false; - bool isDisplayed = false; - for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { - ObjectPtr anObject = *aIt; - // the validity of the data should be checked here in order to avoid display of the objects, - // which were created, then deleted, but flush for the creation event happens after that - // we should not display disabled objects - bool aHide = !anObject->data()->isValid() || - anObject->isDisabled() || - !anObject->isDisplayed(); - if (!aHide) { - // setDisplayed has to be called in order to synchronize internal state of the object - // with list of displayed objects - if (myModule->canDisplayObject(anObject)) { - anObject->setDisplayed(true); - isDisplayed = displayObject(*aIt); - } else - anObject->setDisplayed(false); - } - } - //if (myObjectBrowser) - // myObjectBrowser->processEvent(theMsg); - if (isDisplayed) - myDisplayer->updateViewer(); - //if (aHasPart) { // TODO: Avoid activate last part on loading of document - // activateLastPart(); - //} -} - //****************************************************** void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation) { @@ -705,95 +479,6 @@ void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) myPropertyPanel->setWindowTitle(theOperation->getDescription()->description()); } -bool XGUI_Workshop::event(QEvent * theEvent) -{ - PostponeMessageQtEvent* aPostponedEv = dynamic_cast(theEvent); - if (aPostponedEv) { - std::shared_ptr aEventPtr = aPostponedEv->postponedMessage(); - processEvent(aEventPtr); - return true; - } - return false; -} - -/* - * - */ -void XGUI_Workshop::addFeature(const std::shared_ptr& theMessage) -{ - if (!theMessage) { -#ifdef _DEBUG - qDebug() << "XGUI_Workshop::addFeature: NULL message."; -#endif - return; - } - ActionInfo aFeatureInfo; - aFeatureInfo.initFrom(theMessage); - - QString aWchName = QString::fromStdString(theMessage->workbenchId()); - QStringList aNestedFeatures = - QString::fromStdString(theMessage->nestedFeatures()).split(" ", QString::SkipEmptyParts); - QString aDocKind = QString::fromStdString(theMessage->documentKind()); - QList aNestedActList; - bool isColumnButton = !aNestedFeatures.isEmpty(); - if (isColumnButton) { - QString aNestedActions = QString::fromStdString(theMessage->actionsWhenNested()); - if (aNestedActions.contains("accept")) { - QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll, NULL); - connect(anAction, SIGNAL(triggered()), myOperationMgr, SLOT(commitAllOperations())); - aNestedActList << anAction; - } - if (aNestedActions.contains("abort")) { - QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll, NULL); - connect(anAction, SIGNAL(triggered()), myOperationMgr, SLOT(abortAllOperations())); - aNestedActList << anAction; - } - } - - if (isSalomeMode()) { - QAction* aAction; - if (isColumnButton) { - aAction = salomeConnector()->addNestedFeature(aWchName, aFeatureInfo, aNestedActList); - } else { - aAction = salomeConnector()->addFeature(aWchName, aFeatureInfo); - } - salomeConnector()->setNestedActions(aFeatureInfo.id, aNestedFeatures); - salomeConnector()->setDocumentKind(aFeatureInfo.id, aDocKind); - - myActionsMgr->addCommand(aAction); - myModule->actionCreated(aAction); - } else { - //Find or create Workbench - AppElements_MainMenu* aMenuBar = myMainWindow->menuObject(); - AppElements_Workbench* aPage = aMenuBar->findWorkbench(aWchName); - if (!aPage) { - aPage = addWorkbench(aWchName); - } - //Find or create Group - QString aGroupName = QString::fromStdString(theMessage->groupId()); - AppElements_MenuGroupPanel* aGroup = aPage->findGroup(aGroupName); - if (!aGroup) { - aGroup = aPage->addGroup(aGroupName); - } - // Check if hotkey sequence is already defined: - QKeySequence aHotKey = myActionsMgr->registerShortcut(aFeatureInfo.shortcut); - if(aHotKey != aFeatureInfo.shortcut) { - aFeatureInfo.shortcut = aHotKey; - } - // Create feature... - AppElements_Command* aCommand = aGroup->addFeature(aFeatureInfo, - aDocKind, - aNestedFeatures); - // Enrich created button with accept/abort buttons if necessary - AppElements_Button* aButton = aCommand->button(); - if (aButton->isColumnButton()) { - aButton->setAdditionalButtons(aNestedActList); - } - myActionsMgr->addCommand(aCommand); - myModule->actionCreated(aCommand); - } -} - /* * Makes a signal/slot connections between Property Panel * and given operation. The given operation becomes a @@ -1754,24 +1439,6 @@ void XGUI_Workshop::closeDocument() aMgr->closeAll(); } -//************************************************************** -bool XGUI_Workshop::displayObject(ObjectPtr theObj) -{ - if (!myModule->canDisplayObject(theObj)) - return false; - - ResultBodyPtr aBody = std::dynamic_pointer_cast(theObj); - if (aBody.get() != NULL) { - int aNb = myDisplayer->objectsCount(); - myDisplayer->display(theObj, false); - if (aNb == 0) - viewer()->fitAll(); - } else if (!(myIsLoadingData || myPartActivating)) - myDisplayer->display(theObj, false); - - return true; -} - void XGUI_Workshop::addHistoryMenu(QObject* theObject, const char* theSignal, const char* theSlot) { XGUI_HistoryMenu* aMenu = NULL; diff --git a/src/XGUI/XGUI_Workshop.h b/src/XGUI/XGUI_Workshop.h index fccb8575d..b41634aab 100644 --- a/src/XGUI/XGUI_Workshop.h +++ b/src/XGUI/XGUI_Workshop.h @@ -5,7 +5,6 @@ #include "XGUI.h" //#include "XGUI_Constants.h" -#include #include #include #include @@ -33,28 +32,23 @@ class XGUI_ViewerProxy; class XGUI_PropertyPanel; class XGUI_ContextMenuMgr; class XGUI_ModuleConnector; +class XGUI_WorkshopListener; class ModuleBase_Operation; class ModuleBase_IModule; class ModuleBase_IViewer; -class Config_FeatureMessage; -class Config_PointerMessage; - class QWidget; class QDockWidget; class QMainWindow; -class ModelAPI_ObjectUpdatedMessage; -class ModelAPI_ObjectDeletedMessage; -class ModelAPI_ResultPart; class QAction; /**\class XGUI_Workshop * \ingroup GUI * \brief Class which defines a configuration of the application (Workshop) and launches it. */ -class XGUI_EXPORT XGUI_Workshop : public QObject, public Events_Listener +class XGUI_EXPORT XGUI_Workshop : public QObject { Q_OBJECT public: @@ -118,9 +112,6 @@ Q_OBJECT //! Creates and adds a new workbench (menu group) with the given name and returns it AppElements_Workbench* addWorkbench(const QString& theName); - //! Redefinition of Events_Listener method - virtual void processEvent(const std::shared_ptr& theMessage); - //! Returns an object which provides interface to Salome Module (LightApp_Module) XGUI_SalomeConnector* salomeConnector() const { @@ -136,6 +127,13 @@ Q_OBJECT return mySalomeConnector != 0; } + /// Returns true if the loading data process is started and has not been finished yet + /// \return boolean result + bool isLoadingData() const + { + return myIsLoadingData; + }; + //! Returns Object browser XGUI_ObjectsBrowser* objectBrowser() const { @@ -225,6 +223,12 @@ Q_OBJECT QWidget* theParent = 0, const bool theAskAboutDeleteReferences = false); + /// Deactivates the object, if it is active and the module returns that the activation + /// of selection for the object is not possible currently(the current operation uses it) + /// \param theObject an object + /// \param theUpdateViewer a boolean flag to update viewer immediately + void deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer); + signals: /// Emitted when selection happens in Salome viewer void salomeViewerSelection(); @@ -306,33 +310,11 @@ signals: /// \param theOperation an operation void setPropertyPanel(ModuleBase_Operation* theOperation); - /// Procedure to process postponed events - bool event(QEvent * theEvent); - - //Event-loop processing methods: - - /// Process event "Add a feature" - void addFeature(const std::shared_ptr&); - /// Connect to operation signals /// \param theOperation an operation void connectWithOperation(ModuleBase_Operation* theOperation); - /// Process feature update message - void onFeatureUpdatedMsg(const std::shared_ptr& ); - - /// Process feature created message - void onFeatureCreatedMsg(const std::shared_ptr& ); - - /// Process feature redisplay message - void onFeatureRedisplayMsg(const std::shared_ptr& ); - - /// Deactivates the object, if it is active and the module returns that the activation - /// of selection for the object is not possible currently(the current operation uses it) - /// \param theObject an object - /// \param theUpdateViewer a boolean flag to update viewer immediately - void deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer); - +private: /// Display all results //void displayAllResults(); @@ -400,12 +382,6 @@ signals: // Creates Dock widgets: Object browser and Property panel void createDockWidgets(); - /// Displaus object and fit all viewer if the object is first (update viewer will not be called) - /// Asks the module whether the object can be displayed - /// \param theObj an object - /// \return true if the object is displayed - bool displayObject(ObjectPtr theObj); - //! Extends undo/redo toolbutton's with history menu //! \param theObject - in the OpenParts it is a QToolButton by itself, //! in salome mode - QAction that creates a button. @@ -430,14 +406,10 @@ private: XGUI_ViewerProxy* myViewerProxy; XGUI_ContextMenuMgr* myContextMenuMgr; XGUI_ModuleConnector* myModuleConnector; + XGUI_WorkshopListener* myEventsListener; QString myCurrentDir; - bool myUpdatePrefs; - - // Flag to check that part document is in process of activating - bool myPartActivating; - /// The flag is true when we loading a document bool myIsLoadingData; }; diff --git a/src/XGUI/XGUI_WorkshopListener.cpp b/src/XGUI/XGUI_WorkshopListener.cpp new file mode 100755 index 000000000..2a699ca34 --- /dev/null +++ b/src/XGUI/XGUI_WorkshopListener.cpp @@ -0,0 +1,430 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +#include "XGUI_WorkshopListener.h" +#include "XGUI_Workshop.h" +#include "XGUI_Displayer.h" +#include "XGUI_OperationMgr.h" +#include "XGUI_SalomeConnector.h" +#include "XGUI_ActionsMgr.h" +#include "XGUI_PropertyPanel.h" +#include "XGUI_ModuleConnector.h" +#include "XGUI_QtEvents.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef _DEBUG +#include +#include +#endif + +//#define DEBUG_FEATURE_CREATED +//#define DEBUG_FEATURE_REDISPLAY + +XGUI_WorkshopListener::XGUI_WorkshopListener(ModuleBase_IWorkshop* theWorkshop) + : myWorkshop(theWorkshop), + myUpdatePrefs(false) +{ +} + +//****************************************************** +XGUI_WorkshopListener::~XGUI_WorkshopListener(void) +{ +} + +//****************************************************** +void XGUI_WorkshopListener::initializeEventListening() +{ + //Initialize event listening + Events_Loop* aLoop = Events_Loop::loop(); + aLoop->registerListener(this, Events_Error::errorID()); //!< Listening application errors. + aLoop->registerListener(this, Events_Loop::eventByName(Config_FeatureMessage::GUI_EVENT())); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OPERATION_LAUNCHED)); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED)); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + aLoop->registerListener(this, Events_LongOp::eventID()); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_PLUGIN_LOADED)); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SELFILTER_LOADED)); + + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)); +} + +//****************************************************** +void XGUI_WorkshopListener::processEvent(const std::shared_ptr& theMessage) +{ + if (QApplication::instance()->thread() != QThread::currentThread()) { + #ifdef _DEBUG + std::cout << "XGUI_Workshop::processEvent: " << "Working in another thread." << std::endl; + #endif + SessionPtr aMgr = ModelAPI_Session::get(); + PostponeMessageQtEvent* aPostponeEvent = new PostponeMessageQtEvent(theMessage); + QApplication::postEvent(this, aPostponeEvent); + return; + } + + //A message to start feature creation received. + if (theMessage->eventID() == Events_Loop::loop()->eventByName(Config_FeatureMessage::GUI_EVENT())) { + std::shared_ptr aFeatureMsg = + std::dynamic_pointer_cast(theMessage); + if (!aFeatureMsg->isInternal()) { + addFeature(aFeatureMsg); + } + } + // Process creation of Part + else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) { + std::shared_ptr aUpdMsg = + std::dynamic_pointer_cast(theMessage); + onFeatureCreatedMsg(aUpdMsg); + if (myUpdatePrefs) { + XGUI_SalomeConnector* aSalomeConnector = workshop()->salomeConnector(); + if (aSalomeConnector) + aSalomeConnector->createPreferences(); + myUpdatePrefs = false; + } + } + else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_PLUGIN_LOADED)) { + myUpdatePrefs = true; + } + // Redisplay feature + else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)) { + std::shared_ptr aUpdMsg = + std::dynamic_pointer_cast(theMessage); + onFeatureRedisplayMsg(aUpdMsg); + } + //Update property panel on corresponding message. If there is no current operation (no + //property panel), or received message has different feature to the current - do nothing. + else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) { + std::shared_ptr anUpdateMsg = + std::dynamic_pointer_cast(theMessage); + onFeatureUpdatedMsg(anUpdateMsg); + } else if (theMessage->eventID() == Events_LongOp::eventID()) { + if (Events_LongOp::isPerformed()) { + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + } else { + QApplication::restoreOverrideCursor(); + } + } + //An operation passed by message. Start it, process and commit. + else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OPERATION_LAUNCHED)) { + std::shared_ptr aPartSetMsg = + std::dynamic_pointer_cast(theMessage); + //myPropertyPanel->cleanContent(); + ModuleBase_Operation* anOperation = (ModuleBase_Operation*) aPartSetMsg->pointer(); + XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr(); + + if (anOperationMgr->startOperation(anOperation)) { + workshop()->propertyPanel()->updateContentWidget(anOperation->feature()); + if (!anOperation->getDescription()->hasXmlRepresentation()) { + if (anOperation->commit()) + workshop()->updateCommandStatus(); + } + } + } + else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_SELFILTER_LOADED)) { + std::shared_ptr aMsg = + std::dynamic_pointer_cast(theMessage); + if (aMsg) { + ModuleBase_FilterFactory* aFactory = myWorkshop->selectionFilters(); + if (!aMsg->attributeId().empty()) { + aFactory->assignFilter(aMsg->selectionFilterId(), aMsg->featureId(), aMsg->attributeId(), + aMsg->parameters()); + } + } + } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)) { + // the viewer's update context will not happens until viewer updated is emitted + workshop()->displayer()->enableUpdateViewer(false); + } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)) { + // the viewer's update context is unblocked, the viewer's update works + XGUI_Displayer* aDisplayer = workshop()->displayer(); + aDisplayer->enableUpdateViewer(true); + aDisplayer->updateViewer(); + } else { + //Show error dialog if error message received. + std::shared_ptr anAppError = std::dynamic_pointer_cast(theMessage); + if (anAppError) { + emit errorOccurred(QString::fromLatin1(anAppError->description())); + } + return; + } + if (!workshop()->isSalomeMode()) { + SessionPtr aMgr = ModelAPI_Session::get(); + AppElements_MainWindow* aMainWindow = workshop()->mainWindow(); + if (aMgr->isModified() != aMainWindow->isModifiedState()) + aMainWindow->setModifiedState(aMgr->isModified()); + } +} + +//****************************************************** +void XGUI_WorkshopListener::onFeatureUpdatedMsg(const std::shared_ptr& theMsg) +{ + std::set aFeatures = theMsg->objects(); + XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr(); + if (anOperationMgr->hasOperation()) { + FeaturePtr aCurrentFeature = anOperationMgr->currentOperation()->feature(); + std::set::const_iterator aIt; + for (aIt = aFeatures.begin(); aIt != aFeatures.end(); ++aIt) { + ObjectPtr aNewFeature = (*aIt); + if (aNewFeature == aCurrentFeature) { + workshop()->propertyPanel()->updateContentWidget(aCurrentFeature); + break; + } + } + } + anOperationMgr->onValidateOperation(); + //if (myObjectBrowser) + // myObjectBrowser->processEvent(theMsg); +} + +//****************************************************** +void XGUI_WorkshopListener::onFeatureRedisplayMsg(const std::shared_ptr& theMsg) +{ + std::set aObjects = theMsg->objects(); + std::set::const_iterator aIt; + +#ifdef DEBUG_FEATURE_REDISPLAY + QStringList anInfo; + for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { + anInfo.append(ModuleBase_Tools::objectInfo((*aIt))); + } + QString anInfoStr = anInfo.join(", "); + qDebug(QString("onFeatureRedisplayMsg: %1, %2").arg(aObjects.size()).arg(anInfoStr).toStdString().c_str()); +#endif + + XGUI_Workshop* aWorkshop = workshop(); + XGUI_Displayer* aDisplayer = aWorkshop->displayer(); + for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { + ObjectPtr aObj = (*aIt); + + // Hide the object if it is invalid or concealed one + bool aHide = !aObj->data() || !aObj->data()->isValid() || + aObj->isDisabled() || (!aObj->isDisplayed()); + if (!aHide) { // check that this is not hidden result + ResultPtr aRes = std::dynamic_pointer_cast(aObj); + aHide = aRes && aRes->isConcealed(); + } + if (aHide) + aDisplayer->erase(aObj, false); + else { + // Redisplay the visible object or the object of the current operation + bool isVisibleObject = aDisplayer->isVisible(aObj); + #ifdef DEBUG_FEATURE_REDISPLAY + //QString anObjInfo = ModuleBase_Tools::objectInfo((aObj)); + //qDebug(QString("visible=%1 : display= %2").arg(isVisibleObject).arg(anObjInfo).toStdString().c_str()); + #endif + + if (isVisibleObject) { // redisplay visible object + //displayObject(aObj); // In order to update presentation + // in order to avoid the check whether the object can be redisplayed, the exact method + // of redisplay is called. This modification is made in order to have the line is updated + // by creation of a horizontal constraint on the line by preselection + aDisplayer->redisplay(aObj, false); + // Deactivate object of current operation from selection + aWorkshop->deactivateActiveObject(aObj, false); + } else { // display object if the current operation has it + if (displayObject(aObj)) { + // Deactivate object of current operation from selection + aWorkshop->deactivateActiveObject(aObj, false); + } + } + } + } + aDisplayer->updateViewer(); +} +//****************************************************** +void XGUI_WorkshopListener::onFeatureCreatedMsg(const std::shared_ptr& theMsg) +{ + std::set aObjects = theMsg->objects(); + std::set::const_iterator aIt; +#ifdef DEBUG_FEATURE_CREATED + QStringList anInfo; + for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { + anInfo.append(ModuleBase_Tools::objectInfo((*aIt))); + } + QString anInfoStr = anInfo.join(", "); + qDebug(QString("onFeatureCreatedMsg: %1, %2").arg(aObjects.size()).arg(anInfoStr).toStdString().c_str()); +#endif + + //bool aHasPart = false; + bool isDisplayed = false; + for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { + ObjectPtr anObject = *aIt; + // the validity of the data should be checked here in order to avoid display of the objects, + // which were created, then deleted, but flush for the creation event happens after that + // we should not display disabled objects + bool aHide = !anObject->data()->isValid() || + anObject->isDisabled() || + !anObject->isDisplayed(); + if (!aHide) { + // setDisplayed has to be called in order to synchronize internal state of the object + // with list of displayed objects + if (myWorkshop->module()->canDisplayObject(anObject)) { + anObject->setDisplayed(true); + isDisplayed = displayObject(*aIt); + } else + anObject->setDisplayed(false); + } + } + //if (myObjectBrowser) + // myObjectBrowser->processEvent(theMsg); + if (isDisplayed) + workshop()->displayer()->updateViewer(); + //if (aHasPart) { // TODO: Avoid activate last part on loading of document + // activateLastPart(); + //} +} + +bool XGUI_WorkshopListener::event(QEvent * theEvent) +{ + PostponeMessageQtEvent* aPostponedEv = dynamic_cast(theEvent); + if (aPostponedEv) { + std::shared_ptr aEventPtr = aPostponedEv->postponedMessage(); + processEvent(aEventPtr); + return true; + } + return false; +} + +void XGUI_WorkshopListener::addFeature(const std::shared_ptr& theMessage) +{ + if (!theMessage) { +#ifdef _DEBUG + qDebug() << "XGUI_WorkshopListener::addFeature: NULL message."; +#endif + return; + } + ActionInfo aFeatureInfo; + aFeatureInfo.initFrom(theMessage); + + XGUI_Workshop* aWorkshop = workshop(); + + QString aWchName = QString::fromStdString(theMessage->workbenchId()); + QStringList aNestedFeatures = + QString::fromStdString(theMessage->nestedFeatures()).split(" ", QString::SkipEmptyParts); + QString aDocKind = QString::fromStdString(theMessage->documentKind()); + QList aNestedActList; + bool isColumnButton = !aNestedFeatures.isEmpty(); + if (isColumnButton) { + QString aNestedActions = QString::fromStdString(theMessage->actionsWhenNested()); + XGUI_OperationMgr* anOperationMgr = aWorkshop->operationMgr(); + XGUI_ActionsMgr* anActionsMgr = aWorkshop->actionsMgr(); + if (aNestedActions.contains("accept")) { + QAction* anAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll, NULL); + connect(anAction, SIGNAL(triggered()), anOperationMgr, SLOT(commitAllOperations())); + aNestedActList << anAction; + } + if (aNestedActions.contains("abort")) { + QAction* anAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll, NULL); + connect(anAction, SIGNAL(triggered()), anOperationMgr, SLOT(abortAllOperations())); + aNestedActList << anAction; + } + } + + if (aWorkshop->isSalomeMode()) { + XGUI_SalomeConnector* aSalomeConnector = aWorkshop->salomeConnector(); + QAction* aAction; + if (isColumnButton) { + aAction = aSalomeConnector->addNestedFeature(aWchName, aFeatureInfo, aNestedActList); + } else { + aAction = aSalomeConnector->addFeature(aWchName, aFeatureInfo); + } + aSalomeConnector->setNestedActions(aFeatureInfo.id, aNestedFeatures); + aSalomeConnector->setDocumentKind(aFeatureInfo.id, aDocKind); + + aWorkshop->actionsMgr()->addCommand(aAction); + aWorkshop->module()->actionCreated(aAction); + } else { + //Find or create Workbench + AppElements_MainMenu* aMenuBar = aWorkshop->mainWindow()->menuObject(); + AppElements_Workbench* aPage = aMenuBar->findWorkbench(aWchName); + if (!aPage) { + aPage = aWorkshop->addWorkbench(aWchName); + } + //Find or create Group + QString aGroupName = QString::fromStdString(theMessage->groupId()); + AppElements_MenuGroupPanel* aGroup = aPage->findGroup(aGroupName); + if (!aGroup) { + aGroup = aPage->addGroup(aGroupName); + } + // Check if hotkey sequence is already defined: + XGUI_ActionsMgr* anActionsMgr = aWorkshop->actionsMgr(); + QKeySequence aHotKey = anActionsMgr->registerShortcut(aFeatureInfo.shortcut); + if(aHotKey != aFeatureInfo.shortcut) { + aFeatureInfo.shortcut = aHotKey; + } + // Create feature... + AppElements_Command* aCommand = aGroup->addFeature(aFeatureInfo, + aDocKind, + aNestedFeatures); + // Enrich created button with accept/abort buttons if necessary + AppElements_Button* aButton = aCommand->button(); + if (aButton->isColumnButton()) { + aButton->setAdditionalButtons(aNestedActList); + } + aWorkshop->actionsMgr()->addCommand(aCommand); + aWorkshop->module()->actionCreated(aCommand); + } +} + + +//************************************************************** +bool XGUI_WorkshopListener::displayObject(ObjectPtr theObj) +{ + XGUI_Workshop* aWorkshop = workshop(); + if (!aWorkshop->module()->canDisplayObject(theObj)) + return false; + + XGUI_Displayer* aDisplayer = aWorkshop->displayer(); + ResultBodyPtr aBody = std::dynamic_pointer_cast(theObj); + if (aBody.get() != NULL) { + int aNb = aDisplayer->objectsCount(); + aDisplayer->display(theObj, false); + if (aNb == 0) + myWorkshop->viewer()->fitAll(); + } else if (!aWorkshop->isLoadingData()) + aDisplayer->display(theObj, false); + + return true; +} + +XGUI_Workshop* XGUI_WorkshopListener::workshop() const +{ + XGUI_ModuleConnector* aConnector = dynamic_cast(myWorkshop); + return aConnector->workshop(); +} diff --git a/src/XGUI/XGUI_WorkshopListener.h b/src/XGUI/XGUI_WorkshopListener.h new file mode 100755 index 000000000..71d0a9985 --- /dev/null +++ b/src/XGUI/XGUI_WorkshopListener.h @@ -0,0 +1,78 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +#ifndef XGUI_WORKSHOP_LISTENER_H +#define XGUI_WORKSHOP_LISTENER_H + +#include "XGUI.h" +#include +#include + +#include + +#include + +class Config_FeatureMessage; + +class ModelAPI_ObjectUpdatedMessage; +class XGUI_Workshop; + +class ModuleBase_IWorkshop; + +class QString; + +/**\class XGUI_WorkshopListener + * \ingroup GUI + * \brief Class which process the events from the event loop. + */ +class XGUI_EXPORT XGUI_WorkshopListener : public QObject, public Events_Listener +{ + Q_OBJECT +public: + /// Constructor + /// \param theConnector a Salome connector object. + /// Used only if the workshop is launched in Salome environment + XGUI_WorkshopListener(ModuleBase_IWorkshop* theWorkshop); + virtual ~XGUI_WorkshopListener(); + + /// Register this class in the events loop for several types of events + void initializeEventListening(); + + //! Redefinition of Events_Listener method + virtual void processEvent(const std::shared_ptr& theMessage); + +signals: + /// Emitted when error in applivation happens + void errorOccurred(const QString&); + +protected: + /// Procedure to process postponed events + bool event(QEvent * theEvent); + + /// Process event "Add a feature" + void addFeature(const std::shared_ptr&); + + /// Process feature update message + void onFeatureUpdatedMsg(const std::shared_ptr& ); + + /// Process feature created message + void onFeatureCreatedMsg(const std::shared_ptr& ); + + /// Process feature redisplay message + void onFeatureRedisplayMsg(const std::shared_ptr& ); + + /// Displaus object and fit all viewer if the object is first (update viewer will not be called) + /// Asks the module whether the object can be displayed + /// \param theObj an object + /// \return true if the object is displayed + bool displayObject(ObjectPtr theObj); + + /// Returns the workshop + XGUI_Workshop* workshop() const; + +private: + ModuleBase_IWorkshop* myWorkshop; // the current workshop + + bool myUpdatePrefs; +}; + +#endif