]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModuleBase/ModuleBase_Tools.cpp
Salome HOME
7c51ccc9aeb3bdbb29db403f80b12357e4fa42a0
[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     aMessageBox.addButton(QObject::tr("Replace"), QMessageBox::ActionRole);
1108   }
1109
1110   if (!aText.isEmpty()) {
1111     aMessageBox.setText(aText);
1112     aMessageBox.setInformativeText(QObject::tr("Would you like to continue?"));
1113     if (!aDetailedText.isEmpty())
1114       aMessageBox.setDetailedText(aDetailedText);
1115     aMessageBox.exec();
1116     QMessageBox::ButtonRole aButtonRole = aMessageBox.buttonRole(aMessageBox.clickedButton());
1117
1118     if (aButtonRole == QMessageBox::NoRole)
1119       return false;
1120
1121     if (aButtonRole == QMessageBox::ActionRole) {
1122       foreach (FeaturePtr aObj, aParameterFeatures)
1123         ModelAPI_ReplaceParameterMessage::send(aObj, 0);
1124     }
1125     else
1126       theReferencesToDelete.insert(aFeaturesRefsToParameterOnly.begin(),
1127                                    aFeaturesRefsToParameterOnly.end());
1128   }
1129   return true;
1130 }
1131
1132 //**************************************************************
1133 bool warningAboutConflict(QWidget* theParent, const std::string& theWarningText)
1134 {
1135   QMessageBox aMessageBox(theParent);
1136   aMessageBox.setWindowTitle(QObject::tr("Conflicts in constraint"));
1137   aMessageBox.setIcon(QMessageBox::Warning);
1138   aMessageBox.setText((theWarningText + "\nConstraints will be removed or substituted").c_str());
1139
1140   QCheckBox* aCheckBox = new QCheckBox;
1141
1142   aCheckBox->setTristate(false);
1143   aCheckBox->setText("switch off the notifications.");
1144
1145   aMessageBox.setCheckBox(aCheckBox);
1146   aMessageBox.setStandardButtons(QMessageBox::Ok);
1147
1148   aMessageBox.exec();
1149
1150   if (aCheckBox->isChecked())
1151   {
1152     ModuleBase_Preferences::resourceMgr()->setValue(SKETCH_TAB_NAME,
1153                                                     "notify_change_constraint", false);
1154   }
1155
1156   return true;
1157 }
1158
1159 //**************************************************************
1160 void convertToFeatures(const QObjectPtrList& theObjects, std::set<FeaturePtr>& theFeatures)
1161 {
1162   QObjectPtrList::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
1163   for(; anIt != aLast; anIt++) {
1164     ObjectPtr anObject = *anIt;
1165     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
1166     // for parameter result, use the corresponded reature to be removed
1167     if (!aFeature.get() && anObject->groupName() == ModelAPI_ResultParameter::group()) {
1168       aFeature = ModelAPI_Feature::feature(anObject);
1169     }
1170     if (aFeature.get())
1171       theFeatures.insert(aFeature);
1172   }
1173 }
1174
1175 //**************************************************************
1176 void convertToFolders(const QObjectPtrList& theObjects,
1177                                          std::set<FolderPtr>& theFolders)
1178 {
1179   QObjectPtrList::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
1180   for(; anIt != aLast; anIt++) {
1181     ObjectPtr anObject = *anIt;
1182     FolderPtr aFeature = std::dynamic_pointer_cast<ModelAPI_Folder>(anObject);
1183     if (aFeature.get())
1184       theFolders.insert(aFeature);
1185   }
1186 }
1187
1188
1189 //**************************************************************
1190 QString translate(const Events_InfoMessage& theMessage)
1191 {
1192   QString aMessage;
1193
1194   if (!theMessage.empty()) {
1195     std::string aStr = Config_Translator::translate(theMessage);
1196     if (!aStr.empty()) {
1197       std::string aCodec = Config_Translator::codec(theMessage);
1198       aMessage = QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str());
1199     }
1200   }
1201
1202   return aMessage;
1203 }
1204
1205 QString translate(const std::string& theContext, const std::string& theMessage)
1206 {
1207   QString aMessage;
1208
1209   if (!theMessage.empty()) {
1210     std::string aStr = Config_Translator::translate(theContext, theMessage);
1211     if (!aStr.empty()) {
1212       std::string aCodec = Config_Translator::codec(theContext);
1213       aMessage = QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str());
1214     }
1215   }
1216
1217   return aMessage;
1218 }
1219
1220 void setPointBallHighlighting(AIS_InteractiveObject* theAIS)
1221 {
1222   static Handle(Image_AlienPixMap) aPixMap;
1223   if(aPixMap.IsNull()) {
1224     // Load icon for the presentation
1225     std::string aFile;
1226     char* anEnv = getenv("SHAPER_ROOT_DIR");
1227     if(anEnv) {
1228       aFile = std::string(anEnv) +
1229         FSEP + "share" + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
1230     } else {
1231       anEnv = getenv("CADBUILDER_ROOT_DIR");
1232       if (anEnv)
1233         aFile = std::string(anEnv) + FSEP + "resources";
1234     }
1235
1236     aFile += FSEP;
1237     static const std::string aMarkerName = "marker_dot.png";
1238     aFile += aMarkerName;
1239     aPixMap = new Image_AlienPixMap();
1240     if(!aPixMap->Load(aFile.c_str())) {
1241       // The icon for constraint is not found
1242       static const std::string aMsg =
1243         "Error: Point market not found by path: \"" + aFile + "\". Falling back.";
1244       //Events_InfoMessage("ModuleBase_Tools::setPointBallHighlighting", aMsg).send();
1245     }
1246   }
1247
1248   Handle(Graphic3d_AspectMarker3d) anAspect;
1249   Handle(Prs3d_Drawer) aDrawer = theAIS->DynamicHilightAttributes();
1250   if (aDrawer.IsNull()) {
1251     if (ModuleBase_IViewer::DefaultHighlightDrawer.IsNull())
1252       return;
1253     aDrawer = new Prs3d_Drawer(*ModuleBase_IViewer::DefaultHighlightDrawer);
1254     if (!aDrawer->HasOwnPointAspect()) {
1255       aDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_BALL, Quantity_NOC_BLACK, 2.0));
1256     }
1257   }
1258   if(aDrawer->HasOwnPointAspect()) {
1259     Handle(Prs3d_PointAspect) aPntAspect = aDrawer->PointAspect();
1260     if(aPixMap->IsEmpty()) {
1261       anAspect = aPntAspect->Aspect();
1262       anAspect->SetType(Aspect_TOM_BALL);
1263     } else {
1264       if(aPixMap->Format() == Image_PixMap::ImgGray) {
1265         aPixMap->SetFormat (Image_PixMap::ImgAlpha);
1266       } else if(aPixMap->Format() == Image_PixMap::ImgGrayF) {
1267         aPixMap->SetFormat (Image_PixMap::ImgAlphaF);
1268       }
1269       anAspect = new Graphic3d_AspectMarker3d(aPixMap);
1270       aPntAspect->SetAspect(anAspect);
1271     }
1272     aDrawer->SetPointAspect(aPntAspect);
1273           theAIS->SetDynamicHilightAttributes(aDrawer);
1274   }
1275 }
1276
1277 FeaturePtr createParameter(const QString& theText)
1278 {
1279   FeaturePtr aParameter;
1280   QStringList aList = theText.split("=");
1281   if (aList.count() != 2) {
1282     return aParameter;
1283   }
1284   QString aParamName = aList.at(0).trimmed();
1285
1286   if (isNameExist(aParamName, FeaturePtr())) {
1287     return aParameter;
1288   }
1289
1290   if (!ModelAPI_Expression::isVariable(aParamName.toStdString())) {
1291     return aParameter;
1292   }
1293
1294   QString aExpression = aList.at(1).trimmed();
1295   if (aExpression.isEmpty()) {
1296     return aParameter;
1297   }
1298
1299   SessionPtr aMgr = ModelAPI_Session::get();
1300   std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
1301
1302   aParameter = aDoc->addFeature("Parameter", false);
1303   if (aParameter.get()) {
1304     AttributeStringPtr aNameAttr = aParameter->string("variable");
1305     aNameAttr->setValue(aParamName.toStdString());
1306
1307     AttributeStringPtr aExprAttr = aParameter->string("expression");
1308     aExprAttr->setValue(aExpression.toStdString());
1309     aParameter->execute();
1310
1311     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
1312     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
1313   }
1314   return aParameter;
1315 }
1316
1317 void editParameter(FeaturePtr theParam, const QString& theText)
1318 {
1319   QStringList aList = theText.split("=");
1320   QString aParamName = aList.at(0).trimmed();
1321
1322   QString aExpression = aList.at(1).trimmed();
1323   if (aExpression.isEmpty()) {
1324     return;
1325   }
1326
1327   if (isNameExist(aParamName, theParam)) {
1328     return;
1329   }
1330   AttributeStringPtr aNameAttr = theParam->string("variable");
1331   aNameAttr->setValue(aParamName.toStdString());
1332
1333   AttributeStringPtr aExprAttr = theParam->string("expression");
1334   aExprAttr->setValue(aExpression.toStdString());
1335   theParam->execute();
1336
1337   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
1338 }
1339
1340 bool isNameExist(const QString& theName, FeaturePtr theIgnoreParameter)
1341 {
1342   SessionPtr aMgr = ModelAPI_Session::get();
1343   std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
1344   FeaturePtr aParamFeature;
1345   int aNbFeatures = aDoc->numInternalFeatures();
1346   std::wstring aName = theName.toStdWString();
1347   for (int i = 0; i < aNbFeatures; i++) {
1348     aParamFeature = aDoc->internalFeature(i);
1349     if (aParamFeature && aParamFeature->getKind() == "Parameter") {
1350       if ((theIgnoreParameter != aParamFeature) && (aParamFeature->name() == aName))
1351         return true;
1352     }
1353   }
1354   return false;
1355 }
1356
1357 FeaturePtr findParameter(const QString& theName)
1358 {
1359   SessionPtr aMgr = ModelAPI_Session::get();
1360   std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
1361   FeaturePtr aParamFeature;
1362   int aNbFeatures = aDoc->numInternalFeatures();
1363   std::wstring aName = theName.toStdWString();
1364   for (int i = 0; i < aNbFeatures; i++) {
1365     aParamFeature = aDoc->internalFeature(i);
1366     if (aParamFeature && aParamFeature->getKind() == "Parameter") {
1367       if (aParamFeature->name() == aName)
1368         return aParamFeature;
1369     }
1370   }
1371   return FeaturePtr();
1372 }
1373
1374
1375 //********************************************************************
1376 std::wstring generateName(const AttributePtr& theAttribute,
1377   ModuleBase_IWorkshop* theWorkshop)
1378 {
1379   std::wstring aName;
1380   if (theAttribute.get() != NULL) {
1381     FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
1382     if (aFeature.get()) {
1383       std::string aXmlCfg, aDescription;
1384       theWorkshop->module()->getXMLRepresentation(aFeature->getKind(), aXmlCfg, aDescription);
1385
1386       ModuleBase_WidgetFactory aFactory(aXmlCfg, theWorkshop);
1387       std::string anAttributeTitle;
1388       aFactory.getAttributeTitle(theAttribute->id(), anAttributeTitle);
1389
1390       std::wstringstream aStreamName;
1391       aStreamName << theAttribute->owner()->data()->name() << "/" << anAttributeTitle.c_str();
1392       aName = aStreamName.str();
1393     }
1394   }
1395   return aName;
1396 }
1397
1398 bool isSameShape(const TopoDS_Shape& theShape1, const TopoDS_Shape& theShape2)
1399 {
1400   // In case of compound we cannot rely on simple comparison method.
1401   // If the compound is generated by Group feature then this compound is alwais new.
1402   // So, we have to compare content of these compounds
1403   if (theShape1.ShapeType() != theShape2.ShapeType())
1404     return false;
1405
1406   if (theShape1.ShapeType() != TopAbs_COMPOUND)
1407     return theShape1.IsSame(theShape2);
1408
1409   TopoDS_Iterator aIt1(theShape1);
1410   TopoDS_Iterator aIt2(theShape2);
1411
1412   for (; aIt1.More() && aIt2.More(); aIt1.Next(), aIt2.Next()) {
1413     if (!(aIt1.Value()).IsSame(aIt2.Value()))
1414       return false;
1415   }
1416   return true;
1417 }
1418
1419 qreal currentPixelRatio()
1420 {
1421   QWindowList aWnds = qApp->topLevelWindows();
1422   if (aWnds.size() > 0)
1423     return aWnds.first()->devicePixelRatio();
1424   return qApp->primaryScreen()->devicePixelRatio();
1425 }
1426
1427
1428 // Set displaying status to every element on group
1429 static void setDisplayingByLoop(DocumentPtr theDoc, int theSize,
1430   std::string theGroup, bool theDisplayFromScript, int theDisplayingId)
1431 {
1432   for (int anIndex = theSize - 1; anIndex >= 0; --anIndex) {
1433     ObjectPtr anObject = theDoc->object(theGroup, anIndex);
1434     anObject->setDisplayed((theDisplayingId == 1 && anIndex == theSize - 1) ||
1435                            theDisplayingId == 2);
1436   }
1437 }
1438
1439 void setDisplaying(ResultPartPtr thePart, bool theDisplayFromScript)
1440 {
1441   static bool isDoingDisplay = false;
1442
1443   if (isDoingDisplay)
1444     return;
1445
1446   isDoingDisplay = true;
1447   DocumentPtr aDoc = thePart->partDoc();
1448   int aConstructionSize = aDoc->size(ModelAPI_ResultConstruction::group());
1449   int aGroupSize = aDoc->size(ModelAPI_ResultGroup::group());
1450   int aFieldSize = aDoc->size(ModelAPI_ResultField::group());
1451   int aResultSize = aDoc->size(ModelAPI_ResultBody::group());
1452
1453   int aDisplayingId = -1;
1454   if (theDisplayFromScript) {
1455     aDisplayingId = ModuleBase_Preferences::resourceMgr()->integerValue("General",
1456       "part_visualization_script", -1);
1457     // Increase ID to prevert using "As stored in HDF"
1458     ++aDisplayingId;
1459   }
1460   else {
1461     aDisplayingId = ModuleBase_Preferences::resourceMgr()->integerValue("General",
1462       "part_visualization_study", -1);
1463
1464     // if chosen "As stored in HDF" then don't change displaying
1465     if (aDisplayingId == 0)
1466       return;
1467   }
1468
1469   setDisplayingByLoop(aDoc, aConstructionSize, ModelAPI_ResultConstruction::group(),
1470                       theDisplayFromScript, aDisplayingId);
1471   setDisplayingByLoop(aDoc, aGroupSize, ModelAPI_ResultGroup::group(),
1472                       theDisplayFromScript, aDisplayingId);
1473   setDisplayingByLoop(aDoc, aFieldSize, ModelAPI_ResultField::group(),
1474                       theDisplayFromScript, aDisplayingId);
1475   setDisplayingByLoop(aDoc, aResultSize, ModelAPI_ResultBody::group(),
1476                       theDisplayFromScript, aDisplayingId);
1477   isDoingDisplay = false;
1478 }
1479
1480 } // namespace ModuleBase_Tools
1481
1482