Salome HOME
A regression correction for the following case:
[modules/shaper.git] / src / ModuleBase / ModuleBase_Tools.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        ModuleBase_Tools.cpp
4 // Created:     11 July 2014
5 // Author:      Vitaly Smetannikov
6
7 #include "ModuleBase_Tools.h"
8
9 #include <ModuleBase_ParamIntSpinBox.h>
10 #include <ModuleBase_ParamSpinBox.h>
11
12 #include <ModelAPI_Attribute.h>
13 #include <ModelAPI_AttributeRefAttr.h>
14 #include <ModelAPI_AttributeReference.h>
15 #include <ModelAPI_AttributeSelection.h>
16 #include <ModelAPI_Data.h>
17 #include <ModelAPI_Result.h>
18 #include <ModelAPI_ResultCompSolid.h>
19 #include <ModelAPI_ResultParameter.h>
20 #include <ModelAPI_Tools.h>
21
22 #include <TopoDS_Iterator.hxx>
23
24 #include <GeomDataAPI_Point2D.h>
25 #include <Events_Error.h>
26
27 #include <Config_PropManager.h>
28
29 #include <QWidget>
30 #include <QLayout>
31 #include <QPainter>
32 #include <QBitmap>
33 #include <QDoubleSpinBox>
34 #include <QGraphicsDropShadowEffect>
35 #include <QColor>
36
37 #include <sstream>
38
39 const double tolerance = 1e-7;
40
41 //#define DEBUG_ACTIVATE_WINDOW
42 //#define DEBUG_SET_FOCUS
43
44 namespace ModuleBase_Tools {
45
46 //******************************************************************
47
48 //******************************************************************
49
50 void adjustMargins(QWidget* theWidget)
51 {
52   if(!theWidget)
53     return;
54   adjustMargins(theWidget->layout());
55 }
56
57 void adjustMargins(QLayout* theLayout)
58 {
59   if(!theLayout)
60     return;
61   theLayout->setContentsMargins(2, 5, 2, 5);
62   theLayout->setSpacing(4);
63 }
64
65 void zeroMargins(QWidget* theWidget)
66 {
67   if(!theWidget)
68     return;
69   zeroMargins(theWidget->layout());
70 }
71
72 void zeroMargins(QLayout* theLayout)
73 {
74   if(!theLayout)
75     return;
76   theLayout->setContentsMargins(0, 0, 0, 0);
77   theLayout->setSpacing(5);
78 }
79
80 void activateWindow(QWidget* theWidget, const QString& theInfo)
81 {
82   theWidget->activateWindow();
83
84 #ifdef DEBUG_ACTIVATE_WINDOW
85   qDebug(QString("activateWindow: %1").arg(theInfo).toStdString().c_str());
86 #endif
87 }
88
89 void setFocus(QWidget* theWidget, const QString& theInfo)
90 {
91   theWidget->setFocus();
92
93 #ifdef DEBUG_SET_FOCUS
94   qDebug(QString("setFocus: %1").arg(theInfo).toStdString().c_str());
95 #endif
96 }
97
98 void setShadowEffect(QWidget* theWidget, const bool isSetEffect)
99 {
100   if (isSetEffect) {
101     QGraphicsDropShadowEffect* aGlowEffect = new QGraphicsDropShadowEffect();
102     aGlowEffect->setOffset(.0);
103     aGlowEffect->setBlurRadius(10.0);
104     aGlowEffect->setColor(QColor(0, 170, 255)); // Light-blue color, #00AAFF
105     theWidget->setGraphicsEffect(aGlowEffect);
106   }
107   else {
108     QGraphicsEffect* anEffect = theWidget->graphicsEffect();
109     if(anEffect)
110     anEffect->deleteLater();
111     theWidget->setGraphicsEffect(NULL);
112   }
113 }
114
115 QPixmap composite(const QString& theAdditionalIcon, const QString& theIcon)
116 {
117   QImage anIcon(theIcon);
118   QImage anAditional(theAdditionalIcon);
119
120   if (anIcon.isNull())
121     return QPixmap();
122
123   int anAddWidth = anAditional.width();
124   int anAddHeight = anAditional.height();
125
126   int aWidth = anIcon.width();
127   int aHeight = anIcon.height();
128
129   int aStartWidthPos = aWidth - anAddWidth - 1;
130   int aStartHeightPos = aHeight - anAddHeight - 1;
131
132   for (int i = 0; i < anAddWidth && i + aStartWidthPos < aWidth; i++)
133   {
134     for (int j = 0; j < anAddHeight && j + aStartHeightPos < aHeight; j++)
135     {
136       if (qAlpha(anAditional.pixel(i, j)) > 0)
137         anIcon.setPixel(i + aStartWidthPos, j + aStartHeightPos, anAditional.pixel(i, j));
138     }
139   }
140   return QPixmap::fromImage(anIcon);
141 }
142
143 QPixmap lighter(const QString& theIcon, const int theLighterValue)
144 {
145   QImage anIcon(theIcon);
146   if (anIcon.isNull())
147     return QPixmap();
148
149   QImage aResult(theIcon);
150   for ( int i = 0; i < anIcon.width(); i++ )
151   {
152     for ( int j = 0; j < anIcon.height(); j++ )
153     {
154       QRgb anRgb = anIcon.pixel( i, j );
155       QColor aPixelColor(qRed(anRgb), qGreen(anRgb), qBlue(anRgb),
156                          qAlpha( aResult.pixel( i, j ) ));
157
158       QColor aLighterColor = aPixelColor.lighter(theLighterValue);
159       aResult.setPixel(i, j, qRgba( aLighterColor.red(), aLighterColor.green(),
160                                     aLighterColor.blue(), aLighterColor.alpha() ) );
161     }
162   }
163   return QPixmap::fromImage(aResult);
164 }
165
166 void setSpinText(ModuleBase_ParamSpinBox* theSpin, const QString& theText)
167 {
168   if (theSpin->text() == theText) 
169     return;
170   // In order to avoid extra text setting because it will
171   // reset cursor position in control
172   bool isBlocked = theSpin->blockSignals(true);
173   theSpin->setText(theText);
174   theSpin->blockSignals(isBlocked);
175 }
176
177 void setSpinValue(QDoubleSpinBox* theSpin, double theValue)
178 {
179   if (fabs(theSpin->value() - theValue) < tolerance)
180     return;
181   bool isBlocked = theSpin->blockSignals(true);
182   theSpin->setValue(theValue);
183   theSpin->blockSignals(isBlocked);
184 }
185
186 void setSpinValue(ModuleBase_ParamSpinBox* theSpin, double theValue)
187 {
188   if (fabs(theSpin->value() - theValue) < tolerance)
189     return;
190   bool isBlocked = theSpin->blockSignals(true);
191   theSpin->setValue(theValue);
192   theSpin->blockSignals(isBlocked);
193 }
194
195 void setSpinText(ModuleBase_ParamIntSpinBox* theSpin, const QString& theText)
196 {
197   // In order to avoid extra text setting because it will
198   // reset cursor position in control
199   if (theSpin->text() == theText)
200     return;
201   bool isBlocked = theSpin->blockSignals(true);
202   theSpin->setText(theText);
203   theSpin->blockSignals(isBlocked);
204 }
205
206 void setSpinValue(ModuleBase_ParamIntSpinBox* theSpin, int theValue)
207 {
208   if (theSpin->value() == theValue)
209     return;
210   bool isBlocked = theSpin->blockSignals(true);
211   theSpin->setValue(theValue);
212   theSpin->blockSignals(isBlocked);
213 }
214
215 QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo)
216 {
217   QString aFeatureStr = "feature";
218   if (!theObj.get())
219     return aFeatureStr;
220
221   std::ostringstream aPtrStr;
222   aPtrStr << "[" << theObj.get() << "]";
223
224   ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
225   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
226   if(aRes.get()) {
227     aFeatureStr.append(QString("(result%1)").arg(aPtrStr.str().c_str()).toStdString() .c_str());
228     if (aRes->isDisabled())
229       aFeatureStr.append("[disabled]");
230     if (aRes->isConcealed())
231       aFeatureStr.append("[concealed]");
232     if (ModelAPI_Tools::hasSubResults(aRes))
233       aFeatureStr.append("[hasSubResults]");
234
235     aFeature = ModelAPI_Feature::feature(aRes);
236   }
237   else
238     aFeatureStr.append(aPtrStr.str().c_str());
239
240   if (aFeature.get()) {
241     aFeatureStr.append(QString(": %1").arg(aFeature->getKind().c_str()).toStdString().c_str());
242     if (aFeature->data()->isValid()) {
243       aFeatureStr.append(QString(", name=%1").arg(aFeature->data()->name().c_str()).toStdString()
244                                                                                        .c_str());
245     }
246     if (isUseAttributesInfo) {
247       std::list<AttributePtr> anAttrs = aFeature->data()->attributes("");
248       std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
249       QStringList aValues;
250       for(; anIt != aLast; anIt++) {
251         AttributePtr anAttr = *anIt;
252         QString aValue = "not defined";
253         std::string aType = anAttr->attributeType();
254         if (aType == GeomDataAPI_Point2D::typeId()) {
255           std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
256                                                                                          anAttr);
257           if (aPoint.get())
258             aValue = QString("(%1, %2)").arg(aPoint->x()).arg(aPoint->y());
259         }
260         else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
261         }
262
263         aValues.push_back(QString("%1: %2").arg(anAttr->id().c_str()).arg(aValue).toStdString().c_str());
264       }
265       if (!aValues.empty())
266         aFeatureStr.append(QString(", attributes: %1").arg(aValues.join(", ").toStdString().c_str()));
267     }
268   }
269
270   return aFeatureStr;
271 }
272
273 typedef QMap<QString, TopAbs_ShapeEnum> ShapeTypes;
274 static ShapeTypes MyShapeTypes;
275
276 TopAbs_ShapeEnum shapeType(const QString& theType)
277 {
278   if (MyShapeTypes.count() == 0) {
279     MyShapeTypes["face"] = TopAbs_FACE;
280     MyShapeTypes["faces"] = TopAbs_FACE;
281     MyShapeTypes["vertex"] = TopAbs_VERTEX;
282     MyShapeTypes["vertices"] = TopAbs_VERTEX;
283     MyShapeTypes["wire"] = TopAbs_WIRE;
284     MyShapeTypes["edge"] = TopAbs_EDGE;
285     MyShapeTypes["edges"] = TopAbs_EDGE;
286     MyShapeTypes["shell"] = TopAbs_SHELL;
287     MyShapeTypes["solid"] = TopAbs_SOLID;
288     MyShapeTypes["solids"] = TopAbs_SOLID;
289     MyShapeTypes["objects"] = TopAbs_SHAPE;
290   }
291   QString aType = theType.toLower();
292   if (MyShapeTypes.contains(aType))
293     return MyShapeTypes[aType];
294   Events_Error::send("Shape type defined in XML is not implemented!");
295   return TopAbs_SHAPE;
296 }
297
298 void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature, bool& hasParameter, bool& hasSubFeature)
299 {
300   hasResult = false;
301   hasFeature = false;
302   hasParameter = false;
303   hasSubFeature = false;
304   foreach(ObjectPtr aObj, theObjects) {
305     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
306     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
307     ResultParameterPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aResult);
308
309     hasResult |= (aResult.get() != NULL);
310     hasFeature |= (aFeature.get() != NULL);
311     hasParameter |= (aConstruction.get() != NULL);
312     if (hasFeature) 
313       hasSubFeature |= (ModelAPI_Tools::compositeOwner(aFeature) != NULL);
314     if (hasFeature && hasResult  && hasParameter && hasSubFeature)
315       break;
316   }
317 }
318
319 void setDefaultDeviationCoefficient(const TopoDS_Shape& theShape,
320                                     const Handle(Prs3d_Drawer)& theDrawer)
321 {
322   if (theShape.IsNull())
323     return;
324   TopAbs_ShapeEnum aType = theShape.ShapeType();
325   if ((aType == TopAbs_EDGE) || (aType == TopAbs_WIRE)) 
326     theDrawer->SetDeviationCoefficient(1.e-4);
327 }
328
329 Quantity_Color color(const std::string& theSection,
330                      const std::string& theName,
331                      const std::string& theDefault)
332 {
333   std::vector<int> aColor = Config_PropManager::color(theSection, theName, theDefault);
334   return Quantity_Color(aColor[0] / 255., aColor[1] / 255., aColor[2] / 255., Quantity_TOC_RGB);
335 }
336
337 ObjectPtr getObject(const AttributePtr& theAttribute)
338 {
339   ObjectPtr anObject;
340   std::string anAttrType = theAttribute->attributeType();
341   if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
342     AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
343     if (anAttr != NULL && anAttr->isObject())
344       anObject = anAttr->object();
345   }
346   if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
347     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
348     if (anAttr != NULL)
349       anObject = anAttr->context();
350   }
351   if (anAttrType == ModelAPI_AttributeReference::typeId()) {
352     AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
353     if (anAttr.get() != NULL)
354       anObject = anAttr->value();
355   }
356   return anObject;
357 }
358
359 TopAbs_ShapeEnum getCompoundSubType(const TopoDS_Shape& theShape)
360 {
361   TopAbs_ShapeEnum aShapeType = theShape.ShapeType();
362
363   // for compounds check sub-shapes: it may be compound of needed type:
364   // Booleans may produce compounds of Solids
365   if (aShapeType == TopAbs_COMPOUND) {
366     for(TopoDS_Iterator aSubs(theShape); aSubs.More(); aSubs.Next()) {
367       if (!aSubs.Value().IsNull()) {
368         TopAbs_ShapeEnum aSubType = aSubs.Value().ShapeType();
369         if (aSubType == TopAbs_COMPOUND) { // compound of compound(s)
370           aShapeType = TopAbs_COMPOUND;
371           break;
372         }
373         if (aShapeType == TopAbs_COMPOUND) {
374           aShapeType = aSubType;
375         } else if (aShapeType != aSubType) { // compound of shapes of different types
376           aShapeType = TopAbs_COMPOUND;
377           break;
378         }
379       }
380     }
381   }
382   return aShapeType;
383 }
384
385 } // namespace ModuleBase_Tools
386
387