]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_FacesPanel.cpp
Salome HOME
55b0c17864d4bde8a87ac716025f2ba246ceb633
[modules/shaper.git] / src / XGUI / XGUI_FacesPanel.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_FacesPanel.h"
22
23 #include <Config_PropManager.h>
24 #include <Events_Loop.h>
25 #include <GeomAlgoAPI_CompoundBuilder.h>
26
27 #include <ModelAPI_Events.h>
28
29 #include <ModuleBase_ISelection.h>
30 #include "ModuleBase_IWorkshop.h"
31 #include "ModuleBase_ListView.h"
32 #include "ModuleBase_ResultPrs.h"
33 #include "ModuleBase_Tools.h"
34 #include "ModuleBase_ViewerPrs.h"
35
36 #include "XGUI_Tools.h"
37 #include "XGUI_Workshop.h"
38
39 #include <QAction>
40 #include <QCheckBox>
41 #include <QFocusEvent>
42 #include <QGridLayout>
43 #include <QListWidget>
44 #include <QMainWindow>
45
46 static const int LayoutMargin = 3;
47
48 //********************************************************************
49 XGUI_FacesPanel::XGUI_FacesPanel(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop)
50   : QDockWidget(theParent), myIsActive(false), myWorkshop(theWorkshop)
51 {
52   setWindowTitle(tr("Hide Faces"));
53   QAction* aViewAct = toggleViewAction();
54   setStyleSheet("::title { position: relative; padding-left: 5px; text-align: left center }");
55
56   QWidget* aContent = new QWidget(this);
57   QGridLayout* aMainLayout = new QGridLayout(aContent);
58   aMainLayout->setContentsMargins(LayoutMargin, LayoutMargin, LayoutMargin, LayoutMargin);
59   setWidget(aContent);
60
61   myHiddenOrTransparent = new QCheckBox(tr("Transparent"), aContent);
62   connect(myHiddenOrTransparent, SIGNAL(toggled(bool)), SLOT(onTransparencyChanged()));
63
64   myListView = new ModuleBase_ListView(aContent, "", "Hidden/transparent faces in 3D view");
65   connect(myListView, SIGNAL(deleteActionClicked()), SLOT(onDeleteItem()));
66
67   aMainLayout->addWidget(myHiddenOrTransparent, 0, 0);
68   aMainLayout->addWidget(myListView->getControl(), 1, 0);
69
70   myListView->getControl()->setFocusPolicy(Qt::StrongFocus);
71   myListView->getControl()->viewport()->installEventFilter(this);
72 }
73
74 //********************************************************************
75 void XGUI_FacesPanel::reset(const bool isToFlushRedisplay)
76 {
77   // clear internal containers
78   myListView->getControl()->clear();
79   myItems.clear();
80
81   // restore previous view of presentations
82   bool isModified = redisplayObjects(myItemObjects, false);
83   isModified = displayHiddenObjects(myHiddenObjects, false) || isModified;
84   if (isModified && isToFlushRedisplay)
85     Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
86
87   updateProcessedObjects(myItems, myItemObjects);
88   myHiddenObjects.clear();
89   myLastItemIndex = 0; // it should be after redisplay as flag used in customize
90 }
91
92 //********************************************************************
93 bool XGUI_FacesPanel::eventFilter(QObject* theObject, QEvent *theEvent)
94 {
95   QWidget* aWidget = qobject_cast<QWidget*>(theObject);
96   if (theEvent->type() == QEvent::MouseButtonRelease)
97   {
98     if (myListView->getControl()->viewport() == aWidget)
99       setActivePanel(true);
100   }
101   // pass the event on to the parent class
102   return QObject::eventFilter(theObject, theEvent);
103 }
104
105 //********************************************************************
106 void XGUI_FacesPanel::setActivePanel(const bool theIsActive)
107 {
108   if (myIsActive == theIsActive)
109     return;
110
111   ModuleBase_Tools::setShadowEffect(myListView->getControl(), theIsActive);
112   myIsActive = theIsActive;
113
114   if (myIsActive)
115   {
116     emit activated();
117     // selection should be activated after emit signal, that deactivates current widget(selection)
118     activateSelection(theIsActive);
119   }
120   else
121   {
122     // selection should be activated after emit signal, that deactivates current widget(selection)
123     activateSelection(theIsActive);
124     emit deactivated();
125   }
126 }
127
128 //********************************************************************
129 bool XGUI_FacesPanel::useTransparency() const
130 {
131   return myHiddenOrTransparent->isChecked();
132 }
133
134 //********************************************************************
135 void XGUI_FacesPanel::restoreObjects(const std::set<ObjectPtr>& theHiddenObjects)
136 {
137   std::set<int> anIndicesToBeRemoved;
138   for (QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator anItemsIt = myItems.begin();
139     anItemsIt != myItems.end(); anItemsIt++)
140   {
141     ModuleBase_ViewerPrsPtr aPrs = anItemsIt.value();
142     ObjectPtr anObject = aPrs->object();
143     if (theHiddenObjects.find(anObject) == theHiddenObjects.end()) // not found
144       continue;
145     anIndicesToBeRemoved.insert(anItemsIt.key());
146   }
147
148   // remove from myItes container
149   for (std::set<int>::const_iterator aToBeRemovedIt = anIndicesToBeRemoved.begin();
150     aToBeRemovedIt != anIndicesToBeRemoved.end(); aToBeRemovedIt++)
151   {
152     myItems.remove(*aToBeRemovedIt);
153   }
154   if (!anIndicesToBeRemoved.empty()) // means that myItems has been changed
155     updateProcessedObjects(myItems, myItemObjects);
156   myListView->removeItems(anIndicesToBeRemoved);
157
158   // remove from container of hidden objects
159   for (std::set<ObjectPtr>::const_iterator aHiddenIt = theHiddenObjects.begin();
160     aHiddenIt != theHiddenObjects.end(); aHiddenIt++)
161   {
162     if (myHiddenObjects.find(*aHiddenIt) != myHiddenObjects.end()) /// found objects
163       myHiddenObjects.erase(*aHiddenIt);
164   }
165 }
166
167 //********************************************************************
168 bool XGUI_FacesPanel::processAction(ModuleBase_ActionType theActionType)
169 {
170   switch (theActionType) {
171     //case ActionEnter:
172     //  return processEnter();
173     case ActionEscape:
174       setActivePanel(false);
175       return true;
176     case ActionDelete:
177       return processDelete();
178     //case ActionUndo:
179     //case ActionRedo:
180     default:
181       return false;
182   }
183 }
184
185 //********************************************************************
186 void XGUI_FacesPanel::processSelection()
187 {
188   QList<ModuleBase_ViewerPrsPtr> aSelected = myWorkshop->selection()->getSelected(
189                                                        ModuleBase_ISelection::Viewer);
190   bool isModified = false;
191   static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
192   for (int i = 0; i < aSelected.size(); i++) {
193     ModuleBase_ViewerPrsPtr aPrs = aSelected[i];
194     ObjectPtr anObject = aPrs->object();
195     if (!anObject.get())
196       continue;
197     if (ModuleBase_Tools::getSelectedShape(aPrs).ShapeType() != TopAbs_FACE)
198       continue;
199
200     Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(
201       aPrs->interactive());
202     if (aResultPrs.IsNull())
203       continue;
204
205     myItems.insert(myLastItemIndex, aPrs);
206     myListView->addItem(generateName(aPrs), myLastItemIndex);
207     myLastItemIndex++;
208     isModified = true;
209
210     if (aResultPrs->hasSubShapeVisible(ModuleBase_Tools::getSelectedShape(aPrs))) // redisplay
211       ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
212     else { // erase object because it is entirely hidden
213       anObject->setDisplayed(false);
214       myHiddenObjects.insert(anObject);
215       ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
216     }
217   }
218   if (isModified)
219   {
220     updateProcessedObjects(myItems, myItemObjects);
221     Events_Loop::loop()->flush(aDispEvent);
222   }
223 }
224
225 //********************************************************************
226 bool XGUI_FacesPanel::processDelete()
227 {
228   //appendFirstSelectionInHistory();
229   QModelIndexList anIndices = myListView->getControl()->selectionModel()->selectedIndexes();
230
231   std::set<int> aSelectedIds;
232   myListView->getSelectedIndices(aSelectedIds);
233   if (aSelectedIds.empty())
234     return false;
235
236   bool isModified = false;
237   std::set<ObjectPtr> aRestoredObjects;
238   for (std::set<int>::const_iterator anIt = aSelectedIds.begin(); anIt != aSelectedIds.end();
239        anIt++) {
240     ModuleBase_ViewerPrsPtr aPrs = myItems[*anIt];
241     if (aRestoredObjects.find(aPrs->object()) == aRestoredObjects.end())
242       aRestoredObjects.insert(aPrs->object());
243     myItems.remove(*anIt);
244     isModified = true;
245   }
246   if (isModified) {
247     bool isRedisplayed = redisplayObjects(aRestoredObjects, false);
248     isRedisplayed = displayHiddenObjects(aRestoredObjects, false) || isRedisplayed;
249     if (isRedisplayed)
250       Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
251     // should be after flush of redisplay to have items object to be updated
252     updateProcessedObjects(myItems, myItemObjects);
253   }
254
255   myListView->removeSelectedItems();
256   // Restore selection
257   myListView->restoreSelection(anIndices);
258   //appendSelectionInHistory();
259   return true;
260 }
261
262 //********************************************************************
263 bool XGUI_FacesPanel::redisplayObjects(
264   const std::set<std::shared_ptr<ModelAPI_Object> >& theObjects,
265   const bool isToFlushRedisplay)
266 {
267   if (theObjects.empty())
268     return false;
269
270   bool isModified = false;
271   static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
272   for (std::set<ObjectPtr>::const_iterator anIt = theObjects.begin(); anIt != theObjects.end();
273        anIt++)
274   {
275     ObjectPtr anObject = *anIt;
276     if (!anObject->isDisplayed())
277       continue;
278     ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
279     isModified = true;
280   }
281   if (isModified && isToFlushRedisplay)
282     Events_Loop::loop()->flush(aDispEvent);
283   return isModified;
284 }
285
286 //********************************************************************
287 bool XGUI_FacesPanel::displayHiddenObjects(
288   const std::set<std::shared_ptr<ModelAPI_Object> >& theObjects,
289   const bool isToFlushRedisplay)
290 {
291   if (theObjects.empty())
292     return false;
293
294   bool isModified = false;
295   static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
296
297   for (std::set<ObjectPtr>::const_iterator anIt = theObjects.begin(); anIt != theObjects.end();
298        anIt++)
299   {
300     ObjectPtr anObject = *anIt;
301     // if the object was hidden by this panel
302     if (anObject->isDisplayed() || myHiddenObjects.find(anObject) == myHiddenObjects.end())
303       continue;
304     myHiddenObjects.erase(anObject);
305     anObject->setDisplayed(true); // it means that the object is hidden by hide all faces
306     ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
307     isModified = true;
308   }
309
310   if (isModified && isToFlushRedisplay)
311     Events_Loop::loop()->flush(aDispEvent);
312   return isModified;
313 }
314
315
316 //********************************************************************
317 void XGUI_FacesPanel::updateProcessedObjects(QMap<int, ModuleBase_ViewerPrsPtr> theItems,
318                                              std::set<ObjectPtr>& theObjects)
319 {
320   theObjects.clear();
321   for (QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator anIt = theItems.begin();
322        anIt != theItems.end(); anIt++) {
323     ModuleBase_ViewerPrsPtr aPrs = anIt.value();
324     ObjectPtr anObject = aPrs.get() ? aPrs->object() : ObjectPtr();
325     if (anObject.get() && theObjects.find(anObject) != theObjects.end())
326       continue;
327     theObjects.insert(anObject);
328   }
329 }
330
331 //********************************************************************
332 void XGUI_FacesPanel::closeEvent(QCloseEvent* theEvent)
333 {
334   QDockWidget::closeEvent(theEvent);
335   emit closed();
336 }
337
338 //********************************************************************
339 void XGUI_FacesPanel::activateSelection(bool toActivate)
340 {
341   QIntList aShapeTypes;
342   aShapeTypes.append(TopAbs_FACE);
343
344   if (toActivate) {
345     myWorkshop->activateSubShapesSelection(aShapeTypes);
346   } else {
347     myWorkshop->deactivateSubShapesSelection();
348   }
349   if (toActivate)
350     activateSelectionFilters();
351   else
352     deactivateSelectionFilters();
353 }
354
355 //********************************************************************
356 QString XGUI_FacesPanel::generateName(const ModuleBase_ViewerPrsPtr& thePrs)
357 {
358   if (!thePrs.get() || !thePrs->object().get())
359     return "Undefined";
360
361   GeomShapePtr aContext;
362   ObjectPtr anObject = thePrs->object();
363   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
364   if (aResult.get())
365     aContext = aResult->shape();
366   else {
367     // TODO if there is this case
368   }
369
370   QString aName = anObject->data()->name().c_str();
371   if (aContext.get()) {
372     GeomShapePtr aSubShape(new GeomAPI_Shape());
373     aSubShape->setImpl(new TopoDS_Shape(ModuleBase_Tools::getSelectedShape(thePrs)));
374     if (!aSubShape->isEqual(aContext))
375       aName += QString("_%1").arg(GeomAlgoAPI_CompoundBuilder::id(aContext, aSubShape));
376   }
377   return aName;
378 }
379
380 //********************************************************************
381 bool XGUI_FacesPanel::customizeObject(const ObjectPtr& theObject,
382                                       const AISObjectPtr& thePresentation)
383 {
384   if (myLastItemIndex == 0) // do nothing because there was no activity in the pane after reset
385     return false;
386
387   if (thePresentation.get() == NULL)
388     return false;
389
390   if (myItemObjects.find(theObject) == myItemObjects.end()) // not found
391     return false;
392
393   // if the object is displayed, the hidden faces are collected and set to the presentation
394   bool isModified = false;
395   NCollection_List<TopoDS_Shape> aHiddenSubShapes;
396   for (QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator anIt = myItems.begin();
397     anIt != myItems.end(); anIt++) {
398     ModuleBase_ViewerPrsPtr aPrs = anIt.value();
399     if (aPrs.get() && aPrs->object() != theObject)
400       continue;
401     TopoDS_Shape aShape = ModuleBase_Tools::getSelectedShape(aPrs);
402     if (!aHiddenSubShapes.Contains(aShape))
403       aHiddenSubShapes.Append(aShape);
404   }
405
406   Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(
407     thePresentation->impl<Handle(AIS_InteractiveObject)>());
408   if (aResultPrs.IsNull())
409     return false;
410
411   isModified = aResultPrs->setSubShapeHidden(aHiddenSubShapes);
412
413   double aTransparency = !useTransparency() ? 1
414     : Config_PropManager::real("Visualization", "hidden_face_transparency");
415   isModified = aResultPrs->setHiddenSubShapeTransparency(aTransparency) || isModified;
416
417   return isModified;
418 }
419
420 //********************************************************************
421 void XGUI_FacesPanel::onDeleteItem()
422 {
423   processDelete();
424 }
425
426 //********************************************************************
427 void XGUI_FacesPanel::onTransparencyChanged()
428 {
429   bool isModified = redisplayObjects(myItemObjects, false);
430   if (isModified)
431     Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
432
433 }
434
435 //********************************************************************
436 void XGUI_FacesPanel::onClosed()
437 {
438   setActivePanel(false);
439   reset(true);
440 }