X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_Workshop.cpp;h=c80c8a7aefc0f02908614c0abc7b7857f0f1b5b6;hb=c2fe0ed8a7a43b7c9f34cd9ec89c7fb079a07045;hp=1a1f7382dc25522e745ffb81c72455c91de0c9e3;hpb=b948502434f1af72184656e478095dae3fe00f96;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 1a1f7382d..c80c8a7ae 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -8,16 +8,29 @@ #include "XGUI_Workbench.h" #include "XGUI_Workshop.h" #include "XGUI_Viewer.h" -#include "XGUI_WidgetFactory.h" +#include "ModuleBase_WidgetFactory.h" #include "XGUI_SelectionMgr.h" - +#include "XGUI_ObjectsBrowser.h" +#include "XGUI_Displayer.h" +#include "XGUI_OperationMgr.h" +#include "XGUI_SalomeConnector.h" +#include "XGUI_SalomeViewer.h" +#include "XGUI_ActionsMgr.h" +#include "XGUI_ErrorDialog.h" +#include "XGUI_ViewerProxy.h" +#include "XGUI_PropertyPanel.h" + +#include #include #include #include #include -#include +#include +#include +#include #include +#include #include #include @@ -27,6 +40,7 @@ #include #include #include +#include #ifdef _DEBUG #include @@ -38,13 +52,32 @@ #include #endif -XGUI_Workshop::XGUI_Workshop() - : QObject(), - myCurrentOperation(NULL), - myPartSetModule(NULL) +XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) + : QObject(), + myCurrentFile(QString()), + myPartSetModule(NULL), + mySalomeConnector(theConnector), + myPropertyPanel(0), + myObjectBrowser(0), + myDisplayer(0) { - myMainWindow = new XGUI_MainWindow(); + myMainWindow = mySalomeConnector? 0 : new XGUI_MainWindow(); + + myDisplayer = new XGUI_Displayer(this); + mySelector = new XGUI_SelectionMgr(this); + connect(mySelector, SIGNAL(selectionChanged()), this, SLOT(changeCurrentDocument())); + + myOperationMgr = new XGUI_OperationMgr(this); + myActionsMgr = new XGUI_ActionsMgr(this); + myErrorDlg = new XGUI_ErrorDialog(myMainWindow); + + myViewerProxy = new XGUI_ViewerProxy(this); + + connect(myOperationMgr, SIGNAL(operationStarted()), this, SLOT(onOperationStarted())); + connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)), + this, SLOT(onOperationStopped(ModuleBase_Operation*))); + connect(this, SIGNAL(errorOccurred(const QString&)), myErrorDlg, SLOT(addError(const QString&))); } //****************************************************** @@ -57,31 +90,41 @@ void XGUI_Workshop::startApplication() { initMenu(); //Initialize event listening - Event_Loop* aLoop = Event_Loop::loop(); + Events_Loop* aLoop = Events_Loop::loop(); + aLoop->registerListener(this, Events_Error::errorID()); //!< Listening application errors. //TODO(sbh): Implement static method to extract event id [SEID] - Event_ID aFeatureId = aLoop->eventByName("FeatureEvent"); + Events_ID aFeatureId = aLoop->eventByName(EVENT_FEATURE_LOADED); aLoop->registerListener(this, aFeatureId); - Event_ID aPartSetId = aLoop->eventByName("PartSetModuleEvent"); + Events_ID aPartSetId = aLoop->eventByName("PartSetModuleEvent"); aLoop->registerListener(this, aPartSetId); + Events_ID aFeatureUpdatedId = aLoop->eventByName(EVENT_FEATURE_UPDATED); + aLoop->registerListener(this, aFeatureUpdatedId); activateModule(); - myMainWindow->show(); - - // Testing of document creation - //std::shared_ptr aMgr = ModelAPI_PluginManager::get(); - //std::shared_ptr aPoint1 = aMgr->rootDocument()->addFeature("Point"); - //std::shared_ptr aPart = aMgr->rootDocument()->addFeature("Part"); - //aPart->execute(); - //aMgr->setCurrentDocument(aPart->data()->docRef("PartDocument")->value()); - //std::shared_ptr aPoint2 = aMgr->rootDocument()->addFeature("Point"); - //aPoint2 = aMgr->rootDocument()->addFeature("Point"); - - //aPart = aMgr->rootDocument()->addFeature("Part"); - //aPart->execute(); + if (myMainWindow) { + myMainWindow->show(); + updateCommandStatus(); + } + onNew(); } //****************************************************** void XGUI_Workshop::initMenu() { + if (isSalomeMode()) { + // Create only Undo, Redo commands + salomeConnector()->addEditCommand("UNDO_CMD", + tr("Undo"), tr("Undo last command"), + QIcon(":pictures/undo.png"), + false, this, SLOT(onUndo()), + QKeySequence::Undo); + salomeConnector()->addEditCommand("REDO_CMD", + tr("Redo"), tr("Redo last command"), + QIcon(":pictures/redo.png"), + false, this, SLOT(onRedo()), + QKeySequence::Redo); + salomeConnector()->addEditMenuSeparator(); + return; + } XGUI_Workbench* aPage = myMainWindow->menuObject()->generalPage(); // File commands group @@ -96,9 +139,11 @@ void XGUI_Workshop::initMenu() aCommand = aGroup->addFeature("UNDO_CMD", tr("Undo"), tr("Undo last command"), QIcon(":pictures/undo.png"), QKeySequence::Undo); + aCommand->connectTo(this, SLOT(onUndo())); aCommand = aGroup->addFeature("REDO_CMD", tr("Redo"), tr("Redo last command"), QIcon(":pictures/redo.png"), QKeySequence::Redo); + aCommand->connectTo(this, SLOT(onRedo())); aCommand = aGroup->addFeature("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"), QIcon(":pictures/rebuild.png")); @@ -112,9 +157,9 @@ void XGUI_Workshop::initMenu() QIcon(":pictures/open.png"), QKeySequence::Open); aCommand->connectTo(this, SLOT(onOpen())); - aCommand = aGroup->addFeature("NEW_CMD", tr("New"), tr("Create a new document"), - QIcon(":pictures/new.png"), QKeySequence::New); - aCommand->connectTo(this, SLOT(onNew())); + //aCommand = aGroup->addFeature("NEW_CMD", tr("New"), tr("Create a new document"), + // QIcon(":pictures/new.png"), QKeySequence::New); + //aCommand->connectTo(this, SLOT(onNew())); aCommand = aGroup->addFeature("EXIT_CMD", tr("Exit"), tr("Exit application"), QIcon(":pictures/close.png"), QKeySequence::Close); @@ -130,33 +175,71 @@ XGUI_Workbench* XGUI_Workshop::addWorkbench(const QString& theName) } //****************************************************** -void XGUI_Workshop::processEvent(const Event_Message* theMessage) +void XGUI_Workshop::processEvent(const Events_Message* theMessage) { - const Config_FeatureMessage* aFeatureMsg = - dynamic_cast(theMessage); - if (aFeatureMsg) { + static Events_ID aFeatureLoadedId = Events_Loop::loop()->eventByName(EVENT_FEATURE_LOADED); + if (theMessage->eventID() == aFeatureLoadedId) { + const Config_FeatureMessage* aFeatureMsg = dynamic_cast(theMessage); addFeature(aFeatureMsg); return; } - const Config_PointerMessage* aPartSetMsg = - dynamic_cast(theMessage); + static Events_ID aFeatureUpdatedId = Events_Loop::loop()->eventByName(EVENT_FEATURE_UPDATED); + if (theMessage->eventID() == aFeatureUpdatedId) + { + myPropertyPanel->updateContentWidget(); + } + const Config_PointerMessage* aPartSetMsg = dynamic_cast(theMessage); if (aPartSetMsg) { - ModuleBase_Operation* aOperation = (ModuleBase_Operation*)(aPartSetMsg->pointer()); - setCurrentOperation(aOperation); - if(aOperation->xmlRepresentation().isEmpty()) { //!< No need for property panel - myCurrentOperation->start(); - myCurrentOperation->commit(); - } else { - fillPropertyPanel(aOperation); + ModuleBase_Operation* anOperation = + (ModuleBase_Operation*)(aPartSetMsg->pointer()); + + if (myOperationMgr->startOperation(anOperation)) { + if (anOperation->getDescription()->xmlRepresentation().isEmpty()) { + anOperation->commit(); + updateCommandStatus(); + } } return; } + const Events_Error* anAppError = dynamic_cast(theMessage); + if (anAppError) { + emit errorOccurred(QString::fromLatin1(anAppError->description())); + myErrorDlg->show(); + myErrorDlg->raise(); + myErrorDlg->activateWindow(); + } -#ifdef _DEBUG - qDebug() << "XGUI_Workshop::ProcessEvent: " - << "Catch message, but it can not be processed."; -#endif +} +//****************************************************** +void XGUI_Workshop::onOperationStarted() +{ + ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); + + if(!aOperation->getDescription()->xmlRepresentation().isEmpty()) { //!< No need for property panel + connectWithOperation(aOperation); + + showPropertyPanel(); + + ModuleBase_WidgetFactory aFactory = ModuleBase_WidgetFactory(aOperation); + aFactory.createWidget(myPropertyPanel->contentWidget()); + myPropertyPanel->setModelWidgets(aFactory.getWrappedWidgets()); + myPropertyPanel->setWindowTitle(aOperation->getDescription()->description()); + } +} + +//****************************************************** +void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) +{ + ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); + + if(aOperation->getDescription()->xmlRepresentation().isEmpty()) { //!< No need for property panel + updateCommandStatus(); + } else { + hidePropertyPanel(); + updateCommandStatus(); + myActionsMgr->restoreCommandState(); + } } /* @@ -171,53 +254,44 @@ void XGUI_Workshop::addFeature(const Config_FeatureMessage* theMessage) return; } //Find or create Workbench - XGUI_MainMenu* aMenuBar = myMainWindow->menuObject(); QString aWchName = QString::fromStdString(theMessage->workbenchId()); - XGUI_Workbench* aPage = aMenuBar->findWorkbench(aWchName); - if (!aPage) { - aPage = addWorkbench(aWchName); - } - //Find or create Group - QString aGroupName = QString::fromStdString(theMessage->groupId()); - XGUI_MenuGroupPanel* aGroup = aPage->findGroup(aGroupName); - if (!aGroup) { - aGroup = aPage->addGroup(aGroupName); - } - //Create feature... - QString aFeatureId = QString::fromStdString(theMessage->id()); - XGUI_Command* aCommand = aGroup->addFeature(QString::fromStdString(theMessage->id()), - QString::fromStdString(theMessage->text()), - QString::fromStdString(theMessage->tooltip()), - QIcon(theMessage->icon().c_str()) - //TODO(sbh): QKeySequence - ); - myPartSetModule->featureCreated(aCommand); -} + QString aNestedFeatures = QString::fromStdString(theMessage->nestedFeatures()); + bool isUsePropPanel = theMessage->isUseInput(); + if (isSalomeMode()) { + QString aId = QString::fromStdString(theMessage->id()); + salomeConnector()->addFeature(aWchName, + QString::fromStdString(theMessage->id()), + aId, + QString::fromStdString(theMessage->tooltip()), + QIcon(theMessage->icon().c_str()), + isUsePropPanel, this, + SLOT(onFeatureTriggered()), QKeySequence()); + myActionsMgr->addCommand(aId, salomeConnector()->command(aId)); + salomeConnector()->setNestedActions(aId, aNestedFeatures.split(" ")); -/* - * - */ -void XGUI_Workshop::fillPropertyPanel(ModuleBase_Operation* theOperation) -{ - connectToPropertyPanel(theOperation); - QWidget* aPropWidget = myMainWindow->findChild(XGUI::PROP_PANEL_WDG); - qDeleteAll(aPropWidget->children()); - theOperation->start(); - XGUI_WidgetFactory aFactory = XGUI_WidgetFactory(theOperation); - aFactory.fillWidget(aPropWidget); -} - -void XGUI_Workshop::setCurrentOperation(ModuleBase_Operation* theOperation) -{ - //FIXME: Ask user about aborting of current operation? - if (myCurrentOperation) { - //TODO get isOperation from document - if (myCurrentOperation->isRunning()) - myCurrentOperation->abort(); + } else { - myCurrentOperation->deleteLater(); + XGUI_MainMenu* aMenuBar = myMainWindow->menuObject(); + XGUI_Workbench* aPage = aMenuBar->findWorkbench(aWchName); + if (!aPage) { + aPage = addWorkbench(aWchName); + } + //Find or create Group + QString aGroupName = QString::fromStdString(theMessage->groupId()); + XGUI_MenuGroupPanel* aGroup = aPage->findGroup(aGroupName); + if (!aGroup) { + aGroup = aPage->addGroup(aGroupName); + } + //Create feature... + XGUI_Command* aCommand = aGroup->addFeature(QString::fromStdString(theMessage->id()), + QString::fromStdString(theMessage->text()), + QString::fromStdString(theMessage->tooltip()), + QIcon(theMessage->icon().c_str()), + QKeySequence(), isUsePropPanel); + aCommand->setUnblockableCommands(aNestedFeatures.split(" ")); + myActionsMgr->addCommand(aCommand); + myPartSetModule->featureCreated(aCommand); } - myCurrentOperation = theOperation; } /* @@ -225,21 +299,52 @@ void XGUI_Workshop::setCurrentOperation(ModuleBase_Operation* theOperation) * and given operation. The given operation becomes a * current operation and previous operation if exists */ -void XGUI_Workshop::connectToPropertyPanel(ModuleBase_Operation* theOperation) +void XGUI_Workshop::connectWithOperation(ModuleBase_Operation* theOperation) { - QDockWidget* aPanel = myMainWindow->findChild(XGUI::PROP_PANEL); - QPushButton* aOkBtn = aPanel->findChild(XGUI::PROP_PANEL_OK); + QPushButton* aOkBtn = myPropertyPanel->findChild(XGUI::PROP_PANEL_OK); connect(aOkBtn, SIGNAL(clicked()), theOperation, SLOT(commit())); - QPushButton* aCancelBtn = aPanel->findChild(XGUI::PROP_PANEL_CANCEL); + QPushButton* aCancelBtn = myPropertyPanel->findChild(XGUI::PROP_PANEL_CANCEL); connect(aCancelBtn, SIGNAL(clicked()), theOperation, SLOT(abort())); - connect(theOperation, SIGNAL(started()), myMainWindow, SLOT(showPropertyPanel())); - connect(theOperation, SIGNAL(stopped()), myMainWindow, SLOT(hidePropertyPanel())); + QAction* aCommand = 0; + if (isSalomeMode()) { + aCommand = salomeConnector()->command(theOperation->getDescription()->operationId()); + } else { + XGUI_MainMenu* aMenu = myMainWindow->menuObject(); + aCommand = aMenu->feature(theOperation->getDescription()->operationId()); + } + //Abort operation on uncheck the command + connect(aCommand, SIGNAL(triggered(bool)), theOperation, SLOT(setRunning(bool))); +} + +/* + * Saves document with given name. + */ +void XGUI_Workshop::saveDocument(QString theName) +{ + QApplication::restoreOverrideCursor(); + boost::shared_ptr aMgr = ModelAPI_PluginManager::get(); + boost::shared_ptr aDoc = aMgr->rootDocument(); + aDoc->save(theName.toLatin1().constData()); + QApplication::restoreOverrideCursor(); } //****************************************************** void XGUI_Workshop::onExit() { + boost::shared_ptr aMgr = ModelAPI_PluginManager::get(); + boost::shared_ptr aDoc = aMgr->rootDocument(); + if(aDoc->isModified()) { + int anAnswer = QMessageBox::question( + myMainWindow, tr("Save current file"), + tr("The document is modified, save before exit?"), + QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel); + if(anAnswer == QMessageBox::Save) { + onSave(); + } else if (anAnswer == QMessageBox::Cancel) { + return; + } + } qApp->exit(); } @@ -247,28 +352,104 @@ void XGUI_Workshop::onExit() void XGUI_Workshop::onNew() { QApplication::setOverrideCursor(Qt::WaitCursor); - myMainWindow->showObjectBrowser(); - myMainWindow->showPythonConsole(); - QMdiSubWindow* aWnd = myMainWindow->viewer()->createView(); - aWnd->showMaximized(); + if (objectBrowser() == 0) { + createDockWidgets(); + mySelector->connectViewers(); + } + myViewerProxy->connectToViewer(); + showObjectBrowser(); + if (!isSalomeMode()) { + myMainWindow->showPythonConsole(); + QMdiSubWindow* aWnd = myMainWindow->viewer()->createView(); + aWnd->showMaximized(); + updateCommandStatus(); + } QApplication::restoreOverrideCursor(); } //****************************************************** void XGUI_Workshop::onOpen() { - QString aFileName = QFileDialog::getOpenFileName(mainWindow()); + //save current file before close if modified + boost::shared_ptr aMgr = ModelAPI_PluginManager::get(); + boost::shared_ptr aDoc = aMgr->rootDocument(); + if(aDoc->isModified()) { + //TODO(sbh): re-launch the app? + int anAnswer = QMessageBox::question( + myMainWindow, tr("Save current file"), + tr("The document is modified, save before opening another?"), + QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel); + if(anAnswer == QMessageBox::Save) { + onSave(); + } else if (anAnswer == QMessageBox::Cancel) { + return; + } + aDoc->close(); + myCurrentFile = ""; + } + + //show file dialog, check if readable and open + myCurrentFile = QFileDialog::getOpenFileName(mainWindow()); + if(myCurrentFile.isEmpty()) + return; + QFileInfo aFileInfo(myCurrentFile); + if(!aFileInfo.exists() || !aFileInfo.isReadable()) { + QMessageBox::critical(myMainWindow, tr("Warning"), tr("Unable to open the file.")); + myCurrentFile = ""; + return; + } + QApplication::setOverrideCursor(Qt::WaitCursor); + aDoc->load(myCurrentFile.toLatin1().constData()); + QApplication::restoreOverrideCursor(); + updateCommandStatus(); } //****************************************************** void XGUI_Workshop::onSave() { + if(myCurrentFile.isEmpty()) { + onSaveAs(); + return; + } + saveDocument(myCurrentFile); + updateCommandStatus(); } //****************************************************** void XGUI_Workshop::onSaveAs() { - QString aFileName = QFileDialog::getSaveFileName(mainWindow()); + QString aTemp = myCurrentFile; + myCurrentFile = QFileDialog::getSaveFileName(mainWindow()); + if(myCurrentFile.isEmpty()) { + myCurrentFile = aTemp; + return; + } + QFileInfo aFileInfo(myCurrentFile); + if(aFileInfo.exists() && !aFileInfo.isWritable()) { + QMessageBox::critical(myMainWindow, tr("Warning"), tr("Unable to save the file.")); + return; + } + onSave(); +} + +//****************************************************** +void XGUI_Workshop::onUndo() +{ + objectBrowser()->setCurrentIndex(QModelIndex()); + boost::shared_ptr aMgr = ModelAPI_PluginManager::get(); + boost::shared_ptr aDoc = aMgr->rootDocument(); + aDoc->undo(); + updateCommandStatus(); +} + +//****************************************************** +void XGUI_Workshop::onRedo() +{ + objectBrowser()->setCurrentIndex(QModelIndex()); + boost::shared_ptr aMgr = ModelAPI_PluginManager::get(); + boost::shared_ptr aDoc = aMgr->rootDocument(); + aDoc->redo(); + updateCommandStatus(); } //****************************************************** @@ -340,3 +521,140 @@ bool XGUI_Workshop::activateModule() myPartSetModule->createFeatures(); return true; } + +//****************************************************** +void XGUI_Workshop::updateCommandStatus() +{ + if (isSalomeMode()) // TODO: update commands in SALOME + return; + XGUI_MainMenu* aMenuBar = myMainWindow->menuObject(); + + QList aCommands = aMenuBar->features(); + QList::const_iterator aIt; + + boost::shared_ptr aMgr = ModelAPI_PluginManager::get(); + if (aMgr->hasRootDocument()) { + XGUI_Command* aUndoCmd; + XGUI_Command* aRedoCmd; + for (aIt = aCommands.constBegin(); aIt != aCommands.constEnd(); ++aIt) { + if ((*aIt)->id() == "UNDO_CMD") + aUndoCmd = (*aIt); + else if ((*aIt)->id() == "REDO_CMD") + aRedoCmd = (*aIt); + else // Enable all commands + (*aIt)->enable(); + } + boost::shared_ptr aDoc = aMgr->rootDocument(); + aUndoCmd->setEnabled(aDoc->canUndo()); + aRedoCmd->setEnabled(aDoc->canRedo()); + } else { + for (aIt = aCommands.constBegin(); aIt != aCommands.constEnd(); ++aIt) { + if ((*aIt)->id() == "NEW_CMD") + (*aIt)->enable(); + else if ((*aIt)->id() == "EXIT_CMD") + (*aIt)->enable(); + else + (*aIt)->disable(); + } + } +} + +//****************************************************** +QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent) +{ + QDockWidget* aObjDock = new QDockWidget(theParent); + aObjDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + aObjDock->setWindowTitle(tr("Object browser")); + myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock); + aObjDock->setWidget(myObjectBrowser); + return aObjDock; +} + +//****************************************************** +/* + * Creates dock widgets, places them in corresponding area + * and tabifies if necessary. + */ +void XGUI_Workshop::createDockWidgets() +{ + QMainWindow* aDesktop = isSalomeMode()? salomeConnector()->desktop() : + myMainWindow; + QDockWidget* aObjDock = createObjectBrowser(aDesktop); + aDesktop->addDockWidget(Qt::LeftDockWidgetArea, aObjDock); + myPropertyPanel = new XGUI_PropertyPanel(aDesktop); + aDesktop->addDockWidget(Qt::LeftDockWidgetArea, myPropertyPanel); + hidePropertyPanel(); //tabifyDockWidget(aObjDock, myPropertyPanel); +} + +//****************************************************** +void XGUI_Workshop::showPropertyPanel() +{ + QAction* aViewAct = myPropertyPanel->toggleViewAction(); + //setEnabled(true); + myPropertyPanel->show(); + myPropertyPanel->raise(); +} + +//****************************************************** +void XGUI_Workshop::hidePropertyPanel() +{ + QAction* aViewAct = myPropertyPanel->toggleViewAction(); + //setEnabled(false); + myPropertyPanel->hide(); +} + +//****************************************************** +void XGUI_Workshop::showObjectBrowser() +{ + myObjectBrowser->parentWidget()->show(); +} + +//****************************************************** +void XGUI_Workshop::hideObjectBrowser() +{ + myObjectBrowser->parentWidget()->hide(); +} + +//****************************************************** +void XGUI_Workshop::onFeatureTriggered() +{ + QAction* aCmd = dynamic_cast(sender()); + if (aCmd) { + QString aId = salomeConnector()->commandId(aCmd); + if (!aId.isNull()) + myPartSetModule->launchOperation(aId); + } +} + +//****************************************************** +void XGUI_Workshop::changeCurrentDocument() +{ + QFeatureList aFeatures = objectBrowser()->selectedFeatures(); + + // Set current document + if (aFeatures.size() > 0) { + FeaturePtr aFeature = aFeatures.first(); + + boost::shared_ptr aMgr = ModelAPI_PluginManager::get(); + boost::shared_ptr aDocRef = aFeature->data()->docRef("PartDocument"); + if (aDocRef) + aMgr->setCurrentDocument(aDocRef->value()); + } +} + +//****************************************************** +void XGUI_Workshop::salomeViewerSelectionChanged() +{ + emit salomeViewerSelection(); +} + + +//************************************************************** +XGUI_SalomeViewer* XGUI_Workshop::salomeViewer() const +{ + return mySalomeConnector->viewer(); +}