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