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