]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModuleBase/ModuleBase_Tools.cpp
Salome HOME
1. Correction for perfomance problem by Apply button state update: do not listen...
[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 #include <ModuleBase_WidgetFactory.h>
12 #include <ModuleBase_IWorkshop.h>
13 #include <ModuleBase_IModule.h>
14
15 #include <ModelAPI_Attribute.h>
16 #include <ModelAPI_AttributeRefAttr.h>
17 #include <ModelAPI_AttributeReference.h>
18 #include <ModelAPI_AttributeSelection.h>
19 #include <ModelAPI_AttributeSelectionList.h>
20 #include <ModelAPI_AttributeRefList.h>
21 #include <ModelAPI_AttributeRefAttrList.h>
22 #include <Events_Loop.h>
23
24 #include <ModelAPI_Data.h>
25 #include <ModelAPI_Result.h>
26 #include <ModelAPI_ResultCompSolid.h>
27 #include <ModelAPI_ResultParameter.h>
28 #include <ModelAPI_Tools.h>
29 #include <ModelAPI_Session.h>
30 #include <ModelAPI_Events.h>
31
32 #include <TopoDS_Iterator.hxx>
33
34 #include <GeomDataAPI_Point2D.h>
35 #include <Events_Error.h>
36
37 #include <Config_PropManager.h>
38
39 #include <QWidget>
40 #include <QLayout>
41 #include <QPainter>
42 #include <QBitmap>
43 #include <QDoubleSpinBox>
44 #include <QGraphicsDropShadowEffect>
45 #include <QColor>
46
47 #include <sstream>
48 #include <string>
49
50 const double tolerance = 1e-7;
51
52 //#define DEBUG_ACTIVATE_WINDOW
53 //#define DEBUG_SET_FOCUS
54
55 namespace ModuleBase_Tools {
56
57 //******************************************************************
58
59 //******************************************************************
60
61 void adjustMargins(QWidget* theWidget)
62 {
63   if(!theWidget)
64     return;
65   adjustMargins(theWidget->layout());
66 }
67
68 void adjustMargins(QLayout* theLayout)
69 {
70   if(!theLayout)
71     return;
72   theLayout->setContentsMargins(2, 5, 2, 5);
73   theLayout->setSpacing(4);
74 }
75
76 void zeroMargins(QWidget* theWidget)
77 {
78   if(!theWidget)
79     return;
80   zeroMargins(theWidget->layout());
81 }
82
83 void zeroMargins(QLayout* theLayout)
84 {
85   if(!theLayout)
86     return;
87   theLayout->setContentsMargins(0, 0, 0, 0);
88   theLayout->setSpacing(5);
89 }
90
91 void activateWindow(QWidget* theWidget, const QString& theInfo)
92 {
93   theWidget->activateWindow();
94
95 #ifdef DEBUG_ACTIVATE_WINDOW
96   qDebug(QString("activateWindow: %1").arg(theInfo).toStdString().c_str());
97 #endif
98 }
99
100 void setFocus(QWidget* theWidget, const QString& theInfo)
101 {
102   theWidget->setFocus();
103
104 #ifdef DEBUG_SET_FOCUS
105   qDebug(QString("setFocus: %1").arg(theInfo).toStdString().c_str());
106 #endif
107 }
108
109 void setShadowEffect(QWidget* theWidget, const bool isSetEffect)
110 {
111   if (isSetEffect) {
112     QGraphicsDropShadowEffect* aGlowEffect = new QGraphicsDropShadowEffect();
113     aGlowEffect->setOffset(.0);
114     aGlowEffect->setBlurRadius(10.0);
115     aGlowEffect->setColor(QColor(0, 170, 255)); // Light-blue color, #00AAFF
116     theWidget->setGraphicsEffect(aGlowEffect);
117   }
118   else {
119     QGraphicsEffect* anEffect = theWidget->graphicsEffect();
120     if(anEffect)
121     anEffect->deleteLater();
122     theWidget->setGraphicsEffect(NULL);
123   }
124 }
125
126 QPixmap composite(const QString& theAdditionalIcon, const QString& theIcon)
127 {
128   QImage anIcon(theIcon);
129   QImage anAditional(theAdditionalIcon);
130
131   if (anIcon.isNull())
132     return QPixmap();
133
134   int anAddWidth = anAditional.width();
135   int anAddHeight = anAditional.height();
136
137   int aWidth = anIcon.width();
138   int aHeight = anIcon.height();
139
140   int aStartWidthPos = aWidth - anAddWidth - 1;
141   int aStartHeightPos = aHeight - anAddHeight - 1;
142
143   for (int i = 0; i < anAddWidth && i + aStartWidthPos < aWidth; i++)
144   {
145     for (int j = 0; j < anAddHeight && j + aStartHeightPos < aHeight; j++)
146     {
147       if (qAlpha(anAditional.pixel(i, j)) > 0)
148         anIcon.setPixel(i + aStartWidthPos, j + aStartHeightPos, anAditional.pixel(i, j));
149     }
150   }
151   return QPixmap::fromImage(anIcon);
152 }
153
154 QPixmap lighter(const QString& theIcon, const int theLighterValue)
155 {
156   QImage anIcon(theIcon);
157   if (anIcon.isNull())
158     return QPixmap();
159
160   QImage aResult(theIcon);
161   for ( int i = 0; i < anIcon.width(); i++ )
162   {
163     for ( int j = 0; j < anIcon.height(); j++ )
164     {
165       QRgb anRgb = anIcon.pixel( i, j );
166       QColor aPixelColor(qRed(anRgb), qGreen(anRgb), qBlue(anRgb),
167                          qAlpha( aResult.pixel( i, j ) ));
168
169       QColor aLighterColor = aPixelColor.lighter(theLighterValue);
170       aResult.setPixel(i, j, qRgba( aLighterColor.red(), aLighterColor.green(),
171                                     aLighterColor.blue(), aLighterColor.alpha() ) );
172     }
173   }
174   return QPixmap::fromImage(aResult);
175 }
176
177 void setSpinText(ModuleBase_ParamSpinBox* theSpin, const QString& theText)
178 {
179   if (theSpin->text() == theText) 
180     return;
181   // In order to avoid extra text setting because it will
182   // reset cursor position in control
183   bool isBlocked = theSpin->blockSignals(true);
184   theSpin->setText(theText);
185   theSpin->blockSignals(isBlocked);
186 }
187
188 void setSpinValue(QDoubleSpinBox* theSpin, double theValue)
189 {
190   if (fabs(theSpin->value() - theValue) < tolerance)
191     return;
192   bool isBlocked = theSpin->blockSignals(true);
193   theSpin->setValue(theValue);
194   theSpin->blockSignals(isBlocked);
195 }
196
197 void setSpinValue(ModuleBase_ParamSpinBox* theSpin, double theValue)
198 {
199   if (fabs(theSpin->value() - theValue) < tolerance)
200     return;
201   bool isBlocked = theSpin->blockSignals(true);
202   theSpin->setValue(theValue);
203   theSpin->blockSignals(isBlocked);
204 }
205
206 void setSpinText(ModuleBase_ParamIntSpinBox* theSpin, const QString& theText)
207 {
208   // In order to avoid extra text setting because it will
209   // reset cursor position in control
210   if (theSpin->text() == theText)
211     return;
212   bool isBlocked = theSpin->blockSignals(true);
213   theSpin->setText(theText);
214   theSpin->blockSignals(isBlocked);
215 }
216
217 void setSpinValue(ModuleBase_ParamIntSpinBox* theSpin, int theValue)
218 {
219   if (theSpin->value() == theValue)
220     return;
221   bool isBlocked = theSpin->blockSignals(true);
222   theSpin->setValue(theValue);
223   theSpin->blockSignals(isBlocked);
224 }
225
226 QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo)
227 {
228   QString aFeatureStr = "feature";
229   if (!theObj.get())
230     return aFeatureStr;
231
232   std::ostringstream aPtrStr;
233   aPtrStr << "[" << theObj.get() << "]";
234
235   ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
236   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
237   if(aRes.get()) {
238     aFeatureStr.append(QString("(result%1)").arg(aPtrStr.str().c_str()).toStdString() .c_str());
239     if (aRes->isDisabled())
240       aFeatureStr.append("[disabled]");
241     if (aRes->isConcealed())
242       aFeatureStr.append("[concealed]");
243     if (ModelAPI_Tools::hasSubResults(aRes))
244       aFeatureStr.append("[hasSubResults]");
245
246     aFeature = ModelAPI_Feature::feature(aRes);
247   }
248   else
249     aFeatureStr.append(aPtrStr.str().c_str());
250
251   if (aFeature.get()) {
252     aFeatureStr.append(QString(": %1").arg(aFeature->getKind().c_str()).toStdString().c_str());
253     if (aFeature->data()->isValid()) {
254       aFeatureStr.append(QString(", name=%1").arg(aFeature->data()->name().c_str()).toStdString()
255                                                                                        .c_str());
256     }
257     if (isUseAttributesInfo) {
258       std::list<AttributePtr> anAttrs = aFeature->data()->attributes("");
259       std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
260       QStringList aValues;
261       for(; anIt != aLast; anIt++) {
262         AttributePtr anAttr = *anIt;
263         QString aValue = "not defined";
264         std::string aType = anAttr->attributeType();
265         if (aType == GeomDataAPI_Point2D::typeId()) {
266           std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
267                                                                                          anAttr);
268           if (aPoint.get())
269             aValue = QString("(%1, %2)").arg(aPoint->x()).arg(aPoint->y());
270         }
271         else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
272         }
273
274         aValues.push_back(QString("%1: %2").arg(anAttr->id().c_str()).arg(aValue).toStdString().c_str());
275       }
276       if (!aValues.empty())
277         aFeatureStr.append(QString(", attributes: %1").arg(aValues.join(", ").toStdString().c_str()));
278     }
279   }
280
281   return aFeatureStr;
282 }
283
284 typedef QMap<QString, TopAbs_ShapeEnum> ShapeTypes;
285 static ShapeTypes MyShapeTypes;
286
287 TopAbs_ShapeEnum shapeType(const QString& theType)
288 {
289   if (MyShapeTypes.count() == 0) {
290     MyShapeTypes["face"] = TopAbs_FACE;
291     MyShapeTypes["faces"] = TopAbs_FACE;
292     MyShapeTypes["vertex"] = TopAbs_VERTEX;
293     MyShapeTypes["vertices"] = TopAbs_VERTEX;
294     MyShapeTypes["wire"] = TopAbs_WIRE;
295     MyShapeTypes["edge"] = TopAbs_EDGE;
296     MyShapeTypes["edges"] = TopAbs_EDGE;
297     MyShapeTypes["shell"] = TopAbs_SHELL;
298     MyShapeTypes["solid"] = TopAbs_SOLID;
299     MyShapeTypes["solids"] = TopAbs_SOLID;
300     MyShapeTypes["objects"] = TopAbs_SHAPE;
301   }
302   QString aType = theType.toLower();
303   if (MyShapeTypes.contains(aType))
304     return MyShapeTypes[aType];
305   Events_Error::send("Shape type defined in XML is not implemented!");
306   return TopAbs_SHAPE;
307 }
308
309 void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature,
310                   bool& hasParameter, bool& hasCompositeOwner)
311 {
312   hasResult = false;
313   hasFeature = false;
314   hasParameter = false;
315   hasCompositeOwner = false;
316   foreach(ObjectPtr aObj, theObjects) {
317     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
318     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
319     ResultParameterPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aResult);
320
321     hasResult |= (aResult.get() != NULL);
322     hasFeature |= (aFeature.get() != NULL);
323     hasParameter |= (aConstruction.get() != NULL);
324     if (hasFeature) 
325       hasCompositeOwner |= (ModelAPI_Tools::compositeOwner(aFeature) != NULL);
326     if (hasFeature && hasResult  && hasParameter && hasCompositeOwner)
327       break;
328   }
329 }
330
331 void setDefaultDeviationCoefficient(const TopoDS_Shape& theShape,
332                                     const Handle(Prs3d_Drawer)& theDrawer)
333 {
334   if (theShape.IsNull())
335     return;
336   TopAbs_ShapeEnum aType = theShape.ShapeType();
337   if ((aType == TopAbs_EDGE) || (aType == TopAbs_WIRE)) 
338     theDrawer->SetDeviationCoefficient(1.e-4);
339 }
340
341 Quantity_Color color(const std::string& theSection,
342                      const std::string& theName,
343                      const std::string& theDefault)
344 {
345   std::vector<int> aColor = Config_PropManager::color(theSection, theName, theDefault);
346   return Quantity_Color(aColor[0] / 255., aColor[1] / 255., aColor[2] / 255., Quantity_TOC_RGB);
347 }
348
349 ObjectPtr getObject(const AttributePtr& theAttribute)
350 {
351   ObjectPtr anObject;
352   std::string anAttrType = theAttribute->attributeType();
353   if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
354     AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
355     if (anAttr != NULL && anAttr->isObject())
356       anObject = anAttr->object();
357   }
358   if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
359     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
360     if (anAttr != NULL)
361       anObject = anAttr->context();
362   }
363   if (anAttrType == ModelAPI_AttributeReference::typeId()) {
364     AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
365     if (anAttr.get() != NULL)
366       anObject = anAttr->value();
367   }
368   return anObject;
369 }
370
371 TopAbs_ShapeEnum getCompoundSubType(const TopoDS_Shape& theShape)
372 {
373   TopAbs_ShapeEnum aShapeType = theShape.ShapeType();
374
375   // for compounds check sub-shapes: it may be compound of needed type:
376   // Booleans may produce compounds of Solids
377   if (aShapeType == TopAbs_COMPOUND) {
378     for(TopoDS_Iterator aSubs(theShape); aSubs.More(); aSubs.Next()) {
379       if (!aSubs.Value().IsNull()) {
380         TopAbs_ShapeEnum aSubType = aSubs.Value().ShapeType();
381         if (aSubType == TopAbs_COMPOUND) { // compound of compound(s)
382           aShapeType = TopAbs_COMPOUND;
383           break;
384         }
385         if (aShapeType == TopAbs_COMPOUND) {
386           aShapeType = aSubType;
387         } else if (aShapeType != aSubType) { // compound of shapes of different types
388           aShapeType = TopAbs_COMPOUND;
389           break;
390         }
391       }
392     }
393   }
394   return aShapeType;
395 }
396
397 void getParameters(QStringList& theParameters)
398 {
399   theParameters.clear();
400
401   SessionPtr aSession = ModelAPI_Session::get();
402   std::list<DocumentPtr> aDocList;
403   DocumentPtr anActiveDocument = aSession->activeDocument();
404   DocumentPtr aRootDocument = aSession->moduleDocument();
405   aDocList.push_back(anActiveDocument);
406   if (anActiveDocument != aRootDocument) {
407     aDocList.push_back(aRootDocument);
408   }
409   std::string aGroupId = ModelAPI_ResultParameter::group();
410   for(std::list<DocumentPtr>::const_iterator it = aDocList.begin(); it != aDocList.end(); ++it) {
411     DocumentPtr aDocument = *it;
412     int aSize = aDocument->size(aGroupId);
413     for (int i = 0; i < aSize; i++) {
414       ObjectPtr anObject = aDocument->object(aGroupId, i);
415       std::string aParameterName = anObject->data()->name();
416       theParameters.append(aParameterName.c_str());
417     }
418   }
419 }
420
421 std::string findGreedAttribute(ModuleBase_IWorkshop* theWorkshop, const FeaturePtr& theFeature)
422 {
423   std::string anAttributeId;
424
425   std::string aXmlCfg, aDescription;
426   theWorkshop->module()->getXMLRepresentation(theFeature->getKind(), aXmlCfg, aDescription);
427
428   ModuleBase_WidgetFactory aFactory(aXmlCfg, theWorkshop);
429   std::string anAttributeTitle;
430   aFactory.getGreedAttribute(anAttributeId);
431
432   return anAttributeId;
433 }
434
435 void setObject(const AttributePtr& theAttribute, const ObjectPtr& theObject,
436                const GeomShapePtr& theShape, ModuleBase_IWorkshop* theWorkshop,
437                const bool theTemporarily)
438 {
439   if (!theAttribute.get())
440     return;
441
442   std::string aType = theAttribute->attributeType();
443   if (aType == ModelAPI_AttributeReference::typeId()) {
444     AttributeReferencePtr aRef = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
445     ObjectPtr aObject = aRef->value();
446     if (!(aObject && aObject->isSame(theObject))) {
447       aRef->setValue(theObject);
448     }
449   } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
450     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
451
452     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
453     if (anAttribute.get())
454       aRefAttr->setAttr(anAttribute);
455     else {
456       ObjectPtr aObject = aRefAttr->object();
457       if (!(aObject && aObject->isSame(theObject))) {
458         aRefAttr->setObject(theObject);
459       }
460     }
461   } else if (aType == ModelAPI_AttributeSelection::typeId()) {
462     AttributeSelectionPtr aSelectAttr =
463                              std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
464     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
465     if (aSelectAttr.get() != NULL) {
466       aSelectAttr->setValue(aResult, theShape, theTemporarily);
467     }
468   }
469   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
470     AttributeSelectionListPtr aSelectionListAttr =
471                          std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
472     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
473     if (!aSelectionListAttr->isInList(aResult, theShape, theTemporarily))
474       aSelectionListAttr->append(aResult, theShape, theTemporarily);
475   }
476   else if (aType == ModelAPI_AttributeRefList::typeId()) {
477     AttributeRefListPtr aRefListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
478     if (!aRefListAttr->isInList(theObject))
479       aRefListAttr->append(theObject);
480   }
481   else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
482     AttributeRefAttrListPtr aRefAttrListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(theAttribute);
483     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
484
485     if (anAttribute.get()) {
486       if (!aRefAttrListAttr->isInList(anAttribute))
487         aRefAttrListAttr->append(anAttribute);
488     }
489     else {
490       if (!aRefAttrListAttr->isInList(theObject))
491         aRefAttrListAttr->append(theObject);
492     }
493   }
494 }
495
496 GeomShapePtr getShape(const AttributePtr& theAttribute, ModuleBase_IWorkshop* theWorkshop)
497 {
498   GeomShapePtr aShape;
499   if (!theAttribute.get())
500     return aShape;
501
502   std::string aType = theAttribute->attributeType();
503   if (aType == ModelAPI_AttributeReference::typeId()) {
504   } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
505     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
506     if (aRefAttr.get() && !aRefAttr->isObject()) {
507       AttributePtr anAttribute = aRefAttr->attr();
508       aShape = theWorkshop->module()->findShape(anAttribute);
509     }
510   } else if (aType == ModelAPI_AttributeSelection::typeId()) {
511     AttributeSelectionPtr aSelectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
512                                                                                  (theAttribute);
513     aShape = aSelectAttr->value();
514   }
515   return aShape;
516 }
517
518 void flushUpdated(ObjectPtr theObject)
519 {
520   blockUpdateViewer(true);
521
522   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
523
524   blockUpdateViewer(false);
525 }
526
527 void blockUpdateViewer(const bool theValue)
528 {
529   // the viewer update should be blocked in order to avoid the temporary feature content
530   // when the solver processes the feature, the redisplay message can be flushed
531   // what caused the display in the viewer preliminary states of object
532   // e.g. fillet feature, angle value change
533   std::shared_ptr<Events_Message> aMsg;
534   if (theValue) {
535     aMsg = std::shared_ptr<Events_Message>(
536         new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)));
537   }
538   else {
539     // the viewer update should be unblocked
540     aMsg = std::shared_ptr<Events_Message>(
541         new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)));
542   }
543   Events_Loop::loop()->send(aMsg);
544 }
545
546 } // namespace ModuleBase_Tools
547
548