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