]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_WorkshopListener.cpp
Salome HOME
bos #29475 Option to create new part on study open
[modules/shaper.git] / src / XGUI / XGUI_WorkshopListener.cpp
1 // Copyright (C) 2014-2022  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 email : webmaster.salome@opencascade.com
18 //
19
20 #include "XGUI_WorkshopListener.h"
21
22 #ifndef HAVE_SALOME
23 #include <AppElements_MainWindow.h>
24 #endif
25
26 #include <Config_FeatureMessage.h>
27 #include <Config_PointerMessage.h>
28 #include <Config_Keywords.h>
29
30 #include <Events_InfoMessage.h>
31 #include <Events_Loop.h>
32 #include <Events_LongOp.h>
33
34 #include <ModelAPI_Object.h>
35 #include <ModelAPI_Events.h>
36 #include <ModelAPI_Session.h>
37 #include <ModelAPI_Result.h>
38 #include <ModelAPI_Feature.h>
39 #include <ModelAPI_Data.h>
40 #include <ModelAPI_Tools.h>
41 #include <ModelAPI_ResultField.h>
42
43 #include <ModuleBase_Events.h>
44 #include <ModuleBase_IModule.h>
45 #include <ModuleBase_IViewer.h>
46 #include <ModuleBase_IWorkshop.h>
47 #include <ModuleBase_Operation.h>
48 #include <ModuleBase_OperationDescription.h>
49 #include <ModuleBase_OperationFeature.h>
50 #include <ModuleBase_Tools.h>
51 #include <ModuleBase_WidgetSelector.h>
52
53 #include <SUIT_Application.h>
54 #include <SUIT_Session.h>
55
56 #include "XGUI_ActionsMgr.h"
57 #include "XGUI_Displayer.h"
58 #include "XGUI_ErrorMgr.h"
59 #include "XGUI_FacesPanel.h"
60 #include "XGUI_OperationMgr.h"
61 #include "XGUI_ModuleConnector.h"
62 #include "XGUI_PropertyPanel.h"
63 #include "XGUI_QtEvents.h"
64 #include "XGUI_SalomeConnector.h"
65 #include "XGUI_SelectionMgr.h"
66 #include "XGUI_Workshop.h"
67
68 #include <QAction>
69 #include <QApplication>
70 #include <QMainWindow>
71 #include <QThread>
72
73 #ifdef _DEBUG
74 #include <QDebug>
75 #include <iostream>
76 #endif
77
78 #ifdef WIN32
79 #pragma warning(disable : 4189) // for declaration of unused variables (MAYBE_UNUSED)
80 #endif
81
82 //#define DEBUG_FEATURE_CREATED
83 //#define DEBUG_FEATURE_REDISPLAY
84 //#define DEBUG_FEATURE_UPDATED
85 //#define DEBUG_RESULT_COMPSOLID
86
87 #ifdef DEBUG_FEATURE_REDISPLAY
88 const std::string DebugFeatureKind = "";//"Extrusion";
89 #endif
90
91 XGUI_WorkshopListener::XGUI_WorkshopListener(XGUI_Workshop* theWorkshop)
92   : myWorkshop(theWorkshop),
93     myUpdatePrefs(false)
94 {
95 }
96
97 //******************************************************
98 XGUI_WorkshopListener::~XGUI_WorkshopListener(void)
99 {
100 }
101
102 //******************************************************
103 void XGUI_WorkshopListener::initializeEventListening()
104 {
105   //Initialize event listening
106   Events_Loop* aLoop = Events_Loop::loop();
107   aLoop->registerListener(this, Events_InfoMessage::errorID());  //!< Listening application errors.
108   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
109   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
110   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
111   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES));
112   aLoop->registerListener(this, Events_LongOp::eventID());
113   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_PLUGIN_LOADED));
114
115   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED));
116   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED));
117   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION));
118   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION));
119
120   aLoop->registerListener(this, Events_Loop::eventByName("FinishOperation"));
121   aLoop->registerListener(this, Events_Loop::eventByName("AbortOperation"));
122   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_AUTOMATIC_RECOMPUTATION_ENABLE));
123   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_AUTOMATIC_RECOMPUTATION_DISABLE));
124 }
125
126 //******************************************************
127 void XGUI_WorkshopListener::processEvent(const std::shared_ptr<Events_Message>& theMessage)
128 {
129   if (QApplication::instance() &&
130       QApplication::instance()->thread() != QThread::currentThread()) {
131     #ifdef _DEBUG
132     std::cout << "XGUI_Workshop::processEvent: " << "Working in another thread." << std::endl;
133     #endif
134     SessionPtr aMgr = ModelAPI_Session::get();
135     PostponeMessageQtEvent* aPostponeEvent = new PostponeMessageQtEvent(theMessage);
136     QApplication::postEvent(this, aPostponeEvent);
137     return;
138   }
139
140   // Process creation of Part
141   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
142     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
143         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
144     onFeatureCreatedMsg(aUpdMsg);
145     if (myUpdatePrefs) {
146       XGUI_SalomeConnector* aSalomeConnector = workshop()->salomeConnector();
147       if (aSalomeConnector)
148         aSalomeConnector->createPreferences();
149       myUpdatePrefs = false;
150     }
151   }
152   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_PLUGIN_LOADED)) {
153     myUpdatePrefs = true;
154   }
155   // Redisplay feature
156   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)) {
157     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
158       std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
159     onFeatureRedisplayMsg(aUpdMsg);
160   }
161   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_VISUAL_ATTRIBUTES)) {
162     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
163       std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
164     std::set<ObjectPtr> aObjList = aUpdMsg->objects();
165     std::set<ObjectPtr>::const_iterator aIt;
166     std::list<ResultPtr>::const_iterator aResIt;
167     XGUI_Displayer* aDisplayer = workshop()->displayer();
168     AISObjectPtr aAIS;
169     for (aIt = aObjList.begin(); aIt != aObjList.end(); ++aIt) {
170       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*aIt);
171       if (aFeature) {
172         aAIS = aDisplayer->getAISObject(aFeature);
173         if (aAIS.get())
174           workshop()->module()->customizePresentation(aFeature, aAIS);
175
176         std::list<ResultPtr> aResults = aFeature->results();
177         for (aResIt = aResults.begin(); aResIt != aResults.end(); ++aResIt) {
178           aAIS = aDisplayer->getAISObject(*aResIt);
179           if (aAIS.get())
180             workshop()->module()->customizePresentation(*aResIt, aAIS);
181         }
182       }
183     }
184   } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION)) {
185     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
186         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
187     onFeatureEmptyPresentationMsg(aUpdMsg);
188   } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION)) {
189     ModuleBase_ModelWidget* aWidget = workshop()->propertyPanel()->activeWidget();
190     if (aWidget) {
191       ModuleBase_WidgetSelector* aWidgetSelector =
192         dynamic_cast<ModuleBase_WidgetSelector*>(aWidget);
193       if (aWidgetSelector)
194         workshop()->selector()->setSelected(aWidgetSelector->getAttributeSelection());
195     }
196   }
197   else if (theMessage->eventID() == Events_Loop::eventByName("FinishOperation")/* ||
198           theMessage->eventID() == Events_Loop::eventByName("AbortOperation")*/)
199   {
200     XGUI_FacesPanel* aFacesPanel = workshop()->facesPanel();
201     if (aFacesPanel)
202       aFacesPanel->reset(false); // do not flush redisplay, it is flushed after event
203   }
204   //Update property panel on corresponding message. If there is no current operation (no
205   //property panel), or received message has different feature to the current - do nothing.
206   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
207     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
208         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
209     onFeatureUpdatedMsg(anUpdateMsg);
210   } else if (theMessage->eventID() == Events_LongOp::eventID()) {
211     if (Events_LongOp::isPerformed()) {
212       QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
213     } else {
214       QApplication::restoreOverrideCursor();
215     }
216   } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)) {
217     // the viewer's update context will not happens until viewer updated is emitted
218       workshop()->displayer()->enableUpdateViewer(false);
219   } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)) {
220     // the viewer's update context is unblocked, the viewer's update works
221     XGUI_Displayer* aDisplayer = workshop()->displayer();
222     aDisplayer->enableUpdateViewer(true);
223   } else if ((theMessage->eventID() ==
224     Events_Loop::eventByName(EVENT_AUTOMATIC_RECOMPUTATION_ENABLE)) ||
225     (theMessage->eventID() ==
226       Events_Loop::eventByName(EVENT_AUTOMATIC_RECOMPUTATION_DISABLE))) {
227     myWorkshop->updateAutoComputeState();
228   } else {
229     //Show error dialog if error message received.
230     std::shared_ptr<Events_InfoMessage> anIngfoMsg =
231       std::dynamic_pointer_cast<Events_InfoMessage>(theMessage);
232     if (anIngfoMsg) {
233       emit errorOccurred(anIngfoMsg);
234     }
235     return;
236   }
237 #ifndef HAVE_SALOME
238     SessionPtr aMgr = ModelAPI_Session::get();
239     AppElements_MainWindow* aMainWindow = workshop()->mainWindow();
240     if (aMgr->isModified() != aMainWindow->isModifiedState())
241       aMainWindow->setModifiedState(aMgr->isModified());
242 #endif
243 }
244
245 //******************************************************
246 void XGUI_WorkshopListener::onFeatureUpdatedMsg(
247                                      const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
248 {
249 #ifdef DEBUG_FEATURE_UPDATED
250   std::set<ObjectPtr> anObjects = theMsg->objects();
251   std::set<ObjectPtr>::const_iterator aIt;
252   QStringList anInfo;
253   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
254     anInfo.append(ModuleBase_Tools::objectInfo((*aIt)));
255   }
256   QString anInfoStr = anInfo.join(";\t");
257   qDebug(QString("onFeatureUpdatedMsg: %1, %2")
258     .arg(anObjects.size()).arg(anInfoStr).toStdString().c_str());
259 #endif
260   std::set<ObjectPtr> aFeatures = theMsg->objects();
261   XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr();
262   if (anOperationMgr->hasOperation()) {
263     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
264                                                       (anOperationMgr->currentOperation());
265     if (aFOperation) {
266       FeaturePtr aCurrentFeature = aFOperation->feature();
267       std::set<ObjectPtr>::const_iterator aIt;
268       for (aIt = aFeatures.begin(); aIt != aFeatures.end(); ++aIt) {
269         ObjectPtr aNewFeature = (*aIt);
270         if (aNewFeature == aCurrentFeature) {
271           workshop()->propertyPanel()->updateContentWidget(aCurrentFeature);
272           break;
273         }
274       }
275     }
276   }
277   //anOperationMgr->onValidateOperation();
278
279   //if (myObjectBrowser)
280   //  myObjectBrowser->processEvent(theMsg);
281 }
282
283 //******************************************************
284 void XGUI_WorkshopListener::
285   onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
286 {
287   std::set<ObjectPtr> anObjects = theMsg->objects();
288   std::set<ObjectPtr>::const_iterator aIt;
289
290 #ifdef DEBUG_FEATURE_REDISPLAY
291   QStringList anInfo;
292   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
293     anInfo.append(ModuleBase_Tools::objectInfo((*aIt)));
294   }
295   QString anInfoStr = anInfo.join(";\t");
296   qDebug(QString("onFeatureRedisplayMsg: %1, %2")
297     .arg(anObjects.size()).arg(anInfoStr).toStdString().c_str());
298 #endif
299
300   XGUI_Workshop* aWorkshop = workshop();
301   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
302   bool aRedisplayed = false;
303   //std::list<ObjectPtr> aHiddenObjects;
304   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
305     ObjectPtr aObj = (*aIt);
306
307     // Hide the object if it is invalid or concealed one
308     bool aHide = !aObj->data() || !aObj->data()->isValid() ||
309       aObj->isDisabled() || (!aObj->isDisplayed());
310
311     if (!aHide) { // check that this is not hidden result
312       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
313       aHide = aRes && aRes->isConcealed();
314
315       // Hide the presentation with an empty shape. But isDisplayed state of the object should not
316       // be changed to the object becomes visible when the shape becomes not empty
317       if (!aHide && aRes.get())
318         aHide = !aRes->shape().get() || aRes->shape()->isNull();
319     }
320
321 #ifdef DEBUG_RESULT_COMPSOLID
322     ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
323     if (aRes.get()) {
324       ResultCompSolidPtr aCompSolidRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aRes);
325       if (aCompSolidRes.get()) {
326           qDebug(QString("COMPSOLID, numberOfSubs = %1")
327             .arg(aCompSolidRes->numberOfSubs()).toStdString().c_str());
328       }
329       if (ModelAPI_Tools::compSolidOwner(aRes))
330         qDebug("COMPSOLID sub-object");
331     }
332 #endif
333     #ifdef DEBUG_FEATURE_REDISPLAY
334       QString anObjInfo = ModuleBase_Tools::objectInfo((aObj));
335       FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
336       if (aFeature.get()) {
337         std::string aKind = aFeature->getKind();
338         if (aKind == DebugFeatureKind || DebugFeatureKind.empty()) {
339           qDebug(QString("visible=%1, hide=%2 : display= %2").arg(aDisplayer->isVisible(aObj))
340                                             .arg(aHide).arg(anObjInfo).toStdString().c_str());
341         }
342       }
343     #endif
344     if (aHide) {
345       //we should provide objects which are hidden in the viewer, e.g. sketch always should
346       // visualizes all sub-features, if some features are to be hidden, sould be proposed may
347       // be to removed #1223
348       // aHiddenObjects.push_back(aObj);
349       aRedisplayed = aDisplayer->erase(aObj, false) || aRedisplayed;
350       #ifdef DEBUG_FEATURE_REDISPLAY
351         // Redisplay the visible object or the object of the current operation
352         bool isVisibleObject = aDisplayer->isVisible(aObj);
353
354         QString anObjInfo = ModuleBase_Tools::objectInfo((aObj));
355       #endif
356     }
357     else {
358       // Redisplay the visible object or the object of the current operation
359       bool isVisibleObject = aDisplayer->isVisible(aObj);
360       #ifdef DEBUG_FEATURE_REDISPLAY
361         QString anObjInfo = ModuleBase_Tools::objectInfo((aObj));
362       #endif
363
364       if (isVisibleObject)  { // redisplay visible object
365         //displayObject(aObj);  // In order to update presentation
366         // in order to avoid the check whether the object can be redisplayed, the exact method
367         // of redisplay is called. This modification is made in order to have the line is updated
368         // by creation of a horizontal constraint on the line by preselection
369         if (ModelAPI_Tools::hasSubResults(std::dynamic_pointer_cast<ModelAPI_Result>(aObj))) {
370           aRedisplayed = aDisplayer->erase(aObj, false) || aRedisplayed;
371         }
372         else {
373           aRedisplayed = aDisplayer->redisplay(aObj, false) || aRedisplayed;
374           // Deactivate object of current operation from selection
375           aWorkshop->deactivateActiveObject(aObj, false);
376         }
377       } else { // display object if the current operation has it
378         if (displayObject(aObj)) {
379           aRedisplayed = true;
380           // Deactivate object of current operation from selection
381           aWorkshop->deactivateActiveObject(aObj, false);
382         }
383       }
384     }
385   }
386
387   // this processing should be moved in another place in order to do not cause problems in
388   // flush messages chain
389   //if (aHiddenObjects.size() > 0)
390   //  myWorkshop->module()->processHiddenObject(aHiddenObjects);
391
392   bool isCustomized = customizeFeature(anObjects, aRedisplayed);
393   if (aRedisplayed || isCustomized) {
394     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION));
395
396     // Do not update viewer here because it can be called in a loop
397     // In this case Update has to be called after redisplay event
398     //aDisplayer->updateViewer();
399   }
400 }
401
402 //******************************************************
403 void XGUI_WorkshopListener::
404   onFeatureCreatedMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
405 {
406   bool isLoadedScript = false;
407   SUIT_Session* aSession = SUIT_Session::session();
408   if (aSession)
409   {
410     QVariant aVar = aSession->activeApplication()->property("IsLoadedScript");
411     isLoadedScript = !aVar.isNull() && aVar.toBool();
412   }
413
414   std::set<ObjectPtr> anObjects = theMsg->objects();
415   std::set<ObjectPtr>::const_iterator aIt;
416 #ifdef DEBUG_FEATURE_CREATED
417   QStringList anInfo;
418   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
419     anInfo.append(ModuleBase_Tools::objectInfo((*aIt)));
420   }
421   QString anInfoStr = anInfo.join(";\t");
422   qDebug(QString("onFeatureCreatedMsg: %1, %2")
423     .arg(anObjects.size()).arg(anInfoStr).toStdString().c_str());
424 #endif
425
426   //bool aHasPart = false;
427   bool aDisplayed = false;
428   if (!isLoadedScript) {
429     for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
430       ObjectPtr anObject = *aIt;
431
432 #ifdef DEBUG_RESULT_COMPSOLID
433       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
434       if (aRes.get()) {
435         ResultCompSolidPtr aCompSolidRes =
436             std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aRes);
437         if (aCompSolidRes.get()) {
438             qDebug(QString("COMPSOLID, numberOfSubs = %1")
439               .arg(aCompSolidRes->numberOfSubs()).toStdString().c_str());
440         }
441         if (ModelAPI_Tools::compSolidOwner(aRes))
442           qDebug("COMPSOLID sub-object");
443       }
444 #endif
445
446       ResultBodyPtr aRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(anObject);
447
448       if (aRes.get() && aRes->numberOfSubs() > 0)
449         for (int anIndex = 0; anIndex < aRes->numberOfSubs(); ++anIndex)
450           setDisplayed(aRes->subResult(anIndex), aDisplayed);
451       else
452         setDisplayed(anObject, aDisplayed);
453     }
454   }
455   MAYBE_UNUSED bool isCustomized = customizeFeature(anObjects, aDisplayed);
456
457   //if (myObjectBrowser)
458   //  myObjectBrowser->processEvent(theMsg);
459   if (aDisplayed) {
460     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION));
461     workshop()->displayer()->updateViewer();
462   }
463   //if (aHasPart) { // TODO: Avoid activate last part on loading of document
464   //  activateLastPart();
465   //}
466 }
467
468 //******************************************************
469 void XGUI_WorkshopListener::onFeatureEmptyPresentationMsg(
470                                       const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
471 {
472   std::set<ObjectPtr> anObjects = theMsg->objects();
473   std::set<ObjectPtr>::const_iterator aIt;
474 #ifdef DEBUG_FEATURE_CREATED
475   QStringList anInfo;
476   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
477     anInfo.append(ModuleBase_Tools::objectInfo((*aIt)));
478   }
479   QString anInfoStr = anInfo.join(";\t");
480   qDebug(QString("onFeatureEmptyPresentationMsg: %1, %2")
481     .arg(anObjects.size()).arg(anInfoStr).toStdString().c_str());
482 #endif
483
484   XGUI_Workshop* aWorkshop = workshop();
485   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
486
487   bool aRedisplayed = false;
488   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
489     ObjectPtr anObject = *aIt;
490     aRedisplayed = aDisplayer->erase(anObject, false) || aRedisplayed;
491   }
492
493   if (aRedisplayed)
494     aDisplayer->updateViewer();
495 }
496
497 bool XGUI_WorkshopListener::event(QEvent * theEvent)
498 {
499   PostponeMessageQtEvent* aPostponedEv = dynamic_cast<PostponeMessageQtEvent*>(theEvent);
500   if (aPostponedEv) {
501     std::shared_ptr<Events_Message> aEventPtr = aPostponedEv->postponedMessage();
502     processEvent(aEventPtr);
503     return true;
504   }
505   return false;
506 }
507
508 //**************************************************************
509 bool XGUI_WorkshopListener::displayObject(ObjectPtr theObj)
510 {
511 #ifdef DEBUG_RESULT_COMPSOLID
512   ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
513   if (aRes.get() && (ModelAPI_Tools::hasSubResults(aRes) || ModelAPI_Tools::compSolidOwner(aRes))) {
514     ResultCompSolidPtr aCompSolidRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aRes);
515     if (aCompSolidRes.get()) {
516       qDebug("COMPSOLID: displayObject");
517     }
518   }
519 #endif
520
521   bool aDisplayed = false;
522   XGUI_Workshop* aWorkshop = workshop();
523   // do not display the object if it has sub objects. They should be displayed separately.
524   if (!aWorkshop->module()->canDisplayObject(theObj) ||
525       ModelAPI_Tools::hasSubResults(std::dynamic_pointer_cast<ModelAPI_Result>(theObj)))
526     return aDisplayed;
527
528   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
529   return aDisplayer->display(theObj, false);
530 }
531
532 bool XGUI_WorkshopListener::customizeFeature(const std::set<ObjectPtr>& theObjects,
533                                                    bool theForceRedisplay)
534 {
535   XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr();
536   FeaturePtr aCurrentFeature;
537   if (anOperationMgr->hasOperation()) {
538     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
539                                                       (anOperationMgr->currentOperation());
540     if (aFOperation) {
541       aCurrentFeature = aFOperation->feature();
542     }
543   }
544
545   bool aCustomized = false;
546   if (aCurrentFeature.get()) {
547     // the customize presentation should be redisplayed if force redislayed is true or
548     // if a list of message objects contains the operation feature for case when
549     // the feature is hidden, but arguments of the feature are modified
550     // e.g. extrusion is hidden(h=0) but sketch is chosen
551     if (theForceRedisplay || theObjects.find(aCurrentFeature) != theObjects.end()) {
552       aCustomized = myWorkshop->module()->customizeFeature(aCurrentFeature,
553                                  ModuleBase_IModule::CustomizeArguments, false) || aCustomized;
554       aCustomized = myWorkshop->module()->customizeFeature(aCurrentFeature,
555                                    ModuleBase_IModule::CustomizeResults, false) || aCustomized;
556       aCustomized = myWorkshop->module()->customizeFeature(aCurrentFeature,
557                         ModuleBase_IModule::CustomizeHighlightedObjects, false) || aCustomized;
558     }
559   }
560   return aCustomized;
561 }
562
563 XGUI_Workshop* XGUI_WorkshopListener::workshop() const
564 {
565   return myWorkshop;
566 }
567
568
569 void XGUI_WorkshopListener::setDisplayed(ObjectPtr theObject, bool& theDisplayed)
570 {
571   // the validity of the data should be checked here in order to avoid display of the objects,
572   // which were created, then deleted, but flush for the creation event happens after that
573   // we should not display disabled objects
574   bool aHide = !theObject->data()->isValid() ||
575                 theObject->isDisabled() ||
576                !theObject->isDisplayed();
577   if (!aHide) { // check that this is not hidden result
578     ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
579     aHide = aRes && aRes->isConcealed();
580     // Hide the presentation with an empty shape. But isDisplayed state of the object should not
581     // be changed to the object becomes visible when the shape becomes not empty
582     if (!aHide && aRes.get())
583       aHide = !aRes->shape().get() || aRes->shape()->isNull();
584   }
585   if (!aHide) {
586     // setDisplayed has to be called in order to synchronize internal state of the object
587     // with list of displayed objects
588     if (myWorkshop->module()->canDisplayObject(theObject)) {
589       theObject->setDisplayed(true);
590       theDisplayed = displayObject(theObject);
591     }
592     else
593       theObject->setDisplayed(false);
594   }
595 }