]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_Workshop.cpp
Salome HOME
Draft of transparency
[modules/shaper.git] / src / XGUI / XGUI_Workshop.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "XGUI_Workshop.h"
22
23 #include "XGUI_ActionsMgr.h"
24 #include "XGUI_MenuMgr.h"
25 #include "XGUI_ColorDialog.h"
26 #include "XGUI_DeflectionDialog.h"
27 #include "XGUI_TransparencyWidget.h"
28 #include "XGUI_ContextMenuMgr.h"
29 #include "XGUI_Displayer.h"
30 #include "XGUI_ErrorDialog.h"
31 #include "XGUI_ErrorMgr.h"
32 #include "XGUI_ModuleConnector.h"
33 #include "XGUI_ObjectsBrowser.h"
34 #include "XGUI_OperationMgr.h"
35 #include "XGUI_PropertyPanel.h"
36 #include "XGUI_PropertyDialog.h"
37 #include "XGUI_SalomeConnector.h"
38 #include "XGUI_Selection.h"
39 #include "XGUI_SelectionMgr.h"
40 #include "XGUI_Tools.h"
41 #include "XGUI_ViewerProxy.h"
42 #include "XGUI_WorkshopListener.h"
43 #include <XGUI_CustomPrs.h>
44 #include <XGUI_HistoryMenu.h>
45 #include <XGUI_QtEvents.h>
46 #include <XGUI_DataModel.h>
47
48 #ifndef HAVE_SALOME
49 #include <AppElements_Button.h>
50 #include <AppElements_Command.h>
51 #include <AppElements_MainMenu.h>
52 #include <AppElements_MainWindow.h>
53 #include <AppElements_MenuGroupPanel.h>
54 #include <AppElements_Viewer.h>
55 #include <AppElements_Workbench.h>
56 #endif
57
58 #include <ModelAPI_AttributeDocRef.h>
59 #include <ModelAPI_AttributeIntArray.h>
60 #include <ModelAPI_AttributeDouble.h>
61 #include <ModelAPI_Data.h>
62 #include <ModelAPI_Events.h>
63 #include <ModelAPI_Feature.h>
64 #include <ModelAPI_Object.h>
65 #include <ModelAPI_ResultBody.h>
66 #include <ModelAPI_ResultConstruction.h>
67 #include <ModelAPI_ResultGroup.h>
68 #include <ModelAPI_ResultParameter.h>
69 #include <ModelAPI_ResultField.h>
70 #include <ModelAPI_Session.h>
71 #include <ModelAPI_Validator.h>
72 #include <ModelAPI_ResultCompSolid.h>
73 #include <ModelAPI_Tools.h>
74
75 //#include <PartSetPlugin_Part.h>
76
77 #include <Events_Loop.h>
78 #include <Events_InfoMessage.h>
79 #include <Events_LongOp.h>
80
81 #include <ModuleBase_IModule.h>
82 #include <ModuleBase_IViewer.h>
83 #include <ModuleBase_Operation.h>
84 #include <ModuleBase_OperationDescription.h>
85 #include <ModuleBase_PageBase.h>
86 #include <ModuleBase_Preferences.h>
87 #include <ModuleBase_SelectionValidator.h>
88 #include <ModuleBase_Tools.h>
89 #include <ModuleBase_WidgetFactory.h>
90 #include <ModuleBase_OperationFeature.h>
91 #include <ModuleBase_OperationAction.h>
92 #include <ModuleBase_PagedContainer.h>
93 #include <ModuleBase_WidgetValidated.h>
94 #include <ModuleBase_ModelWidget.h>
95 #include <ModuleBase_ResultPrs.h>
96
97 #include <Config_Common.h>
98 #include <Config_FeatureMessage.h>
99 #include <Config_ModuleReader.h>
100 #include <Config_PointerMessage.h>
101 #include <Config_PropManager.h>
102 #include <Config_DataModelReader.h>
103 #include <Config_Translator.h>
104 #include <Config_WidgetAPI.h>
105 #include <Config_Keywords.h>
106
107 #include <SUIT_ResourceMgr.h>
108
109 #include <AIS_Trihedron.hxx>
110 #ifdef BEFORE_TRIHEDRON_PATCH
111 #include <AIS_Point.hxx>
112 #include <AIS_Axis.hxx>
113 #endif
114
115 #include <QApplication>
116 #include <QFileDialog>
117 #include <QMessageBox>
118 #include <QMdiSubWindow>
119 #include <QMainWindow>
120 #include <QPushButton>
121 #include <QDockWidget>
122 #include <QLayout>
123 #include <QThread>
124 #include <QObject>
125 #include <QMenu>
126 #include <QToolButton>
127 #include <QAction>
128 #include <QDesktopWidget>
129
130 #include <iterator>
131
132 #ifdef TINSPECTOR
133 #include <CDF_Session.hxx>
134 #include <CDF_Application.hxx>
135 #include <TInspector_Communicator.hxx>
136 #include <VInspector_CallBack.hxx>
137 static TInspector_Communicator* MyTCommunicator;
138 static Handle(VInspector_CallBack) MyVCallBack;
139
140 #endif
141
142 #ifdef _DEBUG
143 #include <QDebug>
144 #include <iostream>
145 #endif
146
147 #ifdef WIN32
148 #include <windows.h>
149 #else
150 #include <dlfcn.h>
151 #endif
152
153 QString XGUI_Workshop::MOVE_TO_END_COMMAND = QObject::tr("Move to the end");
154
155 //#define DEBUG_DELETE
156 //#define DEBUG_FEATURE_NAME
157 //#define DEBUG_CLEAN_HISTORY
158
159 XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
160     : QObject(),
161       myCurrentDir(QString()),
162       myModule(NULL),
163       mySalomeConnector(theConnector),
164       myPropertyPanel(0),
165       myObjectBrowser(0),
166       myDisplayer(0)
167       //myViewerSelMode(TopAbs_FACE)
168 {
169   mySelector = new XGUI_SelectionMgr(this);
170   myModuleConnector = new XGUI_ModuleConnector(this);
171   myOperationMgr = new XGUI_OperationMgr(this, 0);
172   ModuleBase_IWorkshop* aWorkshop = moduleConnector();
173   // Has to be defined first in order to get errors and messages from other components
174   myEventsListener = new XGUI_WorkshopListener(aWorkshop);
175
176   SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr();
177 #ifndef HAVE_SALOME
178   myMainWindow = new AppElements_MainWindow();
179
180   bool aCloc = aResMgr->booleanValue("language", "locale", true);
181   if (aCloc)
182     QLocale::setDefault( QLocale::c() );
183   else
184     QLocale::setDefault( QLocale::system() );
185 #endif
186   QString aPath = Config_XMLReader::pluginConfigFile().c_str();
187   QDir aDir(aPath);
188
189   // Load translations
190   QStringList aLangs;
191   aLangs << "*_en.ts"; // load by default eng translations
192   QString aCurrLang = aResMgr->stringValue("language", "language", "en");
193   if(aCurrLang != "en") {
194     aLangs << "*_" + aCurrLang + ".ts"; // then replace with translated files
195   }
196
197   foreach(QString aLang, aLangs) {
198     QStringList aFilters;
199     aFilters << aLang;
200     QStringList aTsFiles = aDir.entryList(aFilters, QDir::Files);
201     foreach(QString aFileName, aTsFiles) {
202       Config_Translator::load(aFileName.toStdString());
203     }
204   }
205
206   myDataModelXMLReader = new Config_DataModelReader();
207   //myDataModelXMLReader->readAll();
208
209   myDisplayer = new XGUI_Displayer(this);
210
211   connect(mySelector, SIGNAL(selectionChanged()), this, SLOT(updateCommandStatus()));
212
213   myActionsMgr = new XGUI_ActionsMgr(this);
214   myMenuMgr = new XGUI_MenuMgr(this);
215   myErrorDlg = new XGUI_ErrorDialog(QApplication::desktop());
216   myContextMenuMgr = new XGUI_ContextMenuMgr(this);
217   connect(myContextMenuMgr, SIGNAL(actionTriggered(const QString&, bool)), this,
218           SLOT(onContextMenuCommand(const QString&, bool)));
219
220   myViewerProxy = new XGUI_ViewerProxy(this);
221   //connect(myViewerProxy, SIGNAL(selectionChanged()),
222   //        myActionsMgr,  SLOT(updateOnViewSelection()));
223
224   myOperationMgr->setWorkshop(aWorkshop);
225
226   myErrorMgr = new XGUI_ErrorMgr(this, aWorkshop);
227
228   connect(myOperationMgr, SIGNAL(operationResumed(ModuleBase_Operation*)),
229           SLOT(onOperationResumed(ModuleBase_Operation*)));
230   connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)),
231           SLOT(onOperationStopped(ModuleBase_Operation*)));
232   connect(myOperationMgr, SIGNAL(operationCommitted(ModuleBase_Operation*)),
233           SLOT(onOperationCommitted(ModuleBase_Operation*)));
234   connect(myOperationMgr, SIGNAL(operationAborted(ModuleBase_Operation*)),
235           SLOT(onOperationAborted(ModuleBase_Operation*)));
236
237 #ifndef HAVE_SALOME
238   connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit()));
239   onTrihedronVisibilityChanged(true);
240 #endif
241
242   connect(myEventsListener, SIGNAL(errorOccurred(std::shared_ptr<Events_InfoMessage>)),
243           myErrorDlg, SLOT(addError(std::shared_ptr<Events_InfoMessage>)));
244
245   //Config_PropManager::registerProp("Visualization", "object_default_color", "Object color",
246   //                                 Config_Prop::Color, "225,225,225");
247
248   Config_PropManager::registerProp("Visualization", "result_body_color", "Result color",
249                                    Config_Prop::Color, ModelAPI_ResultBody::DEFAULT_COLOR());
250   Config_PropManager::registerProp("Visualization", "result_group_color", "Group color",
251                                    Config_Prop::Color, ModelAPI_ResultGroup::DEFAULT_COLOR());
252   Config_PropManager::registerProp("Visualization", "result_construction_color",
253                                    "Construction color",
254                                    Config_Prop::Color,
255                                    ModelAPI_ResultConstruction::DEFAULT_COLOR());
256   Config_PropManager::registerProp("Visualization", "result_part_color", "Part color",
257                                    Config_Prop::Color, ModelAPI_ResultPart::DEFAULT_COLOR());
258   Config_PropManager::registerProp("Visualization", "result_field_color", "Field color",
259                                    Config_Prop::Color, ModelAPI_ResultField::DEFAULT_COLOR());
260
261   if (ModuleBase_Preferences::resourceMgr()->booleanValue("Viewer", "face-selection", true))
262     myViewerSelMode.append(TopAbs_FACE);
263   if (ModuleBase_Preferences::resourceMgr()->booleanValue("Viewer", "edge-selection", true))
264     myViewerSelMode.append(TopAbs_EDGE);
265   if (ModuleBase_Preferences::resourceMgr()->booleanValue("Viewer", "vertex-selection", true))
266     myViewerSelMode.append(TopAbs_VERTEX);
267   //IMP: an attempt to use result selection with other selection modes
268   myViewerSelMode.append(ModuleBase_ResultPrs::Sel_Result);//TopAbs_VERTEX);
269   myViewerSelMode.append(TopAbs_COMPSOLID);
270 }
271
272 //******************************************************
273 XGUI_Workshop::~XGUI_Workshop(void)
274 {
275 #ifdef _DEBUG
276 #ifdef MISSED_TRANSLATION
277   // Save Missed translations
278   Config_Translator::saveMissedTranslations();
279 #endif
280 #endif
281
282   delete myDisplayer;
283   delete myDataModelXMLReader;
284 }
285
286 //******************************************************
287 void XGUI_Workshop::startApplication()
288 {
289   //Initialize event listening
290   myEventsListener->initializeEventListening();
291
292   myDataModelXMLReader->readAll();
293   initMenu();
294
295   Config_PropManager::registerProp("Plugins", "default_path", "Default Path",
296                                    Config_Prop::Directory, "");
297
298
299   registerValidators();
300
301   // Calling of  loadCustomProps before activating module is required
302   // by Config_PropManger to restore user-defined path to plugins
303   ModuleBase_Preferences::loadCustomProps();
304   createModule();
305
306 #ifndef HAVE_SALOME
307   myMainWindow->show();
308   updateCommandStatus();
309 #endif
310
311   onNew();
312
313   myViewerProxy->connectViewProxy();
314   connect(myViewerProxy, SIGNAL(trihedronVisibilityChanged(bool)),
315           SLOT(onTrihedronVisibilityChanged(bool)));
316
317   emit applicationStarted();
318 }
319
320 void XGUI_Workshop::activateModule()
321 {
322   myModule->activateSelectionFilters();
323
324   connect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)),
325     myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr)));
326   connect(myDisplayer, SIGNAL(beforeObjectErase(ObjectPtr, AISObjectPtr)),
327     myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr)));
328
329   updateCommandStatus();
330
331   // TODO: get default selection mode
332
333   // activate visualized objects in the viewer
334   activateObjectsSelection(displayer()->displayedObjects());
335   myOperationMgr->activate();
336 }
337
338 void XGUI_Workshop::deactivateModule()
339 {
340   myModule->deactivateSelectionFilters();
341
342   // remove internal displayer filter
343   displayer()->deactivateSelectionFilters();
344
345   disconnect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)),
346     myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr)));
347   disconnect(myDisplayer, SIGNAL(beforeObjectErase(ObjectPtr, AISObjectPtr)),
348     myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr)));
349
350   XGUI_Displayer* aDisplayer = displayer();
351   QObjectPtrList aDisplayed = aDisplayer->displayedObjects();
352   aDisplayer->deactivateObjects(aDisplayed, true);
353   Handle(AIS_InteractiveContext) aContext = viewer()->AISContext();
354   Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(aDisplayer->getTrihedron());
355   /// deactivate trihedron in selection modes
356   TColStd_ListOfInteger aTColModes;
357   aContext->ActivatedModes(aTrihedron, aTColModes);
358   TColStd_ListIteratorOfListOfInteger itr( aTColModes );
359   for (; itr.More(); itr.Next() ) {
360     Standard_Integer aMode = itr.Value();
361     aContext->Deactivate(aTrihedron, aMode);
362   }
363 #ifdef BEFORE_TRIHEDRON_PATCH
364   /// Trihedron problem: objects stayed in the viewer, should be removed manually
365   /// otherwise in SALOME happens crash by HideAll in the viewer
366   aContext->Remove(aTrihedron->Position(), true);
367   aContext->Remove(aTrihedron->Axis(), true);
368   aContext->Remove(aTrihedron->XAxis(), true);
369   aContext->Remove(aTrihedron->YAxis(), true);
370 #endif
371
372   myOperationMgr->deactivate();
373 }
374
375 //******************************************************
376 void XGUI_Workshop::initMenu()
377 {
378   myContextMenuMgr->createActions();
379
380 #ifdef HAVE_SALOME
381   // Create only Undo, Redo commands
382   QAction* aAction = salomeConnector()->addDesktopCommand("UNDO_CMD", tr("Undo"),
383                                                         tr("Undo last command"),
384                                                         QIcon(":pictures/undo.png"),
385                                                         QKeySequence::Undo, false,
386                                                         "MEN_DESK_EDIT");
387   QString aToolBarTitle = tr( "INF_DESK_TOOLBAR_STANDARD" );
388   salomeConnector()->addActionInToolbar( aAction,aToolBarTitle  );
389
390   connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onUndo()));
391   addHistoryMenu(aAction, SIGNAL(updateUndoHistory(const QList<ActionInfo>&)), SLOT(onUndo(int)));
392
393   aAction = salomeConnector()->addDesktopCommand("REDO_CMD", tr("Redo"), tr("Redo last command"),
394                                               QIcon(":pictures/redo.png"), QKeySequence::Redo,
395                                               false, "MEN_DESK_EDIT");
396   salomeConnector()->addActionInToolbar( aAction, aToolBarTitle );
397
398   connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRedo()));
399   addHistoryMenu(aAction, SIGNAL(updateRedoHistory(const QList<ActionInfo>&)), SLOT(onRedo(int)));
400
401   salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT");
402   //aAction = salomeConnector()->addDesktopCommand("REBUILD_CMD", tr("Rebuild"),
403   //                                            tr("Rebuild data objects"),
404   //                                            QIcon(":pictures/rebuild.png"), QKeySequence(),
405   //                                            false, "MEN_DESK_EDIT");
406   //salomeConnector()->addActionInToolbar( aAction, aToolBarTitle );
407
408   //connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRebuild()));
409   //salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT");
410
411   aAction = salomeConnector()->addDesktopCommand("SAVEAS_CMD", tr("Export native..."),
412                                              tr("Export the current document into a native file"),
413                                               QIcon(), QKeySequence(),
414                                               false, "MEN_DESK_FILE");
415   connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onSaveAs()));
416
417   aAction = salomeConnector()->addDesktopCommand("OPEN_CMD", tr("Import native..."),
418                                               tr("Import native file"),
419                                               QIcon(), QKeySequence(),
420                                               false, "MEN_DESK_FILE");
421   connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onOpen()));
422   salomeConnector()->addDesktopMenuSeparator("MEN_DESK_FILE");
423
424 #else
425   // File commands group
426   AppElements_MenuGroupPanel* aGroup = myMainWindow->menuObject()->generalPage();
427
428   AppElements_Command* aCommand;
429
430   aCommand = aGroup->addFeature("SAVE_CMD", tr("Save"), tr("Save the document"),
431                                 QIcon(":pictures/save.png"), QKeySequence::Save);
432   aCommand->connectTo(this, SLOT(onSave()));
433   //aCommand->disable();
434
435   aCommand = aGroup->addFeature("SAVEAS_CMD", tr("Save as..."), tr("Save the document into a file"),
436                                 QIcon(":pictures/save.png"), QKeySequence());
437   aCommand->connectTo(this, SLOT(onSaveAs()));
438
439   QString aUndoId = "UNDO_CMD";
440   aCommand = aGroup->addFeature(aUndoId, tr("Undo"), tr("Undo last command"),
441                                 QIcon(":pictures/undo.png"), QKeySequence::Undo);
442   aCommand->connectTo(this, SLOT(onUndo()));
443   AppElements_Button* aUndoButton = qobject_cast<AppElements_Button*>(aGroup->widget(aUndoId));
444   addHistoryMenu(aUndoButton,
445                  SIGNAL(updateUndoHistory(const QList<ActionInfo>&)),
446                  SLOT(onUndo(int)));
447
448   QString aRedoId = "REDO_CMD";
449   aCommand = aGroup->addFeature(aRedoId, tr("Redo"), tr("Redo last command"),
450                                 QIcon(":pictures/redo.png"), QKeySequence::Redo);
451   aCommand->connectTo(this, SLOT(onRedo()));
452   AppElements_Button* aRedoButton = qobject_cast<AppElements_Button*>(aGroup->widget(aRedoId));
453   addHistoryMenu(aRedoButton,
454                  SIGNAL(updateRedoHistory(const QList<ActionInfo>&)),
455                  SLOT(onRedo(int)));
456
457   //aCommand = aGroup->addFeature("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"),
458   //  QIcon(":pictures/rebuild.png"), QKeySequence());
459   //aCommand->connectTo(this, SLOT(onRebuild()));
460
461   //aCommand->disable();
462
463   aCommand = aGroup->addFeature("OPEN_CMD", tr("Open..."), tr("Open a new document"),
464                                 QIcon(":pictures/open.png"), QKeySequence::Open);
465   aCommand->connectTo(this, SLOT(onOpen()));
466
467   aCommand = aGroup->addFeature("PREF_CMD", tr("Preferences"), tr("Edit preferences"),
468                                 QIcon(":pictures/preferences.png"), QKeySequence::Preferences);
469   aCommand->connectTo(this, SLOT(onPreferences()));
470
471   aCommand = aGroup->addFeature("EXIT_CMD", tr("Exit"), tr("Exit application"),
472                                 QIcon(":pictures/close.png"), QKeySequence::Close);
473   aCommand->connectTo(this, SLOT(onExit()));
474 #endif
475 }
476
477 #ifndef HAVE_SALOME
478 AppElements_Workbench* XGUI_Workshop::addWorkbench(const QString& theName)
479 {
480   AppElements_MainMenu* aMenuBar = myMainWindow->menuObject();
481   return aMenuBar->addWorkbench(theName);
482 }
483 #endif
484
485 //******************************************************
486 QMainWindow* XGUI_Workshop::desktop() const
487 {
488 #ifdef HAVE_SALOME
489   return salomeConnector()->desktop();
490 #else
491   return myMainWindow;
492 #endif
493 }
494
495 //******************************************************
496 void XGUI_Workshop::onStartWaiting()
497 {
498   if (Events_LongOp::isPerformed()) {
499     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
500   }
501 }
502
503 //******************************************************
504 void XGUI_Workshop::onAcceptActionClicked()
505 {
506   QAction* anAction = dynamic_cast<QAction*>(sender());
507   XGUI_OperationMgr* anOperationMgr = operationMgr();
508   if (anOperationMgr) {
509     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
510                                                     (anOperationMgr->currentOperation());
511     if (aFOperation) {
512       //if (errorMgr()->canProcessClick(anAction, aFOperation->feature()))
513       myOperationMgr->commitOperation();
514     }
515   }
516 }
517
518 //******************************************************
519 void XGUI_Workshop::onPreviewActionClicked()
520 {
521   ModuleBase_IPropertyPanel* aPanel = propertyPanel();
522   if (aPanel) {
523     ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
524     if (anActiveWidget && anActiveWidget->getValueState() == ModuleBase_ModelWidget::ModifiedInPP) {
525       anActiveWidget->storeValue();
526     }
527   }
528   std::shared_ptr<Events_Message> aMsg = std::shared_ptr<Events_Message>(
529                 new Events_Message(Events_Loop::eventByName(EVENT_PREVIEW_REQUESTED)));
530   Events_Loop::loop()->send(aMsg);
531 }
532
533 //******************************************************
534 void XGUI_Workshop::deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer)
535 {
536   if (!myModule->canActivateSelection(theObject)) {
537     if (myDisplayer->isActive(theObject)) {
538       QObjectPtrList anObjects;
539       anObjects.append(theObject);
540       myDisplayer->deactivateObjects(anObjects, theUpdateViewer);
541     }
542   }
543 }
544
545 //******************************************************
546 bool XGUI_Workshop::isFeatureOfNested(const FeaturePtr& theFeature)
547 {
548   bool aHasNested = false;
549   std::string aFeatureKind = theFeature->getKind();
550 #ifdef HAVE_SALOME
551     XGUI_SalomeConnector* aSalomeConnector = salomeConnector();
552     if (aSalomeConnector->isFeatureOfNested(actionsMgr()->action(aFeatureKind.c_str())))
553       aHasNested = true;
554 #else
555     AppElements_MainMenu* aMenuBar = mainWindow()->menuObject();
556     AppElements_Command* aCommand = aMenuBar->feature(aFeatureKind.c_str());
557     if (aCommand && aCommand->button()->additionalButtonWidget())
558       aHasNested = true;
559 #endif
560   return aHasNested;
561 }
562
563 void XGUI_Workshop::fillPropertyPanel(ModuleBase_Operation* theOperation)
564 {
565   ModuleBase_OperationFeature* aFOperation =
566     dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
567   if (!aFOperation)
568     return;
569
570   showPropertyPanel();
571   myPropertyPanel->cleanContent();
572
573   QList<ModuleBase_ModelWidget*> aWidgets;
574   if (!module()->createWidgets(theOperation, aWidgets)) {
575     QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation();
576     ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), myModuleConnector);
577     aFactory.createWidget(myPropertyPanel->contentWidget());
578     aWidgets = aFactory.getModelWidgets();
579   }
580
581   // check compatibility of feature and widgets
582   FeaturePtr aFeature = aFOperation->feature();
583   std::string aFeatureKind = aFeature->getKind();
584   foreach (ModuleBase_ModelWidget* aWidget, aWidgets) {
585     if (!aWidget->attributeID().empty() && !aFeature->attribute(aWidget->attributeID()).get()) {
586       std::string anErrorMsg = "The feature '%1' has no attribute '%2' used by widget '%3'.";
587       Events_InfoMessage("XGUI_Workshop", anErrorMsg)
588         .arg(aFeatureKind).arg(aWidget->attributeID())
589         .arg(aWidget->metaObject()->className()).send();
590       myPropertyPanel->cleanContent();
591       return;
592     }
593   }
594   // for performance purpose, flush should be done after all controls are filled
595   bool isUpdateFlushed = false;
596   foreach (ModuleBase_ModelWidget* aWidget, aWidgets) {
597     bool isStoreValue = !aFOperation->isEditOperation() &&
598                         !aWidget->getDefaultValue().empty() &&
599                         !aWidget->isComputedDefault();
600     aWidget->setFeature(aFeature, isStoreValue, isUpdateFlushed);
601     if (!isStoreValue)
602       aWidget->restoreValue();
603     aWidget->enableFocusProcessing();
604   }
605   ModuleBase_Tools::flushUpdated(aFeature);
606
607   // update visible state of Preview button
608   std::shared_ptr<Config_FeatureMessage> aFeatureInfo;
609 #ifdef HAVE_SALOME
610   aFeatureInfo = mySalomeConnector->featureInfo(aFeatureKind.c_str());
611 #else
612   AppElements_MainMenu* aMenuBar = mainWindow()->menuObject();
613   AppElements_Command* aCommand = aMenuBar->feature(aFeatureKind.c_str());
614   if (aCommand)
615     aFeatureInfo = aCommand->featureMessage();
616 #endif
617   bool anIsAutoPreview = true;
618   if (aFeatureInfo.get())
619     anIsAutoPreview = aFeatureInfo->isAutoPreview();
620   else {
621     std::string aXmlCfg, aDescription;
622     module()->getXMLRepresentation(aFeatureKind, aXmlCfg, aDescription);
623     ModuleBase_WidgetFactory aFactory(aXmlCfg, moduleConnector());
624     anIsAutoPreview = aFactory.widgetAPI()->getBooleanAttribute(FEATURE_AUTO_PREVIEW, true);
625   }
626
627   if (!anIsAutoPreview) {
628     myPropertyPanel->findButton(PROP_PANEL_PREVIEW)->setVisible(true);
629     // send signal about preview should not be computed automatically, click on preview
630     // button should initiate it
631     std::shared_ptr<Events_Message> aMsg = std::shared_ptr<Events_Message>(
632                   new Events_Message(Events_Loop::eventByName(EVENT_PREVIEW_BLOCKED)));
633     Events_Loop::loop()->send(aMsg);
634   }
635   myPropertyPanel->setModelWidgets(aWidgets);
636   aFOperation->setPropertyPanel(myPropertyPanel);
637
638   myModule->propertyPanelDefined(theOperation);
639
640 #ifndef DEBUG_FEATURE_NAME
641   myPropertyPanel->setWindowTitle(theOperation->getDescription()->description());
642 #else
643   std::string aFeatureName = aFeature->name();
644   myPropertyPanel->setWindowTitle(QString("%1: %2")
645     .arg(theOperation->getDescription()->description())
646     .arg(aFeatureName.c_str()));
647 #endif
648
649   myErrorMgr->setPropertyPanel(myPropertyPanel);
650 }
651
652 void XGUI_Workshop::connectToPropertyPanel(const bool isToConnect)
653 {
654   XGUI_PropertyPanel* aPropertyPanel = propertyPanel();
655   if (aPropertyPanel) {
656     const QList<ModuleBase_ModelWidget*>& aWidgets = aPropertyPanel->modelWidgets();
657     foreach (ModuleBase_ModelWidget* aWidget, aWidgets) {
658        myModule->connectToPropertyPanel(aWidget, isToConnect);
659        if (isToConnect) {
660         connect(aWidget, SIGNAL(valueStateChanged(int)), this, SLOT(onWidgetStateChanged(int)));
661         connect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onValuesChanged()));
662         connect(aWidget, SIGNAL(objectUpdated()), this, SLOT(onWidgetObjectUpdated()));
663        }
664       else {
665         disconnect(aWidget, SIGNAL(valueStateChanged(int)), this, SLOT(onWidgetStateChanged(int)));
666         disconnect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onValuesChanged()));
667         disconnect(aWidget, SIGNAL(objectUpdated()), this, SLOT(onWidgetObjectUpdated()));
668       }
669     }
670   }
671 }
672
673 //******************************************************
674 void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation)
675 {
676   setGrantedFeatures(theOperation);
677
678   if (theOperation->getDescription()->hasXmlRepresentation()) {  //!< No need for property panel
679     fillPropertyPanel(theOperation);
680     connectToPropertyPanel(true);
681   }
682   updateCommandStatus();
683
684   myModule->operationResumed(theOperation);
685 }
686
687
688 //******************************************************
689 void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
690 {
691   updateCommandStatus();
692
693   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
694                                                                         (theOperation);
695   if (!aFOperation)
696     return;
697
698   ModuleBase_ISelection* aSel = mySelector->selection();
699   QObjectPtrList aObj = aSel->selectedPresentations();
700   //!< No need for property panel
701   hidePropertyPanel();
702   myPropertyPanel->cleanContent();
703
704   connectToPropertyPanel(false);
705   myModule->operationStopped(aFOperation);
706
707   // the deactivated objects of the current operation should be activated back.
708   // They were deactivated on operation start or an object redisplay
709   QObjectPtrList anObjects;
710   FeaturePtr aFeature = aFOperation->feature();
711   if (aFeature.get()) { // feature may be not created (plugin load fail)
712     if (myDisplayer->isVisible(aFeature) && !myDisplayer->isActive(aFeature))
713       anObjects.append(aFeature);
714     std::list<ResultPtr> aResults;
715     ModelAPI_Tools::allResults(aFeature, aResults);
716     std::list<ResultPtr>::const_iterator aIt;
717     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
718       ResultPtr anObject = *aIt;
719       if (myDisplayer->isVisible(anObject) && !myDisplayer->isActive(anObject)) {
720         anObjects.append(anObject);
721       }
722     }
723   }
724   activateObjectsSelection(anObjects);
725 }
726
727
728 void XGUI_Workshop::onOperationCommitted(ModuleBase_Operation* theOperation)
729 {
730   myModule->operationCommitted(theOperation);
731 }
732
733 void XGUI_Workshop::onOperationAborted(ModuleBase_Operation* theOperation)
734 {
735   myModule->operationAborted(theOperation);
736 }
737
738 void XGUI_Workshop::setGrantedFeatures(ModuleBase_Operation* theOperation)
739 {
740   ModuleBase_OperationFeature* aFOperation =
741     dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
742   if (!aFOperation)
743     return;
744
745   QStringList aGrantedIds;
746   if (isSalomeMode()) {
747     const std::shared_ptr<Config_FeatureMessage>& anInfo =
748                          mySalomeConnector->featureInfo(theOperation->id());
749     if (anInfo.get())
750       aGrantedIds = QString::fromStdString(anInfo->nestedFeatures())
751                                    .split(" ", QString::SkipEmptyParts);
752   }
753   else
754     aGrantedIds = myActionsMgr->nestedCommands(theOperation->id());
755
756   ModuleBase_IModule* aModule = module();
757   if (aModule)
758     aModule->grantedOperationIds(theOperation, aGrantedIds);
759
760   aFOperation->setGrantedOperationIds(aGrantedIds);
761 }
762
763 //******************************************************
764 void XGUI_Workshop::saveDocument(const QString& theName, std::list<std::string>& theFileNames)
765 {
766   QApplication::restoreOverrideCursor();
767   SessionPtr aMgr = ModelAPI_Session::get();
768
769   std::list<DocumentPtr> aDocList = aMgr->allOpenedDocuments();
770   std::list<DocumentPtr>::const_iterator aIt;
771   for (aIt = aDocList.cbegin(); aIt != aDocList.cend(); aIt++) {
772     std::list<bool> aState = myObjectBrowser->getStateForDoc(*aIt);
773     (*aIt)->storeNodesState(aState);
774   }
775
776   aMgr->save(theName.toLatin1().constData(), theFileNames);
777
778   QApplication::restoreOverrideCursor();
779 }
780
781 //******************************************************
782 bool XGUI_Workshop::abortAllOperations()
783 {
784   return myOperationMgr->abortAllOperations();
785 }
786
787 //******************************************************
788 void XGUI_Workshop::operationStarted(ModuleBase_Operation* theOperation)
789 {
790   setGrantedFeatures(theOperation);
791   if (!theOperation->getDescription()->hasXmlRepresentation()) {  //!< No need for property panel
792     updateCommandStatus();
793   }
794   else {
795     myModule->operationStarted(theOperation);
796   }
797 }
798
799 //******************************************************
800 void XGUI_Workshop::onOpen()
801 {
802   if(!abortAllOperations())
803     return;
804   //save current file before close if modified
805   SessionPtr aSession = ModelAPI_Session::get();
806   if (aSession->isModified()) {
807     //TODO(sbh): re-launch the app?
808     int anAnswer = QMessageBox::question(
809         desktop(), tr("Save current file"),
810         tr("The document is modified, save before opening another?"),
811         QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel);
812     if (anAnswer == QMessageBox::Save) {
813       onSave();
814     } else if (anAnswer == QMessageBox::Cancel) {
815       return;
816     }
817     myCurrentDir = "";
818   }
819
820   //show file dialog, check if readable and open
821   QString aDirectory = QFileDialog::getExistingDirectory(desktop(), tr("Select directory"));
822   openDirectory(aDirectory);
823 }
824
825 //******************************************************
826 void XGUI_Workshop::openDirectory(const QString& theDirectory)
827 {
828   myCurrentDir = theDirectory;
829   if (myCurrentDir.isEmpty())
830     return;
831
832   QFileInfo aFileInfo(myCurrentDir);
833   if (!aFileInfo.exists() || !aFileInfo.isReadable()) {
834     QMessageBox::critical(desktop(), tr("Warning"), tr("Unable to open the file."));
835     myCurrentDir = "";
836     return;
837   }
838
839   QApplication::setOverrideCursor(Qt::WaitCursor);
840   module()->closeDocument();
841   SessionPtr aSession = ModelAPI_Session::get();
842   aSession->closeAll();
843   aSession->load(myCurrentDir.toLatin1().constData());
844   myObjectBrowser->rebuildDataTree();
845
846   // Open first level of data tree
847   DocumentPtr aRootDoc = aSession->moduleDocument();
848   std::list<bool> aStates;
849   aRootDoc->restoreNodesState(aStates);
850   myObjectBrowser->setStateForDoc(aRootDoc, aStates);
851
852   updateCommandStatus();
853 #ifndef HAVE_SALOME
854   myMainWindow->setCurrentDir(myCurrentDir, true);
855 #endif
856   QApplication::restoreOverrideCursor();
857 }
858
859 //******************************************************
860 void XGUI_Workshop::onNew()
861 {
862   QApplication::setOverrideCursor(Qt::WaitCursor);
863   if (objectBrowser() == 0) {
864     createDockWidgets();
865     mySelector->connectViewers();
866   }
867   myViewerProxy->connectToViewer();
868   showObjectBrowser();
869 #ifndef HAVE_SALOME
870   myMainWindow->showPythonConsole();
871   QMdiSubWindow* aWnd = myMainWindow->viewer()->createView();
872   aWnd->showMaximized();
873   updateCommandStatus();
874 #endif
875   myContextMenuMgr->connectViewer();
876   QApplication::restoreOverrideCursor();
877 }
878
879 #ifndef HAVE_SALOME
880 //******************************************************
881 void XGUI_Workshop::onExit()
882 {
883   SessionPtr aMgr = ModelAPI_Session::get();
884   if (aMgr->isModified()) {
885     int anAnswer = QMessageBox::question(
886         myMainWindow, tr("Save current file"), tr("The document is modified, save before exit?"),
887         QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel);
888     if (anAnswer == QMessageBox::Save) {
889       bool saved = onSave();
890       if (!saved) {
891         return;
892       }
893     } else if (anAnswer == QMessageBox::Cancel) {
894       return;
895     }
896   }
897   qApp->exit();
898 }
899
900 //******************************************************
901 void XGUI_Workshop::onPreferences()
902 {
903   ModuleBase_Prefs aModif;
904   ModuleBase_Preferences::editPreferences(aModif);
905   if (aModif.size() > 0) {
906     QString aSection;
907     foreach (ModuleBase_Pref aPref, aModif)
908     {
909       aSection = aPref.first;
910       if (aSection == ModuleBase_Preferences::VIEWER_SECTION) {
911         myMainWindow->viewer()->updateFromResources();
912       } else if (aSection == ModuleBase_Preferences::MENU_SECTION) {
913         myMainWindow->menuObject()->updateFromResources();
914       }
915     }
916     displayer()->redisplayObjects();
917   }
918 }
919 #endif
920
921 //******************************************************
922 void XGUI_Workshop::onTrihedronVisibilityChanged(bool theState)
923 {
924   XGUI_Displayer* aDisplayer = displayer();
925   if (aDisplayer)
926     aDisplayer->displayTrihedron(theState);
927 }
928
929 //******************************************************
930 bool XGUI_Workshop::onSave()
931 {
932   if(!myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
933     return false;
934   if (myCurrentDir.isEmpty()) {
935     return onSaveAs();
936   }
937   std::list<std::string> aFiles;
938   saveDocument(myCurrentDir, aFiles);
939   updateCommandStatus();
940 #ifndef HAVE_SALOME
941     myMainWindow->setModifiedState(false);
942 #endif
943   return true;
944 }
945
946 //******************************************************
947 bool XGUI_Workshop::onSaveAs()
948 {
949   if(!myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
950     return false;
951   QFileDialog dialog(desktop());
952   dialog.setWindowTitle(tr("Select directory to save files..."));
953   dialog.setFileMode(QFileDialog::Directory);
954   dialog.setFilter(QDir::AllDirs);
955   dialog.setOptions(QFileDialog::HideNameFilterDetails | QFileDialog::ShowDirsOnly);
956   dialog.setViewMode(QFileDialog::Detail);
957
958   if (!dialog.exec()) {
959     return false;
960   }
961
962   QString aTempDir = dialog.selectedFiles().first();
963   QDir aDir(aTempDir);
964   if (aDir.exists() && !aDir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).isEmpty()) {
965     int answer = QMessageBox::question(
966         desktop(),
967         // Title of the dialog which asks user if he wants to save study
968         // in existing non-empty folder
969         tr("Save"),
970         tr("The directory already contains some files, save anyway?"),
971         QMessageBox::Save | QMessageBox::Cancel);
972     if (answer == QMessageBox::Cancel) {
973       return false;
974     }
975   }
976   myCurrentDir = aTempDir;
977 #ifndef HAVE_SALOME
978     myMainWindow->setCurrentDir(myCurrentDir, false);
979     myMainWindow->setModifiedState(false);
980 #endif
981   return onSave();
982 }
983
984 //******************************************************
985 void XGUI_Workshop::onUndo(int theTimes)
986 {
987   objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
988   SessionPtr aMgr = ModelAPI_Session::get();
989   std::list<std::string> aUndoList = aMgr->undoList();
990   if (aMgr->isOperation()) {
991     /// this is important for nested operations
992     /// when sketch operation is active, this condition is false and
993     /// the sketch operation is not aborted
994     operationMgr()->onAbortOperation();
995   }
996   std::list<std::string>::const_iterator aIt = aUndoList.cbegin();
997   for (int i = 0; (i < theTimes) && (aIt != aUndoList.cend()); ++i, ++aIt) {
998     aMgr->undo();
999     if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND)
1000       myObjectBrowser->rebuildDataTree();
1001   }
1002
1003   operationMgr()->updateApplyOfOperations();
1004   updateCommandStatus();
1005 }
1006
1007 //******************************************************
1008 void XGUI_Workshop::onRedo(int theTimes)
1009 {
1010   // the viewer update should be blocked in order to avoid the features blinking. For the created
1011   // feature a results are created, the flush of the created signal caused the viewer redisplay for
1012   // each created result. After a redisplay signal is flushed. So, the viewer update is blocked
1013   // until redo of all possible objects happens
1014   bool isUpdateEnabled = myDisplayer->enableUpdateViewer(false);
1015
1016   objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
1017   SessionPtr aMgr = ModelAPI_Session::get();
1018   std::list<std::string> aRedoList = aMgr->redoList();
1019   if (aMgr->isOperation()) {
1020     /// this is important for nested operations
1021     /// when sketch operation is active, this condition is false and
1022     /// the sketch operation is not aborted
1023     operationMgr()->onAbortOperation();
1024   }
1025   std::list<std::string>::const_iterator aIt = aRedoList.cbegin();
1026   for (int i = 0; (i < theTimes) && (aIt != aRedoList.cend()); ++i, ++aIt) {
1027     aMgr->redo();
1028     if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND)
1029       myObjectBrowser->rebuildDataTree();
1030   }
1031   operationMgr()->updateApplyOfOperations();
1032   updateCommandStatus();
1033
1034   // unblock the viewer update functionality and make update on purpose
1035   myDisplayer->enableUpdateViewer(isUpdateEnabled);
1036   myDisplayer->updateViewer();
1037 }
1038
1039 //******************************************************
1040 //void XGUI_Workshop::onRebuild()
1041 //{
1042 //  SessionPtr aMgr = ModelAPI_Session::get();
1043 //  bool aWasOperation = aMgr->isOperation(); // keep this value
1044 //  if (!aWasOperation) {
1045 //    aMgr->startOperation("Rebuild");
1046 //  }
1047 //  static const Events_ID aRebuildEvent = Events_Loop::loop()->eventByName("Rebuild");
1048 //  Events_Loop::loop()->send(std::shared_ptr<Events_Message>(
1049 //    new Events_Message(aRebuildEvent, this)));
1050 //  if (!aWasOperation) {
1051 //    aMgr->finishOperation();
1052 //  }
1053 //  updateCommandStatus();
1054 //}
1055
1056 //******************************************************
1057 void XGUI_Workshop::onWidgetStateChanged(int thePreviousState)
1058 {
1059   ModuleBase_ModelWidget* anActiveWidget = 0;
1060   ModuleBase_Operation* anOperation = myOperationMgr->currentOperation();
1061   if (anOperation) {
1062     ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
1063     if (aPanel)
1064       anActiveWidget = aPanel->activeWidget();
1065   }
1066   if (anActiveWidget)
1067     operationMgr()->onValidateOperation();
1068
1069   myModule->widgetStateChanged(thePreviousState);
1070 }
1071
1072 //******************************************************
1073 void XGUI_Workshop::onValuesChanged()
1074 {
1075   ModuleBase_ModelWidget* aSenderWidget = (ModuleBase_ModelWidget*)(sender());
1076   if (!aSenderWidget || aSenderWidget->canAcceptFocus())
1077     return;
1078
1079   ModuleBase_ModelWidget* anActiveWidget = 0;
1080   ModuleBase_Operation* anOperation = myOperationMgr->currentOperation();
1081   if (anOperation) {
1082     ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
1083     if (aPanel)
1084       anActiveWidget = aPanel->activeWidget();
1085   }
1086   if (anActiveWidget) {
1087     ModuleBase_WidgetValidated* aWidgetValidated = dynamic_cast<ModuleBase_WidgetValidated*>
1088                                                                            (anActiveWidget);
1089     if (aWidgetValidated)
1090       aWidgetValidated->clearValidatedCash();
1091   }
1092 }
1093
1094 void XGUI_Workshop::onWidgetObjectUpdated()
1095 {
1096   operationMgr()->onValidateOperation();
1097 }
1098
1099 ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule)
1100 {
1101   QString libName = QString::fromStdString(library(theModule.toStdString()));
1102   if (libName.isEmpty()) {
1103     qWarning(qPrintable(tr("Information about module \"%1\" doesn't exist.").arg(theModule)));
1104     return 0;
1105   }
1106
1107   QString err;
1108   CREATE_FUNC crtInst = 0;
1109
1110 #ifdef WIN32
1111   HINSTANCE modLib = ::LoadLibrary((LPTSTR) qPrintable(libName));
1112   if (!modLib) {
1113     LPVOID lpMsgBuf;
1114     ::FormatMessage(
1115         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
1116         0, ::GetLastError(), 0, (LPTSTR) & lpMsgBuf, 0, 0);
1117     QString aMsg((char*) &lpMsgBuf);
1118     err = QString("Failed to load  %1. %2").arg(libName).arg(aMsg);
1119     ::LocalFree(lpMsgBuf);
1120   } else {
1121     crtInst = (CREATE_FUNC) ::GetProcAddress(modLib, CREATE_MODULE);
1122     if (!crtInst) {
1123       LPVOID lpMsgBuf;
1124       ::FormatMessage(
1125           FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
1126               | FORMAT_MESSAGE_IGNORE_INSERTS,
1127           0, ::GetLastError(), 0, (LPTSTR) & lpMsgBuf, 0, 0);
1128       QString aMsg((char*) &lpMsgBuf);
1129       err = QString("Failed to find  %1 function. %2").arg( CREATE_MODULE).arg(aMsg);
1130       ::LocalFree(lpMsgBuf);
1131     }
1132   }
1133 #else
1134   void* modLib = dlopen( libName.toLatin1(), RTLD_LAZY | RTLD_GLOBAL );
1135   if ( !modLib ) {
1136     err = QString( "Can not load library %1. %2" ).arg( libName ).arg( dlerror() );
1137   } else {
1138     crtInst = (CREATE_FUNC)dlsym( modLib, CREATE_MODULE );
1139     if ( !crtInst ) {
1140       err = QString( "Failed to find function %1. %2" ).arg( CREATE_MODULE ).arg( dlerror() );
1141     }
1142   }
1143 #endif
1144
1145   ModuleBase_IModule* aModule = crtInst ? crtInst(myModuleConnector) : 0;
1146
1147   if (!err.isEmpty()) {
1148     if (desktop()) {
1149       Events_InfoMessage("XGUI_Workshop", err.toStdString()).send();
1150     } else {
1151       qWarning(qPrintable(err));
1152     }
1153   }
1154   return aModule;
1155 }
1156
1157 //******************************************************
1158 bool XGUI_Workshop::createModule()
1159 {
1160   Config_ModuleReader aModuleReader;
1161   QString moduleName = QString::fromStdString(aModuleReader.getModuleName());
1162   myModule = loadModule(moduleName);
1163   if (!myModule)
1164     return false;
1165
1166   //connect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)),
1167   //  myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr)));
1168   //connect(myDisplayer, SIGNAL(beforeObjectErase(ObjectPtr, AISObjectPtr)),
1169   //  myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr)));
1170
1171   myModule->createFeatures();
1172 #ifdef HAVE_SALOME
1173   salomeConnector()->createFeatureActions();
1174 #endif
1175   //myActionsMgr->update();
1176   return true;
1177 }
1178
1179 //******************************************************
1180 void XGUI_Workshop::updateCommandStatus()
1181 {
1182   QList<QAction*> aCommands;
1183 #ifdef HAVE_SALOME
1184     aCommands = salomeConnector()->commandList();
1185 #else
1186     AppElements_MainMenu* aMenuBar = myMainWindow->menuObject();
1187     foreach (AppElements_Command* aCmd, aMenuBar->features())
1188       aCommands.append(aCmd);
1189 #endif
1190   SessionPtr aMgr = ModelAPI_Session::get();
1191   if (aMgr->hasModuleDocument()) {
1192     foreach(QAction* aCmd, aCommands) {
1193       QString aId = aCmd->data().toString();
1194       if (aId == "UNDO_CMD")
1195         aCmd->setEnabled(myModule->canUndo());
1196       else if (aId == "REDO_CMD")
1197         aCmd->setEnabled(myModule->canRedo());
1198       else
1199         // Enable all commands
1200         aCmd->setEnabled(true);
1201     }
1202     updateHistory();
1203   } else {
1204     foreach(QAction* aCmd, aCommands) {
1205       QString aId = aCmd->data().toString();
1206       if (aId == "NEW_CMD")
1207         aCmd->setEnabled(true);
1208       else if (aId == "EXIT_CMD")
1209         aCmd->setEnabled(true);
1210       else
1211         aCmd->setEnabled(false);
1212     }
1213   }
1214   myActionsMgr->updateCommandsStatus();
1215   emit commandStatusUpdated();
1216 }
1217
1218 void XGUI_Workshop::updateHistory()
1219 {
1220   std::list<std::string> aUndoList = ModelAPI_Session::get()->undoList();
1221   QList<ActionInfo> aUndoRes = processHistoryList(aUndoList);
1222   emit updateUndoHistory(aUndoRes);
1223
1224   std::list<std::string> aRedoList = ModelAPI_Session::get()->redoList();
1225   QList<ActionInfo> aRedoRes = processHistoryList(aRedoList);
1226   emit updateRedoHistory(aRedoRes);
1227 }
1228
1229 //******************************************************
1230 QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent)
1231 {
1232   QDockWidget* aObjDock = new QDockWidget(theParent);
1233   aObjDock->setAllowedAreas(Qt::LeftDockWidgetArea |
1234                             Qt::RightDockWidgetArea |
1235                             Qt::BottomDockWidgetArea);
1236   aObjDock->setWindowTitle(tr("Object browser"));
1237   aObjDock->setStyleSheet(
1238       "::title { position: relative; padding-left: 5px; text-align: left center }");
1239   myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock, this);
1240   myObjectBrowser->setXMLReader(myDataModelXMLReader);
1241   myModule->customizeObjectBrowser(myObjectBrowser);
1242   aObjDock->setWidget(myObjectBrowser);
1243
1244   myContextMenuMgr->connectObjectBrowser();
1245   return aObjDock;
1246 }
1247
1248 //******************************************************
1249 /*
1250  * Creates dock widgets, places them in corresponding area
1251  * and tabifies if necessary.
1252  */
1253 void XGUI_Workshop::createDockWidgets()
1254 {
1255   QMainWindow* aDesktop = desktop();
1256   QDockWidget* aObjDock = createObjectBrowser(aDesktop);
1257   aDesktop->addDockWidget(Qt::LeftDockWidgetArea, aObjDock);
1258   myPropertyPanel = new XGUI_PropertyPanel(aDesktop, myOperationMgr);
1259   myPropertyPanel->setupActions(myActionsMgr);
1260   myPropertyPanel->setAllowedAreas(Qt::LeftDockWidgetArea |
1261                                    Qt::RightDockWidgetArea |
1262                                    Qt::BottomDockWidgetArea);
1263   aDesktop->addDockWidget(Qt::LeftDockWidgetArea, myPropertyPanel);
1264   hidePropertyPanel();  ///<! Invisible by default
1265   hideObjectBrowser();
1266   aDesktop->tabifyDockWidget(aObjDock, myPropertyPanel);
1267   myPropertyPanel->installEventFilter(myOperationMgr);
1268
1269   QAction* aOkAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept);
1270   connect(aOkAct, SIGNAL(triggered()), this, SLOT(onAcceptActionClicked()));
1271
1272   QAction* aCancelAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort);
1273   connect(aCancelAct, SIGNAL(triggered()), myOperationMgr, SLOT(onAbortOperation()));
1274
1275   QAction* aPreviewAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Preview);
1276   connect(aPreviewAct, SIGNAL(triggered()), this, SLOT(onPreviewActionClicked()));
1277
1278   connect(myPropertyPanel, SIGNAL(keyReleased(QObject*, QKeyEvent*)),
1279           myOperationMgr,  SLOT(onKeyReleased(QObject*, QKeyEvent*)));
1280   connect(myPropertyPanel, SIGNAL(enterClicked(QObject*)),
1281           myOperationMgr,  SLOT(onProcessEnter(QObject*)));
1282 }
1283
1284 //******************************************************
1285 void XGUI_Workshop::showPropertyPanel()
1286 {
1287   QAction* aViewAct = myPropertyPanel->toggleViewAction();
1288   ///<! Restore ability to close panel from the window's menu
1289   aViewAct->setEnabled(true);
1290   myPropertyPanel->show();
1291   myPropertyPanel->raise();
1292
1293   // The next code is necessary to made the property panel the active window
1294   // in order to operation manager could process key events of the panel.
1295   // otherwise they are ignored. It happens only if the same(activateWindow) is
1296   // not happened by property panel activation(e.g. resume operation of Sketch)
1297   ModuleBase_Tools::setFocus(myPropertyPanel, "XGUI_Workshop::showPropertyPanel()");
1298 }
1299
1300 //******************************************************
1301 void XGUI_Workshop::hidePropertyPanel()
1302 {
1303   QAction* aViewAct = myPropertyPanel->toggleViewAction();
1304   ///<! Do not allow to show empty property panel
1305   aViewAct->setEnabled(false);
1306   myPropertyPanel->hide();
1307
1308   // the property panel is active window of the desktop, when it is
1309   // hidden, it is undefined which window becomes active. By this reason
1310   // it is defined to perform the desktop as the active window.
1311   // in SALOME mode, workstack made the PyConsole the active window,
1312   // set the focus on it. As a result, shortcuts of the application, like
1313   // are processed by this console. For example Undo actions.
1314   // It is possible that this code is to be moved to SHAPER package
1315   QMainWindow* aDesktop = desktop();
1316   ModuleBase_Tools::setFocus(aDesktop, "XGUI_Workshop::showPropertyPanel()");
1317 }
1318
1319 //******************************************************
1320 void XGUI_Workshop::showObjectBrowser()
1321 {
1322   if (!isSalomeMode())
1323     myObjectBrowser->parentWidget()->show();
1324 }
1325
1326 //******************************************************
1327 void XGUI_Workshop::hideObjectBrowser()
1328 {
1329   if (!isSalomeMode())
1330     myObjectBrowser->parentWidget()->hide();
1331 }
1332
1333 //******************************************************
1334 void XGUI_Workshop::salomeViewerSelectionChanged()
1335 {
1336   emit salomeViewerSelection();
1337 }
1338
1339 //**************************************************************
1340 ModuleBase_IViewer* XGUI_Workshop::salomeViewer() const
1341 {
1342   return mySalomeConnector->viewer();
1343 }
1344
1345 //**************************************************************
1346 void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
1347 {
1348   QObjectPtrList aObjects = mySelector->selection()->selectedObjects();
1349   if (theId == "DELETE_CMD")
1350     deleteObjects();
1351   else if (theId == "CLEAN_HISTORY_CMD")
1352     cleanHistory();
1353   else if (theId == "MOVE_CMD")
1354     moveObjects();
1355   else if (theId == "COLOR_CMD")
1356     changeColor(aObjects);
1357   else if (theId == "DEFLECTION_CMD")
1358     changeDeflection(aObjects);
1359 #ifdef USE_TRANSPARENCY
1360   else if (theId == "TRANSPARENCY_CMD")
1361     changeTransparency(aObjects);
1362 #endif
1363   else if (theId == "SHOW_CMD") {
1364     showObjects(aObjects, true);
1365     mySelector->updateSelectionBy(ModuleBase_ISelection::Browser);
1366     updateCommandStatus();
1367   }
1368   else if (theId == "HIDE_CMD") {
1369     showObjects(aObjects, false);
1370     updateCommandStatus();
1371   }
1372   else if (theId == "SHOW_ONLY_CMD") {
1373     showOnlyObjects(aObjects);
1374     mySelector->updateSelectionBy(ModuleBase_ISelection::Browser);
1375     updateCommandStatus();
1376   }
1377   else if (theId == "SHADING_CMD")
1378     setDisplayMode(aObjects, XGUI_Displayer::Shading);
1379   else if (theId == "WIREFRAME_CMD")
1380     setDisplayMode(aObjects, XGUI_Displayer::Wireframe);
1381   else if (theId == "HIDEALL_CMD") {
1382     QObjectPtrList aList = myDisplayer->displayedObjects();
1383     foreach (ObjectPtr aObj, aList) {
1384       if (module()->canEraseObject(aObj))
1385         aObj->setDisplayed(false);
1386     }
1387     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1388 #ifdef HAVE_SALOME
1389     //issue #2159 Hide all incomplete behavior
1390     viewer()->eraseAll();
1391 #endif
1392     updateCommandStatus();
1393   } else if (theId == "SELECT_VERTEX_CMD") {
1394     setViewerSelectionMode(TopAbs_VERTEX);
1395   } else if (theId == "SELECT_EDGE_CMD") {
1396     setViewerSelectionMode(TopAbs_EDGE);
1397   } else if (theId == "SELECT_FACE_CMD") {
1398     setViewerSelectionMode(TopAbs_FACE);
1399   } else if (theId == "SELECT_RESULT_CMD") {
1400     //setViewerSelectionMode(-1);
1401     //IMP: an attempt to use result selection with other selection modes
1402     setViewerSelectionMode(ModuleBase_ResultPrs::Sel_Result);
1403     setViewerSelectionMode(TopAbs_COMPSOLID);
1404   } else if (theId == "SHOW_RESULTS_CMD") {
1405     highlightResults(aObjects);
1406   } else if (theId == "SHOW_FEATURE_CMD") {
1407     highlightFeature(aObjects);
1408   }
1409 #ifdef TINSPECTOR
1410   else if (theId == "TINSPECTOR_VIEW") {
1411     Handle(CDF_Application) anApplication = CDF_Session::CurrentSession()->CurrentApplication();
1412     if (!anApplication.IsNull())
1413     {
1414       if (!MyTCommunicator)
1415       {
1416         MyTCommunicator = new TInspector_Communicator();
1417
1418         NCollection_List<Handle(Standard_Transient)> aParameters;
1419         aParameters.Append(anApplication);
1420         Handle(AIS_InteractiveContext) aContext = viewer()->AISContext();
1421         if (!aContext.IsNull())
1422           aParameters.Append(aContext);
1423
1424         MyVCallBack = new VInspector_CallBack();
1425         myDisplayer->setCallBack(MyVCallBack);
1426         #ifndef HAVE_SALOME
1427         AppElements_Viewer* aViewer = mainWindow()->viewer();
1428         if (aViewer)
1429           aViewer->setCallBack(MyVCallBack);
1430         #endif
1431         aParameters.Append(MyVCallBack);
1432
1433         MyTCommunicator->RegisterPlugin("TKDFBrowser");
1434         MyTCommunicator->RegisterPlugin("TKShapeView");
1435         MyTCommunicator->RegisterPlugin("TKVInspector");
1436         MyTCommunicator->RegisterPlugin("SMBrowser"); // custom plugin to view ModelAPI
1437         //MyTCommunicator->RegisterPlugin("TKSMBrowser"); // custom plugin to view ModelAPI
1438
1439         MyTCommunicator->Init(aParameters);
1440         MyTCommunicator->Activate("TKSMBrowser"); // to have button in TInspector
1441         MyTCommunicator->Activate("TKVInspector"); // to have filled callback by model
1442         MyTCommunicator->Activate("TKDFBrowser");
1443       }
1444       MyTCommunicator->SetVisible(true);
1445     }
1446   }
1447 #endif
1448 }
1449
1450 //**************************************************************
1451 void XGUI_Workshop::setViewerSelectionMode(int theMode)
1452 {
1453   if (theMode == -1)
1454     myViewerSelMode.clear();
1455   else {
1456     if (myViewerSelMode.contains(theMode))
1457       myViewerSelMode.removeAll(theMode);
1458     else
1459       myViewerSelMode.append(theMode);
1460   }
1461   activateObjectsSelection(myDisplayer->displayedObjects());
1462 }
1463
1464 //**************************************************************
1465 void XGUI_Workshop::activateObjectsSelection(const QObjectPtrList& theList)
1466 {
1467   QIntList aModes;
1468   module()->activeSelectionModes(aModes);
1469   if (aModes.isEmpty() && (myViewerSelMode.length() > 0))
1470     aModes.append(myViewerSelMode);
1471   myDisplayer->activateObjects(aModes, theList);
1472 }
1473
1474 //**************************************************************
1475 void XGUI_Workshop::deleteObjects()
1476 {
1477   ModuleBase_IModule* aModule = module();
1478   // allow the module to delete objects, do nothing if it has succeed
1479   if (aModule->deleteObjects()) {
1480     updateCommandStatus();
1481     return;
1482   }
1483
1484   QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
1485   if (!abortAllOperations())
1486     return;
1487
1488   bool hasResult = false;
1489   bool hasFeature = false;
1490   bool hasParameter = false;
1491   bool hasCompositeOwner = false;
1492   bool hasResultInHistory = false;
1493   ModuleBase_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter, hasCompositeOwner,
1494                                  hasResultInHistory);
1495   if (!(hasFeature || hasParameter))
1496     return;
1497
1498   // delete objects
1499   std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
1500   std::set<FeaturePtr> aFeatures;
1501   ModuleBase_Tools::convertToFeatures(anObjects, aFeatures);
1502   ModelAPI_Tools::findAllReferences(aFeatures, aReferences);
1503
1504   bool aDone = false;
1505   QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text() + " %1";
1506   aDescription = aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", "));
1507   ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, module());
1508
1509   operationMgr()->startOperation(anOpAction);
1510
1511   std::set<FeaturePtr> aFeatureRefsToDelete;
1512   if (ModuleBase_Tools::askToDelete(aFeatures, aReferences, desktop(), aFeatureRefsToDelete)) {
1513     // WORKAROUND, should be done before each object remove, if it presents in XGUI_DataModel tree
1514     // It is necessary to clear selection in order to avoid selection changed event during
1515     // deletion and negative consequences connected with processing of already deleted items
1516     mySelector->clearSelection();
1517
1518     if (!aFeatureRefsToDelete.empty())
1519       aFeatures.insert(aFeatureRefsToDelete.begin(), aFeatureRefsToDelete.end());
1520     aDone = ModelAPI_Tools::removeFeatures(aFeatures, false);
1521   }
1522   if (aDone)
1523     operationMgr()->commitOperation();
1524   else
1525     operationMgr()->abortOperation(operationMgr()->currentOperation());
1526 }
1527
1528 //**************************************************************
1529 void addRefsToFeature(const FeaturePtr& theFeature,
1530                       const std::map<FeaturePtr, std::set<FeaturePtr> >& theMainList,
1531                       std::set<FeaturePtr>& theReferences)
1532 {
1533   //if (theReferences.find(theFeature) != theReferences.end())
1534   //  return;
1535   if (theMainList.find(theFeature) == theMainList.end())
1536     return; // this feature is not in the selection list, so exists without references to it
1537   std::set<FeaturePtr> aMainReferences = theMainList.at(theFeature);
1538
1539   std::set<FeaturePtr>::const_iterator anIt = aMainReferences.begin(),
1540                                        aLast = aMainReferences.end();
1541   for (; anIt != aLast; anIt++) {
1542     FeaturePtr aRefFeature = *anIt;
1543     if (theReferences.find(aRefFeature) == theReferences.end())
1544       theReferences.insert(aRefFeature);
1545     addRefsToFeature(aRefFeature, theMainList, theReferences);
1546   }
1547 }
1548
1549 //**************************************************************
1550 void XGUI_Workshop::cleanHistory()
1551 {
1552   if (!abortAllOperations())
1553     return;
1554
1555   QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
1556   std::set<FeaturePtr> aFeatures;
1557   ModuleBase_Tools::convertToFeatures(anObjects, aFeatures);
1558
1559 #ifdef DEBUG_CLEAN_HISTORY
1560   QStringList anInfo;
1561   std::set<FeaturePtr>::const_iterator aFIt;
1562   for (aFIt = aFeatures.begin(); aFIt != aFeatures.end(); ++aFIt) {
1563     FeaturePtr aFeature = ModelAPI_Feature::feature(*aFIt);
1564     anInfo.append(aFeature->name().c_str());
1565   }
1566   QString anInfoStr = anInfo.join(";\t");
1567   qDebug(QString("cleanHistory for: [%1] - %2").
1568     arg(aFeatures.size()).arg(anInfoStr).toStdString().c_str());
1569 #endif
1570
1571   std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
1572   ModelAPI_Tools::findAllReferences(aFeatures, aReferences, true, false);
1573   // find for each object whether all reference values are in the map as key, that means that there
1574   // is no other reference in the model to this object, so it might be removed by cleaning history
1575   // sk_1(ext_1, vertex_1) + (sk_3, bool_1) - cann't be deleted, dependency to bool_1
1576   // ext_1(bool_1, sk_3)  - cann't be deleted, dependency to bool_1
1577   // vertex_1()
1578   // sk_2(ext_2) + (bool_1)  - cann't be deleted, dependency to bool_1
1579   // ext_2(bool_1)  - cann't be deleted, dependency to bool_1
1580   // sk_3()
1581   // Information: bool_1 is not selected
1582   std::set<FeaturePtr> anUnusedObjects;
1583   std::map<FeaturePtr, std::set<FeaturePtr> >::const_iterator aMainIt = aReferences.begin(),
1584                                                               aMainLast = aReferences.end();
1585   for (; aMainIt != aMainLast; aMainIt++) {
1586     FeaturePtr aMainListFeature = aMainIt->first;
1587     std::set<FeaturePtr> aMainRefList = aMainIt->second;
1588     std::set<FeaturePtr>::const_iterator aRefIt = aMainRefList.begin(),
1589                                                   aRefLast = aMainRefList.end();
1590     bool aFeatureOutOfTheList = false;
1591     for (; aRefIt != aRefLast && !aFeatureOutOfTheList; aRefIt++) {
1592       FeaturePtr aRefFeature = *aRefIt;
1593       aFeatureOutOfTheList = aReferences.find(aRefFeature) == aReferences.end();
1594     }
1595     if (!aFeatureOutOfTheList)
1596       anUnusedObjects.insert(aMainListFeature);
1597   }
1598
1599 #ifdef DEBUG_CLEAN_HISTORY
1600   anInfo.clear();
1601   for (aFIt = anUnusedObjects.begin(); aFIt != anUnusedObjects.end(); ++aFIt) {
1602     FeaturePtr aFeature = *aFIt;
1603     anInfo.append(aFeature->name().c_str());
1604   }
1605   qDebug(QString("unused objects: [%1] - %2").
1606     arg(anInfo.size()).arg(anInfo.join(";\t")).toStdString().c_str());
1607 #endif
1608
1609   // warn about the references remove, break the delete operation if the user chose it
1610   if (!anUnusedObjects.empty()) {
1611     QStringList aNames;
1612     foreach (const FeaturePtr& aFeature, anUnusedObjects) {
1613       aNames.append(aFeature->name().c_str());
1614     }
1615     aNames.sort();
1616     QString anUnusedNames = aNames.join(", ");
1617
1618     QString anActionId = "CLEAN_HISTORY_CMD";
1619     QString aDescription = contextMenuMgr()->action(anActionId)->text();
1620
1621     QMessageBox aMessageBox(desktop());
1622     aMessageBox.setWindowTitle(aDescription);
1623     aMessageBox.setIcon(QMessageBox::Warning);
1624     aMessageBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1625     aMessageBox.setDefaultButton(QMessageBox::No);
1626
1627     const char* aKeyStr = "Unused features are the following: "
1628                           "%1.\nThese features will be deleted.\nWould you like to continue?";
1629     QString aText = QString(tr(aKeyStr).arg(anUnusedNames));
1630     aMessageBox.setText(aText);
1631     if (aMessageBox.exec() == QMessageBox::No)
1632       return;
1633
1634     // 1. start operation
1635     aDescription += "by deleting of " +
1636       aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", "));
1637     ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, module());
1638     operationMgr()->startOperation(anOpAction);
1639
1640     // WORKAROUND, should be done before each object remove, if it presents in XGUI_DataModel tree
1641     // It is necessary to clear selection in order to avoid selection changed event during
1642     // deletion and negative consequences connected with processing of already deleted items
1643     mySelector->clearSelection();
1644
1645     std::set<FeaturePtr> anIgnoredFeatures;
1646     if (ModelAPI_Tools::removeFeatures(anUnusedObjects, true)) {
1647       operationMgr()->commitOperation();
1648     }
1649     else {
1650       operationMgr()->abortOperation(operationMgr()->currentOperation());
1651     }
1652   }
1653   else {
1654     QString anActionId = "CLEAN_HISTORY_CMD";
1655     QString aDescription = contextMenuMgr()->action(anActionId)->text();
1656
1657     QMessageBox aMessageBox(desktop());
1658     aMessageBox.setWindowTitle(aDescription);
1659     aMessageBox.setIcon(QMessageBox::Warning);
1660     aMessageBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1661     aMessageBox.setDefaultButton(QMessageBox::No);
1662
1663     QString aText;
1664     aMessageBox.setStandardButtons(QMessageBox::Ok);
1665     aMessageBox.setDefaultButton(QMessageBox::Ok);
1666
1667     aText = QString(tr("All features are relevant, there is nothing to be deleted"));
1668     aMessageBox.setText(aText);
1669
1670     if (aMessageBox.exec() == QMessageBox::No)
1671       return;
1672   }
1673 }
1674
1675 //**************************************************************
1676 void XGUI_Workshop::moveObjects()
1677 {
1678   if (!abortAllOperations())
1679     return;
1680
1681   SessionPtr aMgr = ModelAPI_Session::get();
1682
1683   QString anActionId = "MOVE_CMD";
1684   QString aDescription = contextMenuMgr()->action(anActionId)->text();
1685   aMgr->startOperation(aDescription.toStdString());
1686
1687   QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
1688   // It is necessary to clear selection in order to avoid selection changed event during
1689   // moving and negative consequences connected with processing of already moved items
1690   mySelector->clearSelection();
1691   // check whether the object can be moved. There should not be parts which are not loaded
1692   std::set<FeaturePtr> aFeatures;
1693   ModuleBase_Tools::convertToFeatures(anObjects, aFeatures);
1694   if (!XGUI_Tools::canRemoveOrRename(desktop(), aFeatures))
1695     return;
1696
1697   DocumentPtr anActiveDocument = aMgr->activeDocument();
1698   FeaturePtr aCurrentFeature = anActiveDocument->currentFeature(true);
1699   std::set<FeaturePtr>::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end();
1700   for (; anIt != aLast; anIt++) {
1701     FeaturePtr aFeature = *anIt;
1702     if (!aFeature.get() || !myModule->canApplyAction(aFeature, anActionId))
1703       continue;
1704
1705     anActiveDocument->moveFeature(aFeature, aCurrentFeature);
1706     aCurrentFeature = anActiveDocument->currentFeature(true);
1707   }
1708   aMgr->finishOperation();
1709 }
1710
1711 //**************************************************************
1712 bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theObjects)
1713 {
1714   std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
1715   std::set<FeaturePtr> aFeatures;
1716   ModuleBase_Tools::convertToFeatures(theObjects, aFeatures);
1717
1718   return ModelAPI_Tools::removeFeaturesAndReferences(aFeatures);
1719 }
1720
1721 bool hasResults(QObjectPtrList theObjects, const std::set<std::string>& theTypes)
1722 {
1723   bool isFoundResultType = false;
1724   foreach(ObjectPtr anObj, theObjects)
1725   {
1726     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
1727     if (aResult.get() == NULL)
1728       continue;
1729
1730     isFoundResultType = theTypes.find(aResult->groupName()) != theTypes.end();
1731     if (isFoundResultType)
1732       break;
1733   }
1734   return isFoundResultType;
1735 }
1736
1737 //**************************************************************
1738 // Returns the list of all features for theDocument and all features of
1739 // all nested parts.
1740 std::list<FeaturePtr> allFeatures(const DocumentPtr& theDocument)
1741 {
1742   std::list<FeaturePtr> aResultList;
1743   std::list<FeaturePtr> anAllFeatures = theDocument->allFeatures();
1744   foreach (const FeaturePtr& aFeature, anAllFeatures) {
1745     // The order of appending features of the part and the part itself is important
1746
1747     // Append features from a part feature
1748     std::list<ResultPtr> aResults;
1749     ModelAPI_Tools::allResults(aFeature, aResults);
1750     foreach (const ResultPtr& aResult, aResults) {
1751       ResultPartPtr aResultPart =
1752           std::dynamic_pointer_cast<ModelAPI_ResultPart>(aResult);
1753       if (aResultPart.get() && aResultPart->partDoc().get()) {
1754         // Recursion
1755         std::list<FeaturePtr> anAllFeatures = allFeatures(aResultPart->partDoc());
1756         aResultList.insert(aResultList.end(), anAllFeatures.begin(), anAllFeatures.end());
1757       }
1758     }
1759
1760     aResultList.push_back(aFeature);
1761   }
1762   return aResultList;
1763 }
1764
1765 //**************************************************************
1766 // Returns the list of features placed between theObject and the current feature
1767 // in the same document. Excludes theObject, includes the current feature.
1768 std::list<FeaturePtr> toCurrentFeatures(const ObjectPtr& theObject)
1769 {
1770   std::list<FeaturePtr> aResult;
1771   DocumentPtr aDocument = theObject->document();
1772   std::list<FeaturePtr> anAllFeatures = allFeatures(aDocument);
1773   // find the object iterator
1774   std::list<FeaturePtr>::iterator aObjectIt =
1775     std::find(anAllFeatures.begin(), anAllFeatures.end(), theObject);
1776   if (aObjectIt == anAllFeatures.end())
1777     return aResult;
1778   // find the current feature iterator
1779   std::list<FeaturePtr>::iterator aCurrentIt =
1780     std::find(anAllFeatures.begin(), anAllFeatures.end(), aDocument->currentFeature(true));
1781   if (aCurrentIt == anAllFeatures.end())
1782     return aResult;
1783   // check the right order
1784   if (std::distance(aObjectIt, anAllFeatures.end()) <=
1785       std::distance(aCurrentIt, anAllFeatures.end()))
1786     return aResult;
1787   // exclude the object
1788   std::advance(aObjectIt, 1);
1789   // include the current feature
1790   std::advance(aCurrentIt, 1);
1791   return std::list<FeaturePtr>(aObjectIt, aCurrentIt);
1792 }
1793
1794 bool XGUI_Workshop::canMoveFeature()
1795 {
1796   QString anActionId = "MOVE_CMD";
1797
1798   QObjectPtrList aObjects = mySelector->selection()->selectedObjects();
1799   QObjectPtrList aValidatedObjects;
1800   foreach (ObjectPtr aObject, aObjects) {
1801     if (!myModule->canApplyAction(aObject, anActionId))
1802       continue;
1803     // To be moved feature should be in active document
1804     if (aObject->document() != ModelAPI_Session::get()->activeDocument())
1805       continue;
1806     aValidatedObjects.append(aObject);
1807   }
1808   if (aValidatedObjects.size() != aObjects.size())
1809     aObjects = aValidatedObjects;
1810
1811   bool aCanMove = !aObjects.empty();
1812
1813   QObjectPtrList::const_iterator anIt = aObjects.begin(), aLast = aObjects.end();
1814   for (; anIt != aLast && aCanMove; anIt++) {
1815     ObjectPtr aObject = *anIt;
1816     // 1. Get features placed between selected and current in the document
1817     std::list<FeaturePtr> aFeaturesBetween = toCurrentFeatures(aObject);
1818     // if aFeaturesBetween is empty it means wrong order or aObject is the current feature
1819     if (aFeaturesBetween.empty())
1820       aCanMove = false;
1821     else {
1822       std::set<FeaturePtr> aPlacedFeatures(aFeaturesBetween.begin(), aFeaturesBetween.end());
1823       // 2. Get all reference features to the selected object in the document
1824       std::set<FeaturePtr> aRefFeatures;
1825       ModuleBase_Tools::refsToFeatureInFeatureDocument(aObject, aRefFeatures);
1826
1827       if (aRefFeatures.empty())
1828         continue;
1829       else {
1830         // 3. Find any placed features in all reference features
1831         std::set<FeaturePtr> aIntersectionFeatures;
1832         std::set_intersection(aRefFeatures.begin(), aRefFeatures.end(),
1833                               aPlacedFeatures.begin(), aPlacedFeatures.end(),
1834                               std::inserter(aIntersectionFeatures, aIntersectionFeatures.begin()));
1835         // 4. Return false if any reference feature is placed before current feature
1836         if (!aIntersectionFeatures.empty())
1837           aCanMove = false;
1838       }
1839     }
1840   }
1841   return aCanMove;
1842 }
1843
1844 //**************************************************************
1845 bool XGUI_Workshop::canBeShaded(const ObjectPtr& theObject) const
1846 {
1847   bool aCanBeShaded = myDisplayer->canBeShaded(theObject);
1848   if (!aCanBeShaded) {
1849     ResultCompSolidPtr aCompsolidResult =
1850                 std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
1851     if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids
1852       for(int i = 0; i < aCompsolidResult->numberOfSubs() && !aCanBeShaded; i++)
1853         aCanBeShaded = myDisplayer->canBeShaded(aCompsolidResult->subResult(i));
1854     }
1855   }
1856   return aCanBeShaded;
1857 }
1858
1859 //**************************************************************
1860 bool XGUI_Workshop::canChangeProperty(const QString& theActionName) const
1861 {
1862   if (theActionName == "COLOR_CMD" ||
1863       theActionName == "DEFLECTION_CMD"
1864 #ifdef USE_TRANSPARENCY
1865       || theActionName == "TRANSPARENCY_CMD"
1866 #endif
1867       ) {
1868     QObjectPtrList aObjects = mySelector->selection()->selectedObjects();
1869
1870     std::set<std::string> aTypes;
1871     aTypes.insert(ModelAPI_ResultGroup::group());
1872     aTypes.insert(ModelAPI_ResultConstruction::group());
1873     aTypes.insert(ModelAPI_ResultBody::group());
1874     aTypes.insert(ModelAPI_ResultPart::group());
1875
1876     return hasResults(aObjects, aTypes);
1877   }
1878   return false;
1879 }
1880
1881 void setColor(ResultPtr theResult, const std::vector<int>& theColor)
1882 {
1883   if (!theResult.get())
1884     return;
1885
1886   AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
1887   if (aColorAttr.get() != NULL) {
1888     if (!aColorAttr->size()) {
1889       aColorAttr->setSize(3);
1890     }
1891     aColorAttr->setValue(0, theColor[0]);
1892     aColorAttr->setValue(1, theColor[1]);
1893     aColorAttr->setValue(2, theColor[2]);
1894   }
1895 }
1896
1897 //**************************************************************
1898 void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
1899 {
1900
1901   AttributeIntArrayPtr aColorAttr;
1902   // 1. find the current color of the object. This is a color of AIS presentation
1903   // The objects are iterated until a first valid color is found
1904   std::vector<int> aColor;
1905   foreach(ObjectPtr anObject, theObjects) {
1906     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
1907     if (aResult.get()) {
1908       XGUI_CustomPrs::getResultColor(aResult, aColor);
1909     }
1910     else {
1911       // TODO: remove the obtaining a color from the AIS object
1912       // this does not happen never because:
1913       // 1. The color can be changed only on results
1914       // 2. The result can be not visualized in the viewer(e.g. Origin Construction)
1915       AISObjectPtr anAISObj = myDisplayer->getAISObject(anObject);
1916       if (anAISObj.get()) {
1917         aColor.resize(3);
1918         anAISObj->getColor(aColor[0], aColor[1], aColor[2]);
1919       }
1920     }
1921     if (!aColor.empty())
1922       break;
1923   }
1924   if (aColor.size() != 3)
1925     return;
1926
1927   if (!abortAllOperations())
1928   return;
1929   // 2. show the dialog to change the value
1930   XGUI_ColorDialog* aDlg = new XGUI_ColorDialog(desktop());
1931   aDlg->setColor(aColor);
1932   aDlg->move(QCursor::pos());
1933   bool isDone = aDlg->exec() == QDialog::Accepted;
1934   if (!isDone)
1935     return;
1936
1937   bool isRandomColor = aDlg->isRandomColor();
1938
1939   // 3. abort the previous operation and start a new one
1940   SessionPtr aMgr = ModelAPI_Session::get();
1941   QString aDescription = contextMenuMgr()->action("COLOR_CMD")->text();
1942   aMgr->startOperation(aDescription.toStdString());
1943
1944   // 4. set the value to all results
1945   std::vector<int> aColorResult = aDlg->getColor();
1946   foreach(ObjectPtr anObj, theObjects) {
1947     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
1948     if (aResult.get() != NULL) {
1949       ResultCompSolidPtr aCompsolidResult =
1950         std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
1951       if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids
1952         for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
1953           setColor(aCompsolidResult->subResult(i), !isRandomColor ? aColorResult :
1954                                                                     aDlg->getRandomColor());
1955         }
1956       }
1957       setColor(aResult, !isRandomColor ? aColorResult : aDlg->getRandomColor());
1958     }
1959   }
1960   aMgr->finishOperation();
1961   updateCommandStatus();
1962 }
1963
1964 //**************************************************************
1965 void setDeflection(ResultPtr theResult, const double theDeflection)
1966 {
1967   if (!theResult.get())
1968     return;
1969
1970   AttributeDoublePtr aDeflectionAttr = theResult->data()->real(ModelAPI_Result::DEFLECTION_ID());
1971   if (aDeflectionAttr.get() != NULL)
1972     aDeflectionAttr->setValue(theDeflection);
1973 }
1974
1975 //**************************************************************
1976 void setTransparency(ResultPtr theResult, double theTransparency)
1977 {
1978   if (!theResult.get())
1979     return;
1980
1981   AttributeDoublePtr anAttribute = theResult->data()->real(ModelAPI_Result::TRANSPARENCY_ID());
1982   if (anAttribute.get() != NULL)
1983     anAttribute->setValue(theTransparency);
1984 }
1985
1986 //**************************************************************
1987 void setTransparency(double theTransparency, const QObjectPtrList& theObjects)
1988 {
1989   foreach(ObjectPtr anObj, theObjects) {
1990     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
1991     if (aResult.get() != NULL) {
1992       ResultCompSolidPtr aCompsolidResult =
1993         std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
1994       if (aCompsolidResult.get() != NULL) { // change property for all sub-solids
1995         for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
1996           setTransparency(aCompsolidResult->subResult(i), theTransparency);
1997         }
1998       }
1999       setTransparency(aResult, theTransparency);
2000     }
2001   }
2002 }
2003
2004 //**************************************************************
2005 void XGUI_Workshop::changeDeflection(const QObjectPtrList& theObjects)
2006 {
2007   AttributeDoublePtr aDoubleAttr;
2008   // 1. find the current property of the object. This is a property of AIS presentation
2009   // The objects are iterated until a first valid property is found
2010   double aDeflection = -1;
2011   foreach(ObjectPtr anObject, theObjects) {
2012     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
2013     if (aResult.get()) {
2014       aDeflection = XGUI_CustomPrs::getResultDeflection(aResult);
2015     }
2016     else {
2017       // TODO: remove the obtaining a property from the AIS object
2018       // this does not happen never because:
2019       // 1. The property can be changed only on results
2020       // 2. The result can be not visualized in the viewer(e.g. Origin Construction)
2021       AISObjectPtr anAISObj = myDisplayer->getAISObject(anObject);
2022       if (anAISObj.get()) {
2023         aDeflection = anAISObj->getDeflection();
2024       }
2025     }
2026     if (aDeflection > 0)
2027       break;
2028   }
2029   if (aDeflection < 0)
2030     return;
2031
2032   if (!abortAllOperations())
2033   return;
2034   // 2. show the dialog to change the value
2035   XGUI_DeflectionDialog* aDlg = new XGUI_DeflectionDialog(desktop());
2036   aDlg->setDeflection(aDeflection);
2037   aDlg->move(QCursor::pos());
2038   bool isDone = aDlg->exec() == QDialog::Accepted;
2039   if (!isDone)
2040     return;
2041
2042   // 3. abort the previous operation and start a new one
2043   SessionPtr aMgr = ModelAPI_Session::get();
2044   QString aDescription = contextMenuMgr()->action("DEFLECTION_CMD")->text();
2045   aMgr->startOperation(aDescription.toStdString());
2046
2047   // 4. set the value to all results
2048   aDeflection = aDlg->getDeflection();
2049   foreach(ObjectPtr anObj, theObjects) {
2050     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
2051     if (aResult.get() != NULL) {
2052       ResultCompSolidPtr aCompsolidResult =
2053         std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
2054       if (aCompsolidResult.get() != NULL) { // change property for all sub-solids
2055         for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
2056           setDeflection(aCompsolidResult->subResult(i), aDeflection);
2057         }
2058       }
2059       setDeflection(aResult, aDeflection);
2060     }
2061   }
2062   aMgr->finishOperation();
2063   updateCommandStatus();
2064 }
2065
2066 //**************************************************************
2067 void XGUI_Workshop::changeTransparency(const QObjectPtrList& theObjects)
2068 {
2069   AttributeDoublePtr aDoubleAttr;
2070   // 1. find the current property of the object. This is a property of AIS presentation
2071   // The objects are iterated until a first valid property is found
2072   double aCurrentValue = -1;
2073   foreach(ObjectPtr anObject, theObjects) {
2074     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
2075     if (aResult.get()) {
2076       aCurrentValue = XGUI_CustomPrs::getResultTransparency(aResult);
2077     }
2078     else {
2079       // TODO: remove the obtaining a property from the AIS object
2080       // this does not happen never because:
2081       // 1. The property can be changed only on results
2082       // 2. The result can be not visualized in the viewer(e.g. Origin Construction)
2083       AISObjectPtr anAISObj = myDisplayer->getAISObject(anObject);
2084       if (anAISObj.get()) {
2085         aCurrentValue = anAISObj->getDeflection();
2086       }
2087     }
2088     if (aCurrentValue > 0)
2089       break;
2090   }
2091   if (aCurrentValue < 0)
2092     return;
2093
2094   if (!abortAllOperations())
2095   return;
2096
2097   // 2. show the dialog to change the value
2098   XGUI_PropertyDialog* aDlg = new XGUI_PropertyDialog(desktop());
2099   aDlg->setWindowTitle("Transparency");
2100   XGUI_TransparencyWidget* aTransparencyWidget = new XGUI_TransparencyWidget(aDlg);
2101   connect(aTransparencyWidget, SIGNAL(transparencyValueChanged()),
2102           this, SLOT(onTransparencyValueChanged()));
2103   connect(aTransparencyWidget, SIGNAL(previewStateChanged()),
2104           this, SLOT(onPreviewStateChanged()));
2105   aDlg->setContent(aTransparencyWidget);
2106   aTransparencyWidget->setValue(aCurrentValue);
2107
2108   // 3. abort the previous operation and start a new one
2109   SessionPtr aMgr = ModelAPI_Session::get();
2110   QString aDescription = contextMenuMgr()->action("TRANSPARENCY_CMD")->text();
2111   aMgr->startOperation(aDescription.toStdString());
2112
2113   aDlg->move(QCursor::pos());
2114   bool isDone = aDlg->exec() == QDialog::Accepted;
2115   if (!isDone)
2116     return;
2117
2118   // 4. set the value to all results
2119   aCurrentValue = aTransparencyWidget->getValue();
2120   setTransparency(aCurrentValue, theObjects);
2121
2122   aMgr->finishOperation();
2123   updateCommandStatus();
2124 }
2125
2126 //**************************************************************
2127 void XGUI_Workshop::onTransparencyValueChanged()
2128 {
2129   XGUI_TransparencyWidget* aTransparencyWidget = (XGUI_TransparencyWidget*)sender();
2130   if (!aTransparencyWidget || !aTransparencyWidget->isPreviewNeeded())
2131     return;
2132
2133   QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
2134   setTransparency(aTransparencyWidget->getValue(), anObjects);
2135   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
2136 }
2137
2138 //**************************************************************
2139 void XGUI_Workshop::onPreviewStateChanged()
2140 {
2141   XGUI_TransparencyWidget* aTransparencyWidget = (XGUI_TransparencyWidget*)sender();
2142   if (!aTransparencyWidget || !aTransparencyWidget->isPreviewNeeded())
2143     return;
2144
2145   QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
2146   setTransparency(aTransparencyWidget->getValue(), anObjects);
2147   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
2148 }
2149
2150 //**************************************************************
2151 #define SET_DISPLAY_GROUP(aGroupName, aDisplay) \
2152 for (int i = 0; i < aDoc->size(aGroupName); i++) { \
2153   aDoc->object(aGroupName, i)->setDisplayed(aDisplay); \
2154 }
2155 void XGUI_Workshop::showObjects(const QObjectPtrList& theList, bool isVisible)
2156 {
2157   foreach (ObjectPtr aObj, theList) {
2158     aObj->setDisplayed(isVisible);
2159   }
2160   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
2161 }
2162
2163 //**************************************************************
2164 void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList)
2165 {
2166   // Hide all displayed objects
2167   QObjectPtrList aList = myDisplayer->displayedObjects();
2168   foreach (ObjectPtr aObj, aList) {
2169     if (module()->canEraseObject(aObj))
2170       aObj->setDisplayed(false);
2171   }
2172   //Do not use eraseAll if you didn't send Redisplay event:
2173   //all objects are erased from viewer, but considered as displayed in displayer
2174   // Problem in bug 2218
2175   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
2176 #ifdef HAVE_SALOME
2177     //issue #2159 Hide all incomplete behavior
2178     viewer()->eraseAll();
2179 #endif
2180
2181   // Show only objects from the list
2182   foreach (ObjectPtr aObj, theList) {
2183     aObj->setDisplayed(true);
2184   }
2185   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
2186 }
2187
2188
2189 //**************************************************************
2190 void XGUI_Workshop::registerValidators() const
2191 {
2192   SessionPtr aMgr = ModelAPI_Session::get();
2193   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
2194 }
2195
2196 //**************************************************************
2197 void XGUI_Workshop::displayDocumentResults(DocumentPtr theDoc)
2198 {
2199   if (!theDoc)
2200     return;
2201   displayGroupResults(theDoc, ModelAPI_ResultConstruction::group());
2202   displayGroupResults(theDoc, ModelAPI_ResultBody::group());
2203 }
2204
2205 //**************************************************************
2206 void XGUI_Workshop::displayGroupResults(DocumentPtr theDoc, std::string theGroup)
2207 {
2208   for (int i = 0; i < theDoc->size(theGroup); i++)
2209     theDoc->object(theGroup, i)->setDisplayed(true);
2210     //displayObject(theDoc->object(theGroup, i));
2211   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
2212 }
2213
2214 //**************************************************************
2215 void XGUI_Workshop::setDisplayMode(const QObjectPtrList& theList, int theMode)
2216 {
2217   foreach(ObjectPtr aObj, theList) {
2218     myDisplayer->setDisplayMode(aObj, (XGUI_Displayer::DisplayMode)theMode, false);
2219
2220     ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aObj);
2221     if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids
2222       for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
2223           myDisplayer->setDisplayMode(aCompsolidResult->subResult(i),
2224                                       (XGUI_Displayer::DisplayMode)theMode, false);
2225       }
2226     }
2227   }
2228   if (theList.size() > 0)
2229     myDisplayer->updateViewer();
2230 }
2231
2232 //**************************************************************
2233 void XGUI_Workshop::closeDocument()
2234 {
2235   ModuleBase_Operation* anOperation = operationMgr()->currentOperation();
2236   while (anOperation) {
2237     anOperation->abort();
2238     anOperation = operationMgr()->currentOperation();
2239   }
2240   //myDisplayer->closeLocalContexts();
2241   myDisplayer->eraseAll();
2242   objectBrowser()->clearContent();
2243
2244   module()->closeDocument();
2245
2246   // data model need not process the document's signals about objects modifications as
2247   // the document is closed
2248   //bool isBlocked = objectBrowser()->dataModel()->blockEventsProcessing(true);
2249
2250   SessionPtr aMgr = ModelAPI_Session::get();
2251   aMgr->closeAll();
2252
2253   //objectBrowser()->dataModel()->blockEventsProcessing(isBlocked);
2254 }
2255
2256 void XGUI_Workshop::addHistoryMenu(QObject* theObject, const char* theSignal, const char* theSlot)
2257 {
2258   XGUI_HistoryMenu* aMenu = NULL;
2259   if (isSalomeMode()) {
2260     QAction* anAction = qobject_cast<QAction*>(theObject);
2261     if (!anAction)
2262       return;
2263     aMenu = new XGUI_HistoryMenu(anAction);
2264   } else {
2265     QToolButton* aButton =  qobject_cast<QToolButton*>(theObject);
2266     aMenu = new XGUI_HistoryMenu(aButton);
2267   }
2268   connect(this, theSignal, aMenu, SLOT(setHistory(const QList<ActionInfo>&)));
2269   connect(aMenu, SIGNAL(actionSelected(int)), this, theSlot);
2270 }
2271
2272 QList<ActionInfo> XGUI_Workshop::processHistoryList(const std::list<std::string>& theList) const
2273 {
2274   QList<ActionInfo> aResult;
2275   std::list<std::string>::const_iterator it = theList.cbegin();
2276   for (; it != theList.cend(); it++) {
2277     QString anId = QString::fromStdString(*it);
2278     bool isEditing = anId.endsWith(ModuleBase_OperationFeature::EditSuffix());
2279     if (isEditing) {
2280       anId.chop(ModuleBase_OperationFeature::EditSuffix().size());
2281     }
2282     ActionInfo anInfo;
2283     QAction* aContextMenuAct = myContextMenuMgr->actionByName(anId);
2284     if (aContextMenuAct) {
2285       anInfo.initFrom(aContextMenuAct);
2286     } else {
2287       anInfo = myActionsMgr->actionInfoById(anId);
2288     }
2289     if (isEditing) {
2290       anInfo.text = anInfo.text.prepend("Modify ");
2291     }
2292     aResult << anInfo;
2293   }
2294   return aResult;
2295 }
2296
2297 void XGUI_Workshop::setStatusBarMessage(const QString& theMessage)
2298 {
2299 #ifdef HAVE_SALOME
2300   salomeConnector()->putInfo(theMessage, -1);
2301 #else
2302   myMainWindow->putInfo(theMessage, -1);
2303 #endif
2304 }
2305
2306 void XGUI_Workshop::synchronizeViewer()
2307 {
2308   SessionPtr aMgr = ModelAPI_Session::get();
2309   QList<DocumentPtr> aDocs;
2310   aDocs.append(aMgr->activeDocument());
2311   aDocs.append(aMgr->moduleDocument());
2312
2313   foreach(DocumentPtr aDoc, aDocs) {
2314     synchronizeGroupInViewer(aDoc, ModelAPI_ResultConstruction::group(), false);
2315     synchronizeGroupInViewer(aDoc, ModelAPI_ResultBody::group(), false);
2316     synchronizeGroupInViewer(aDoc, ModelAPI_ResultPart::group(), false);
2317     synchronizeGroupInViewer(aDoc, ModelAPI_ResultGroup::group(), false);
2318   }
2319 }
2320
2321 void XGUI_Workshop::synchronizeGroupInViewer(const DocumentPtr& theDoc,
2322                                              const std::string& theGroup,
2323                                              bool theUpdateViewer)
2324 {
2325   ObjectPtr aObj;
2326   int aSize = theDoc->size(theGroup);
2327   for (int i = 0; i < aSize; i++) {
2328     aObj = theDoc->object(theGroup, i);
2329     if (aObj->isDisplayed()) {
2330       // Hide the presentation with an empty shape. But isDisplayed state of the object should not
2331       // be changed to the object becomes visible when the shape becomes not empty
2332       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
2333       if (aRes.get() && (!aRes->shape().get() || aRes->shape()->isNull()))
2334         continue;
2335       myDisplayer->display(aObj, false);
2336     }
2337   }
2338   if (theUpdateViewer)
2339     myDisplayer->updateViewer();
2340 }
2341
2342 void XGUI_Workshop::highlightResults(const QObjectPtrList& theObjects)
2343 {
2344   FeaturePtr aFeature;
2345   QObjectPtrList aSelList = theObjects;
2346   bool aHasHidden = false;
2347   foreach(ObjectPtr aObj, theObjects) {
2348     aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
2349     if (aFeature.get()) {
2350       std::list<ResultPtr> aResults;
2351       ModelAPI_Tools::allResults(aFeature, aResults);
2352       std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aIt;
2353       for(aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) {
2354         aHasHidden |= (*aIt)->isConcealed();
2355         aSelList.append(*aIt);
2356       }
2357     }
2358   }
2359   if (aSelList.count() > theObjects.count()) {
2360     // if something was found
2361     bool aBlocked = objectBrowser()->blockSignals(true);
2362     objectBrowser()->setObjectsSelected(aSelList);
2363     objectBrowser()->blockSignals(aBlocked);
2364   }
2365   if (aHasHidden)
2366     QMessageBox::information(desktop(), tr("Find results"),
2367                              tr("Results not found"), QMessageBox::Ok);
2368 }
2369
2370 void XGUI_Workshop::highlightFeature(const QObjectPtrList& theObjects)
2371 {
2372   ResultPtr aResult;
2373   QObjectPtrList aSelList = theObjects;
2374   FeaturePtr aFeature;
2375   foreach(ObjectPtr aObj, theObjects) {
2376     aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
2377     if (aResult.get()) {
2378       aFeature = ModelAPI_Feature::feature(aResult);
2379       if (aFeature.get()) {
2380         aSelList.append(aFeature);
2381       }
2382     }
2383   }
2384   if (aSelList.count() > theObjects.count()) {
2385     // if something was found
2386     bool aBlocked = objectBrowser()->blockSignals(true);
2387     objectBrowser()->setObjectsSelected(aSelList);
2388     objectBrowser()->blockSignals(aBlocked);
2389   }
2390 }