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