]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp
Salome HOME
Merge branch 'master' of newgeom:newgeom
[modules/shaper.git] / src / ModuleBase / ModuleBase_WidgetShapeSelector.cpp
1 // File:        ModuleBase_WidgetShapeSelector.h
2 // Created:     2 June 2014
3 // Author:      Vitaly Smetannikov
4
5 #include "ModuleBase_WidgetShapeSelector.h"
6 #include <ModuleBase_IWorkshop.h>
7 #include "ModuleBase_WidgetValue.h"
8 #include <ModuleBase_Tools.h>
9 #include "ModuleBase_WidgetValueFeature.h"
10
11 #include <Events_Loop.h>
12 #include <ModelAPI_Events.h>
13 #include <ModelAPI_Tools.h>
14
15 #include <ModelAPI_Data.h>
16 #include <ModelAPI_Object.h>
17 #include <ModelAPI_Result.h>
18 #include <ModelAPI_AttributeReference.h>
19 #include <Config_WidgetAPI.h>
20
21 #include <GeomAPI_Shape.h>
22
23 #include <TopoDS_Shape.hxx>
24 #include <TopExp_Explorer.hxx>
25
26 #include <QWidget>
27 #include <QLayout>
28 #include <QLabel>
29 #include <QLineEdit>
30 #include <QToolButton>
31 #include <QString>
32 #include <QEvent>
33 #include <QDockWidget>
34
35 #include <stdexcept>
36
37 typedef QMap<QString, TopAbs_ShapeEnum> ShapeTypes;
38 static ShapeTypes MyShapeTypes;
39
40 TopAbs_ShapeEnum ModuleBase_WidgetShapeSelector::shapeType(const QString& theType)
41 {
42   if (MyShapeTypes.count() == 0) {
43     MyShapeTypes["face"] = TopAbs_FACE;
44     MyShapeTypes["vertex"] = TopAbs_VERTEX;
45     MyShapeTypes["wire"] = TopAbs_WIRE;
46     MyShapeTypes["edge"] = TopAbs_EDGE;
47     MyShapeTypes["shell"] = TopAbs_SHELL;
48     MyShapeTypes["solid"] = TopAbs_SOLID;
49   }
50   if (MyShapeTypes.contains(theType))
51     return MyShapeTypes[theType];
52   throw std::invalid_argument("Shape type defined in XML is not implemented!");
53 }
54
55 ModuleBase_WidgetShapeSelector::ModuleBase_WidgetShapeSelector(QWidget* theParent,
56                                                      ModuleBase_IWorkshop* theWorkshop,
57                                                      const Config_WidgetAPI* theData,
58                                                      const std::string& theParentId)
59     : ModuleBase_ModelWidget(theParent, theData, theParentId),
60       myWorkshop(theWorkshop), myIsActive(false)
61 {
62   myContainer = new QWidget(theParent);
63   QHBoxLayout* aLayout = new QHBoxLayout(myContainer);
64   ModuleBase_Tools::adjustMargins(aLayout);
65
66   QString aLabelText = QString::fromStdString(theData->widgetLabel());
67   QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
68   myLabel = new QLabel(aLabelText, myContainer);
69   if (!aLabelIcon.isEmpty())
70     myLabel->setPixmap(QPixmap(aLabelIcon));
71
72   aLayout->addWidget(myLabel);
73
74   QString aToolTip = QString::fromStdString(theData->widgetTooltip());
75   myTextLine = new QLineEdit(myContainer);
76   myTextLine->setReadOnly(true);
77   myTextLine->setToolTip(aToolTip);
78   myTextLine->installEventFilter(this);
79
80   myBasePalet = myTextLine->palette();
81   myInactivePalet = myBasePalet;
82   myInactivePalet.setBrush(QPalette::Base, QBrush(Qt::gray, Qt::Dense6Pattern));
83   myTextLine->setPalette(myInactivePalet);
84
85   aLayout->addWidget(myTextLine, 1);
86
87   std::string aTypes = theData->getProperty("shape_types");
88   myShapeTypes = QString(aTypes.c_str()).split(' ');
89 }
90
91 //********************************************************************
92 ModuleBase_WidgetShapeSelector::~ModuleBase_WidgetShapeSelector()
93 {
94 }
95
96 //********************************************************************
97 bool ModuleBase_WidgetShapeSelector::storeValue() const
98 {
99   FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(mySelectedObject);
100   if (aSelectedFeature == myFeature)  // In order to avoid selection of the same object
101     return false;
102
103   DataPtr aData = myFeature->data();
104   boost::shared_ptr<ModelAPI_AttributeReference> aRef = boost::dynamic_pointer_cast<
105       ModelAPI_AttributeReference>(aData->attribute(attributeID()));
106
107   ObjectPtr aObject = aRef->value();
108   if (!(aObject && aObject->isSame(mySelectedObject))) {
109     aRef->setValue(mySelectedObject);
110     updateObject(myFeature);
111   }
112   return true;
113 }
114
115 //********************************************************************
116 bool ModuleBase_WidgetShapeSelector::restoreValue()
117 {
118   DataPtr aData = myFeature->data();
119   boost::shared_ptr<ModelAPI_AttributeReference> aRef = aData->reference(attributeID());
120
121   bool isBlocked = this->blockSignals(true);
122   mySelectedObject = aRef->value();
123   updateSelectionName();
124
125   this->blockSignals(isBlocked);
126   return true;
127 }
128
129 //********************************************************************
130 QList<QWidget*> ModuleBase_WidgetShapeSelector::getControls() const
131 {
132   QList<QWidget*> aControls;
133   aControls.append(myLabel);
134   aControls.append(myTextLine);
135   return aControls;
136 }
137
138 //********************************************************************
139 void ModuleBase_WidgetShapeSelector::onSelectionChanged()
140 {
141   QList<ObjectPtr> aObjects = myWorkshop->selectedObjects();
142   if (aObjects.size() > 0) {
143     ObjectPtr aObject = aObjects.first();
144     if ((!mySelectedObject) && (!aObject))
145       return;
146     if (mySelectedObject && aObject && mySelectedObject->isSame(aObject))
147       return;
148
149     // Check that the selection corresponds to selection type
150     if (!isAccepted(aObject))
151       return;
152
153     setObject(aObject);
154   }
155 }
156
157 //********************************************************************
158 void ModuleBase_WidgetShapeSelector::setObject(ObjectPtr theObj)
159 {
160   if (mySelectedObject == theObj)
161     return;
162   mySelectedObject = theObj;
163   if (mySelectedObject) {
164     raisePanel();
165     static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TOHIDE);
166     ModelAPI_EventCreator::get()->sendUpdated(mySelectedObject, anEvent);
167     Events_Loop::loop()->flush(anEvent);
168   } 
169   updateSelectionName();
170   activateSelection(false);
171   emit valuesChanged();
172   emit focusOutWidget(this);
173 }
174
175 //********************************************************************
176 bool ModuleBase_WidgetShapeSelector::isAccepted(const ObjectPtr theResult) const
177 {
178   ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(theResult);
179   if (myFeature) {
180     // We can not select a result of our feature
181     const std::list<boost::shared_ptr<ModelAPI_Result>>& aRes = myFeature->results();
182     std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aIt;
183     for (aIt = aRes.cbegin(); aIt != aRes.cend(); ++aIt) {
184       if ((*aIt) == aResult)
185         return false;
186     }
187   }
188   boost::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
189   if (!aShapePtr)
190     return false;
191   TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
192   if (aShape.IsNull())
193     return false;
194
195   TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
196   if (aShapeType == TopAbs_COMPOUND) {
197     foreach (QString aType, myShapeTypes) {
198       TopExp_Explorer aEx(aShape, shapeType(aType));
199       if (aEx.More())
200         return true;
201     }
202   } else {
203     foreach (QString aType, myShapeTypes) {
204       if (shapeType(aType) == aShapeType)
205         return true;
206     }
207   }
208   return false;
209 }
210
211 //********************************************************************
212 void ModuleBase_WidgetShapeSelector::updateSelectionName()
213 {
214   if (mySelectedObject) {
215     std::string aName = mySelectedObject->data()->name();
216     myTextLine->setText(QString::fromStdString(aName));
217   } else {
218     if (myIsActive) {
219       QString aMsg = tr("Select a ");
220       int i = 0;
221       foreach (QString aType, myShapeTypes) {
222         if (i > 0)
223           aMsg += " or ";
224         aMsg += aType;
225         i++;
226       }
227       myTextLine->setText(aMsg);
228     } else
229       myTextLine->setText(tr("No object selected"));
230   }
231 }
232
233
234 //********************************************************************
235 void ModuleBase_WidgetShapeSelector::activateSelection(bool toActivate)
236 {
237   myIsActive = toActivate;
238   if (myIsActive)
239     myTextLine->setPalette(myBasePalet);
240   else
241     myTextLine->setPalette(myInactivePalet);
242   updateSelectionName();
243
244   if (myIsActive)
245     connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
246   else
247     disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
248 }
249
250 //********************************************************************
251 void ModuleBase_WidgetShapeSelector::raisePanel() const
252 {
253   QWidget* aParent = myContainer->parentWidget();
254   QWidget* aLastPanel = 0;
255   while (!aParent->inherits("QDockWidget")) {
256     aLastPanel = aParent;
257     aParent = aParent->parentWidget();
258     if (!aParent)
259       return;
260   }
261   if (aParent->inherits("QDockWidget")) {
262     QDockWidget* aTabWgt = (QDockWidget*) aParent;
263     aTabWgt->raise();
264   }
265 }
266
267 //********************************************************************
268 bool ModuleBase_WidgetShapeSelector::focusTo()
269 {
270   activateSelection(true);
271   return true;
272 }
273
274 //********************************************************************
275 bool ModuleBase_WidgetShapeSelector::eventFilter(QObject* theObj, QEvent* theEvent)
276 {
277   if (theObj == myTextLine) {
278     if (theEvent->type() == QEvent::FocusIn)
279       activateSelection(true);
280   }
281   return ModuleBase_ModelWidget::eventFilter(theObj, theEvent);
282 }
283
284 //********************************************************************
285 bool ModuleBase_WidgetShapeSelector::setValue(ModuleBase_WidgetValue* theValue)
286 {
287   if (theValue) {
288     ModuleBase_WidgetValueFeature* aFeatureValue =
289         dynamic_cast<ModuleBase_WidgetValueFeature*>(theValue);
290     if (aFeatureValue && aFeatureValue->object()) {
291       ObjectPtr aObject = aFeatureValue->object();
292       if (isAccepted(aObject)) {
293         setObject(aObject);
294         return true;
295       }
296     }
297   }
298   return false;
299 }
300