Salome HOME
d0d12a789749d9d353b746d1f86014fdba6d9f9a
[modules/shaper.git] / src / XGUI / XGUI_Workshop.cpp
1 #include "ModuleBase_IModule.h"
2 #include "XGUI_Constants.h"
3 #include "XGUI_Command.h"
4 #include "XGUI_MainMenu.h"
5 #include "XGUI_MainWindow.h"
6 #include "XGUI_MenuGroupPanel.h"
7 #include "XGUI_Tools.h"
8 #include "XGUI_Workbench.h"
9 #include "XGUI_Workshop.h"
10 #include "XGUI_Viewer.h"
11 #include "XGUI_SelectionMgr.h"
12 #include "XGUI_Selection.h"
13 #include "XGUI_ObjectsBrowser.h"
14 #include "XGUI_Displayer.h"
15 #include "XGUI_OperationMgr.h"
16 #include "XGUI_SalomeConnector.h"
17 #include "XGUI_SalomeViewer.h"
18 #include "XGUI_ActionsMgr.h"
19 #include "XGUI_ErrorDialog.h"
20 #include "XGUI_ViewerProxy.h"
21 #include "XGUI_PropertyPanel.h"
22 #include "XGUI_ContextMenuMgr.h"
23 #include "XGUI_ModuleConnector.h"
24 #include "XGUI_Preferences.h"
25 #include <XGUI_QtEvents.h>
26
27 #include <ModelAPI_Events.h>
28 #include <ModelAPI_Session.h>
29 #include <ModelAPI_Feature.h>
30 #include <ModelAPI_Data.h>
31 #include <ModelAPI_AttributeDocRef.h>
32 #include <ModelAPI_Object.h>
33 #include <ModelAPI_Validator.h>
34 #include <ModelAPI_ResultConstruction.h>
35 #include <ModelAPI_ResultBody.h>
36
37 #include <PartSetPlugin_Part.h>
38
39 #include <Events_Loop.h>
40 #include <Events_Error.h>
41 #include <Events_LongOp.h>
42
43 #include <ModuleBase_Operation.h>
44 #include <ModuleBase_Operation.h>
45 #include <ModuleBase_OperationDescription.h>
46 #include <ModuleBase_SelectionValidator.h>
47 #include "ModuleBase_WidgetFactory.h"
48
49 #include <Config_Common.h>
50 #include <Config_FeatureMessage.h>
51 #include <Config_PointerMessage.h>
52 #include <Config_ModuleReader.h>
53
54 #include <QApplication>
55 #include <QFileDialog>
56 #include <QMessageBox>
57 #include <QMdiSubWindow>
58 #include <QPushButton>
59 #include <QDockWidget>
60 #include <QLayout>
61 #include <QThread>
62 #include <QObject>
63
64 #ifdef _DEBUG
65 #include <QDebug>
66 #include <iostream>
67 #endif
68
69 #ifdef WIN32
70 #include <windows.h>
71 #else
72 #include <dlfcn.h>
73 #endif
74
75 QMap<QString, QString> XGUI_Workshop::myIcons;
76
77 QString XGUI_Workshop::featureIcon(const std::string& theId)
78 {
79   QString aId(theId.c_str());
80   if (myIcons.contains(aId))
81     return myIcons[aId];
82   return QString();
83 }
84
85 XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
86     : QObject(),
87       myCurrentDir(QString()),
88       myModule(NULL),
89       mySalomeConnector(theConnector),
90       myPropertyPanel(0),
91       myObjectBrowser(0),
92       myDisplayer(0),
93       myUpdatePrefs(false),
94       myPartActivating(false)
95 {
96   myMainWindow = mySalomeConnector ? 0 : new XGUI_MainWindow();
97
98   myDisplayer = new XGUI_Displayer(this);
99
100   mySelector = new XGUI_SelectionMgr(this);
101   //connect(mySelector, SIGNAL(selectionChanged()), this, SLOT(updateModuleCommands()));
102
103   myOperationMgr = new XGUI_OperationMgr(this);
104   myActionsMgr = new XGUI_ActionsMgr(this);
105   myErrorDlg = new XGUI_ErrorDialog(myMainWindow);
106   myContextMenuMgr = new XGUI_ContextMenuMgr(this);
107   connect(myContextMenuMgr, SIGNAL(actionTriggered(const QString&, bool)), this,
108           SLOT(onContextMenuCommand(const QString&, bool)));
109
110   myViewerProxy = new XGUI_ViewerProxy(this);
111   connect(myViewerProxy, SIGNAL(selectionChanged()), this, SLOT(updateCommandsOnViewSelection()));
112
113   myModuleConnector = new XGUI_ModuleConnector(this);
114
115   connect(myOperationMgr, SIGNAL(operationStarted()), SLOT(onOperationStarted()));
116   connect(myOperationMgr, SIGNAL(operationResumed()), SLOT(onOperationStarted()));
117   connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)),
118           SLOT(onOperationStopped(ModuleBase_Operation*)));
119   connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit()));
120   connect(myOperationMgr, SIGNAL(operationStarted()), myActionsMgr, SLOT(update()));
121   connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)), myActionsMgr,
122           SLOT(update()));
123   connect(this, SIGNAL(errorOccurred(const QString&)), myErrorDlg, SLOT(addError(const QString&)));
124 }
125
126 //******************************************************
127 XGUI_Workshop::~XGUI_Workshop(void)
128 {
129   delete myDisplayer;
130 }
131
132 //******************************************************
133 void XGUI_Workshop::startApplication()
134 {
135   initMenu();
136   //Initialize event listening
137   Events_Loop* aLoop = Events_Loop::loop();
138   aLoop->registerListener(this, Events_Error::errorID());  //!< Listening application errors.
139   //TODO(sbh): Implement static method to extract event id [SEID]
140   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_LOADED));
141   // TODO Is it good to use non standard event within workshop?
142   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OPERATION_LAUNCHED));
143   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
144   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
145   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
146   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
147   aLoop->registerListener(this, Events_Loop::eventByName("LongOperation"));
148   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_PLUGIN_LOADED));
149   aLoop->registerListener(this, Events_Loop::eventByName("CurrentDocumentChanged"));
150
151   registerValidators();
152   activateModule();
153   if (myMainWindow) {
154     myMainWindow->show();
155     updateCommandStatus();
156   }
157   XGUI_Preferences::loadCustomProps();
158   onNew();
159 }
160
161 //******************************************************
162 void XGUI_Workshop::initMenu()
163 {
164   myContextMenuMgr->createActions();
165
166   if (isSalomeMode()) {
167     // Create only Undo, Redo commands
168     QAction* aAction = salomeConnector()->addEditCommand("UNDO_CMD", tr("Undo"),
169                                                          tr("Undo last command"),
170                                                          QIcon(":pictures/undo.png"),
171                                                          QKeySequence::Undo, false);
172     connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onUndo()));
173     aAction = salomeConnector()->addEditCommand("REDO_CMD", tr("Redo"), tr("Redo last command"),
174                                                 QIcon(":pictures/redo.png"), QKeySequence::Redo,
175                                                 false);
176     connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRedo()));
177     salomeConnector()->addEditMenuSeparator();
178     return;
179   }
180   // File commands group
181   XGUI_MenuGroupPanel* aGroup = myMainWindow->menuObject()->generalPage();
182
183   XGUI_Command* aCommand;
184
185   aCommand = aGroup->addFeature("SAVE_CMD", tr("Save..."), tr("Save the document"),
186                                 QIcon(":pictures/save.png"), QKeySequence::Save);
187   aCommand->connectTo(this, SLOT(onSave()));
188   //aCommand->disable();
189
190   aCommand = aGroup->addFeature("UNDO_CMD", tr("Undo"), tr("Undo last command"),
191                                 QIcon(":pictures/undo.png"), QKeySequence::Undo);
192   aCommand->connectTo(this, SLOT(onUndo()));
193
194   aCommand = aGroup->addFeature("REDO_CMD", tr("Redo"), tr("Redo last command"),
195                                 QIcon(":pictures/redo.png"), QKeySequence::Redo);
196   aCommand->connectTo(this, SLOT(onRedo()));
197
198   aCommand = aGroup->addFeature("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"),
199                                 QIcon(":pictures/rebuild.png"));
200
201   aCommand = aGroup->addFeature("SAVEAS_CMD", tr("Save as..."), tr("Save the document into a file"),
202                                 QIcon(":pictures/save.png"));
203   aCommand->connectTo(this, SLOT(onSaveAs()));
204   //aCommand->disable();
205
206   aCommand = aGroup->addFeature("OPEN_CMD", tr("Open..."), tr("Open a new document"),
207                                 QIcon(":pictures/open.png"), QKeySequence::Open);
208   aCommand->connectTo(this, SLOT(onOpen()));
209
210   //aCommand = aGroup->addFeature("NEW_CMD", tr("New"), tr("Create a new document"),
211   //                              QIcon(":pictures/new.png"), QKeySequence::New);
212   //aCommand->connectTo(this, SLOT(onNew()));
213
214   aCommand = aGroup->addFeature("PREF_CMD", tr("Preferences"), tr("Edit preferences"),
215                                 QIcon(":pictures/preferences.png"), QKeySequence::Preferences);
216   aCommand->connectTo(this, SLOT(onPreferences()));
217
218   aCommand = aGroup->addFeature("EXIT_CMD", tr("Exit"), tr("Exit application"),
219                                 QIcon(":pictures/close.png"), QKeySequence::Close);
220   aCommand->connectTo(this, SLOT(onExit()));
221   //FIXME: SBH's test action. Can be used for some GUI tests.
222 //  #ifdef _DEBUG
223 //    aCommand = aGroup->addFeature("TEST_CMD", "Test!", "Private debug button",
224 //                                  QIcon(":pictures/close.png"), QKeySequence(), true);
225 //    aCommand->connectTo(myMainWindow, SLOT(dockPythonConsole()));
226 //  #endif
227 }
228
229 //******************************************************
230 XGUI_Workbench* XGUI_Workshop::addWorkbench(const QString& theName)
231 {
232   XGUI_MainMenu* aMenuBar = myMainWindow->menuObject();
233   return aMenuBar->addWorkbench(theName);
234 }
235
236 //******************************************************
237 void XGUI_Workshop::processEvent(const boost::shared_ptr<Events_Message>& theMessage)
238 {
239   if (QApplication::instance()->thread() != QThread::currentThread()) {
240     #ifdef _DEBUG
241     std::cout << "XGUI_Workshop::processEvent: " << "Working in another thread." << std::endl;
242     #endif
243     SessionPtr aMgr = ModelAPI_Session::get();
244     PostponeMessageQtEvent* aPostponeEvent = new PostponeMessageQtEvent(theMessage);
245     QApplication::postEvent(this, aPostponeEvent);
246     return;
247   }
248
249   //A message to start feature creation received.
250   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_LOADED)) {
251     boost::shared_ptr<Config_FeatureMessage> aFeatureMsg =
252        boost::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
253     if (!aFeatureMsg->isInternal()) {
254       addFeature(aFeatureMsg);
255     }
256   }
257
258   // Process creation of Part
259   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
260     boost::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
261         boost::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
262     onFeatureCreatedMsg(aUpdMsg);
263     if (myUpdatePrefs) {
264       if (mySalomeConnector)
265         mySalomeConnector->createPreferences();
266       myUpdatePrefs = false;
267     }
268   }
269   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_PLUGIN_LOADED)) {
270     myUpdatePrefs = true;
271   }
272
273   // Redisplay feature
274   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)) {
275     boost::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
276         boost::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
277     onFeatureRedisplayMsg(aUpdMsg);
278   }
279
280   //Update property panel on corresponding message. If there is no current operation (no
281   //property panel), or received message has different feature to the current - do nothing.
282   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
283     boost::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
284         boost::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
285     onFeatureUpdatedMsg(anUpdateMsg);
286   }
287
288   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
289     boost::shared_ptr<ModelAPI_ObjectDeletedMessage> aDelMsg =
290         boost::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
291     onObjectDeletedMsg(aDelMsg);
292   }
293
294   else if (theMessage->eventID() == Events_LongOp::eventID()) {
295     if (Events_LongOp::isPerformed())
296       QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
297     else
298       QApplication::restoreOverrideCursor();
299   }
300
301   //An operation passed by message. Start it, process and commit.
302   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OPERATION_LAUNCHED)) {
303     boost::shared_ptr<Config_PointerMessage> aPartSetMsg =
304         boost::dynamic_pointer_cast<Config_PointerMessage>(theMessage);
305     //myPropertyPanel->cleanContent();
306     ModuleBase_Operation* anOperation = (ModuleBase_Operation*) aPartSetMsg->pointer();
307
308     if (myOperationMgr->startOperation(anOperation)) {
309       myPropertyPanel->updateContentWidget(anOperation->feature());
310       if (!anOperation->getDescription()->hasXmlRepresentation()) {
311         if (anOperation->commit())
312           updateCommandStatus();
313       }
314     }
315   }
316   else if (theMessage->eventID() == Events_Loop::loop()->eventByName("CurrentDocumentChanged")) {
317     // Find and Activate active part
318     if (myPartActivating)
319       return;
320     SessionPtr aMgr = ModelAPI_Session::get();
321     DocumentPtr aActiveDoc = aMgr->activeDocument();
322     DocumentPtr aDoc = aMgr->moduleDocument();
323     if (aActiveDoc == aDoc) {
324       activatePart(ResultPartPtr()); 
325       return;
326     }
327     std::string aGrpName = ModelAPI_ResultPart::group();
328     for (int i = 0; i < aDoc->size(aGrpName); i++) {
329       ResultPartPtr aPart = boost::dynamic_pointer_cast<ModelAPI_ResultPart>(aDoc->object(aGrpName, i));
330       if (aPart->partDoc() == aActiveDoc) {
331         activatePart(aPart); // Activate a part which corresponds to active Doc
332         return;
333       }
334     }
335     // If not found then activate global document
336     activatePart(ResultPartPtr()); 
337
338   } else {
339     //Show error dialog if error message received.
340     boost::shared_ptr<Events_Error> anAppError = boost::dynamic_pointer_cast<Events_Error>(theMessage);
341     if (anAppError) {
342       emit errorOccurred(QString::fromLatin1(anAppError->description()));
343     }
344   }
345   if (!isSalomeMode()) {
346     SessionPtr aMgr = ModelAPI_Session::get();
347     if (aMgr->isModified() != myMainWindow->isModifiedState())
348       myMainWindow->setModifiedState(aMgr->isModified());
349   }
350 }
351
352
353 //******************************************************
354 void XGUI_Workshop::onStartWaiting()
355 {
356   if (Events_LongOp::isPerformed()) {
357     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
358   }
359 }
360
361 //******************************************************
362 void XGUI_Workshop::onFeatureUpdatedMsg(const boost::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
363 {
364   std::set<ObjectPtr> aFeatures = theMsg->objects();
365   if (myOperationMgr->hasOperation()) {
366     FeaturePtr aCurrentFeature = myOperationMgr->currentOperation()->feature();
367     std::set<ObjectPtr>::const_iterator aIt;
368     for (aIt = aFeatures.begin(); aIt != aFeatures.end(); ++aIt) {
369       ObjectPtr aNewFeature = (*aIt);
370       if (aNewFeature == aCurrentFeature) {
371         myPropertyPanel->updateContentWidget(aCurrentFeature);
372         break;
373       }
374     }
375   }
376   myOperationMgr->validateCurrentOperation();
377   if (myObjectBrowser)
378     myObjectBrowser->processEvent(theMsg);
379 }
380
381 //******************************************************
382 void XGUI_Workshop::onFeatureRedisplayMsg(const boost::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
383 {
384   std::set<ObjectPtr> aObjects = theMsg->objects();
385   std::set<ObjectPtr>::const_iterator aIt;
386   for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
387     ObjectPtr aObj = (*aIt);
388     if (!aObj->data() || !aObj->data()->isValid())
389       myDisplayer->erase(aObj, false);
390     else {
391       if (myDisplayer->isVisible(aObj))  // TODO VSV: Correction sketch drawing
392         myDisplayer->display(aObj, false);  // In order to update presentation
393       else {
394         if (myOperationMgr->hasOperation()) {
395           ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
396           if (aOperation->hasObject(aObj)) {  // Display only current operation results
397             myDisplayer->display(aObj, false);
398           }
399         }
400       }
401     }
402   }
403   myDisplayer->updateViewer();
404 }
405
406 //******************************************************
407 void XGUI_Workshop::onFeatureCreatedMsg(const boost::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
408 {
409   std::set<ObjectPtr> aObjects = theMsg->objects();
410
411   std::set<ObjectPtr>::const_iterator aIt;
412   bool aHasPart = false;
413   bool isDisplayed = false;
414   for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
415     ResultPartPtr aPart = boost::dynamic_pointer_cast<ModelAPI_ResultPart>(*aIt);
416     if (aPart) {
417       aHasPart = true;
418       // If a feature is created from the aplication's python console  
419       // it doesn't stored in the operation mgr and doesn't displayed
420     } else if (myOperationMgr->hasOperation()) {
421       ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
422       if (aOperation->hasObject(*aIt)) {  // Display only current operation results
423         myDisplayer->display(*aIt, false);
424         isDisplayed = true;
425       }
426     }
427   }
428   if (myObjectBrowser)
429     myObjectBrowser->processEvent(theMsg);
430   if (isDisplayed)
431     myDisplayer->updateViewer();
432   if (aHasPart) {
433     activateLastPart();
434   }
435 }
436
437 //******************************************************
438 void XGUI_Workshop::onObjectDeletedMsg(const boost::shared_ptr<ModelAPI_ObjectDeletedMessage>& theMsg)
439 {
440   if (myObjectBrowser)
441     myObjectBrowser->processEvent(theMsg);
442   //std::set<ObjectPtr> aFeatures = theMsg->objects();
443 }
444
445 //******************************************************
446 void XGUI_Workshop::onOperationStarted()
447 {
448   ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
449   if (this->isSalomeMode()) 
450     aOperation->setNestedFeatures(mySalomeConnector->nestedActions(aOperation->id()));
451   else 
452     aOperation->setNestedFeatures(myActionsMgr->nestedCommands(aOperation->id()));
453   
454   if (aOperation->getDescription()->hasXmlRepresentation()) {  //!< No need for property panel
455     connectWithOperation(aOperation);
456
457     showPropertyPanel();
458     QString aXmlRepr = aOperation->getDescription()->xmlRepresentation();
459     ModuleBase_WidgetFactory aFactory = ModuleBase_WidgetFactory(aXmlRepr.toStdString(),
460                                                                  myModuleConnector);
461
462     myPropertyPanel->cleanContent();
463     aFactory.createWidget(myPropertyPanel->contentWidget());
464
465     QList<ModuleBase_ModelWidget*> aWidgets = aFactory.getModelWidgets();
466     QList<ModuleBase_ModelWidget*>::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end();
467     ModuleBase_ModelWidget* aWidget;
468     for (; anIt != aLast; anIt++) {
469       aWidget = *anIt;
470       aWidget->setFeature(aOperation->feature());
471       QObject::connect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onWidgetValuesChanged()));
472       // Init default values
473       if (!aOperation->isEditOperation() && !aWidget->isComputedDefault()) {
474         aWidget->storeValue();
475       }
476     }
477
478     myPropertyPanel->setModelWidgets(aWidgets);
479     myPropertyPanel->setWindowTitle(aOperation->getDescription()->description());
480   }
481   updateCommandStatus();
482 }
483
484 //******************************************************
485 void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
486 {
487   //!< No need for property panel
488   updateCommandStatus();
489   hidePropertyPanel();
490   myPropertyPanel->cleanContent();
491 }
492
493 bool XGUI_Workshop::event(QEvent * theEvent)
494 {
495   PostponeMessageQtEvent* aPostponedEv = dynamic_cast<PostponeMessageQtEvent*>(theEvent);
496   if (aPostponedEv) {
497 #ifdef _DEBUG
498     std::cout << "XGUI_Workshop::event " << "Got PostponeMessageQtEvent" << std::endl;
499     bool isMyThread = (QApplication::instance()->thread() == QThread::currentThread());
500     std::cout << "XGUI_Workshop::event " << "I am in the Qt's thread: "
501               << isMyThread << std::endl;
502 #endif
503     boost::shared_ptr<Events_Message> aEventPtr = aPostponedEv->postponedMessage();
504     processEvent(aEventPtr);
505     return true;
506   }
507   return false;
508 }
509
510 /*
511  *
512  */
513 void XGUI_Workshop::addFeature(const boost::shared_ptr<Config_FeatureMessage>& theMessage)
514 {
515   if (!theMessage) {
516 #ifdef _DEBUG
517     qDebug() << "XGUI_Workshop::addFeature: NULL message.";
518 #endif
519     return;
520   }
521   // Remember features icons
522   myIcons[QString::fromStdString(theMessage->id())] = QString::fromStdString(theMessage->icon());
523
524   //Find or create Workbench
525   QString aWchName = QString::fromStdString(theMessage->workbenchId());
526   QString aNestedFeatures = QString::fromStdString(theMessage->nestedFeatures());
527   bool isUsePropPanel = theMessage->isUseInput();
528   QString aFeatureId = QString::fromStdString(theMessage->id());
529   if (isSalomeMode()) {
530     QAction* aAction = salomeConnector()->addFeature(aWchName, aFeatureId,
531                                                      QString::fromStdString(theMessage->text()),
532                                                      QString::fromStdString(theMessage->tooltip()),
533                                                      QIcon(theMessage->icon().c_str()),
534                                                      QKeySequence(), isUsePropPanel);
535     salomeConnector()->setNestedActions(aFeatureId, aNestedFeatures.split(" ", QString::SkipEmptyParts));
536     myActionsMgr->addCommand(aAction);
537     myModule->featureCreated(aAction);
538   } else {
539
540     XGUI_MainMenu* aMenuBar = myMainWindow->menuObject();
541     XGUI_Workbench* aPage = aMenuBar->findWorkbench(aWchName);
542     if (!aPage) {
543       aPage = addWorkbench(aWchName);
544     }
545     //Find or create Group
546     QString aGroupName = QString::fromStdString(theMessage->groupId());
547     XGUI_MenuGroupPanel* aGroup = aPage->findGroup(aGroupName);
548     if (!aGroup) {
549       aGroup = aPage->addGroup(aGroupName);
550     }
551     // Check if hotkey sequence is already defined:
552     QKeySequence aHotKey = myActionsMgr->registerShortcut(
553         QString::fromStdString(theMessage->keysequence()));
554     // Create feature...
555     XGUI_Command* aCommand = aGroup->addFeature(aFeatureId,
556                                                 QString::fromStdString(theMessage->text()),
557                                                 QString::fromStdString(theMessage->tooltip()),
558                                                 QIcon(theMessage->icon().c_str()), aHotKey,
559                                                 isUsePropPanel);
560     aCommand->setNestedCommands(aNestedFeatures.split(" ", QString::SkipEmptyParts));
561     myActionsMgr->addCommand(aCommand);
562     myModule->featureCreated(aCommand);
563   }
564 }
565
566 /*
567  * Makes a signal/slot connections between Property Panel
568  * and given operation. The given operation becomes a
569  * current operation and previous operation if exists
570  */
571 void XGUI_Workshop::connectWithOperation(ModuleBase_Operation* theOperation)
572 {
573   QAction* aCommand = 0;
574   if (isSalomeMode()) {
575     aCommand = salomeConnector()->command(theOperation->getDescription()->operationId());
576   } else {
577     XGUI_MainMenu* aMenu = myMainWindow->menuObject();
578     aCommand = aMenu->feature(theOperation->getDescription()->operationId());
579   }
580   //Abort operation on uncheck the command
581   if (aCommand)
582     connect(aCommand, SIGNAL(triggered(bool)), theOperation, SLOT(setRunning(bool)));
583 }
584
585 /*
586  * Saves document with given name.
587  */
588 void XGUI_Workshop::saveDocument(const QString& theName, std::list<std::string>& theFileNames)
589 {
590   QApplication::restoreOverrideCursor();
591   SessionPtr aMgr = ModelAPI_Session::get();
592   aMgr->save(theName.toLatin1().constData(), theFileNames);
593   QApplication::restoreOverrideCursor();
594 }
595
596 bool XGUI_Workshop::isActiveOperationAborted()
597 {
598   if(!myOperationMgr->hasOperation())
599     return true;
600   return myOperationMgr->abortOperation();
601 }
602
603 //******************************************************
604 void XGUI_Workshop::onExit()
605 {
606   SessionPtr aMgr = ModelAPI_Session::get();
607   if (aMgr->isModified()) {
608     int anAnswer = QMessageBox::question(
609         myMainWindow, tr("Save current file"), tr("The document is modified, save before exit?"),
610         QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel);
611     if (anAnswer == QMessageBox::Save) {
612       bool saved = onSave();
613       if (!saved) {
614         return;
615       }
616     } else if (anAnswer == QMessageBox::Cancel) {
617       return;
618     }
619   }
620   qApp->exit();
621 }
622
623 //******************************************************
624 void XGUI_Workshop::onNew()
625 {
626   QApplication::setOverrideCursor(Qt::WaitCursor);
627   if (objectBrowser() == 0) {
628     createDockWidgets();
629     mySelector->connectViewers();
630   }
631   myViewerProxy->connectToViewer();
632   showObjectBrowser();
633   if (!isSalomeMode()) {
634     myMainWindow->showPythonConsole();
635     QMdiSubWindow* aWnd = myMainWindow->viewer()->createView();
636     aWnd->showMaximized();
637     updateCommandStatus();
638   }
639   myContextMenuMgr->connectViewer();
640   QApplication::restoreOverrideCursor();
641 }
642
643 //******************************************************
644 void XGUI_Workshop::onOpen()
645 {
646   if(!isActiveOperationAborted())
647     return;
648   //save current file before close if modified
649   SessionPtr aSession = ModelAPI_Session::get();
650   if (aSession->isModified()) {
651     //TODO(sbh): re-launch the app?
652     int anAnswer = QMessageBox::question(
653         myMainWindow, tr("Save current file"),
654         tr("The document is modified, save before opening another?"),
655         QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel);
656     if (anAnswer == QMessageBox::Save) {
657       onSave();
658     } else if (anAnswer == QMessageBox::Cancel) {
659       return;
660     }
661     aSession->moduleDocument()->close();
662     myCurrentDir = "";
663   }
664
665   //show file dialog, check if readable and open
666   myCurrentDir = QFileDialog::getExistingDirectory(mainWindow());
667   if (myCurrentDir.isEmpty())
668     return;
669   QFileInfo aFileInfo(myCurrentDir);
670   if (!aFileInfo.exists() || !aFileInfo.isReadable()) {
671     QMessageBox::critical(myMainWindow, tr("Warning"), tr("Unable to open the file."));
672     myCurrentDir = "";
673     return;
674   }
675   QApplication::setOverrideCursor(Qt::WaitCursor);
676   aSession->load(myCurrentDir.toLatin1().constData());
677   myObjectBrowser->rebuildDataTree();
678   displayAllResults();
679   updateCommandStatus();
680   QApplication::restoreOverrideCursor();
681 }
682
683 //******************************************************
684 bool XGUI_Workshop::onSave()
685 {
686   if(!isActiveOperationAborted())
687     return false;
688   if (myCurrentDir.isEmpty()) {
689     return onSaveAs();
690   }
691   std::list<std::string> aFiles;
692   saveDocument(myCurrentDir, aFiles);
693   updateCommandStatus();
694   myMainWindow->setModifiedState(false);
695   return true;
696 }
697
698 //******************************************************
699 bool XGUI_Workshop::onSaveAs()
700 {
701   if(!isActiveOperationAborted())
702     return false;
703   QFileDialog dialog(mainWindow());
704   dialog.setWindowTitle(tr("Select directory to save files..."));
705   dialog.setFileMode(QFileDialog::Directory);
706   dialog.setFilter(tr("Folders (*)"));
707   dialog.setOptions(QFileDialog::HideNameFilterDetails | QFileDialog::ShowDirsOnly);
708   dialog.setViewMode(QFileDialog::Detail);
709
710   if (!dialog.exec()) {
711     return false;
712   }
713   QString aTempDir = dialog.selectedFiles().first();
714   QDir aDir(aTempDir);
715   if (aDir.exists() && !aDir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).isEmpty()) {
716     int answer = QMessageBox::question(
717         myMainWindow,
718         //: Title of the dialog which asks user if he wants to save study in existing non-empty folder
719         tr("Save"),
720         tr("The folder already contains some files, save anyway?"),
721         QMessageBox::Save | QMessageBox::Cancel);
722     if (answer == QMessageBox::Cancel) {
723       return false;
724     }
725   }
726   myCurrentDir = aTempDir;
727   if (!isSalomeMode()) {
728     myMainWindow->setCurrentDir(myCurrentDir, false);
729     myMainWindow->setModifiedState(false);
730   }
731   return onSave();
732 }
733
734 //******************************************************
735 void XGUI_Workshop::onUndo()
736 {
737   objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
738   SessionPtr aMgr = ModelAPI_Session::get();
739   if (aMgr->isOperation())
740     operationMgr()->abortOperation();
741   aMgr->undo();
742   updateCommandStatus();
743 }
744
745 //******************************************************
746 void XGUI_Workshop::onRedo()
747 {
748   objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
749   SessionPtr aMgr = ModelAPI_Session::get();
750   if (aMgr->isOperation())
751     operationMgr()->abortOperation();
752   aMgr->redo();
753   updateCommandStatus();
754 }
755
756 //******************************************************
757 void XGUI_Workshop::onPreferences()
758 {
759   XGUI_Prefs aModif;
760   XGUI_Preferences::editPreferences(aModif);
761   if (aModif.size() > 0) {
762     QString aSection;
763     foreach (XGUI_Pref aPref, aModif)
764     {
765       aSection = aPref.first;
766       if (aSection == XGUI_Preferences::VIEWER_SECTION) {
767         if (!isSalomeMode())
768           myMainWindow->viewer()->updateFromResources();
769       } else if (aSection == XGUI_Preferences::MENU_SECTION) {
770         if (!isSalomeMode())
771           myMainWindow->menuObject()->updateFromResources();
772       }
773     }
774   }
775 }
776
777 //******************************************************
778 ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule)
779 {
780   QString libName = QString::fromStdString(library(theModule.toStdString()));
781   if (libName.isEmpty()) {
782     qWarning(qPrintable(tr("Information about module \"%1\" doesn't exist.").arg(theModule)));
783     return 0;
784   }
785
786   QString err;
787   CREATE_FUNC crtInst = 0;
788
789 #ifdef WIN32
790   HINSTANCE modLib = ::LoadLibrary((LPTSTR) qPrintable(libName));
791   if (!modLib) {
792     LPVOID lpMsgBuf;
793     ::FormatMessage(
794         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
795         0, ::GetLastError(), 0, (LPTSTR) & lpMsgBuf, 0, 0);
796     QString aMsg((char*) &lpMsgBuf);
797     err = QString("Failed to load  %1. %2").arg(libName).arg(aMsg);
798     ::LocalFree(lpMsgBuf);
799   } else {
800     crtInst = (CREATE_FUNC) ::GetProcAddress(modLib, CREATE_MODULE);
801     if (!crtInst) {
802       LPVOID lpMsgBuf;
803       ::FormatMessage(
804           FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
805               | FORMAT_MESSAGE_IGNORE_INSERTS,
806           0, ::GetLastError(), 0, (LPTSTR) & lpMsgBuf, 0, 0);
807       QString aMsg((char*) &lpMsgBuf);
808       err = QString("Failed to find  %1 function. %2").arg( CREATE_MODULE).arg(aMsg);
809       ::LocalFree(lpMsgBuf);
810     }
811   }
812 #else
813   void* modLib = dlopen( libName.toLatin1(), RTLD_LAZY | RTLD_GLOBAL );
814   if ( !modLib ) {
815     err = QString( "Can not load library %1. %2" ).arg( libName ).arg( dlerror() );
816   } else {
817     crtInst = (CREATE_FUNC)dlsym( modLib, CREATE_MODULE );
818     if ( !crtInst ) {
819       err = QString( "Failed to find function %1. %2" ).arg( CREATE_MODULE ).arg( dlerror() );
820     }
821   }
822 #endif
823
824   ModuleBase_IModule* aModule = crtInst ? crtInst(this) : 0;
825
826   if (!err.isEmpty()) {
827     if (mainWindow()) {
828       QMessageBox::warning(mainWindow(), tr("Error"), err);
829     } else {
830       qWarning(qPrintable(err));
831     }
832   }
833   return aModule;
834 }
835
836 //******************************************************
837 bool XGUI_Workshop::activateModule()
838 {
839   Config_ModuleReader aModuleReader;
840   QString moduleName = QString::fromStdString(aModuleReader.getModuleName());
841   myModule = loadModule(moduleName);
842   if (!myModule)
843     return false;
844   myModule->createFeatures();
845   myActionsMgr->update();
846   return true;
847 }
848
849 //******************************************************
850 void XGUI_Workshop::updateCommandStatus()
851 {
852   QList<QAction*> aCommands;
853   if (isSalomeMode()) {  // update commands in SALOME mode
854     aCommands = salomeConnector()->commandList();
855   } else {
856     XGUI_MainMenu* aMenuBar = myMainWindow->menuObject();
857     foreach (XGUI_Command* aCmd, aMenuBar->features())
858       aCommands.append(aCmd);
859   }
860   SessionPtr aMgr = ModelAPI_Session::get();
861   if (aMgr->hasModuleDocument()) {
862     QAction* aUndoCmd;
863     QAction* aRedoCmd;
864     foreach(QAction* aCmd, aCommands)
865     {
866       QString aId = aCmd->data().toString();
867       if (aId == "UNDO_CMD")
868         aUndoCmd = aCmd;
869       else if (aId == "REDO_CMD")
870         aRedoCmd = aCmd;
871       else
872         // Enable all commands
873         aCmd->setEnabled(true);
874     }
875     aUndoCmd->setEnabled(aMgr->canUndo());
876     aRedoCmd->setEnabled(aMgr->canRedo());
877   } else {
878     foreach(QAction* aCmd, aCommands)
879     {
880       QString aId = aCmd->data().toString();
881       if (aId == "NEW_CMD")
882         aCmd->setEnabled(true);
883       else if (aId == "EXIT_CMD")
884         aCmd->setEnabled(true);
885       else
886         aCmd->setEnabled(false);
887     }
888   }
889   myActionsMgr->update();
890 }
891
892 //******************************************************
893 QList<QAction*> XGUI_Workshop::getModuleCommands() const
894 {
895   QList<QAction*> aCommands;
896   if (isSalomeMode()) {  // update commands in SALOME mode
897     aCommands = salomeConnector()->commandList();
898   } else {
899     XGUI_MainMenu* aMenuBar = myMainWindow->menuObject();
900     foreach(XGUI_Command* aCmd, aMenuBar->features())
901     {
902       aCommands.append(aCmd);
903     }
904   }
905   return aCommands;
906 }
907
908 //******************************************************
909 QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent)
910 {
911   QDockWidget* aObjDock = new QDockWidget(theParent);
912   aObjDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
913   aObjDock->setWindowTitle(tr("Object browser"));
914   aObjDock->setStyleSheet(
915       "::title { position: relative; padding-left: 5px; text-align: left center }");
916   myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock);
917   connect(myObjectBrowser, SIGNAL(activePartChanged(ObjectPtr)), this,
918           SLOT(changeCurrentDocument(ObjectPtr)));
919   aObjDock->setWidget(myObjectBrowser);
920
921   myContextMenuMgr->connectObjectBrowser();
922   return aObjDock;
923 }
924
925 //******************************************************
926 /*
927  * Creates dock widgets, places them in corresponding area
928  * and tabifies if necessary.
929  */
930 void XGUI_Workshop::createDockWidgets()
931 {
932   QMainWindow* aDesktop = isSalomeMode() ? salomeConnector()->desktop() : myMainWindow;
933   QDockWidget* aObjDock = createObjectBrowser(aDesktop);
934   aDesktop->addDockWidget(Qt::LeftDockWidgetArea, aObjDock);
935   myPropertyPanel = new XGUI_PropertyPanel(aDesktop);
936   myPropertyPanel->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
937   aDesktop->addDockWidget(Qt::LeftDockWidgetArea, myPropertyPanel);
938   hidePropertyPanel();  //<! Invisible by default
939   hideObjectBrowser();
940   aDesktop->tabifyDockWidget(aObjDock, myPropertyPanel);
941
942   QPushButton* aOkBtn = myPropertyPanel->findChild<QPushButton*>(XGUI::PROP_PANEL_OK);
943   connect(aOkBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onCommitOperation()));
944   QPushButton* aCancelBtn = myPropertyPanel->findChild<QPushButton*>(XGUI::PROP_PANEL_CANCEL);
945   connect(aCancelBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onAbortOperation()));
946 //TODO(sbh): KeyReleasedProblem
947   connect(myPropertyPanel, SIGNAL(keyReleased(QKeyEvent*)), myOperationMgr,
948           SLOT(onKeyReleased(QKeyEvent*)));
949
950   connect(myPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)), myOperationMgr,
951           SLOT(onWidgetActivated(ModuleBase_ModelWidget*)));
952   connect(myOperationMgr, SIGNAL(activateNextWidget(ModuleBase_ModelWidget*)), myPropertyPanel,
953           SLOT(onActivateNextWidget(ModuleBase_ModelWidget*)));
954   connect(myOperationMgr, SIGNAL(operationValidated(bool)), myPropertyPanel,
955           SLOT(setAcceptEnabled(bool)));
956
957 }
958
959 //******************************************************
960 void XGUI_Workshop::showPropertyPanel()
961 {
962   QAction* aViewAct = myPropertyPanel->toggleViewAction();
963   //<! Restore ability to close panel from the window's menu
964   aViewAct->setEnabled(true);
965   myPropertyPanel->show();
966   myPropertyPanel->raise();
967 }
968
969 //******************************************************
970 void XGUI_Workshop::hidePropertyPanel()
971 {
972   QAction* aViewAct = myPropertyPanel->toggleViewAction();
973   //<! Do not allow to show empty property panel
974   aViewAct->setEnabled(false);
975   myPropertyPanel->hide();
976 }
977
978 //******************************************************
979 void XGUI_Workshop::showObjectBrowser()
980 {
981   myObjectBrowser->parentWidget()->show();
982 }
983
984 //******************************************************
985 void XGUI_Workshop::hideObjectBrowser()
986 {
987   myObjectBrowser->parentWidget()->hide();
988 }
989
990 //******************************************************
991 void XGUI_Workshop::onFeatureTriggered()
992 {
993   QAction* aCmd = dynamic_cast<QAction*>(sender());
994   if (aCmd) {
995     QString aId = salomeConnector()->commandId(aCmd);
996     if (!aId.isNull())
997       myModule->launchOperation(aId);
998   }
999 }
1000
1001 //******************************************************
1002 void XGUI_Workshop::changeCurrentDocument(ObjectPtr theObj)
1003 {
1004   SessionPtr aMgr = ModelAPI_Session::get();
1005   if (theObj) {
1006     ResultPartPtr aPart = boost::dynamic_pointer_cast<ModelAPI_ResultPart>(theObj);
1007     if (aPart) {
1008       DocumentPtr aPartDoc = aPart->partDoc();
1009       if (aPartDoc) {
1010         aMgr->setActiveDocument(aPartDoc);
1011         return;
1012       }
1013     }
1014   }
1015   aMgr->setActiveDocument(aMgr->moduleDocument());
1016 }
1017
1018 //******************************************************
1019 void XGUI_Workshop::salomeViewerSelectionChanged()
1020 {
1021   emit salomeViewerSelection();
1022 }
1023
1024 //**************************************************************
1025 XGUI_SalomeViewer* XGUI_Workshop::salomeViewer() const
1026 {
1027   return mySalomeConnector->viewer();
1028 }
1029
1030 //**************************************************************
1031 void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
1032 {
1033   QList<ObjectPtr> aObjects = mySelector->selection()->selectedObjects();
1034   if ((theId == "ACTIVATE_PART_CMD") && (aObjects.size() > 0)) {
1035     ResultPartPtr aPart = boost::dynamic_pointer_cast<ModelAPI_ResultPart>(aObjects.first());
1036     activatePart(aPart);
1037   } else if (theId == "DEACTIVATE_PART_CMD")
1038     activatePart(ResultPartPtr());
1039   else if (theId == "DELETE_CMD")
1040     deleteObjects(aObjects);
1041   else if (theId == "SHOW_CMD")
1042     showObjects(aObjects, true);
1043   else if (theId == "HIDE_CMD")
1044     showObjects(aObjects, false);
1045   else if (theId == "SHOW_ONLY_CMD")
1046     showOnlyObjects(aObjects);
1047 }
1048
1049 //**************************************************************
1050 void XGUI_Workshop::onWidgetValuesChanged()
1051 {
1052   ModuleBase_Operation* anOperation = myOperationMgr->currentOperation();
1053   FeaturePtr aFeature = anOperation->feature();
1054
1055   ModuleBase_ModelWidget* aSenderWidget = dynamic_cast<ModuleBase_ModelWidget*>(sender());
1056   //if (aCustom)
1057   //  aCustom->storeValue(aFeature);
1058
1059   const QList<ModuleBase_ModelWidget*>& aWidgets = myPropertyPanel->modelWidgets();
1060   QList<ModuleBase_ModelWidget*>::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end();
1061   for (; anIt != aLast; anIt++) {
1062     ModuleBase_ModelWidget* aCustom = *anIt;
1063     if (aCustom && (/*!aCustom->isInitialized(aFeature) ||*/aCustom == aSenderWidget)) {
1064       //aCustom->storeValue(aFeature);
1065       aCustom->storeValue();
1066     }
1067   }
1068 }
1069
1070 //**************************************************************
1071 void XGUI_Workshop::activatePart(ResultPartPtr theFeature)
1072 {
1073   if (!myPartActivating) {
1074     myPartActivating = true;
1075     if (theFeature)
1076       theFeature->activate();
1077     changeCurrentDocument(theFeature);
1078     myObjectBrowser->activatePart(theFeature);
1079     myPartActivating = false;
1080   }
1081 }
1082
1083 //**************************************************************
1084 void XGUI_Workshop::activateLastPart()
1085 {
1086   SessionPtr aMgr = ModelAPI_Session::get();
1087   DocumentPtr aDoc = aMgr->moduleDocument();
1088   std::string aGrpName = ModelAPI_ResultPart::group();
1089   ObjectPtr aLastPart = aDoc->object(aGrpName, aDoc->size(aGrpName) - 1);
1090   ResultPartPtr aPart = boost::dynamic_pointer_cast<ModelAPI_ResultPart>(aLastPart);
1091   if (aPart) {
1092     activatePart(aPart);
1093   }
1094 }
1095
1096 //**************************************************************
1097 void XGUI_Workshop::deleteObjects(const QList<ObjectPtr>& theList)
1098 {
1099   QMainWindow* aDesktop = isSalomeMode() ? salomeConnector()->desktop() : myMainWindow;
1100   QMessageBox::StandardButton aRes = QMessageBox::warning(
1101       aDesktop, tr("Delete features"), tr("Seleted features will be deleted. Continue?"),
1102       QMessageBox::No | QMessageBox::Yes, QMessageBox::No);
1103   // ToDo: definbe deleting method
1104   if (aRes == QMessageBox::Yes) {
1105     SessionPtr aMgr = ModelAPI_Session::get();
1106     aMgr->startOperation();
1107     foreach (ObjectPtr aObj, theList)
1108     {
1109       ResultPartPtr aPart = boost::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
1110       if (aPart) {
1111         DocumentPtr aDoc = aPart->document();
1112         if (aDoc == aMgr->activeDocument()) {
1113           aDoc->close();
1114         }
1115         //aMgr->moduleDocument()->removeFeature(aPart->owner());
1116       } else {
1117         FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
1118         if (aFeature)
1119           aObj->document()->removeFeature(aFeature);
1120       }
1121     }
1122     myDisplayer->updateViewer();
1123     aMgr->finishOperation();
1124   }
1125 }
1126
1127 //**************************************************************
1128 void XGUI_Workshop::showObjects(const QList<ObjectPtr>& theList, bool isVisible)
1129 {
1130   foreach (ObjectPtr aObj, theList)
1131   {
1132     ResultPtr aRes = boost::dynamic_pointer_cast<ModelAPI_Result>(aObj);
1133     if (aRes) {
1134       if (isVisible) {
1135         myDisplayer->display(aRes, false);
1136       } else {
1137         myDisplayer->erase(aRes, false);
1138       }
1139     }
1140   }
1141   myDisplayer->updateViewer();
1142 }
1143
1144 //**************************************************************
1145 void XGUI_Workshop::showOnlyObjects(const QList<ObjectPtr>& theList)
1146 {
1147   myDisplayer->eraseAll(false);
1148   showObjects(theList, true);
1149 }
1150
1151
1152 //**************************************************************
1153 void XGUI_Workshop::updateCommandsOnViewSelection()
1154 {
1155   SessionPtr aMgr = ModelAPI_Session::get();
1156   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
1157   XGUI_Selection* aSelection = mySelector->selection();
1158   if (aSelection->getSelected().size() == 0)
1159     return;
1160
1161   QList<QAction*> aActions = getModuleCommands();
1162   foreach(QAction* aAction, aActions)
1163   {
1164     QString aId = aAction->data().toString();
1165     std::list<ModelAPI_Validator*> aValidators;
1166     std::list<std::list<std::string> > anArguments;
1167     aFactory->validators(aId.toStdString(), aValidators, anArguments);
1168     std::list<ModelAPI_Validator*>::iterator aValidator = aValidators.begin();
1169     for (; aValidator != aValidators.end(); aValidator++) {
1170       if (*aValidator) {
1171         const ModuleBase_SelectionValidator* aSelValidator =
1172             dynamic_cast<const ModuleBase_SelectionValidator*>(*aValidator);
1173         if (aSelValidator) {
1174           aAction->setEnabled(aSelValidator->isValid(aSelection));
1175         }
1176       }
1177     }
1178   }
1179 }
1180
1181 //**************************************************************
1182 void XGUI_Workshop::registerValidators() const
1183 {
1184   SessionPtr aMgr = ModelAPI_Session::get();
1185   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
1186 }
1187
1188 //**************************************************************
1189 void XGUI_Workshop::displayAllResults()
1190 {
1191   SessionPtr aMgr = ModelAPI_Session::get();
1192   DocumentPtr aRootDoc = aMgr->moduleDocument();
1193   displayDocumentResults(aRootDoc);
1194   for (int i = 0; i < aRootDoc->size(ModelAPI_ResultPart::group()); i++) {
1195     ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), i);
1196     ResultPartPtr aPart = boost::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
1197     displayDocumentResults(aPart->partDoc());
1198   }
1199   myDisplayer->updateViewer();
1200 }
1201
1202 //**************************************************************
1203 void XGUI_Workshop::displayDocumentResults(DocumentPtr theDoc)
1204 {
1205   if (!theDoc)
1206     return;
1207   displayGroupResults(theDoc, ModelAPI_ResultConstruction::group());
1208   displayGroupResults(theDoc, ModelAPI_ResultBody::group());
1209 }
1210
1211 //**************************************************************
1212 void XGUI_Workshop::displayGroupResults(DocumentPtr theDoc, std::string theGroup)
1213 {
1214   for (int i = 0; i < theDoc->size(theGroup); i++)
1215     myDisplayer->display(theDoc->object(theGroup, i), false);
1216 }