]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Separation of Workshop and events listener in order to make XGUI_Workshop is a child...
authornds <natalia.donis@opencascade.com>
Mon, 29 Jun 2015 06:18:52 +0000 (09:18 +0300)
committernds <natalia.donis@opencascade.com>
Mon, 29 Jun 2015 08:01:10 +0000 (11:01 +0300)
src/XGUI/CMakeLists.txt
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h
src/XGUI/XGUI_WorkshopListener.cpp [new file with mode: 0755]
src/XGUI/XGUI_WorkshopListener.h [new file with mode: 0755]

index d570650ef03b4c518907c4267795842249020178..4da2ebedaa9e5575030f1453611d4aaf259ed7b6 100644 (file)
@@ -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
 )
 
index 0f6cd8c773be3290069b876b37757c29c288d54b..e0ca916c532cb488a60997ca9d0675efc9577431 100644 (file)
@@ -16,6 +16,8 @@
 #include "XGUI_PropertyPanel.h"
 #include "XGUI_ContextMenuMgr.h"
 #include "XGUI_ModuleConnector.h"
+#include "XGUI_WorkshopListener.h"
+
 #include <XGUI_QtEvents.h>
 #include <XGUI_HistoryMenu.h>
 #include <XGUI_CustomPrs.h>
@@ -50,7 +52,6 @@
 #include <Events_Error.h>
 #include <Events_LongOp.h>
 
-#include <ModuleBase_Operation.h>
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_OperationDescription.h>
 #include <ModuleBase_SelectionValidator.h>
@@ -95,8 +96,6 @@
 #include <dlfcn.h>
 #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<Events_Message>& 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<Config_FeatureMessage> aFeatureMsg =
-       std::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
-    if (!aFeatureMsg->isInternal()) {
-      addFeature(aFeatureMsg);
-    }
-  }
-  // Process creation of Part
-  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
-    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(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<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(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<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(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<Config_PointerMessage> aPartSetMsg =
-        std::dynamic_pointer_cast<Config_PointerMessage>(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<Config_SelectionFilterMessage> aMsg = 
-      std::dynamic_pointer_cast<Config_SelectionFilterMessage>(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<Events_Error> anAppError = std::dynamic_pointer_cast<Events_Error>(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<ModelAPI_ObjectUpdatedMessage>& theMsg)
-{
-  std::set<ObjectPtr> aFeatures = theMsg->objects();
-  if (myOperationMgr->hasOperation()) {
-    FeaturePtr aCurrentFeature = myOperationMgr->currentOperation()->feature();
-    std::set<ObjectPtr>::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<ModelAPI_ObjectUpdatedMessage>& theMsg)
-{
-  std::set<ObjectPtr> aObjects = theMsg->objects();
-  std::set<ObjectPtr>::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<ModelAPI_Result>(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<ModelAPI_ObjectUpdatedMessage>& theMsg)
-{
-  std::set<ObjectPtr> aObjects = theMsg->objects();
-  std::set<ObjectPtr>::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<PostponeMessageQtEvent*>(theEvent);
-  if (aPostponedEv) {
-    std::shared_ptr<Events_Message> aEventPtr = aPostponedEv->postponedMessage();
-    processEvent(aEventPtr);
-    return true;
-  }
-  return false;
-}
-
-/*
- *
- */
-void XGUI_Workshop::addFeature(const std::shared_ptr<Config_FeatureMessage>& 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<QAction*> 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<ModelAPI_ResultBody>(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;
index fccb8575dc8c40a51f9f05596e5391353538697c..b41634aab7a05d6875fd78169f70b281bfabe01a 100644 (file)
@@ -5,7 +5,6 @@
 
 #include "XGUI.h"
 //#include "XGUI_Constants.h"
-#include <Events_Listener.h>
 #include <ModuleBase_Definitions.h>
 #include <ModelAPI_Document.h>
 #include <ModelAPI_Feature.h>
@@ -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<Events_Message>& 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<Config_FeatureMessage>&);
-
   /// Connect to operation signals
   /// \param theOperation an operation
   void connectWithOperation(ModuleBase_Operation* theOperation);
 
-  /// Process feature update message
-  void onFeatureUpdatedMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& );
-
-  /// Process feature created message
-  void onFeatureCreatedMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& );
-
-  /// Process feature redisplay message
-  void onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& );
-
-  /// 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 (executable)
index 0000000..2a699ca
--- /dev/null
@@ -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 <AppElements_Workbench.h>
+#include <AppElements_Command.h>
+#include <AppElements_MainMenu.h>
+#include <AppElements_MainWindow.h>
+#include <AppElements_MenuGroupPanel.h>
+#include <AppElements_Button.h>
+
+#include <ModuleBase_IModule.h>
+
+#include <ModelAPI_Object.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Result.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_ResultBody.h>
+
+#include <Events_Loop.h>
+#include <Events_Error.h>
+#include <Events_LongOp.h>
+
+#include <ModuleBase_IWorkshop.h>
+
+#include <ModuleBase_Operation.h>
+#include <ModuleBase_OperationDescription.h>
+#include <ModuleBase_Tools.h>
+#include <ModuleBase_IViewer.h>
+#include <ModuleBase_FilterFactory.h>
+
+#include <Config_FeatureMessage.h>
+#include <Config_PointerMessage.h>
+#include <Config_SelectionFilterMessage.h>
+
+#include <QApplication>
+#include <QMainWindow>
+#include <QThread>
+#include <QAction>
+
+#ifdef _DEBUG
+#include <QDebug>
+#include <iostream>
+#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<Events_Message>& 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<Config_FeatureMessage> aFeatureMsg =
+       std::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
+    if (!aFeatureMsg->isInternal()) {
+      addFeature(aFeatureMsg);
+    }
+  }
+  // Process creation of Part
+  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
+    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
+        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(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<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
+        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(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<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
+        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(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<Config_PointerMessage> aPartSetMsg =
+        std::dynamic_pointer_cast<Config_PointerMessage>(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<Config_SelectionFilterMessage> aMsg = 
+      std::dynamic_pointer_cast<Config_SelectionFilterMessage>(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<Events_Error> anAppError = std::dynamic_pointer_cast<Events_Error>(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<ModelAPI_ObjectUpdatedMessage>& theMsg)
+{
+  std::set<ObjectPtr> aFeatures = theMsg->objects();
+  XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr();
+  if (anOperationMgr->hasOperation()) {
+    FeaturePtr aCurrentFeature = anOperationMgr->currentOperation()->feature();
+    std::set<ObjectPtr>::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<ModelAPI_ObjectUpdatedMessage>& theMsg)
+{
+  std::set<ObjectPtr> aObjects = theMsg->objects();
+  std::set<ObjectPtr>::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<ModelAPI_Result>(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<ModelAPI_ObjectUpdatedMessage>& theMsg)
+{
+  std::set<ObjectPtr> aObjects = theMsg->objects();
+  std::set<ObjectPtr>::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<PostponeMessageQtEvent*>(theEvent);
+  if (aPostponedEv) {
+    std::shared_ptr<Events_Message> aEventPtr = aPostponedEv->postponedMessage();
+    processEvent(aEventPtr);
+    return true;
+  }
+  return false;
+}
+
+void XGUI_WorkshopListener::addFeature(const std::shared_ptr<Config_FeatureMessage>& 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<QAction*> 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<ModelAPI_ResultBody>(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<XGUI_ModuleConnector*>(myWorkshop);
+  return aConnector->workshop();
+}
diff --git a/src/XGUI/XGUI_WorkshopListener.h b/src/XGUI/XGUI_WorkshopListener.h
new file mode 100755 (executable)
index 0000000..71d0a99
--- /dev/null
@@ -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 <Events_Listener.h>
+#include <Events_Message.h>
+
+#include <ModelAPI_Feature.h>
+
+#include <QObject>
+
+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<Events_Message>& 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<Config_FeatureMessage>&);
+
+  /// Process feature update message
+  void onFeatureUpdatedMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& );
+
+  /// Process feature created message
+  void onFeatureCreatedMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& );
+
+  /// Process feature redisplay message
+  void onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& );
+
+  /// 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