Salome HOME
bos #26446 Customize study opening; bos #26447 Customize script execution
[modules/shaper.git] / src / ModuleBase / ModuleBase_Tools.cpp
1 // Copyright (C) 2014-2021  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
58 #ifdef HAVE_SALOME
59 #include <SUIT_Application.h>
60 #include <SUIT_ResourceMgr.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
96 #include <sstream>
97 #include <string>
98
99 #ifdef WIN32
100 #pragma warning(disable : 4996) // for getenv
101 #endif
102
103 const double tolerance = 1e-7;
104 const double DEFAULT_DEVIATION_COEFFICIENT = 1.e-4;
105
106 //#define DEBUG_ACTIVATE_WINDOW
107 //#define DEBUG_SET_FOCUS
108
109 #ifdef WIN32
110 # define FSEP "\\"
111 #else
112 # define FSEP "/"
113 #endif
114
115 namespace ModuleBase_Tools {
116
117 //******************************************************************
118
119   //! Waits for REDISPLAY message and set the Visible flag to the entities
120   //! according to Preferences choice.
121   class ModuleBase_RedisplayListener : public Events_Listener
122   {
123   public:
124     static std::shared_ptr<ModuleBase_RedisplayListener> instance()
125     {
126       static std::shared_ptr<ModuleBase_RedisplayListener>
127           anInstance(new ModuleBase_RedisplayListener);
128       return anInstance;
129     }
130
131     void processEvent(const std::shared_ptr<Events_Message>& theMessage)
132     {
133       if (theMessage->eventID() == Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY))
134       {
135 #if HAVE_SALOME
136         // If the python script is being loaded now, the preferences should be used
137         // to display the required object
138         SUIT_Application * app = SUIT_Session::session()->activeApplication();
139         QVariant aVar = app->property("IsLoadedScript");
140         if (!aVar.isNull() && aVar.toBool()) {
141           DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
142           int aSize = aRootDoc->size(ModelAPI_ResultPart::group());
143           if (aSize > 0) {
144             ObjectPtr anPartObject = aRootDoc->object(ModelAPI_ResultPart::group(), aSize - 1);
145             ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(anPartObject);
146             ModuleBase_Tools::setDisplaying(aPart, true);
147           }
148         }
149 #endif
150       }
151     }
152
153   private:
154     ModuleBase_RedisplayListener()
155     {
156       Events_Loop::loop()->registerListener(this,
157           Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
158     }
159   };
160
161   static std::shared_ptr<ModuleBase_RedisplayListener>
162       RL = ModuleBase_RedisplayListener::instance();
163
164 //******************************************************************
165
166 void adjustMargins(QWidget* theWidget)
167 {
168   if(!theWidget)
169     return;
170   adjustMargins(theWidget->layout());
171 }
172
173 void adjustMargins(QLayout* theLayout)
174 {
175   if(!theLayout)
176     return;
177   theLayout->setContentsMargins(2, 5, 2, 5);
178   theLayout->setSpacing(4);
179 }
180
181 void zeroMargins(QWidget* theWidget)
182 {
183   if(!theWidget)
184     return;
185   zeroMargins(theWidget->layout());
186 }
187
188 void zeroMargins(QLayout* theLayout)
189 {
190   if(!theLayout)
191     return;
192   theLayout->setContentsMargins(0, 0, 0, 0);
193   theLayout->setSpacing(5);
194 }
195
196 void activateWindow(QWidget* theWidget, const QString& theInfo)
197 {
198   if (theWidget) {
199     theWidget->activateWindow();
200     theWidget->raise();
201   }
202
203 #ifdef DEBUG_ACTIVATE_WINDOW
204   qDebug(QString("activateWindow: %1").arg(theInfo).toStdString().c_str());
205 #endif
206 }
207
208 void setFocus(QWidget* theWidget, const QString& theInfo)
209 {
210   activateWindow(theWidget);
211   theWidget->setFocus();
212   // rectangle of focus is not visible on tool button widgets
213   theWidget->update();
214 #ifdef DEBUG_SET_FOCUS
215   qDebug(QString("setFocus: %1").arg(theInfo).toStdString().c_str());
216 #endif
217 }
218
219 void setShadowEffect(QWidget* theWidget, const bool isSetEffect)
220 {
221   if (isSetEffect) {
222     QGraphicsDropShadowEffect* aGlowEffect = new QGraphicsDropShadowEffect();
223     aGlowEffect->setOffset(.0);
224     aGlowEffect->setBlurRadius(10.0);
225     aGlowEffect->setColor(QColor(0, 170, 255)); // Light-blue color, #00AAFF
226     theWidget->setGraphicsEffect(aGlowEffect);
227   }
228   else {
229     QGraphicsEffect* anEffect = theWidget->graphicsEffect();
230     if(anEffect)
231       anEffect->deleteLater();
232     theWidget->setGraphicsEffect(NULL);
233   }
234 }
235
236 QPixmap composite(const QString& theAdditionalIcon, const QString& theIcon)
237 {
238   QImage anIcon = ModuleBase_IconFactory::loadImage(theIcon);
239   QImage anAditional(theAdditionalIcon);
240   return composite(anAditional, anIcon);
241 }
242
243 QPixmap composite(const QImage& theAdditionalIcon, QImage& theIcon)
244 {
245   if (theIcon.isNull())
246     return QPixmap();
247
248   int anAddWidth = theAdditionalIcon.width();
249   int anAddHeight = theAdditionalIcon.height();
250
251   int aWidth = theIcon.width();
252   int aHeight = theIcon.height();
253
254   int aStartWidthPos = aWidth - anAddWidth;
255   int aStartHeightPos = aHeight - anAddHeight;
256
257   for (int i = 0; i < anAddWidth && i + aStartWidthPos < aWidth; i++)
258   {
259     for (int j = 0; j < anAddHeight && j + aStartHeightPos < aHeight; j++)
260     {
261       if (qAlpha(theAdditionalIcon.pixel(i, j)) > 0)
262         theIcon.setPixel(i + aStartWidthPos, j + aStartHeightPos, theAdditionalIcon.pixel(i, j));
263     }
264   }
265   return QPixmap::fromImage(theIcon);
266 }
267
268 QPixmap lighter(const QString& theIcon, const int theLighterValue)
269 {
270   QImage anIcon = ModuleBase_IconFactory::loadImage(theIcon);
271   if (anIcon.isNull())
272     return QPixmap();
273
274   QImage aResult = ModuleBase_IconFactory::loadImage(theIcon);
275   for (int i = 0; i < anIcon.width(); i++)
276   {
277     for (int j = 0; j < anIcon.height(); j++)
278     {
279       QRgb anRgb = anIcon.pixel(i, j);
280       QColor aPixelColor(qRed(anRgb), qGreen(anRgb), qBlue(anRgb),
281                          qAlpha(aResult.pixel(i, j)));
282
283       QColor aLighterColor = aPixelColor.lighter(theLighterValue);
284       aResult.setPixel(i, j, qRgba(aLighterColor.red(), aLighterColor.green(),
285                                     aLighterColor.blue(), aLighterColor.alpha()));
286     }
287   }
288   return QPixmap::fromImage(aResult);
289 }
290
291 void setSpinText(ModuleBase_ParamSpinBox* theSpin, const QString& theText)
292 {
293   if (theSpin->text() == theText)
294     return;
295   // In order to avoid extra text setting because it will
296   // reset cursor position in control
297   bool isBlocked = theSpin->blockSignals(true);
298   theSpin->setText(theText);
299   theSpin->blockSignals(isBlocked);
300 }
301
302 void setSpinValue(QDoubleSpinBox* theSpin, double theValue)
303 {
304   if (fabs(theSpin->value() - theValue) < tolerance)
305     return;
306   bool isBlocked = theSpin->blockSignals(true);
307   theSpin->setValue(theValue);
308   theSpin->blockSignals(isBlocked);
309 }
310
311 void setSpinValue(ModuleBase_ParamSpinBox* theSpin, double theValue)
312 {
313   if (!theSpin->text().isEmpty() && fabs(theSpin->value() - theValue) < tolerance)
314     return;
315   bool isBlocked = theSpin->blockSignals(true);
316   theSpin->setValue(theValue);
317   theSpin->blockSignals(isBlocked);
318 }
319
320 void setSpinText(ModuleBase_ParamIntSpinBox* theSpin, const QString& theText)
321 {
322   // In order to avoid extra text setting because it will
323   // reset cursor position in control
324   if (theSpin->text() == theText)
325     return;
326   bool isBlocked = theSpin->blockSignals(true);
327   theSpin->setText(theText);
328   theSpin->blockSignals(isBlocked);
329 }
330
331 void setSpinValue(ModuleBase_ParamIntSpinBox* theSpin, int theValue)
332 {
333   if (theSpin->value() == theValue)
334     return;
335   bool isBlocked = theSpin->blockSignals(true);
336   theSpin->setValue(theValue);
337   theSpin->blockSignals(isBlocked);
338 }
339
340 QAction* createAction(const QIcon& theIcon, const QString& theText,
341                       QObject* theParent, const QObject* theReceiver,
342                       const char* theMember, const QString& theToolTip,
343                       const QString& theStatusTip)
344 {
345   QAction* anAction = new QAction(theIcon, theText, theParent);
346   anAction->setToolTip(theToolTip.isEmpty() ? theText : theToolTip);
347   anAction->setStatusTip(!theStatusTip.isEmpty() ? theStatusTip :
348                                                    (!theToolTip.isEmpty() ? theToolTip : theText));
349   if (theReceiver)
350     QObject::connect(anAction, SIGNAL(triggered(bool)), theReceiver, theMember);
351
352   return anAction;
353 }
354
355 #ifdef _DEBUG
356 QString objectName(const ObjectPtr& theObj)
357 {
358   if (!theObj.get())
359     return "";
360
361   return QString::fromStdWString(theObj->data()->name());
362 }
363
364 QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo)
365 {
366   QString aFeatureStr = "feature";
367   if (!theObj.get())
368     return aFeatureStr;
369
370   std::ostringstream aPtrStr;
371   aPtrStr << "[" << theObj.get() << "]";
372
373   ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
374   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
375   if(aRes.get()) {
376     aFeatureStr.append(QString("(result%1)").arg(aPtrStr.str().c_str()).toStdString() .c_str());
377     if (aRes->isDisabled())
378       aFeatureStr.append("[disabled]");
379     if (aRes->isConcealed())
380       aFeatureStr.append("[concealed]");
381     if (ModelAPI_Tools::hasSubResults(aRes))
382       aFeatureStr.append("[hasSubResults]");
383
384     aFeature = ModelAPI_Feature::feature(aRes);
385   }
386   else
387     aFeatureStr.append(aPtrStr.str().c_str());
388
389   if (aFeature.get()) {
390     aFeatureStr.append(QString(": %1").arg(aFeature->getKind().c_str()).toStdString().c_str());
391     if (aFeature->data()->isValid()) {
392       aFeatureStr.append(QString(", name=%1")
393         .arg(QString::fromStdWString(theObj->data()->name())).toStdString().c_str());
394     }
395     if (isUseAttributesInfo) {
396       std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes;
397       std::string aPointsInfo = ModelGeomAlgo_Point2D::getPontAttributesInfo(aFeature,
398                                                                           anAttributes).c_str();
399       if (!aPointsInfo.empty())
400         aFeatureStr.append(QString(", attributes: %1")
401           .arg(aPointsInfo.c_str()).toStdString().c_str());
402     }
403   }
404
405   return aFeatureStr;
406 }
407 #endif
408
409 typedef QMap<QString, int> ShapeTypes;
410 static ShapeTypes myShapeTypes;
411
412 int shapeType(const QString& theType)
413 {
414   if (myShapeTypes.count() == 0) {
415     myShapeTypes["compound"]   = TopAbs_COMPOUND;
416     myShapeTypes["compounds"]  = TopAbs_COMPOUND;
417     myShapeTypes["compsolid"]  = TopAbs_COMPSOLID;
418     myShapeTypes["compsolids"] = TopAbs_COMPSOLID;
419     myShapeTypes["solid"]      = TopAbs_SOLID;
420     myShapeTypes["solids"]     = TopAbs_SOLID;
421     myShapeTypes["shell"]      = TopAbs_SHELL;
422     myShapeTypes["shells"]     = TopAbs_SHELL;
423     myShapeTypes["face"]       = TopAbs_FACE;
424     myShapeTypes["faces"]      = TopAbs_FACE;
425     myShapeTypes["wire"]       = TopAbs_WIRE;
426     myShapeTypes["wires"]      = TopAbs_WIRE;
427     myShapeTypes["edge"]       = TopAbs_EDGE;
428     myShapeTypes["edges"]      = TopAbs_EDGE;
429     myShapeTypes["vertex"]     = TopAbs_VERTEX;
430     myShapeTypes["vertices"]   = TopAbs_VERTEX;
431     myShapeTypes["object"]     = ModuleBase_ResultPrs::Sel_Result;
432     myShapeTypes["objects"]    = ModuleBase_ResultPrs::Sel_Result;
433   }
434   QString aType = theType.toLower();
435   if(myShapeTypes.contains(aType))
436     return myShapeTypes[aType];
437   Events_InfoMessage("ModuleBase_Tools", "Shape type defined in XML is not implemented!").send();
438   return TopAbs_SHAPE;
439 }
440
441 void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature,
442                   bool& hasParameter, bool& hasCompositeOwner, bool& hasResultInHistory,
443                   bool& hasFolder)
444 {
445   hasResult = false;
446   hasFeature = false;
447   hasParameter = false;
448   hasCompositeOwner = false;
449   hasResultInHistory = false;
450   hasFolder = false;
451   foreach(ObjectPtr aObj, theObjects) {
452     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
453     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
454     FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(aObj);
455     ResultParameterPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aResult);
456     FieldStepPtr aStep = std::dynamic_pointer_cast<ModelAPI_ResultField::ModelAPI_FieldStep>(aObj);
457
458     hasResult |= ((aResult.get() != NULL) || (aStep.get() != NULL));
459     hasFeature |= (aFeature.get() != NULL);
460     hasFolder |= (aFolder.get() != NULL);
461     hasParameter |= (aConstruction.get() != NULL);
462     if (hasFeature)
463       hasCompositeOwner |= (ModelAPI_Tools::compositeOwner(aFeature) != NULL);
464     else if (aResult.get())
465       hasCompositeOwner |= (ModelAPI_Tools::bodyOwner(aResult) != NULL);
466
467     if (!hasResultInHistory && aResult.get()) {
468       aFeature = ModelAPI_Feature::feature(aResult);
469       hasResultInHistory = aFeature.get() && aFeature->isInHistory();
470     }
471
472     if (hasFeature && hasResult  && hasParameter && hasCompositeOwner)
473       break;
474   }
475 }
476
477 /*bool setDefaultDeviationCoefficient(std::shared_ptr<GeomAPI_Shape> theGeomShape)
478 {
479   if (!theGeomShape.get())
480     return false;
481   // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
482   // correction of deviation for them should not influence to the application performance
483   GeomAPI_ShapeExplorer anExp(theGeomShape, GeomAPI_Shape::FACE);
484   bool anEmpty = anExp.empty();
485   return !anExp.more();
486 }*/
487
488 /*void setDefaultDeviationCoefficient(const std::shared_ptr<ModelAPI_Result>& theResult,
489                                     const Handle(Prs3d_Drawer)& theDrawer)
490 {
491   if (!theResult.get())
492     return;
493   bool aUseDeviation = false;
494
495   std::string aResultGroup = theResult->groupName();
496   if (aResultGroup == ModelAPI_ResultConstruction::group())
497     aUseDeviation = true;
498   else if (aResultGroup == ModelAPI_ResultBody::group()) {
499     GeomShapePtr aGeomShape = theResult->shape();
500     if (aGeomShape.get())
501       aUseDeviation = setDefaultDeviationCoefficient(aGeomShape);
502   }
503   if (aUseDeviation)
504     theDrawer->SetDeviationCoefficient(DEFAULT_DEVIATION_COEFFICIENT);
505 }
506 */
507 void setDefaultDeviationCoefficient(const TopoDS_Shape& theShape,
508                                     const Handle(Prs3d_Drawer)& theDrawer)
509 {
510   if (theShape.IsNull())
511     return;
512   if (theDrawer.IsNull())
513     return;
514
515   std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape());
516   aGeomShape->setImpl(new TopoDS_Shape(theShape));
517
518   // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
519   // correction of deviation for them should not influence to the application performance
520   GeomAPI_ShapeExplorer anExp(aGeomShape, GeomAPI_Shape::FACE);
521   bool isConstruction = !anExp.more();
522
523   double aDeflection;
524   if (isConstruction)
525     aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
526   else
527     aDeflection = Config_PropManager::real("Visualization", "body_deflection");
528
529   theDrawer->SetDeviationCoefficient(aDeflection);
530 }
531
532 Quantity_Color color(const std::string& theSection,
533                      const std::string& theName)
534 {
535   std::vector<int> aColor = Config_PropManager::color(theSection, theName);
536   return Quantity_Color(aColor[0] / 255., aColor[1] / 255., aColor[2] / 255., Quantity_TOC_RGB);
537 }
538
539 ObjectPtr getObject(const AttributePtr& theAttribute)
540 {
541   ObjectPtr anObject;
542   std::string anAttrType = theAttribute->attributeType();
543   if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
544     AttributeRefAttrPtr anAttr =
545       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
546     if (anAttr != NULL && anAttr->isObject())
547       anObject = anAttr->object();
548   }
549   if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
550     AttributeSelectionPtr anAttr =
551       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
552     if (anAttr != NULL)
553       anObject = anAttr->context();
554   }
555   if (anAttrType == ModelAPI_AttributeReference::typeId()) {
556     AttributeReferencePtr anAttr =
557       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
558     if (anAttr.get() != NULL)
559       anObject = anAttr->value();
560   }
561   return anObject;
562 }
563
564 TopAbs_ShapeEnum getCompoundSubType(const TopoDS_Shape& theShape)
565 {
566   TopAbs_ShapeEnum aShapeType = theShape.ShapeType();
567
568   // for compounds check sub-shapes: it may be compound of needed type:
569   // Booleans may produce compounds of Solids
570   if (aShapeType == TopAbs_COMPOUND) {
571     for(TopoDS_Iterator aSubs(theShape); aSubs.More(); aSubs.Next()) {
572       if (!aSubs.Value().IsNull()) {
573         TopAbs_ShapeEnum aSubType = aSubs.Value().ShapeType();
574         if (aSubType == TopAbs_COMPOUND) { // compound of compound(s)
575           aShapeType = TopAbs_COMPOUND;
576           break;
577         }
578         if (aShapeType == TopAbs_COMPOUND) {
579           aShapeType = aSubType;
580         } else if (aShapeType != aSubType) { // compound of shapes of different types
581           aShapeType = TopAbs_COMPOUND;
582           break;
583         }
584       }
585     }
586   }
587   return aShapeType;
588 }
589
590 TopoDS_Shape getSelectedShape(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs)
591 {
592   if (thePrs->shape().get())
593     return thePrs->shape()->impl<TopoDS_Shape>();
594
595   Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(thePrs->owner());
596   if (!anOwner.IsNull())
597     return anOwner->Shape();
598
599   return TopoDS_Shape();
600 }
601
602 void getParameters(QStringList& theParameters)
603 {
604   theParameters.clear();
605
606   SessionPtr aSession = ModelAPI_Session::get();
607   std::list<DocumentPtr> aDocList;
608   DocumentPtr anActiveDocument = aSession->activeDocument();
609   DocumentPtr aRootDocument = aSession->moduleDocument();
610   aDocList.push_back(anActiveDocument);
611   if (anActiveDocument != aRootDocument) {
612     aDocList.push_back(aRootDocument);
613   }
614   std::string aGroupId = ModelAPI_ResultParameter::group();
615   for(std::list<DocumentPtr>::const_iterator it = aDocList.begin(); it != aDocList.end(); ++it) {
616     DocumentPtr aDocument = *it;
617     int aSize = aDocument->size(aGroupId);
618     for (int i = 0; i < aSize; i++) {
619       ObjectPtr anObject = aDocument->object(aGroupId, i);
620       std::wstring aParameterName = anObject->data()->name();
621       theParameters.append(QString::fromStdWString(aParameterName));
622     }
623   }
624 }
625
626 std::string findGreedAttribute(ModuleBase_IWorkshop* theWorkshop,
627                                const FeaturePtr& theFeature)
628 {
629   std::string anAttributeId;
630
631   std::string aXmlCfg, aDescription;
632   theWorkshop->module()->getXMLRepresentation(theFeature->getKind(), aXmlCfg, aDescription);
633
634   ModuleBase_WidgetFactory aFactory(aXmlCfg, theWorkshop);
635   std::string anAttributeTitle;
636   aFactory.getGreedAttribute(anAttributeId);
637
638   return anAttributeId;
639 }
640
641 bool hasObject(const AttributePtr& theAttribute, const ObjectPtr& theObject,
642                const std::shared_ptr<GeomAPI_Shape>& theShape,
643                ModuleBase_IWorkshop* theWorkshop,
644                const bool theTemporarily)
645 {
646   bool aHasObject = false;
647   if (!theAttribute.get())
648     return aHasObject;
649
650   std::string aType = theAttribute->attributeType();
651   if (aType == ModelAPI_AttributeReference::typeId()) {
652     AttributeReferencePtr aRef =
653       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
654     ObjectPtr aObject = aRef->value();
655     aHasObject = aObject && aObject->isSame(theObject);
656     //if (!(aObject && aObject->isSame(theObject))) {
657     //  aRef->setValue(theObject);
658     //}
659   } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
660     AttributeRefAttrPtr aRefAttr =
661       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
662
663     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
664     if (anAttribute.get()) {
665       //aRefAttr->setAttr(anAttribute);
666     }
667     else {
668       ObjectPtr aObject = aRefAttr->object();
669       aHasObject = aObject && aObject->isSame(theObject);
670       //if (!(aObject && aObject->isSame(theObject))) {
671       //  aRefAttr->setObject(theObject);
672       //}
673     }
674   } else if (aType == ModelAPI_AttributeSelection::typeId()) {
675     /*AttributeSelectionPtr aSelectAttr =
676                              std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
677     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
678     if (aSelectAttr.get() != NULL) {
679       aSelectAttr->setValue(aResult, theShape, theTemporarily);
680     }*/
681   }
682   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
683     AttributeSelectionListPtr aSelectionListAttr =
684                          std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
685     aHasObject = aSelectionListAttr->isInList(theObject, theShape, theTemporarily);
686   }
687   else if (aType == ModelAPI_AttributeRefList::typeId()) {
688     AttributeRefListPtr aRefListAttr =
689       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
690     aHasObject = aRefListAttr->isInList(theObject);
691     //if (!theCheckIfAttributeHasObject || !aRefListAttr->isInList(theObject))
692     //  aRefListAttr->append(theObject);
693   }
694   else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
695     AttributeRefAttrListPtr aRefAttrListAttr =
696       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(theAttribute);
697     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
698
699     if (anAttribute.get()) {
700       aHasObject = aRefAttrListAttr->isInList(anAttribute);
701       //if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(anAttribute))
702       //  aRefAttrListAttr->append(anAttribute);
703     }
704     else {
705       aHasObject = aRefAttrListAttr->isInList(theObject);
706       //if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(theObject))
707       //  aRefAttrListAttr->append(theObject);
708     }
709   }
710   return aHasObject;
711 }
712
713 bool setObject(const AttributePtr& theAttribute, const ObjectPtr& theObject,
714                const GeomShapePtr& theShape, ModuleBase_IWorkshop* theWorkshop,
715                const bool theTemporarily, const bool theCheckIfAttributeHasObject)
716 {
717   if (!theAttribute.get())
718     return false;
719
720   bool isDone = true;
721   std::string aType = theAttribute->attributeType();
722   if (aType == ModelAPI_AttributeReference::typeId()) {
723     AttributeReferencePtr aRef =
724       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
725     ObjectPtr aObject = aRef->value();
726     if (!(aObject && aObject->isSame(theObject))) {
727       aRef->setValue(theObject);
728     }
729   } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
730     AttributeRefAttrPtr aRefAttr =
731       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
732
733     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
734     if (anAttribute.get())
735       aRefAttr->setAttr(anAttribute);
736     else {
737       ObjectPtr aObject = aRefAttr->object();
738       if (!(aObject && aObject->isSame(theObject))) {
739         aRefAttr->setObject(theObject);
740       }
741     }
742   } else if (aType == ModelAPI_AttributeSelection::typeId()) {
743     AttributeSelectionPtr aSelectAttr =
744                              std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
745     if (aSelectAttr.get() != NULL) {
746       aSelectAttr->setValue(theObject, theShape, theTemporarily);
747     }
748   }
749   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
750     AttributeSelectionListPtr aSelectionListAttr =
751                          std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
752     if (!theCheckIfAttributeHasObject ||
753       !aSelectionListAttr->isInList(theObject, theShape, theTemporarily))
754       aSelectionListAttr->append(theObject, theShape, theTemporarily);
755   }
756   else if (aType == ModelAPI_AttributeRefList::typeId()) {
757     AttributeRefListPtr aRefListAttr =
758       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
759     if (!theCheckIfAttributeHasObject || !aRefListAttr->isInList(theObject)) {
760       if (theObject.get())
761         aRefListAttr->append(theObject);
762       else
763         isDone = false;
764     }
765   }
766   else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
767     AttributeRefAttrListPtr aRefAttrListAttr =
768       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(theAttribute);
769     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
770
771     if (anAttribute.get()) {
772       if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(anAttribute))
773         aRefAttrListAttr->append(anAttribute);
774     }
775     else {
776       if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(theObject)) {
777         if (theObject.get())
778           aRefAttrListAttr->append(theObject);
779         else
780           isDone = false;
781       }
782     }
783   }
784   return isDone;
785 }
786
787 GeomShapePtr getShape(const AttributePtr& theAttribute, ModuleBase_IWorkshop* theWorkshop)
788 {
789   GeomShapePtr aShape;
790   if (!theAttribute.get())
791     return aShape;
792
793   std::string aType = theAttribute->attributeType();
794   if (aType == ModelAPI_AttributeReference::typeId()) {
795   } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
796     AttributeRefAttrPtr aRefAttr =
797       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
798     if (aRefAttr.get() && !aRefAttr->isObject()) {
799       AttributePtr anAttribute = aRefAttr->attr();
800       aShape = theWorkshop->module()->findShape(anAttribute);
801     }
802   } else if (aType == ModelAPI_AttributeSelection::typeId()) {
803     AttributeSelectionPtr aSelectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
804                                                                                  (theAttribute);
805     aShape = aSelectAttr->value();
806   }
807   else // Geom2D point processing
808     aShape = theWorkshop->module()->findShape(theAttribute);
809   return aShape;
810 }
811
812 void flushUpdated(ObjectPtr theObject)
813 {
814   blockUpdateViewer(true);
815
816   // Fix the problem of not previewed results of constraints applied. Flush Create/Delete
817   // (for the sketch result) to start processing of the sketch in the solver.
818   // TODO: these flushes should be moved in a separate method provided by Model
819   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
820   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES));
821   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
822   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_UPDATE_SELECTION));
823   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
824
825   blockUpdateViewer(false);
826 }
827
828 void blockUpdateViewer(const bool theValue)
829 {
830   // the viewer update should be blocked in order to avoid the temporary feature content
831   // when the solver processes the feature, the redisplay message can be flushed
832   // what caused the display in the viewer preliminary states of object
833   // e.g. fillet feature, angle value change
834   std::shared_ptr<Events_Message> aMsg;
835   if (theValue) {
836     aMsg = std::shared_ptr<Events_Message>(
837         new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)));
838   }
839   else {
840     // the viewer update should be unblocked
841     aMsg = std::shared_ptr<Events_Message>(
842         new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)));
843   }
844   Events_Loop::loop()->send(aMsg);
845 }
846
847 QString wrapTextByWords(const QString& theValue, QWidget* theWidget,
848                                           int theMaxLineInPixels)
849 {
850   static QFontMetrics tfm(theWidget ? theWidget->font() : QApplication::font());
851   static qreal phi = 2.618;
852
853   QRect aBounds = tfm.boundingRect(theValue);
854   if(aBounds.width() <= theMaxLineInPixels)
855     return theValue;
856
857   qreal s = aBounds.width() * aBounds.height();
858   qreal aGoldWidth = sqrt(s*phi);
859
860   QStringList aWords = theValue.split(" ", QString::SkipEmptyParts);
861   QStringList aLines;
862   int n = aWords.count();
863   QString aLine;
864   for (int i = 0; i < n; i++) {
865     QString aLineExt =  i == 0 ? aWords[i] : aLine + " " + aWords[i];
866     qreal anWidthNonExt = tfm.boundingRect(aLine).width();
867     qreal anWidthExt = tfm.boundingRect(aLineExt).width();
868     qreal aDeltaNonExt = fabs(anWidthNonExt-aGoldWidth);
869     qreal aDeltaExt    = fabs(anWidthExt-aGoldWidth);
870     if(aDeltaNonExt < aDeltaExt) {
871       // new line
872       aLines.append(aLine);
873       aLine = aWords[i];
874     }
875     else
876       aLine = aLineExt;
877   }
878
879   if(!aLine.isEmpty())
880     aLines.append(aLine);
881
882   QString aResult = aLines.join("\n");
883   return aResult;
884 }
885
886 //**************************************************************
887 QLocale doubleLocale()
888 {
889   // VSR 01/07/2010: Disable thousands separator for spin box
890   // (to avoid inconsistency of double-2-string and string-2-double conversion)
891   QLocale aLocale;
892   aLocale.setNumberOptions(aLocale.numberOptions() |
893                            QLocale::OmitGroupSeparator |
894                            QLocale::RejectGroupSeparator);
895   return aLocale;
896 }
897
898 //**************************************************************
899 void refsToFeatureInFeatureDocument(const ObjectPtr& theObject,
900                                     std::set<FeaturePtr>& theRefFeatures)
901 {
902   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
903   if (aFeature.get()) {
904     DocumentPtr aFeatureDoc = aFeature->document();
905     // 1. find references in the current document
906     aFeatureDoc->refsToFeature(aFeature, theRefFeatures, false);
907   }
908 }
909
910
911 //**************************************************************
912 /*bool isSubOfComposite(const ObjectPtr& theObject)
913 {
914   bool isSub = false;
915   std::set<FeaturePtr> aRefFeatures;
916   refsToFeatureInFeatureDocument(theObject, aRefFeatures);
917   std::set<FeaturePtr>::const_iterator anIt = aRefFeatures.begin(),
918                                        aLast = aRefFeatures.end();
919   for (; anIt != aLast && !isSub; anIt++) {
920     isSub = isSubOfComposite(theObject, *anIt);
921   }
922   return isSub;
923 }*/
924
925 //**************************************************************
926 /*bool isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature)
927 {
928   bool isSub = false;
929   CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
930   if (aComposite.get()) {
931     isSub = aComposite->isSub(theObject);
932     // the recursive is possible, the parameters are sketch circle and extrusion cut. They are
933     // separated by composite sketch feature
934     if (!isSub) {
935       int aNbSubs = aComposite->numberOfSubs();
936       for (int aSub = 0; aSub < aNbSubs && !isSub; aSub++) {
937         isSub = isSubOfComposite(theObject, aComposite->subFeature(aSub));
938       }
939     }
940   }
941   return isSub;
942 }*/
943
944 //**************************************************************
945 ResultPtr firstResult(const ObjectPtr& theObject)
946 {
947   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
948   if (!aResult.get()) {
949     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
950     if (aFeature.get())
951       aResult = aFeature->firstResult();
952   }
953   return aResult;
954 }
955
956 //**************************************************************
957 bool isFeatureOfResult(const FeaturePtr& theFeature, const std::string& theGroupOfResult)
958 {
959   bool isResult = false;
960
961   if (!theFeature->data()->isValid())
962     return isResult;
963
964   ResultPtr aFirstResult = theFeature->firstResult();
965   if (!aFirstResult.get())
966     return isResult;
967
968   return aFirstResult->groupName() == theGroupOfResult;
969 }
970
971 //**************************************************************
972 bool hasModuleDocumentFeature(const std::set<FeaturePtr>& theFeatures)
973 {
974   bool aFoundModuleDocumentObject = false;
975   DocumentPtr aModuleDoc = ModelAPI_Session::get()->moduleDocument();
976
977   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(), aLast = theFeatures.end();
978   for (; anIt != aLast && !aFoundModuleDocumentObject; anIt++) {
979     FeaturePtr aFeature = *anIt;
980     ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature);
981     if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group())
982       continue;
983     aFoundModuleDocumentObject = aFeature->document() == aModuleDoc;
984   }
985
986   return aFoundModuleDocumentObject;
987 }
988
989 //**************************************************************
990 bool askToDelete(const std::set<FeaturePtr> theFeatures,
991                  const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
992                  QWidget* theParent,
993                  std::set<FeaturePtr>& theReferencesToDelete,
994                  const std::string& thePrefixInfo)
995 {
996   QString aNotActivatedDocWrn;
997   std::wstring aNotActivatedNames;
998   if (!ModelAPI_Tools::allDocumentsActivated(aNotActivatedNames)) {
999     if (ModuleBase_Tools::hasModuleDocumentFeature(theFeatures))
1000       aNotActivatedDocWrn =
1001         QObject::tr("Selected objects can be used in Part documents which are not loaded: %1.\n")
1002                             .arg(QString::fromStdWString(aNotActivatedNames));
1003   }
1004
1005   std::set<FeaturePtr> aFeaturesRefsTo;
1006   std::set<FeaturePtr> aFeaturesRefsToParameter;
1007   std::set<FeaturePtr> aParameterFeatures;
1008   QStringList aPartFeatureNames;
1009   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),
1010                                        aLast = theFeatures.end();
1011   // separate features to references to parameter features and references to others
1012   for (; anIt != aLast; anIt++) {
1013     FeaturePtr aFeature = *anIt;
1014     if (theReferences.find(aFeature) == theReferences.end())
1015       continue;
1016
1017     if (isFeatureOfResult(aFeature, ModelAPI_ResultPart::group()))
1018       aPartFeatureNames.append(QString::fromStdWString(aFeature->name()));
1019
1020     std::set<FeaturePtr> aRefFeatures;
1021     std::set<FeaturePtr> aRefList = theReferences.at(aFeature);
1022     std::set<FeaturePtr>::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end();
1023     for (; aRefIt != aRefLast; aRefIt++) {
1024       FeaturePtr aRefFeature = *aRefIt;
1025       if (theFeatures.find(aRefFeature) == theFeatures.end() && // it is not selected
1026           aRefFeatures.find(aRefFeature) == aRefFeatures.end()) // it is not added
1027         aRefFeatures.insert(aRefFeature);
1028     }
1029
1030     if (isFeatureOfResult(aFeature, ModelAPI_ResultParameter::group())) {
1031       aFeaturesRefsToParameter.insert(aRefFeatures.begin(), aRefFeatures.end());
1032       aParameterFeatures.insert(aFeature);
1033     }
1034     else {
1035       theReferencesToDelete.insert(aRefFeatures.begin(), aRefFeatures.end());
1036     }
1037   }
1038
1039   std::set<FeaturePtr> aFeaturesRefsToParameterOnly;
1040   anIt = aFeaturesRefsToParameter.begin();
1041   aLast = aFeaturesRefsToParameter.end();
1042   // separate features to references to parameter features and references to others
1043   QStringList aParamFeatureNames;
1044   for (; anIt != aLast; anIt++) {
1045     FeaturePtr aFeature = *anIt;
1046     if (theReferencesToDelete.find(aFeature) == theReferencesToDelete.end()) {
1047       aFeaturesRefsToParameterOnly.insert(aFeature);
1048       aParamFeatureNames.append(QString::fromStdWString(aFeature->name()));
1049     }
1050   }
1051   aParamFeatureNames.sort();
1052   QStringList anOtherFeatureNames;
1053   anIt = theReferencesToDelete.begin();
1054   aLast = theReferencesToDelete.end();
1055   for (; anIt != aLast; anIt++) {
1056     FeaturePtr aFeature = *anIt;
1057     if (aFeature->getKind() == "RemoveResults")
1058       continue; // skip the remove results feature mentioning: result will be removed anyway
1059     if (isFeatureOfResult(aFeature, ModelAPI_ResultPart::group()))
1060       aPartFeatureNames.append(QString::fromStdWString(aFeature->name()));
1061     else
1062       anOtherFeatureNames.append(QString::fromStdWString(aFeature->name()));
1063   }
1064   aPartFeatureNames.sort();
1065   anOtherFeatureNames.sort();
1066
1067   QMessageBox aMessageBox(theParent);
1068   aMessageBox.setWindowTitle(QObject::tr("Delete features"));
1069   aMessageBox.setIcon(QMessageBox::Warning);
1070   aMessageBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1071   aMessageBox.setDefaultButton(QMessageBox::No);
1072
1073   QString aText, aDetailedText;
1074   if (!thePrefixInfo.empty())
1075     aText = thePrefixInfo.c_str();
1076   QString aSep = ", ";
1077   if (!aPartFeatureNames.empty()) {
1078     aText += QString(QObject::tr("The following parts will be deleted: %1.\n"))
1079              .arg(aPartFeatureNames.join(aSep));
1080   }
1081   if (!aNotActivatedDocWrn.isEmpty())
1082     aText += aNotActivatedDocWrn;
1083   if (!anOtherFeatureNames.empty()) {
1084     const char* aMsg = "The selected features are used in some\n"
1085                        "other features, which will also be deleted.\n";
1086     const char* aMsgDetails = "The selected features are used"
1087                               " in the following features: %1.\n";
1088     aText += QString(QObject::tr(aMsg));
1089     aDetailedText += QString(QObject::tr(aMsgDetails))
1090                      .arg(anOtherFeatureNames.join(aSep));
1091   }
1092   if (!aParamFeatureNames.empty()) {
1093     const char* aMsg = "The selected parameters are used directly or through\n"
1094                        "a sequence of dependencies in some features.\n"
1095                        "These features will be deleted.\n"
1096                        "Or parameters could be replaced by their values.\n";
1097     const char* aMsgDetails = "Parameters are used in the following features: %1.\n";
1098     aText += QString(QObject::tr(aMsg));
1099     aDetailedText += QString(QObject::tr(aMsgDetails))
1100                      .arg(aParamFeatureNames.join(aSep));
1101 #ifdef _DEBUG
1102     QPushButton *aReplaceButton =
1103 #endif
1104       aMessageBox.addButton(QObject::tr("Replace"), QMessageBox::ActionRole);
1105   }
1106
1107   if (!aText.isEmpty()) {
1108     aMessageBox.setText(aText);
1109     aMessageBox.setInformativeText(QObject::tr("Would you like to continue?"));
1110     if (!aDetailedText.isEmpty())
1111       aMessageBox.setDetailedText(aDetailedText);
1112     aMessageBox.exec();
1113     QMessageBox::ButtonRole aButtonRole = aMessageBox.buttonRole(aMessageBox.clickedButton());
1114
1115     if (aButtonRole == QMessageBox::NoRole)
1116       return false;
1117
1118     if (aButtonRole == QMessageBox::ActionRole) {
1119       foreach (FeaturePtr aObj, aParameterFeatures)
1120         ModelAPI_ReplaceParameterMessage::send(aObj, 0);
1121     }
1122     else
1123       theReferencesToDelete.insert(aFeaturesRefsToParameterOnly.begin(),
1124                                    aFeaturesRefsToParameterOnly.end());
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)
1401 {
1402   int aDisplayingId = -1;
1403   if (theDisplayFromScript) {
1404     aDisplayingId = ModuleBase_Preferences::resourceMgr()->integerValue("General",
1405       "part_visualization_script", -1);
1406     // Increase ID to prevert using "As stored in HDF"
1407     ++aDisplayingId;
1408   }
1409   else {
1410     aDisplayingId = ModuleBase_Preferences::resourceMgr()->integerValue("General",
1411       "part_visualization_study", -1);
1412
1413     // if chosen "As stored in HDF" then don't change displaying
1414     if (aDisplayingId == 0)
1415       return;
1416   }
1417
1418   for (int anIndex = theSize - 1; anIndex >= 0; --anIndex) {
1419     ObjectPtr anObject = theDoc->object(theGroup, anIndex);
1420     anObject->setDisplayed((aDisplayingId == 1 && anIndex == theSize - 1) || aDisplayingId == 2);
1421   }
1422 }
1423
1424 void setDisplaying(ResultPartPtr thePart, bool theDisplayFromScript)
1425 {
1426   DocumentPtr aDoc = thePart->partDoc();
1427   int aConstructionSize = aDoc->size(ModelAPI_ResultConstruction::group());
1428   int aGroupSize = aDoc->size(ModelAPI_ResultGroup::group());
1429   int aFieldSize = aDoc->size(ModelAPI_ResultField::group());
1430   int aResultSize = aDoc->size(ModelAPI_ResultBody::group());
1431   setDisplayingByLoop(aDoc, aConstructionSize,
1432     ModelAPI_ResultConstruction::group(), theDisplayFromScript);
1433   setDisplayingByLoop(aDoc, aGroupSize, ModelAPI_ResultGroup::group(), theDisplayFromScript);
1434   setDisplayingByLoop(aDoc, aFieldSize, ModelAPI_ResultField::group(), theDisplayFromScript);
1435   setDisplayingByLoop(aDoc, aResultSize, ModelAPI_ResultBody::group(), theDisplayFromScript);
1436 }
1437
1438 } // namespace ModuleBase_Tools
1439
1440