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