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