XGUI_Tools.h
XGUI_ViewerProxy.h
XGUI_Workshop.h
+ XGUI_WorkshopListener.h
XGUI_HistoryMenu.h
)
XGUI_Tools.cpp
XGUI_ViewerProxy.cpp
XGUI_Workshop.cpp
+ XGUI_WorkshopListener.cpp
XGUI_HistoryMenu.cpp
)
#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>
#include <Events_Error.h>
#include <Events_LongOp.h>
-#include <ModuleBase_Operation.h>
#include <ModuleBase_Operation.h>
#include <ModuleBase_OperationDescription.h>
#include <ModuleBase_SelectionValidator.h>
#include <dlfcn.h>
#endif
-//#define DEBUG_FEATURE_CREATED
-//#define DEBUG_FEATURE_REDISPLAY
//#define DEBUG_DELETE
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();
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*)));
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");
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();
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
{
}
}
-//******************************************************
-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)
}
}
-//******************************************************
-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)
{
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
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;
#include "XGUI.h"
//#include "XGUI_Constants.h"
-#include <Events_Listener.h>
#include <ModuleBase_Definitions.h>
#include <ModelAPI_Document.h>
#include <ModelAPI_Feature.h>
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:
//! 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
{
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
{
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();
/// \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();
// 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.
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;
};
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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