Salome HOME
Bos #24048: EDF 23096 - Warning too long
[modules/shaper.git] / src / ModuleBase / ModuleBase_Tools.cpp
1 // Copyright (C) 2014-2020  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 email : webmaster.salome@opencascade.com
18 //
19
20 #include "ModuleBase_Tools.h"
21
22 #include <ModuleBase_ParamIntSpinBox.h>
23 #include <ModuleBase_ParamSpinBox.h>
24 #include <ModuleBase_WidgetFactory.h>
25 #include <ModuleBase_IWorkshop.h>
26 #include <ModuleBase_IModule.h>
27 #include <ModuleBase_IViewer.h>
28 #include <ModuleBase_IconFactory.h>
29 #include <ModuleBase_ResultPrs.h>
30 #include <ModuleBase_ViewerPrs.h>
31
32 #include <ModelAPI_Attribute.h>
33 #include <ModelAPI_AttributeRefAttr.h>
34 #include <ModelAPI_AttributeReference.h>
35 #include <ModelAPI_AttributeSelection.h>
36 #include <ModelAPI_AttributeSelectionList.h>
37 #include <ModelAPI_AttributeRefList.h>
38 #include <ModelAPI_AttributeRefAttrList.h>
39 #include <ModelAPI_ResultPart.h>
40 #include <ModelAPI_ResultConstruction.h>
41 #include <ModelAPI_AttributeString.h>
42 #include <ModelAPI_Expression.h>
43 #include <ModelAPI_ResultField.h>
44 #include <Events_Loop.h>
45
46 #include <ModelAPI_Data.h>
47 #include <ModelAPI_Result.h>
48 #include <ModelAPI_ResultParameter.h>
49 #include <ModelAPI_Tools.h>
50 #include <ModelAPI_Session.h>
51 #include <ModelAPI_Events.h>
52 #include <ModelAPI_Folder.h>
53
54 #include <ModelGeomAlgo_Point2D.h>
55
56 #include <StdSelect_BRepOwner.hxx>
57 #include <TopoDS_Iterator.hxx>
58 #include <AIS_InteractiveContext.hxx>
59 #include <Prs3d_LineAspect.hxx>
60 #include <Prs3d_PlaneAspect.hxx>
61
62 #include <GeomDataAPI_Point2D.h>
63 #include <Events_InfoMessage.h>
64 #include <GeomAPI_ShapeExplorer.h>
65
66 #include <Config_PropManager.h>
67 #include <Config_Translator.h>
68
69 #include <Prs3d_PointAspect.hxx>
70 #include <Graphic3d_AspectMarker3d.hxx>
71
72 #include <Image_AlienPixMap.hxx>
73
74 #include <QWidget>
75 #include <QLayout>
76 #include <QPainter>
77 #include <QBitmap>
78 #include <QDoubleSpinBox>
79 #include <QGraphicsDropShadowEffect>
80 #include <QColor>
81 #include <QApplication>
82 #include <QMessageBox>
83 #include <QAction>
84 #include <QTextCodec>
85 #include <QWindow>
86 #include <QScreen>
87
88 #include <sstream>
89 #include <string>
90
91 #ifdef WIN32
92 #pragma warning(disable : 4996) // for getenv
93 #endif
94
95 const double tolerance = 1e-7;
96 const double DEFAULT_DEVIATION_COEFFICIENT = 1.e-4;
97
98 //#define DEBUG_ACTIVATE_WINDOW
99 //#define DEBUG_SET_FOCUS
100
101 #ifdef WIN32
102 # define FSEP "\\"
103 #else
104 # define FSEP "/"
105 #endif
106
107 namespace ModuleBase_Tools {
108
109 //******************************************************************
110
111 //******************************************************************
112
113 void adjustMargins(QWidget* theWidget)
114 {
115   if(!theWidget)
116     return;
117   adjustMargins(theWidget->layout());
118 }
119
120 void adjustMargins(QLayout* theLayout)
121 {
122   if(!theLayout)
123     return;
124   theLayout->setContentsMargins(2, 5, 2, 5);
125   theLayout->setSpacing(4);
126 }
127
128 void zeroMargins(QWidget* theWidget)
129 {
130   if(!theWidget)
131     return;
132   zeroMargins(theWidget->layout());
133 }
134
135 void zeroMargins(QLayout* theLayout)
136 {
137   if(!theLayout)
138     return;
139   theLayout->setContentsMargins(0, 0, 0, 0);
140   theLayout->setSpacing(5);
141 }
142
143 void activateWindow(QWidget* theWidget, const QString& theInfo)
144 {
145   if (theWidget) {
146     theWidget->activateWindow();
147     theWidget->raise();
148   }
149
150 #ifdef DEBUG_ACTIVATE_WINDOW
151   qDebug(QString("activateWindow: %1").arg(theInfo).toStdString().c_str());
152 #endif
153 }
154
155 void setFocus(QWidget* theWidget, const QString& theInfo)
156 {
157   activateWindow(theWidget);
158   theWidget->setFocus();
159   // rectangle of focus is not visible on tool button widgets
160   theWidget->update();
161 #ifdef DEBUG_SET_FOCUS
162   qDebug(QString("setFocus: %1").arg(theInfo).toStdString().c_str());
163 #endif
164 }
165
166 void setShadowEffect(QWidget* theWidget, const bool isSetEffect)
167 {
168   if (isSetEffect) {
169     QGraphicsDropShadowEffect* aGlowEffect = new QGraphicsDropShadowEffect();
170     aGlowEffect->setOffset(.0);
171     aGlowEffect->setBlurRadius(10.0);
172     aGlowEffect->setColor(QColor(0, 170, 255)); // Light-blue color, #00AAFF
173     theWidget->setGraphicsEffect(aGlowEffect);
174   }
175   else {
176     QGraphicsEffect* anEffect = theWidget->graphicsEffect();
177     if(anEffect)
178       anEffect->deleteLater();
179     theWidget->setGraphicsEffect(NULL);
180   }
181 }
182
183 QPixmap composite(const QString& theAdditionalIcon, const QString& theIcon)
184 {
185   QImage anIcon = ModuleBase_IconFactory::loadImage(theIcon);
186   QImage anAditional(theAdditionalIcon);
187   return composite(anAditional, anIcon);
188 }
189
190 QPixmap composite(const QImage& theAdditionalIcon, QImage& theIcon)
191 {
192   if (theIcon.isNull())
193     return QPixmap();
194
195   int anAddWidth = theAdditionalIcon.width();
196   int anAddHeight = theAdditionalIcon.height();
197
198   int aWidth = theIcon.width();
199   int aHeight = theIcon.height();
200
201   int aStartWidthPos = aWidth - anAddWidth;
202   int aStartHeightPos = aHeight - anAddHeight;
203
204   for (int i = 0; i < anAddWidth && i + aStartWidthPos < aWidth; i++)
205   {
206     for (int j = 0; j < anAddHeight && j + aStartHeightPos < aHeight; j++)
207     {
208       if (qAlpha(theAdditionalIcon.pixel(i, j)) > 0)
209         theIcon.setPixel(i + aStartWidthPos, j + aStartHeightPos, theAdditionalIcon.pixel(i, j));
210     }
211   }
212   return QPixmap::fromImage(theIcon);
213 }
214
215 QPixmap lighter(const QString& theIcon, const int theLighterValue)
216 {
217   QImage anIcon = ModuleBase_IconFactory::loadImage(theIcon);
218   if (anIcon.isNull())
219     return QPixmap();
220
221   QImage aResult = ModuleBase_IconFactory::loadImage(theIcon);
222   for (int i = 0; i < anIcon.width(); i++)
223   {
224     for (int j = 0; j < anIcon.height(); j++)
225     {
226       QRgb anRgb = anIcon.pixel(i, j);
227       QColor aPixelColor(qRed(anRgb), qGreen(anRgb), qBlue(anRgb),
228                          qAlpha(aResult.pixel(i, j)));
229
230       QColor aLighterColor = aPixelColor.lighter(theLighterValue);
231       aResult.setPixel(i, j, qRgba(aLighterColor.red(), aLighterColor.green(),
232                                     aLighterColor.blue(), aLighterColor.alpha()));
233     }
234   }
235   return QPixmap::fromImage(aResult);
236 }
237
238 void setSpinText(ModuleBase_ParamSpinBox* theSpin, const QString& theText)
239 {
240   if (theSpin->text() == theText)
241     return;
242   // In order to avoid extra text setting because it will
243   // reset cursor position in control
244   bool isBlocked = theSpin->blockSignals(true);
245   theSpin->setText(theText);
246   theSpin->blockSignals(isBlocked);
247 }
248
249 void setSpinValue(QDoubleSpinBox* theSpin, double theValue)
250 {
251   if (fabs(theSpin->value() - theValue) < tolerance)
252     return;
253   bool isBlocked = theSpin->blockSignals(true);
254   theSpin->setValue(theValue);
255   theSpin->blockSignals(isBlocked);
256 }
257
258 void setSpinValue(ModuleBase_ParamSpinBox* theSpin, double theValue)
259 {
260   if (!theSpin->text().isEmpty() && fabs(theSpin->value() - theValue) < tolerance)
261     return;
262   bool isBlocked = theSpin->blockSignals(true);
263   theSpin->setValue(theValue);
264   theSpin->blockSignals(isBlocked);
265 }
266
267 void setSpinText(ModuleBase_ParamIntSpinBox* theSpin, const QString& theText)
268 {
269   // In order to avoid extra text setting because it will
270   // reset cursor position in control
271   if (theSpin->text() == theText)
272     return;
273   bool isBlocked = theSpin->blockSignals(true);
274   theSpin->setText(theText);
275   theSpin->blockSignals(isBlocked);
276 }
277
278 void setSpinValue(ModuleBase_ParamIntSpinBox* theSpin, int theValue)
279 {
280   if (theSpin->value() == theValue)
281     return;
282   bool isBlocked = theSpin->blockSignals(true);
283   theSpin->setValue(theValue);
284   theSpin->blockSignals(isBlocked);
285 }
286
287 QAction* createAction(const QIcon& theIcon, const QString& theText,
288                       QObject* theParent, const QObject* theReceiver,
289                       const char* theMember, const QString& theToolTip,
290                       const QString& theStatusTip)
291 {
292   QAction* anAction = new QAction(theIcon, theText, theParent);
293   anAction->setToolTip(theToolTip.isEmpty() ? theText : theToolTip);
294   anAction->setStatusTip(!theStatusTip.isEmpty() ? theStatusTip :
295                                                    (!theToolTip.isEmpty() ? theToolTip : theText));
296   if (theReceiver)
297     QObject::connect(anAction, SIGNAL(triggered(bool)), theReceiver, theMember);
298
299   return anAction;
300 }
301
302 #ifdef _DEBUG
303 QString objectName(const ObjectPtr& theObj)
304 {
305   if (!theObj.get())
306     return "";
307
308   return QString::fromStdWString(theObj->data()->name());
309 }
310
311 QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo)
312 {
313   QString aFeatureStr = "feature";
314   if (!theObj.get())
315     return aFeatureStr;
316
317   std::ostringstream aPtrStr;
318   aPtrStr << "[" << theObj.get() << "]";
319
320   ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
321   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
322   if(aRes.get()) {
323     aFeatureStr.append(QString("(result%1)").arg(aPtrStr.str().c_str()).toStdString() .c_str());
324     if (aRes->isDisabled())
325       aFeatureStr.append("[disabled]");
326     if (aRes->isConcealed())
327       aFeatureStr.append("[concealed]");
328     if (ModelAPI_Tools::hasSubResults(aRes))
329       aFeatureStr.append("[hasSubResults]");
330
331     aFeature = ModelAPI_Feature::feature(aRes);
332   }
333   else
334     aFeatureStr.append(aPtrStr.str().c_str());
335
336   if (aFeature.get()) {
337     aFeatureStr.append(QString(": %1").arg(aFeature->getKind().c_str()).toStdString().c_str());
338     if (aFeature->data()->isValid()) {
339       aFeatureStr.append(QString(", name=%1")
340         .arg(QString::fromStdWString(theObj->data()->name())).toStdString().c_str());
341     }
342     if (isUseAttributesInfo) {
343       std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes;
344       std::string aPointsInfo = ModelGeomAlgo_Point2D::getPontAttributesInfo(aFeature,
345                                                                           anAttributes).c_str();
346       if (!aPointsInfo.empty())
347         aFeatureStr.append(QString(", attributes: %1")
348           .arg(aPointsInfo.c_str()).toStdString().c_str());
349     }
350   }
351
352   return aFeatureStr;
353 }
354 #endif
355
356 typedef QMap<QString, int> ShapeTypes;
357 static ShapeTypes myShapeTypes;
358
359 int shapeType(const QString& theType)
360 {
361   if (myShapeTypes.count() == 0) {
362     myShapeTypes["compound"]   = TopAbs_COMPOUND;
363     myShapeTypes["compounds"]  = TopAbs_COMPOUND;
364     myShapeTypes["compsolid"]  = TopAbs_COMPSOLID;
365     myShapeTypes["compsolids"] = TopAbs_COMPSOLID;
366     myShapeTypes["solid"]      = TopAbs_SOLID;
367     myShapeTypes["solids"]     = TopAbs_SOLID;
368     myShapeTypes["shell"]      = TopAbs_SHELL;
369     myShapeTypes["shells"]     = TopAbs_SHELL;
370     myShapeTypes["face"]       = TopAbs_FACE;
371     myShapeTypes["faces"]      = TopAbs_FACE;
372     myShapeTypes["wire"]       = TopAbs_WIRE;
373     myShapeTypes["wires"]      = TopAbs_WIRE;
374     myShapeTypes["edge"]       = TopAbs_EDGE;
375     myShapeTypes["edges"]      = TopAbs_EDGE;
376     myShapeTypes["vertex"]     = TopAbs_VERTEX;
377     myShapeTypes["vertices"]   = TopAbs_VERTEX;
378     myShapeTypes["object"]     = ModuleBase_ResultPrs::Sel_Result;
379     myShapeTypes["objects"]    = ModuleBase_ResultPrs::Sel_Result;
380   }
381   QString aType = theType.toLower();
382   if(myShapeTypes.contains(aType))
383     return myShapeTypes[aType];
384   Events_InfoMessage("ModuleBase_Tools", "Shape type defined in XML is not implemented!").send();
385   return TopAbs_SHAPE;
386 }
387
388 void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature,
389                   bool& hasParameter, bool& hasCompositeOwner, bool& hasResultInHistory,
390                   bool& hasFolder)
391 {
392   hasResult = false;
393   hasFeature = false;
394   hasParameter = false;
395   hasCompositeOwner = false;
396   hasResultInHistory = false;
397   hasFolder = false;
398   foreach(ObjectPtr aObj, theObjects) {
399     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
400     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
401     FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(aObj);
402     ResultParameterPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aResult);
403     FieldStepPtr aStep = std::dynamic_pointer_cast<ModelAPI_ResultField::ModelAPI_FieldStep>(aObj);
404
405     hasResult |= ((aResult.get() != NULL) || (aStep.get() != NULL));
406     hasFeature |= (aFeature.get() != NULL);
407     hasFolder |= (aFolder.get() != NULL);
408     hasParameter |= (aConstruction.get() != NULL);
409     if (hasFeature)
410       hasCompositeOwner |= (ModelAPI_Tools::compositeOwner(aFeature) != NULL);
411     else if (aResult.get())
412       hasCompositeOwner |= (ModelAPI_Tools::bodyOwner(aResult) != NULL);
413
414     if (!hasResultInHistory && aResult.get()) {
415       aFeature = ModelAPI_Feature::feature(aResult);
416       hasResultInHistory = aFeature.get() && aFeature->isInHistory();
417     }
418
419     if (hasFeature && hasResult  && hasParameter && hasCompositeOwner)
420       break;
421   }
422 }
423
424 /*bool setDefaultDeviationCoefficient(std::shared_ptr<GeomAPI_Shape> theGeomShape)
425 {
426   if (!theGeomShape.get())
427     return false;
428   // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
429   // correction of deviation for them should not influence to the application performance
430   GeomAPI_ShapeExplorer anExp(theGeomShape, GeomAPI_Shape::FACE);
431   bool anEmpty = anExp.empty();
432   return !anExp.more();
433 }*/
434
435 /*void setDefaultDeviationCoefficient(const std::shared_ptr<ModelAPI_Result>& theResult,
436                                     const Handle(Prs3d_Drawer)& theDrawer)
437 {
438   if (!theResult.get())
439     return;
440   bool aUseDeviation = false;
441
442   std::string aResultGroup = theResult->groupName();
443   if (aResultGroup == ModelAPI_ResultConstruction::group())
444     aUseDeviation = true;
445   else if (aResultGroup == ModelAPI_ResultBody::group()) {
446     GeomShapePtr aGeomShape = theResult->shape();
447     if (aGeomShape.get())
448       aUseDeviation = setDefaultDeviationCoefficient(aGeomShape);
449   }
450   if (aUseDeviation)
451     theDrawer->SetDeviationCoefficient(DEFAULT_DEVIATION_COEFFICIENT);
452 }
453 */
454 void setDefaultDeviationCoefficient(const TopoDS_Shape& theShape,
455                                     const Handle(Prs3d_Drawer)& theDrawer)
456 {
457   if (theShape.IsNull())
458     return;
459   if (theDrawer.IsNull())
460     return;
461
462   std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape());
463   aGeomShape->setImpl(new TopoDS_Shape(theShape));
464
465   // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
466   // correction of deviation for them should not influence to the application performance
467   GeomAPI_ShapeExplorer anExp(aGeomShape, GeomAPI_Shape::FACE);
468   bool isConstruction = !anExp.more();
469
470   double aDeflection;
471   if (isConstruction)
472     aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
473   else
474     aDeflection = Config_PropManager::real("Visualization", "body_deflection");
475
476   theDrawer->SetDeviationCoefficient(aDeflection);
477 }
478
479 Quantity_Color color(const std::string& theSection,
480                      const std::string& theName)
481 {
482   std::vector<int> aColor = Config_PropManager::color(theSection, theName);
483   return Quantity_Color(aColor[0] / 255., aColor[1] / 255., aColor[2] / 255., Quantity_TOC_RGB);
484 }
485
486 ObjectPtr getObject(const AttributePtr& theAttribute)
487 {
488   ObjectPtr anObject;
489   std::string anAttrType = theAttribute->attributeType();
490   if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
491     AttributeRefAttrPtr anAttr =
492       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
493     if (anAttr != NULL && anAttr->isObject())
494       anObject = anAttr->object();
495   }
496   if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
497     AttributeSelectionPtr anAttr =
498       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
499     if (anAttr != NULL)
500       anObject = anAttr->context();
501   }
502   if (anAttrType == ModelAPI_AttributeReference::typeId()) {
503     AttributeReferencePtr anAttr =
504       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
505     if (anAttr.get() != NULL)
506       anObject = anAttr->value();
507   }
508   return anObject;
509 }
510
511 TopAbs_ShapeEnum getCompoundSubType(const TopoDS_Shape& theShape)
512 {
513   TopAbs_ShapeEnum aShapeType = theShape.ShapeType();
514
515   // for compounds check sub-shapes: it may be compound of needed type:
516   // Booleans may produce compounds of Solids
517   if (aShapeType == TopAbs_COMPOUND) {
518     for(TopoDS_Iterator aSubs(theShape); aSubs.More(); aSubs.Next()) {
519       if (!aSubs.Value().IsNull()) {
520         TopAbs_ShapeEnum aSubType = aSubs.Value().ShapeType();
521         if (aSubType == TopAbs_COMPOUND) { // compound of compound(s)
522           aShapeType = TopAbs_COMPOUND;
523           break;
524         }
525         if (aShapeType == TopAbs_COMPOUND) {
526           aShapeType = aSubType;
527         } else if (aShapeType != aSubType) { // compound of shapes of different types
528           aShapeType = TopAbs_COMPOUND;
529           break;
530         }
531       }
532     }
533   }
534   return aShapeType;
535 }
536
537 TopoDS_Shape getSelectedShape(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs)
538 {
539   if (thePrs->shape().get())
540     return thePrs->shape()->impl<TopoDS_Shape>();
541
542   Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(thePrs->owner());
543   if (!anOwner.IsNull())
544     return anOwner->Shape();
545
546   return TopoDS_Shape();
547 }
548
549 void getParameters(QStringList& theParameters)
550 {
551   theParameters.clear();
552
553   SessionPtr aSession = ModelAPI_Session::get();
554   std::list<DocumentPtr> aDocList;
555   DocumentPtr anActiveDocument = aSession->activeDocument();
556   DocumentPtr aRootDocument = aSession->moduleDocument();
557   aDocList.push_back(anActiveDocument);
558   if (anActiveDocument != aRootDocument) {
559     aDocList.push_back(aRootDocument);
560   }
561   std::string aGroupId = ModelAPI_ResultParameter::group();
562   for(std::list<DocumentPtr>::const_iterator it = aDocList.begin(); it != aDocList.end(); ++it) {
563     DocumentPtr aDocument = *it;
564     int aSize = aDocument->size(aGroupId);
565     for (int i = 0; i < aSize; i++) {
566       ObjectPtr anObject = aDocument->object(aGroupId, i);
567       std::wstring aParameterName = anObject->data()->name();
568       theParameters.append(QString::fromStdWString(aParameterName));
569     }
570   }
571 }
572
573 std::string findGreedAttribute(ModuleBase_IWorkshop* theWorkshop,
574                                const FeaturePtr& theFeature)
575 {
576   std::string anAttributeId;
577
578   std::string aXmlCfg, aDescription;
579   theWorkshop->module()->getXMLRepresentation(theFeature->getKind(), aXmlCfg, aDescription);
580
581   ModuleBase_WidgetFactory aFactory(aXmlCfg, theWorkshop);
582   std::string anAttributeTitle;
583   aFactory.getGreedAttribute(anAttributeId);
584
585   return anAttributeId;
586 }
587
588 bool hasObject(const AttributePtr& theAttribute, const ObjectPtr& theObject,
589                const std::shared_ptr<GeomAPI_Shape>& theShape,
590                ModuleBase_IWorkshop* theWorkshop,
591                const bool theTemporarily)
592 {
593   bool aHasObject = false;
594   if (!theAttribute.get())
595     return aHasObject;
596
597   std::string aType = theAttribute->attributeType();
598   if (aType == ModelAPI_AttributeReference::typeId()) {
599     AttributeReferencePtr aRef =
600       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
601     ObjectPtr aObject = aRef->value();
602     aHasObject = aObject && aObject->isSame(theObject);
603     //if (!(aObject && aObject->isSame(theObject))) {
604     //  aRef->setValue(theObject);
605     //}
606   } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
607     AttributeRefAttrPtr aRefAttr =
608       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
609
610     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
611     if (anAttribute.get()) {
612       //aRefAttr->setAttr(anAttribute);
613     }
614     else {
615       ObjectPtr aObject = aRefAttr->object();
616       aHasObject = aObject && aObject->isSame(theObject);
617       //if (!(aObject && aObject->isSame(theObject))) {
618       //  aRefAttr->setObject(theObject);
619       //}
620     }
621   } else if (aType == ModelAPI_AttributeSelection::typeId()) {
622     /*AttributeSelectionPtr aSelectAttr =
623                              std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
624     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
625     if (aSelectAttr.get() != NULL) {
626       aSelectAttr->setValue(aResult, theShape, theTemporarily);
627     }*/
628   }
629   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
630     AttributeSelectionListPtr aSelectionListAttr =
631                          std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
632     aHasObject = aSelectionListAttr->isInList(theObject, theShape, theTemporarily);
633   }
634   else if (aType == ModelAPI_AttributeRefList::typeId()) {
635     AttributeRefListPtr aRefListAttr =
636       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
637     aHasObject = aRefListAttr->isInList(theObject);
638     //if (!theCheckIfAttributeHasObject || !aRefListAttr->isInList(theObject))
639     //  aRefListAttr->append(theObject);
640   }
641   else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
642     AttributeRefAttrListPtr aRefAttrListAttr =
643       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(theAttribute);
644     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
645
646     if (anAttribute.get()) {
647       aHasObject = aRefAttrListAttr->isInList(anAttribute);
648       //if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(anAttribute))
649       //  aRefAttrListAttr->append(anAttribute);
650     }
651     else {
652       aHasObject = aRefAttrListAttr->isInList(theObject);
653       //if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(theObject))
654       //  aRefAttrListAttr->append(theObject);
655     }
656   }
657   return aHasObject;
658 }
659
660 bool setObject(const AttributePtr& theAttribute, const ObjectPtr& theObject,
661                const GeomShapePtr& theShape, ModuleBase_IWorkshop* theWorkshop,
662                const bool theTemporarily, const bool theCheckIfAttributeHasObject)
663 {
664   if (!theAttribute.get())
665     return false;
666
667   bool isDone = true;
668   std::string aType = theAttribute->attributeType();
669   if (aType == ModelAPI_AttributeReference::typeId()) {
670     AttributeReferencePtr aRef =
671       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
672     ObjectPtr aObject = aRef->value();
673     if (!(aObject && aObject->isSame(theObject))) {
674       aRef->setValue(theObject);
675     }
676   } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
677     AttributeRefAttrPtr aRefAttr =
678       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
679
680     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
681     if (anAttribute.get())
682       aRefAttr->setAttr(anAttribute);
683     else {
684       ObjectPtr aObject = aRefAttr->object();
685       if (!(aObject && aObject->isSame(theObject))) {
686         aRefAttr->setObject(theObject);
687       }
688     }
689   } else if (aType == ModelAPI_AttributeSelection::typeId()) {
690     AttributeSelectionPtr aSelectAttr =
691                              std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
692     if (aSelectAttr.get() != NULL) {
693       aSelectAttr->setValue(theObject, theShape, theTemporarily);
694     }
695   }
696   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
697     AttributeSelectionListPtr aSelectionListAttr =
698                          std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
699     if (!theCheckIfAttributeHasObject ||
700       !aSelectionListAttr->isInList(theObject, theShape, theTemporarily))
701       aSelectionListAttr->append(theObject, theShape, theTemporarily);
702   }
703   else if (aType == ModelAPI_AttributeRefList::typeId()) {
704     AttributeRefListPtr aRefListAttr =
705       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
706     if (!theCheckIfAttributeHasObject || !aRefListAttr->isInList(theObject)) {
707       if (theObject.get())
708         aRefListAttr->append(theObject);
709       else
710         isDone = false;
711     }
712   }
713   else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
714     AttributeRefAttrListPtr aRefAttrListAttr =
715       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(theAttribute);
716     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
717
718     if (anAttribute.get()) {
719       if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(anAttribute))
720         aRefAttrListAttr->append(anAttribute);
721     }
722     else {
723       if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(theObject)) {
724         if (theObject.get())
725           aRefAttrListAttr->append(theObject);
726         else
727           isDone = false;
728       }
729     }
730   }
731   return isDone;
732 }
733
734 GeomShapePtr getShape(const AttributePtr& theAttribute, ModuleBase_IWorkshop* theWorkshop)
735 {
736   GeomShapePtr aShape;
737   if (!theAttribute.get())
738     return aShape;
739
740   std::string aType = theAttribute->attributeType();
741   if (aType == ModelAPI_AttributeReference::typeId()) {
742   } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
743     AttributeRefAttrPtr aRefAttr =
744       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
745     if (aRefAttr.get() && !aRefAttr->isObject()) {
746       AttributePtr anAttribute = aRefAttr->attr();
747       aShape = theWorkshop->module()->findShape(anAttribute);
748     }
749   } else if (aType == ModelAPI_AttributeSelection::typeId()) {
750     AttributeSelectionPtr aSelectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
751                                                                                  (theAttribute);
752     aShape = aSelectAttr->value();
753   }
754   else // Geom2D point processing
755     aShape = theWorkshop->module()->findShape(theAttribute);
756   return aShape;
757 }
758
759 void flushUpdated(ObjectPtr theObject)
760 {
761   blockUpdateViewer(true);
762
763   // Fix the problem of not previewed results of constraints applied. Flush Create/Delete
764   // (for the sketch result) to start processing of the sketch in the solver.
765   // TODO: these flushes should be moved in a separate method provided by Model
766   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
767   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES));
768   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
769   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_UPDATE_SELECTION));
770   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
771
772   blockUpdateViewer(false);
773 }
774
775 void blockUpdateViewer(const bool theValue)
776 {
777   // the viewer update should be blocked in order to avoid the temporary feature content
778   // when the solver processes the feature, the redisplay message can be flushed
779   // what caused the display in the viewer preliminary states of object
780   // e.g. fillet feature, angle value change
781   std::shared_ptr<Events_Message> aMsg;
782   if (theValue) {
783     aMsg = std::shared_ptr<Events_Message>(
784         new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)));
785   }
786   else {
787     // the viewer update should be unblocked
788     aMsg = std::shared_ptr<Events_Message>(
789         new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)));
790   }
791   Events_Loop::loop()->send(aMsg);
792 }
793
794 QString wrapTextByWords(const QString& theValue, QWidget* theWidget,
795                                           int theMaxLineInPixels)
796 {
797   static QFontMetrics tfm(theWidget ? theWidget->font() : QApplication::font());
798   static qreal phi = 2.618;
799
800   QRect aBounds = tfm.boundingRect(theValue);
801   if(aBounds.width() <= theMaxLineInPixels)
802     return theValue;
803
804   qreal s = aBounds.width() * aBounds.height();
805   qreal aGoldWidth = sqrt(s*phi);
806
807   QStringList aWords = theValue.split(" ", QString::SkipEmptyParts);
808   QStringList aLines;
809   int n = aWords.count();
810   QString aLine;
811   for (int i = 0; i < n; i++) {
812     QString aLineExt =  i == 0 ? aWords[i] : aLine + " " + aWords[i];
813     qreal anWidthNonExt = tfm.boundingRect(aLine).width();
814     qreal anWidthExt = tfm.boundingRect(aLineExt).width();
815     qreal aDeltaNonExt = fabs(anWidthNonExt-aGoldWidth);
816     qreal aDeltaExt    = fabs(anWidthExt-aGoldWidth);
817     if(aDeltaNonExt < aDeltaExt) {
818       // new line
819       aLines.append(aLine);
820       aLine = aWords[i];
821     }
822     else
823       aLine = aLineExt;
824   }
825
826   if(!aLine.isEmpty())
827     aLines.append(aLine);
828
829   QString aResult = aLines.join("\n");
830   return aResult;
831 }
832
833 //**************************************************************
834 QLocale doubleLocale()
835 {
836   // VSR 01/07/2010: Disable thousands separator for spin box
837   // (to avoid inconsistency of double-2-string and string-2-double conversion)
838   QLocale aLocale;
839   aLocale.setNumberOptions(aLocale.numberOptions() |
840                            QLocale::OmitGroupSeparator |
841                            QLocale::RejectGroupSeparator);
842   return aLocale;
843 }
844
845 //**************************************************************
846 void refsToFeatureInFeatureDocument(const ObjectPtr& theObject,
847                                     std::set<FeaturePtr>& theRefFeatures)
848 {
849   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
850   if (aFeature.get()) {
851     DocumentPtr aFeatureDoc = aFeature->document();
852     // 1. find references in the current document
853     aFeatureDoc->refsToFeature(aFeature, theRefFeatures, false);
854   }
855 }
856
857
858 //**************************************************************
859 /*bool isSubOfComposite(const ObjectPtr& theObject)
860 {
861   bool isSub = false;
862   std::set<FeaturePtr> aRefFeatures;
863   refsToFeatureInFeatureDocument(theObject, aRefFeatures);
864   std::set<FeaturePtr>::const_iterator anIt = aRefFeatures.begin(),
865                                        aLast = aRefFeatures.end();
866   for (; anIt != aLast && !isSub; anIt++) {
867     isSub = isSubOfComposite(theObject, *anIt);
868   }
869   return isSub;
870 }*/
871
872 //**************************************************************
873 /*bool isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature)
874 {
875   bool isSub = false;
876   CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
877   if (aComposite.get()) {
878     isSub = aComposite->isSub(theObject);
879     // the recursive is possible, the parameters are sketch circle and extrusion cut. They are
880     // separated by composite sketch feature
881     if (!isSub) {
882       int aNbSubs = aComposite->numberOfSubs();
883       for (int aSub = 0; aSub < aNbSubs && !isSub; aSub++) {
884         isSub = isSubOfComposite(theObject, aComposite->subFeature(aSub));
885       }
886     }
887   }
888   return isSub;
889 }*/
890
891 //**************************************************************
892 ResultPtr firstResult(const ObjectPtr& theObject)
893 {
894   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
895   if (!aResult.get()) {
896     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
897     if (aFeature.get())
898       aResult = aFeature->firstResult();
899   }
900   return aResult;
901 }
902
903 //**************************************************************
904 bool isFeatureOfResult(const FeaturePtr& theFeature, const std::string& theGroupOfResult)
905 {
906   bool isResult = false;
907
908   if (!theFeature->data()->isValid())
909     return isResult;
910
911   ResultPtr aFirstResult = theFeature->firstResult();
912   if (!aFirstResult.get())
913     return isResult;
914
915   return aFirstResult->groupName() == theGroupOfResult;
916 }
917
918 //**************************************************************
919 bool hasModuleDocumentFeature(const std::set<FeaturePtr>& theFeatures)
920 {
921   bool aFoundModuleDocumentObject = false;
922   DocumentPtr aModuleDoc = ModelAPI_Session::get()->moduleDocument();
923
924   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(), aLast = theFeatures.end();
925   for (; anIt != aLast && !aFoundModuleDocumentObject; anIt++) {
926     FeaturePtr aFeature = *anIt;
927     ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature);
928     if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group())
929       continue;
930     aFoundModuleDocumentObject = aFeature->document() == aModuleDoc;
931   }
932
933   return aFoundModuleDocumentObject;
934 }
935
936 //**************************************************************
937 bool askToDelete(const std::set<FeaturePtr> theFeatures,
938                  const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
939                  QWidget* theParent,
940                  std::set<FeaturePtr>& theReferencesToDelete,
941                  const std::string& thePrefixInfo)
942 {
943   QString aNotActivatedDocWrn;
944   std::wstring aNotActivatedNames;
945   if (!ModelAPI_Tools::allDocumentsActivated(aNotActivatedNames)) {
946     if (ModuleBase_Tools::hasModuleDocumentFeature(theFeatures))
947       aNotActivatedDocWrn =
948         QObject::tr("Selected objects can be used in Part documents which are not loaded: %1.\n")
949                             .arg(QString::fromStdWString(aNotActivatedNames));
950   }
951
952   std::set<FeaturePtr> aFeaturesRefsTo;
953   std::set<FeaturePtr> aFeaturesRefsToParameter;
954   std::set<FeaturePtr> aParameterFeatures;
955   QStringList aPartFeatureNames;
956   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),
957                                        aLast = theFeatures.end();
958   // separate features to references to parameter features and references to others
959   for (; anIt != aLast; anIt++) {
960     FeaturePtr aFeature = *anIt;
961     if (theReferences.find(aFeature) == theReferences.end())
962       continue;
963
964     if (isFeatureOfResult(aFeature, ModelAPI_ResultPart::group()))
965       aPartFeatureNames.append(QString::fromStdWString(aFeature->name()));
966
967     std::set<FeaturePtr> aRefFeatures;
968     std::set<FeaturePtr> aRefList = theReferences.at(aFeature);
969     std::set<FeaturePtr>::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end();
970     for (; aRefIt != aRefLast; aRefIt++) {
971       FeaturePtr aRefFeature = *aRefIt;
972       if (theFeatures.find(aRefFeature) == theFeatures.end() && // it is not selected
973           aRefFeatures.find(aRefFeature) == aRefFeatures.end()) // it is not added
974         aRefFeatures.insert(aRefFeature);
975     }
976
977     if (isFeatureOfResult(aFeature, ModelAPI_ResultParameter::group())) {
978       aFeaturesRefsToParameter.insert(aRefFeatures.begin(), aRefFeatures.end());
979       aParameterFeatures.insert(aFeature);
980     }
981     else {
982       theReferencesToDelete.insert(aRefFeatures.begin(), aRefFeatures.end());
983     }
984   }
985
986   std::set<FeaturePtr> aFeaturesRefsToParameterOnly;
987   anIt = aFeaturesRefsToParameter.begin();
988   aLast = aFeaturesRefsToParameter.end();
989   // separate features to references to parameter features and references to others
990   QStringList aParamFeatureNames;
991   for (; anIt != aLast; anIt++) {
992     FeaturePtr aFeature = *anIt;
993     if (theReferencesToDelete.find(aFeature) == theReferencesToDelete.end()) {
994       aFeaturesRefsToParameterOnly.insert(aFeature);
995       aParamFeatureNames.append(QString::fromStdWString(aFeature->name()));
996     }
997   }
998   aParamFeatureNames.sort();
999   QStringList anOtherFeatureNames;
1000   anIt = theReferencesToDelete.begin();
1001   aLast = theReferencesToDelete.end();
1002   for (; anIt != aLast; anIt++) {
1003     FeaturePtr aFeature = *anIt;
1004     if (aFeature->getKind() == "RemoveResults")
1005       continue; // skip the remove results feature mentioning: result will be removed anyway
1006     if (isFeatureOfResult(aFeature, ModelAPI_ResultPart::group()))
1007       aPartFeatureNames.append(QString::fromStdWString(aFeature->name()));
1008     else
1009       anOtherFeatureNames.append(QString::fromStdWString(aFeature->name()));
1010   }
1011   aPartFeatureNames.sort();
1012   anOtherFeatureNames.sort();
1013
1014   QMessageBox aMessageBox(theParent);
1015   aMessageBox.setWindowTitle(QObject::tr("Delete features"));
1016   aMessageBox.setIcon(QMessageBox::Warning);
1017   aMessageBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1018   aMessageBox.setDefaultButton(QMessageBox::No);
1019
1020   QString aText, aDetailedText;
1021   if (!thePrefixInfo.empty())
1022     aText = thePrefixInfo.c_str();
1023   QString aSep = ", ";
1024   if (!aPartFeatureNames.empty()) {
1025     aText += QString(QObject::tr("The following parts will be deleted: %1.\n"))
1026              .arg(aPartFeatureNames.join(aSep));
1027   }
1028   if (!aNotActivatedDocWrn.isEmpty())
1029     aText += aNotActivatedDocWrn;
1030   if (!anOtherFeatureNames.empty()) {
1031     const char* aMsg = "The selected features are used in some\n"
1032                        "other features, which will also be deleted.\n";
1033     const char* aMsgDetails = "The selected features are used"
1034                               " in the following features: %1.\n";
1035     aText += QString(QObject::tr(aMsg));
1036     aDetailedText += QString(QObject::tr(aMsgDetails))
1037                      .arg(anOtherFeatureNames.join(aSep));
1038   }
1039   if (!aParamFeatureNames.empty()) {
1040     const char* aMsg = "The selected parameters are used directly or through\n"
1041                        "a sequence of dependencies in some features.\n"
1042                        "These features will be deleted.\n"
1043                        "Or parameters could be replaced by their values.\n";
1044     const char* aMsgDetails = "Parameters are used in the following features: %1.\n";
1045     aText += QString(QObject::tr(aMsg));
1046     aDetailedText += QString(QObject::tr(aMsgDetails))
1047                      .arg(aParamFeatureNames.join(aSep));
1048 #ifdef _DEBUG
1049     QPushButton *aReplaceButton =
1050 #endif
1051       aMessageBox.addButton(QObject::tr("Replace"), QMessageBox::ActionRole);
1052   }
1053
1054   if (!aText.isEmpty()) {
1055     aMessageBox.setText(aText);
1056     aMessageBox.setInformativeText(QObject::tr("Would you like to continue?"));
1057     if (!aDetailedText.isEmpty())
1058       aMessageBox.setDetailedText(aDetailedText);
1059     aMessageBox.exec();
1060     QMessageBox::ButtonRole aButtonRole = aMessageBox.buttonRole(aMessageBox.clickedButton());
1061
1062     if (aButtonRole == QMessageBox::NoRole)
1063       return false;
1064
1065     if (aButtonRole == QMessageBox::ActionRole) {
1066       foreach (FeaturePtr aObj, aParameterFeatures)
1067         ModelAPI_ReplaceParameterMessage::send(aObj, 0);
1068     }
1069     else
1070       theReferencesToDelete.insert(aFeaturesRefsToParameterOnly.begin(),
1071                                    aFeaturesRefsToParameterOnly.end());
1072   }
1073   return true;
1074 }
1075
1076 //**************************************************************
1077 void convertToFeatures(const QObjectPtrList& theObjects, std::set<FeaturePtr>& theFeatures)
1078 {
1079   QObjectPtrList::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
1080   for(; anIt != aLast; anIt++) {
1081     ObjectPtr anObject = *anIt;
1082     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
1083     // for parameter result, use the corresponded reature to be removed
1084     if (!aFeature.get() && anObject->groupName() == ModelAPI_ResultParameter::group()) {
1085       aFeature = ModelAPI_Feature::feature(anObject);
1086     }
1087     if (aFeature.get())
1088       theFeatures.insert(aFeature);
1089   }
1090 }
1091
1092 //**************************************************************
1093 void convertToFolders(const QObjectPtrList& theObjects,
1094                                          std::set<FolderPtr>& theFolders)
1095 {
1096   QObjectPtrList::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
1097   for(; anIt != aLast; anIt++) {
1098     ObjectPtr anObject = *anIt;
1099     FolderPtr aFeature = std::dynamic_pointer_cast<ModelAPI_Folder>(anObject);
1100     if (aFeature.get())
1101       theFolders.insert(aFeature);
1102   }
1103 }
1104
1105
1106 //**************************************************************
1107 QString translate(const Events_InfoMessage& theMessage)
1108 {
1109   QString aMessage;
1110
1111   if (!theMessage.empty()) {
1112     std::string aStr = Config_Translator::translate(theMessage);
1113     if (!aStr.empty()) {
1114       std::string aCodec = Config_Translator::codec(theMessage);
1115       aMessage = QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str());
1116     }
1117   }
1118
1119   return aMessage;
1120 }
1121
1122 QString translate(const std::string& theContext, const std::string& theMessage)
1123 {
1124   QString aMessage;
1125
1126   if (!theMessage.empty()) {
1127     std::string aStr = Config_Translator::translate(theContext, theMessage);
1128     if (!aStr.empty()) {
1129       std::string aCodec = Config_Translator::codec(theContext);
1130       aMessage = QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str());
1131     }
1132   }
1133
1134   return aMessage;
1135 }
1136
1137 void setPointBallHighlighting(AIS_InteractiveObject* theAIS)
1138 {
1139   static Handle(Image_AlienPixMap) aPixMap;
1140   if(aPixMap.IsNull()) {
1141     // Load icon for the presentation
1142     std::string aFile;
1143     char* anEnv = getenv("SHAPER_ROOT_DIR");
1144     if(anEnv) {
1145       aFile = std::string(anEnv) +
1146         FSEP + "share" + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
1147     } else {
1148       anEnv = getenv("CADBUILDER_ROOT_DIR");
1149       if (anEnv)
1150         aFile = std::string(anEnv) + FSEP + "resources";
1151     }
1152
1153     aFile += FSEP;
1154     static const std::string aMarkerName = "marker_dot.png";
1155     aFile += aMarkerName;
1156     aPixMap = new Image_AlienPixMap();
1157     if(!aPixMap->Load(aFile.c_str())) {
1158       // The icon for constraint is not found
1159       static const std::string aMsg =
1160         "Error: Point market not found by path: \"" + aFile + "\". Falling back.";
1161       //Events_InfoMessage("ModuleBase_Tools::setPointBallHighlighting", aMsg).send();
1162     }
1163   }
1164
1165   Handle(Graphic3d_AspectMarker3d) anAspect;
1166   Handle(Prs3d_Drawer) aDrawer = theAIS->DynamicHilightAttributes();
1167   if (aDrawer.IsNull()) {
1168     if (ModuleBase_IViewer::DefaultHighlightDrawer.IsNull())
1169       return;
1170     aDrawer = new Prs3d_Drawer(*ModuleBase_IViewer::DefaultHighlightDrawer);
1171     if (!aDrawer->HasOwnPointAspect()) {
1172       aDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_BALL, Quantity_NOC_BLACK, 2.0));
1173     }
1174   }
1175   if(aDrawer->HasOwnPointAspect()) {
1176     Handle(Prs3d_PointAspect) aPntAspect = aDrawer->PointAspect();
1177     if(aPixMap->IsEmpty()) {
1178       anAspect = aPntAspect->Aspect();
1179       anAspect->SetType(Aspect_TOM_BALL);
1180     } else {
1181       if(aPixMap->Format() == Image_PixMap::ImgGray) {
1182         aPixMap->SetFormat (Image_PixMap::ImgAlpha);
1183       } else if(aPixMap->Format() == Image_PixMap::ImgGrayF) {
1184         aPixMap->SetFormat (Image_PixMap::ImgAlphaF);
1185       }
1186       anAspect = new Graphic3d_AspectMarker3d(aPixMap);
1187       aPntAspect->SetAspect(anAspect);
1188     }
1189     aDrawer->SetPointAspect(aPntAspect);
1190           theAIS->SetDynamicHilightAttributes(aDrawer);
1191   }
1192 }
1193
1194 FeaturePtr createParameter(const QString& theText)
1195 {
1196   FeaturePtr aParameter;
1197   QStringList aList = theText.split("=");
1198   if (aList.count() != 2) {
1199     return aParameter;
1200   }
1201   QString aParamName = aList.at(0).trimmed();
1202
1203   if (isNameExist(aParamName, FeaturePtr())) {
1204     return aParameter;
1205   }
1206
1207   if (!ModelAPI_Expression::isVariable(aParamName.toStdString())) {
1208     return aParameter;
1209   }
1210
1211   QString aExpression = aList.at(1).trimmed();
1212   if (aExpression.isEmpty()) {
1213     return aParameter;
1214   }
1215
1216   SessionPtr aMgr = ModelAPI_Session::get();
1217   std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
1218
1219   aParameter = aDoc->addFeature("Parameter", false);
1220   if (aParameter.get()) {
1221     AttributeStringPtr aNameAttr = aParameter->string("variable");
1222     aNameAttr->setValue(aParamName.toStdString());
1223
1224     AttributeStringPtr aExprAttr = aParameter->string("expression");
1225     aExprAttr->setValue(aExpression.toStdString());
1226     aParameter->execute();
1227
1228     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
1229     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
1230   }
1231   return aParameter;
1232 }
1233
1234 void editParameter(FeaturePtr theParam, const QString& theText)
1235 {
1236   QStringList aList = theText.split("=");
1237   QString aParamName = aList.at(0).trimmed();
1238
1239   QString aExpression = aList.at(1).trimmed();
1240   if (aExpression.isEmpty()) {
1241     return;
1242   }
1243
1244   if (isNameExist(aParamName, theParam)) {
1245     return;
1246   }
1247   AttributeStringPtr aNameAttr = theParam->string("variable");
1248   aNameAttr->setValue(aParamName.toStdString());
1249
1250   AttributeStringPtr aExprAttr = theParam->string("expression");
1251   aExprAttr->setValue(aExpression.toStdString());
1252   theParam->execute();
1253
1254   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
1255 }
1256
1257 bool isNameExist(const QString& theName, FeaturePtr theIgnoreParameter)
1258 {
1259   SessionPtr aMgr = ModelAPI_Session::get();
1260   std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
1261   FeaturePtr aParamFeature;
1262   int aNbFeatures = aDoc->numInternalFeatures();
1263   std::wstring aName = theName.toStdWString();
1264   for (int i = 0; i < aNbFeatures; i++) {
1265     aParamFeature = aDoc->internalFeature(i);
1266     if (aParamFeature && aParamFeature->getKind() == "Parameter") {
1267       if ((theIgnoreParameter != aParamFeature) && (aParamFeature->name() == aName))
1268         return true;
1269     }
1270   }
1271   return false;
1272 }
1273
1274 FeaturePtr findParameter(const QString& theName)
1275 {
1276   SessionPtr aMgr = ModelAPI_Session::get();
1277   std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
1278   FeaturePtr aParamFeature;
1279   int aNbFeatures = aDoc->numInternalFeatures();
1280   std::wstring aName = theName.toStdWString();
1281   for (int i = 0; i < aNbFeatures; i++) {
1282     aParamFeature = aDoc->internalFeature(i);
1283     if (aParamFeature && aParamFeature->getKind() == "Parameter") {
1284       if (aParamFeature->name() == aName)
1285         return aParamFeature;
1286     }
1287   }
1288   return FeaturePtr();
1289 }
1290
1291
1292 //********************************************************************
1293 std::wstring generateName(const AttributePtr& theAttribute,
1294   ModuleBase_IWorkshop* theWorkshop)
1295 {
1296   std::wstring aName;
1297   if (theAttribute.get() != NULL) {
1298     FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
1299     if (aFeature.get()) {
1300       std::string aXmlCfg, aDescription;
1301       theWorkshop->module()->getXMLRepresentation(aFeature->getKind(), aXmlCfg, aDescription);
1302
1303       ModuleBase_WidgetFactory aFactory(aXmlCfg, theWorkshop);
1304       std::string anAttributeTitle;
1305       aFactory.getAttributeTitle(theAttribute->id(), anAttributeTitle);
1306
1307       std::wstringstream aStreamName;
1308       aStreamName << theAttribute->owner()->data()->name() << "/" << anAttributeTitle.c_str();
1309       aName = aStreamName.str();
1310     }
1311   }
1312   return aName;
1313 }
1314
1315 bool isSameShape(const TopoDS_Shape& theShape1, const TopoDS_Shape& theShape2)
1316 {
1317   // In case of compound we cannot rely on simple comparison method.
1318   // If the compound is generated by Group feature then this compound is alwais new.
1319   // So, we have to compare content of these compounds
1320   if (theShape1.ShapeType() != theShape2.ShapeType())
1321     return false;
1322
1323   if (theShape1.ShapeType() != TopAbs_COMPOUND)
1324     return theShape1.IsSame(theShape2);
1325
1326   TopoDS_Iterator aIt1(theShape1);
1327   TopoDS_Iterator aIt2(theShape2);
1328
1329   for (; aIt1.More() && aIt2.More(); aIt1.Next(), aIt2.Next()) {
1330     if (!(aIt1.Value()).IsSame(aIt2.Value()))
1331       return false;
1332   }
1333   return true;
1334 }
1335
1336 qreal currentPixelRatio()
1337 {
1338   QWindowList aWnds = qApp->topLevelWindows();
1339   if (aWnds.size() > 0)
1340     return aWnds.first()->devicePixelRatio();
1341   return qApp->primaryScreen()->devicePixelRatio();
1342 }
1343
1344
1345 } // namespace ModuleBase_Tools
1346
1347