Salome HOME
#2309 Possibility to hide faces : linux compilation correction
[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 <Events_Loop.h>
24 #include "GeomAlgoAPI_CompoundBuilder.h"
25
26 #include <ModelAPI_Events.h>
27
28 #include <ModuleBase_ISelection.h>
29 #include "ModuleBase_IWorkshop.h"
30 #include "ModuleBase_ListView.h"
31 #include "ModuleBase_ResultPrs.h"
32 #include "ModuleBase_Tools.h"
33 #include "ModuleBase_ViewerPrs.h"
34
35 #include "XGUI_Displayer.h"
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   myListView = new ModuleBase_ListView(aContent, "", "Hidden/transparent faces in 3D view");
63   connect(myListView->getControl(), SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
64   connect(myListView, SIGNAL(deleteActionClicked()), SLOT(onDeleteItem()));
65
66   aMainLayout->addWidget(myHiddenOrTransparent, 0, 0);
67   aMainLayout->addWidget(myListView->getControl(), 1, 0);
68
69   myListView->getControl()->setFocusPolicy(Qt::StrongFocus);
70   myListView->getControl()->viewport()->installEventFilter(this);
71 }
72
73 //********************************************************************
74 void XGUI_FacesPanel::reset(const bool isToFlushRedisplay)
75 {
76   // restore presentation state
77   bool isModified = false;
78   std::set<ObjectPtr> aRestoredObjects;
79   for (QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator anIt = myItems.begin();
80     anIt != myItems.end(); anIt++) {
81     if (aRestoredObjects.find(anIt.value()->object()) == aRestoredObjects.end())
82       aRestoredObjects.insert(anIt.value()->object());
83   }
84   // clear internal containers
85   myListView->getControl()->clear();
86   myLastItemIndex = 0;
87   myItems.clear();
88
89   isModified = redisplayObjects(aRestoredObjects, isToFlushRedisplay);
90
91   if (isToFlushRedisplay && isModified)
92     XGUI_Tools::workshop(myWorkshop)->displayer()->updateViewer();
93 }
94
95 //********************************************************************
96 bool XGUI_FacesPanel::eventFilter(QObject* theObject, QEvent *theEvent)
97 {
98   QWidget* aWidget = qobject_cast<QWidget*>(theObject);
99   if (theEvent->type() == QEvent::MouseButtonRelease)
100   {
101     if (myListView->getControl()->viewport() == aWidget)
102       setActivePanel(true);
103   }
104   // pass the event on to the parent class
105   return QObject::eventFilter(theObject, theEvent);
106 }
107
108 //********************************************************************
109 void XGUI_FacesPanel::setActivePanel(const bool theIsActive)
110 {
111   if (myIsActive == theIsActive)
112     return;
113
114   ModuleBase_Tools::setShadowEffect(myListView->getControl(), theIsActive);
115   myIsActive = theIsActive;
116
117   if (myIsActive)
118   {
119     emit activated();
120     // selection should be activated after emit signal, that deactivates current widget(selection)
121     activateSelection(theIsActive);
122   }
123   else
124   {
125     // selection should be activated after emit signal, that deactivates current widget(selection)
126     activateSelection(theIsActive);
127     emit deactivated();
128   }
129 }
130
131 //********************************************************************
132 void XGUI_FacesPanel::restoreObjects(const std::set<ObjectPtr>& theHiddenObjects)
133 {
134   std::set<int> anIndicesToBeRemoved;
135   for (QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator anItemsIt = myItems.begin();
136     anItemsIt != myItems.end(); anItemsIt++)
137   {
138     ModuleBase_ViewerPrsPtr aPrs = anItemsIt.value();
139     ObjectPtr anObject = aPrs->object();
140     if (theHiddenObjects.find(anObject) == theHiddenObjects.end()) // not found
141       continue;
142     anIndicesToBeRemoved.insert(anItemsIt.key());
143   }
144
145   // remove from myItes container
146   for (std::set<int>::const_iterator aToBeRemovedIt = anIndicesToBeRemoved.begin();
147     aToBeRemovedIt != anIndicesToBeRemoved.end(); aToBeRemovedIt++)
148     myItems.remove(*aToBeRemovedIt);
149
150   myListView->removeItems(anIndicesToBeRemoved);
151
152   // remove from container of hidden objects
153   for (std::set<ObjectPtr>::const_iterator aHiddenIt = theHiddenObjects.begin();
154     aHiddenIt != theHiddenObjects.end(); aHiddenIt++)
155   {
156     if (myHiddenObjects.find(*aHiddenIt) != myHiddenObjects.end()) ///< found objects
157       myHiddenObjects.erase(*aHiddenIt);
158   }
159 }
160
161 //********************************************************************
162 bool XGUI_FacesPanel::processAction(ModuleBase_ActionType theActionType)
163 {
164   switch (theActionType) {
165     //case ActionEnter:
166     //  return processEnter();
167     case ActionEscape:
168       setActivePanel(false);
169       return true;
170     case ActionDelete:
171       return processDelete();
172     //case ActionUndo:
173     //case ActionRedo:
174     default:
175       return false;
176   }
177 }
178
179 //********************************************************************
180 void XGUI_FacesPanel::processSelection()
181 {
182   QList<ModuleBase_ViewerPrsPtr> aSelected = myWorkshop->selection()->getSelected(
183                                                        ModuleBase_ISelection::Viewer);
184   bool isModified = false;
185   for (int i = 0; i < aSelected.size(); i++) {
186     ModuleBase_ViewerPrsPtr aPrs = aSelected[i];
187     ObjectPtr anObject = aPrs->object();
188     if (!anObject.get())
189       continue;
190
191     if (ModuleBase_Tools::getSelectedShape(aPrs).ShapeType() != TopAbs_FACE)
192       continue;
193
194     myItems.insert(myLastItemIndex, aPrs);
195     myListView->addItem(generateName(aPrs), myLastItemIndex);
196     isModified = hideFace(myLastItemIndex) || isModified;
197
198     myLastItemIndex++;
199   }
200
201   if (isModified)
202     XGUI_Tools::workshop(myWorkshop)->displayer()->updateViewer();
203 }
204
205 //********************************************************************
206 bool XGUI_FacesPanel::processDelete()
207 {
208   //appendFirstSelectionInHistory();
209   QModelIndexList anIndices = myListView->getControl()->selectionModel()->selectedIndexes();
210
211   std::set<int> aSelectedIds;
212   myListView->getSelectedIndices(aSelectedIds);
213   if (aSelectedIds.empty())
214     return false;
215
216   bool isModified = false;
217   std::set<ObjectPtr> aRestoredObjects;
218   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(myWorkshop)->displayer();
219   for (std::set<int>::const_iterator anIt = aSelectedIds.begin(); anIt != aSelectedIds.end();
220        anIt++) {
221     ModuleBase_ViewerPrsPtr aPrs = myItems[*anIt];
222     if (aRestoredObjects.find(aPrs->object()) == aRestoredObjects.end())
223       aRestoredObjects.insert(aPrs->object());
224     myItems.remove(*anIt);
225   }
226   myListView->removeSelectedItems();
227
228   isModified = redisplayObjects(aRestoredObjects, true) || isModified;
229   if (isModified)
230     XGUI_Tools::workshop(myWorkshop)->displayer()->updateViewer();
231
232   // Restore selection
233   myListView->restoreSelection(anIndices);
234   //appendSelectionInHistory();
235   return true;
236 }
237
238 //********************************************************************
239 bool XGUI_FacesPanel::redisplayObjects(
240   const std::set<std::shared_ptr<ModelAPI_Object> >& theObjects,
241   const bool isToFlushRedisplay)
242 {
243   bool isModified = false;
244   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(myWorkshop)->displayer();
245   static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
246
247   for (std::set<ObjectPtr>::const_iterator anIt = theObjects.begin(); anIt != theObjects.end();
248        anIt++)
249   {
250     ObjectPtr anObject = *anIt;
251     if (!anObject->isDisplayed()) {
252       // if the object was hidden by this panel
253       if (myHiddenObjects.find(anObject) != myHiddenObjects.end())
254         myHiddenObjects.erase(anObject);
255       anObject->setDisplayed(true); // it means that the object is hidden by hide all faces
256       ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
257       isModified = true;
258       //isModified = aDisplayer->display(anObject, false) || isModified;
259     }
260     else {
261       ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
262       isModified = true;
263     }
264   }
265   if (isToFlushRedisplay)
266     Events_Loop::loop()->flush(aDispEvent);
267   return isModified;
268 }
269
270 //********************************************************************
271 bool XGUI_FacesPanel::hideFace(const int theIndex)
272 {
273   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(myWorkshop)->displayer();
274
275   if (!myItems.contains(theIndex))
276     return false;
277
278   ModuleBase_ViewerPrsPtr aPrs = myItems[theIndex];
279
280   AISObjectPtr aAISObj = aDisplayer->getAISObject(aPrs->object());
281   if (aAISObj.get() == NULL)
282     return false;
283   Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(
284     aAISObj->impl<Handle(AIS_InteractiveObject)>());
285   if (aResultPrs.IsNull())
286     return false;
287   // set shape hidden to check whether the presentation should be erased from the viewer
288   bool isModified = false;
289   if (aResultPrs->hasSubShapeVisible(ModuleBase_Tools::getSelectedShape(aPrs)))
290     isModified = aDisplayer->redisplay(aPrs->object(), false) || isModified;
291   else
292   {
293     ObjectPtr anObject = aPrs->object();
294     myHiddenObjects.insert(anObject);
295     static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
296     anObject->setDisplayed(false);
297     isModified = aDisplayer->erase(anObject, false) || isModified;
298     ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
299     Events_Loop::loop()->flush(aDispEvent);
300   }
301   return isModified;
302 }
303
304 //********************************************************************
305 void XGUI_FacesPanel::closeEvent(QCloseEvent* theEvent)
306 {
307   QDockWidget::closeEvent(theEvent);
308   emit closed();
309 }
310
311 //********************************************************************
312 void XGUI_FacesPanel::activateSelection(bool toActivate)
313 {
314   QIntList aShapeTypes;
315   aShapeTypes.append(TopAbs_FACE);
316
317   if (toActivate) {
318     myWorkshop->activateSubShapesSelection(aShapeTypes);
319   } else {
320     myWorkshop->deactivateSubShapesSelection();
321   }
322   if (toActivate)
323     activateSelectionFilters();
324   else
325     deactivateSelectionFilters();
326 }
327
328 //********************************************************************
329 QString XGUI_FacesPanel::generateName(const ModuleBase_ViewerPrsPtr& thePrs)
330 {
331   if (!thePrs.get() || !thePrs->object().get())
332     return "Undefined";
333
334   GeomShapePtr aContext;
335   ObjectPtr anObject = thePrs->object();
336   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
337   if (aResult.get())
338     aContext = aResult->shape();
339   else {
340     // TODO if there is this case
341   }
342
343   QString aName = anObject->data()->name().c_str();
344   if (aContext.get()) {
345     GeomShapePtr aSubShape(new GeomAPI_Shape());
346     aSubShape->setImpl(new TopoDS_Shape(ModuleBase_Tools::getSelectedShape(thePrs)));
347     if (!aSubShape->isEqual(aContext))
348       aName += QString("_%1").arg(GeomAlgoAPI_CompoundBuilder::id(aContext, aSubShape));
349   }
350   return aName;
351 }
352
353 //********************************************************************
354 bool XGUI_FacesPanel::customizeObject(const ObjectPtr& theObject, const bool isDisplayed)
355 {
356   if (isDisplayed && myItems.isEmpty())
357     return false;
358
359   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(myWorkshop)->displayer();
360
361   AISObjectPtr aAISObj = aDisplayer->getAISObject(theObject);
362   if (aAISObj.get() == NULL)
363     return false;
364   Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(
365     aAISObj->impl<Handle(AIS_InteractiveObject)>());
366   if (aResultPrs.IsNull())
367     return false;
368
369   // if the object is displayed, the hidden faces are collected and set to the presentation
370   bool isModified = false;
371   NCollection_List<TopoDS_Shape> aHiddenSubShapes;
372   for (QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator anIt = myItems.begin();
373     anIt != myItems.end(); anIt++) {
374     ModuleBase_ViewerPrsPtr aPrs = anIt.value();
375     if (aPrs.get() && aPrs->object() != theObject)
376       continue;
377     TopoDS_Shape aShape = ModuleBase_Tools::getSelectedShape(aPrs);
378     if (!aHiddenSubShapes.Contains(aShape))
379       aHiddenSubShapes.Append(aShape);
380   }
381   isModified = aResultPrs->setSubShapeHidden(aHiddenSubShapes);
382
383   return isModified;
384 }
385
386 //********************************************************************
387 void XGUI_FacesPanel::onDeleteItem()
388 {
389   processDelete();
390 }
391
392 //********************************************************************
393 void XGUI_FacesPanel::onClosed()
394 {
395   reset(true);
396 }