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