1 // Copyright (C) 2014-2021 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "ModuleBase_Tools.h"
22 #include <ModuleBase_ParamIntSpinBox.h>
23 #include <ModuleBase_ParamSpinBox.h>
24 #include <ModuleBase_WidgetFactory.h>
25 #include <ModuleBase_IWorkshop.h>
26 #include <ModuleBase_IModule.h>
27 #include <ModuleBase_IViewer.h>
28 #include <ModuleBase_IconFactory.h>
29 #include <ModuleBase_ResultPrs.h>
30 #include <ModuleBase_ViewerPrs.h>
32 #include <ModelAPI_Attribute.h>
33 #include <ModelAPI_AttributeRefAttr.h>
34 #include <ModelAPI_AttributeReference.h>
35 #include <ModelAPI_AttributeSelection.h>
36 #include <ModelAPI_AttributeSelectionList.h>
37 #include <ModelAPI_AttributeRefList.h>
38 #include <ModelAPI_AttributeRefAttrList.h>
39 #include <ModelAPI_ResultPart.h>
40 #include <ModelAPI_ResultConstruction.h>
41 #include <ModelAPI_AttributeString.h>
42 #include <ModelAPI_Expression.h>
43 #include <ModelAPI_ResultField.h>
44 #include <Events_Loop.h>
46 #include <ModelAPI_Data.h>
47 #include <ModelAPI_Result.h>
48 #include <ModelAPI_ResultParameter.h>
49 #include <ModelAPI_Tools.h>
50 #include <ModelAPI_Session.h>
51 #include <ModelAPI_Events.h>
52 #include <ModelAPI_Folder.h>
54 #include <ModelGeomAlgo_Point2D.h>
56 #include <StdSelect_BRepOwner.hxx>
57 #include <TopoDS_Iterator.hxx>
58 #include <AIS_InteractiveContext.hxx>
59 #include <Prs3d_LineAspect.hxx>
60 #include <Prs3d_PlaneAspect.hxx>
62 #include <GeomDataAPI_Point2D.h>
63 #include <Events_InfoMessage.h>
64 #include <GeomAPI_ShapeExplorer.h>
66 #include <Config_PropManager.h>
67 #include <Config_Translator.h>
69 #include <Prs3d_PointAspect.hxx>
70 #include <Graphic3d_AspectMarker3d.hxx>
72 #include <Image_AlienPixMap.hxx>
78 #include <QDoubleSpinBox>
79 #include <QGraphicsDropShadowEffect>
81 #include <QApplication>
82 #include <QMessageBox>
92 #pragma warning(disable : 4996) // for getenv
95 const double tolerance = 1e-7;
96 const double DEFAULT_DEVIATION_COEFFICIENT = 1.e-4;
98 //#define DEBUG_ACTIVATE_WINDOW
99 //#define DEBUG_SET_FOCUS
107 namespace ModuleBase_Tools {
109 //******************************************************************
111 //******************************************************************
113 void adjustMargins(QWidget* theWidget)
117 adjustMargins(theWidget->layout());
120 void adjustMargins(QLayout* theLayout)
124 theLayout->setContentsMargins(2, 5, 2, 5);
125 theLayout->setSpacing(4);
128 void zeroMargins(QWidget* theWidget)
132 zeroMargins(theWidget->layout());
135 void zeroMargins(QLayout* theLayout)
139 theLayout->setContentsMargins(0, 0, 0, 0);
140 theLayout->setSpacing(5);
143 void activateWindow(QWidget* theWidget, const QString& theInfo)
146 theWidget->activateWindow();
150 #ifdef DEBUG_ACTIVATE_WINDOW
151 qDebug(QString("activateWindow: %1").arg(theInfo).toStdString().c_str());
155 void setFocus(QWidget* theWidget, const QString& theInfo)
157 activateWindow(theWidget);
158 theWidget->setFocus();
159 // rectangle of focus is not visible on tool button widgets
161 #ifdef DEBUG_SET_FOCUS
162 qDebug(QString("setFocus: %1").arg(theInfo).toStdString().c_str());
166 void setShadowEffect(QWidget* theWidget, const bool isSetEffect)
169 QGraphicsDropShadowEffect* aGlowEffect = new QGraphicsDropShadowEffect();
170 aGlowEffect->setOffset(.0);
171 aGlowEffect->setBlurRadius(10.0);
172 aGlowEffect->setColor(QColor(0, 170, 255)); // Light-blue color, #00AAFF
173 theWidget->setGraphicsEffect(aGlowEffect);
176 QGraphicsEffect* anEffect = theWidget->graphicsEffect();
178 anEffect->deleteLater();
179 theWidget->setGraphicsEffect(NULL);
183 QPixmap composite(const QString& theAdditionalIcon, const QString& theIcon)
185 QImage anIcon = ModuleBase_IconFactory::loadImage(theIcon);
186 QImage anAditional(theAdditionalIcon);
187 return composite(anAditional, anIcon);
190 QPixmap composite(const QImage& theAdditionalIcon, QImage& theIcon)
192 if (theIcon.isNull())
195 int anAddWidth = theAdditionalIcon.width();
196 int anAddHeight = theAdditionalIcon.height();
198 int aWidth = theIcon.width();
199 int aHeight = theIcon.height();
201 int aStartWidthPos = aWidth - anAddWidth;
202 int aStartHeightPos = aHeight - anAddHeight;
204 for (int i = 0; i < anAddWidth && i + aStartWidthPos < aWidth; i++)
206 for (int j = 0; j < anAddHeight && j + aStartHeightPos < aHeight; j++)
208 if (qAlpha(theAdditionalIcon.pixel(i, j)) > 0)
209 theIcon.setPixel(i + aStartWidthPos, j + aStartHeightPos, theAdditionalIcon.pixel(i, j));
212 return QPixmap::fromImage(theIcon);
215 QPixmap lighter(const QString& theIcon, const int theLighterValue)
217 QImage anIcon = ModuleBase_IconFactory::loadImage(theIcon);
221 QImage aResult = ModuleBase_IconFactory::loadImage(theIcon);
222 for (int i = 0; i < anIcon.width(); i++)
224 for (int j = 0; j < anIcon.height(); j++)
226 QRgb anRgb = anIcon.pixel(i, j);
227 QColor aPixelColor(qRed(anRgb), qGreen(anRgb), qBlue(anRgb),
228 qAlpha(aResult.pixel(i, j)));
230 QColor aLighterColor = aPixelColor.lighter(theLighterValue);
231 aResult.setPixel(i, j, qRgba(aLighterColor.red(), aLighterColor.green(),
232 aLighterColor.blue(), aLighterColor.alpha()));
235 return QPixmap::fromImage(aResult);
238 void setSpinText(ModuleBase_ParamSpinBox* theSpin, const QString& theText)
240 if (theSpin->text() == theText)
242 // In order to avoid extra text setting because it will
243 // reset cursor position in control
244 bool isBlocked = theSpin->blockSignals(true);
245 theSpin->setText(theText);
246 theSpin->blockSignals(isBlocked);
249 void setSpinValue(QDoubleSpinBox* theSpin, double theValue)
251 if (fabs(theSpin->value() - theValue) < tolerance)
253 bool isBlocked = theSpin->blockSignals(true);
254 theSpin->setValue(theValue);
255 theSpin->blockSignals(isBlocked);
258 void setSpinValue(ModuleBase_ParamSpinBox* theSpin, double theValue)
260 if (!theSpin->text().isEmpty() && fabs(theSpin->value() - theValue) < tolerance)
262 bool isBlocked = theSpin->blockSignals(true);
263 theSpin->setValue(theValue);
264 theSpin->blockSignals(isBlocked);
267 void setSpinText(ModuleBase_ParamIntSpinBox* theSpin, const QString& theText)
269 // In order to avoid extra text setting because it will
270 // reset cursor position in control
271 if (theSpin->text() == theText)
273 bool isBlocked = theSpin->blockSignals(true);
274 theSpin->setText(theText);
275 theSpin->blockSignals(isBlocked);
278 void setSpinValue(ModuleBase_ParamIntSpinBox* theSpin, int theValue)
280 if (theSpin->value() == theValue)
282 bool isBlocked = theSpin->blockSignals(true);
283 theSpin->setValue(theValue);
284 theSpin->blockSignals(isBlocked);
287 QAction* createAction(const QIcon& theIcon, const QString& theText,
288 QObject* theParent, const QObject* theReceiver,
289 const char* theMember, const QString& theToolTip,
290 const QString& theStatusTip)
292 QAction* anAction = new QAction(theIcon, theText, theParent);
293 anAction->setToolTip(theToolTip.isEmpty() ? theText : theToolTip);
294 anAction->setStatusTip(!theStatusTip.isEmpty() ? theStatusTip :
295 (!theToolTip.isEmpty() ? theToolTip : theText));
297 QObject::connect(anAction, SIGNAL(triggered(bool)), theReceiver, theMember);
303 QString objectName(const ObjectPtr& theObj)
308 return QString::fromStdWString(theObj->data()->name());
311 QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo)
313 QString aFeatureStr = "feature";
317 std::ostringstream aPtrStr;
318 aPtrStr << "[" << theObj.get() << "]";
320 ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
321 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
323 aFeatureStr.append(QString("(result%1)").arg(aPtrStr.str().c_str()).toStdString() .c_str());
324 if (aRes->isDisabled())
325 aFeatureStr.append("[disabled]");
326 if (aRes->isConcealed())
327 aFeatureStr.append("[concealed]");
328 if (ModelAPI_Tools::hasSubResults(aRes))
329 aFeatureStr.append("[hasSubResults]");
331 aFeature = ModelAPI_Feature::feature(aRes);
334 aFeatureStr.append(aPtrStr.str().c_str());
336 if (aFeature.get()) {
337 aFeatureStr.append(QString(": %1").arg(aFeature->getKind().c_str()).toStdString().c_str());
338 if (aFeature->data()->isValid()) {
339 aFeatureStr.append(QString(", name=%1")
340 .arg(QString::fromStdWString(theObj->data()->name())).toStdString().c_str());
342 if (isUseAttributesInfo) {
343 std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes;
344 std::string aPointsInfo = ModelGeomAlgo_Point2D::getPontAttributesInfo(aFeature,
345 anAttributes).c_str();
346 if (!aPointsInfo.empty())
347 aFeatureStr.append(QString(", attributes: %1")
348 .arg(aPointsInfo.c_str()).toStdString().c_str());
356 typedef QMap<QString, int> ShapeTypes;
357 static ShapeTypes myShapeTypes;
359 int shapeType(const QString& theType)
361 if (myShapeTypes.count() == 0) {
362 myShapeTypes["compound"] = TopAbs_COMPOUND;
363 myShapeTypes["compounds"] = TopAbs_COMPOUND;
364 myShapeTypes["compsolid"] = TopAbs_COMPSOLID;
365 myShapeTypes["compsolids"] = TopAbs_COMPSOLID;
366 myShapeTypes["solid"] = TopAbs_SOLID;
367 myShapeTypes["solids"] = TopAbs_SOLID;
368 myShapeTypes["shell"] = TopAbs_SHELL;
369 myShapeTypes["shells"] = TopAbs_SHELL;
370 myShapeTypes["face"] = TopAbs_FACE;
371 myShapeTypes["faces"] = TopAbs_FACE;
372 myShapeTypes["wire"] = TopAbs_WIRE;
373 myShapeTypes["wires"] = TopAbs_WIRE;
374 myShapeTypes["edge"] = TopAbs_EDGE;
375 myShapeTypes["edges"] = TopAbs_EDGE;
376 myShapeTypes["vertex"] = TopAbs_VERTEX;
377 myShapeTypes["vertices"] = TopAbs_VERTEX;
378 myShapeTypes["object"] = ModuleBase_ResultPrs::Sel_Result;
379 myShapeTypes["objects"] = ModuleBase_ResultPrs::Sel_Result;
381 QString aType = theType.toLower();
382 if(myShapeTypes.contains(aType))
383 return myShapeTypes[aType];
384 Events_InfoMessage("ModuleBase_Tools", "Shape type defined in XML is not implemented!").send();
388 void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature,
389 bool& hasParameter, bool& hasCompositeOwner, bool& hasResultInHistory,
394 hasParameter = false;
395 hasCompositeOwner = false;
396 hasResultInHistory = false;
398 foreach(ObjectPtr aObj, theObjects) {
399 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
400 ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
401 FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(aObj);
402 ResultParameterPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aResult);
403 FieldStepPtr aStep = std::dynamic_pointer_cast<ModelAPI_ResultField::ModelAPI_FieldStep>(aObj);
405 hasResult |= ((aResult.get() != NULL) || (aStep.get() != NULL));
406 hasFeature |= (aFeature.get() != NULL);
407 hasFolder |= (aFolder.get() != NULL);
408 hasParameter |= (aConstruction.get() != NULL);
410 hasCompositeOwner |= (ModelAPI_Tools::compositeOwner(aFeature) != NULL);
411 else if (aResult.get())
412 hasCompositeOwner |= (ModelAPI_Tools::bodyOwner(aResult) != NULL);
414 if (!hasResultInHistory && aResult.get()) {
415 aFeature = ModelAPI_Feature::feature(aResult);
416 hasResultInHistory = aFeature.get() && aFeature->isInHistory();
419 if (hasFeature && hasResult && hasParameter && hasCompositeOwner)
424 /*bool setDefaultDeviationCoefficient(std::shared_ptr<GeomAPI_Shape> theGeomShape)
426 if (!theGeomShape.get())
428 // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
429 // correction of deviation for them should not influence to the application performance
430 GeomAPI_ShapeExplorer anExp(theGeomShape, GeomAPI_Shape::FACE);
431 bool anEmpty = anExp.empty();
432 return !anExp.more();
435 /*void setDefaultDeviationCoefficient(const std::shared_ptr<ModelAPI_Result>& theResult,
436 const Handle(Prs3d_Drawer)& theDrawer)
438 if (!theResult.get())
440 bool aUseDeviation = false;
442 std::string aResultGroup = theResult->groupName();
443 if (aResultGroup == ModelAPI_ResultConstruction::group())
444 aUseDeviation = true;
445 else if (aResultGroup == ModelAPI_ResultBody::group()) {
446 GeomShapePtr aGeomShape = theResult->shape();
447 if (aGeomShape.get())
448 aUseDeviation = setDefaultDeviationCoefficient(aGeomShape);
451 theDrawer->SetDeviationCoefficient(DEFAULT_DEVIATION_COEFFICIENT);
454 void setDefaultDeviationCoefficient(const TopoDS_Shape& theShape,
455 const Handle(Prs3d_Drawer)& theDrawer)
457 if (theShape.IsNull())
459 if (theDrawer.IsNull())
462 std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape());
463 aGeomShape->setImpl(new TopoDS_Shape(theShape));
465 // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
466 // correction of deviation for them should not influence to the application performance
467 GeomAPI_ShapeExplorer anExp(aGeomShape, GeomAPI_Shape::FACE);
468 bool isConstruction = !anExp.more();
472 aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
474 aDeflection = Config_PropManager::real("Visualization", "body_deflection");
476 theDrawer->SetDeviationCoefficient(aDeflection);
479 Quantity_Color color(const std::string& theSection,
480 const std::string& theName)
482 std::vector<int> aColor = Config_PropManager::color(theSection, theName);
483 return Quantity_Color(aColor[0] / 255., aColor[1] / 255., aColor[2] / 255., Quantity_TOC_RGB);
486 ObjectPtr getObject(const AttributePtr& theAttribute)
489 std::string anAttrType = theAttribute->attributeType();
490 if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
491 AttributeRefAttrPtr anAttr =
492 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
493 if (anAttr != NULL && anAttr->isObject())
494 anObject = anAttr->object();
496 if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
497 AttributeSelectionPtr anAttr =
498 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
500 anObject = anAttr->context();
502 if (anAttrType == ModelAPI_AttributeReference::typeId()) {
503 AttributeReferencePtr anAttr =
504 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
505 if (anAttr.get() != NULL)
506 anObject = anAttr->value();
511 TopAbs_ShapeEnum getCompoundSubType(const TopoDS_Shape& theShape)
513 TopAbs_ShapeEnum aShapeType = theShape.ShapeType();
515 // for compounds check sub-shapes: it may be compound of needed type:
516 // Booleans may produce compounds of Solids
517 if (aShapeType == TopAbs_COMPOUND) {
518 for(TopoDS_Iterator aSubs(theShape); aSubs.More(); aSubs.Next()) {
519 if (!aSubs.Value().IsNull()) {
520 TopAbs_ShapeEnum aSubType = aSubs.Value().ShapeType();
521 if (aSubType == TopAbs_COMPOUND) { // compound of compound(s)
522 aShapeType = TopAbs_COMPOUND;
525 if (aShapeType == TopAbs_COMPOUND) {
526 aShapeType = aSubType;
527 } else if (aShapeType != aSubType) { // compound of shapes of different types
528 aShapeType = TopAbs_COMPOUND;
537 TopoDS_Shape getSelectedShape(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs)
539 if (thePrs->shape().get())
540 return thePrs->shape()->impl<TopoDS_Shape>();
542 Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(thePrs->owner());
543 if (!anOwner.IsNull())
544 return anOwner->Shape();
546 return TopoDS_Shape();
549 void getParameters(QStringList& theParameters)
551 theParameters.clear();
553 SessionPtr aSession = ModelAPI_Session::get();
554 std::list<DocumentPtr> aDocList;
555 DocumentPtr anActiveDocument = aSession->activeDocument();
556 DocumentPtr aRootDocument = aSession->moduleDocument();
557 aDocList.push_back(anActiveDocument);
558 if (anActiveDocument != aRootDocument) {
559 aDocList.push_back(aRootDocument);
561 std::string aGroupId = ModelAPI_ResultParameter::group();
562 for(std::list<DocumentPtr>::const_iterator it = aDocList.begin(); it != aDocList.end(); ++it) {
563 DocumentPtr aDocument = *it;
564 int aSize = aDocument->size(aGroupId);
565 for (int i = 0; i < aSize; i++) {
566 ObjectPtr anObject = aDocument->object(aGroupId, i);
567 std::wstring aParameterName = anObject->data()->name();
568 theParameters.append(QString::fromStdWString(aParameterName));
573 std::string findGreedAttribute(ModuleBase_IWorkshop* theWorkshop,
574 const FeaturePtr& theFeature)
576 std::string anAttributeId;
578 std::string aXmlCfg, aDescription;
579 theWorkshop->module()->getXMLRepresentation(theFeature->getKind(), aXmlCfg, aDescription);
581 ModuleBase_WidgetFactory aFactory(aXmlCfg, theWorkshop);
582 std::string anAttributeTitle;
583 aFactory.getGreedAttribute(anAttributeId);
585 return anAttributeId;
588 bool hasObject(const AttributePtr& theAttribute, const ObjectPtr& theObject,
589 const std::shared_ptr<GeomAPI_Shape>& theShape,
590 ModuleBase_IWorkshop* theWorkshop,
591 const bool theTemporarily)
593 bool aHasObject = false;
594 if (!theAttribute.get())
597 std::string aType = theAttribute->attributeType();
598 if (aType == ModelAPI_AttributeReference::typeId()) {
599 AttributeReferencePtr aRef =
600 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
601 ObjectPtr aObject = aRef->value();
602 aHasObject = aObject && aObject->isSame(theObject);
603 //if (!(aObject && aObject->isSame(theObject))) {
604 // aRef->setValue(theObject);
606 } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
607 AttributeRefAttrPtr aRefAttr =
608 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
610 AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
611 if (anAttribute.get()) {
612 //aRefAttr->setAttr(anAttribute);
615 ObjectPtr aObject = aRefAttr->object();
616 aHasObject = aObject && aObject->isSame(theObject);
617 //if (!(aObject && aObject->isSame(theObject))) {
618 // aRefAttr->setObject(theObject);
621 } else if (aType == ModelAPI_AttributeSelection::typeId()) {
622 /*AttributeSelectionPtr aSelectAttr =
623 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
624 ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
625 if (aSelectAttr.get() != NULL) {
626 aSelectAttr->setValue(aResult, theShape, theTemporarily);
629 if (aType == ModelAPI_AttributeSelectionList::typeId()) {
630 AttributeSelectionListPtr aSelectionListAttr =
631 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
632 aHasObject = aSelectionListAttr->isInList(theObject, theShape, theTemporarily);
634 else if (aType == ModelAPI_AttributeRefList::typeId()) {
635 AttributeRefListPtr aRefListAttr =
636 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
637 aHasObject = aRefListAttr->isInList(theObject);
638 //if (!theCheckIfAttributeHasObject || !aRefListAttr->isInList(theObject))
639 // aRefListAttr->append(theObject);
641 else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
642 AttributeRefAttrListPtr aRefAttrListAttr =
643 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(theAttribute);
644 AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
646 if (anAttribute.get()) {
647 aHasObject = aRefAttrListAttr->isInList(anAttribute);
648 //if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(anAttribute))
649 // aRefAttrListAttr->append(anAttribute);
652 aHasObject = aRefAttrListAttr->isInList(theObject);
653 //if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(theObject))
654 // aRefAttrListAttr->append(theObject);
660 bool setObject(const AttributePtr& theAttribute, const ObjectPtr& theObject,
661 const GeomShapePtr& theShape, ModuleBase_IWorkshop* theWorkshop,
662 const bool theTemporarily, const bool theCheckIfAttributeHasObject)
664 if (!theAttribute.get())
668 std::string aType = theAttribute->attributeType();
669 if (aType == ModelAPI_AttributeReference::typeId()) {
670 AttributeReferencePtr aRef =
671 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
672 ObjectPtr aObject = aRef->value();
673 if (!(aObject && aObject->isSame(theObject))) {
674 aRef->setValue(theObject);
676 } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
677 AttributeRefAttrPtr aRefAttr =
678 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
680 AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
681 if (anAttribute.get())
682 aRefAttr->setAttr(anAttribute);
684 ObjectPtr aObject = aRefAttr->object();
685 if (!(aObject && aObject->isSame(theObject))) {
686 aRefAttr->setObject(theObject);
689 } else if (aType == ModelAPI_AttributeSelection::typeId()) {
690 AttributeSelectionPtr aSelectAttr =
691 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
692 if (aSelectAttr.get() != NULL) {
693 aSelectAttr->setValue(theObject, theShape, theTemporarily);
696 if (aType == ModelAPI_AttributeSelectionList::typeId()) {
697 AttributeSelectionListPtr aSelectionListAttr =
698 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
699 if (!theCheckIfAttributeHasObject ||
700 !aSelectionListAttr->isInList(theObject, theShape, theTemporarily))
701 aSelectionListAttr->append(theObject, theShape, theTemporarily);
703 else if (aType == ModelAPI_AttributeRefList::typeId()) {
704 AttributeRefListPtr aRefListAttr =
705 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
706 if (!theCheckIfAttributeHasObject || !aRefListAttr->isInList(theObject)) {
708 aRefListAttr->append(theObject);
713 else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
714 AttributeRefAttrListPtr aRefAttrListAttr =
715 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(theAttribute);
716 AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
718 if (anAttribute.get()) {
719 if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(anAttribute))
720 aRefAttrListAttr->append(anAttribute);
723 if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(theObject)) {
725 aRefAttrListAttr->append(theObject);
734 GeomShapePtr getShape(const AttributePtr& theAttribute, ModuleBase_IWorkshop* theWorkshop)
737 if (!theAttribute.get())
740 std::string aType = theAttribute->attributeType();
741 if (aType == ModelAPI_AttributeReference::typeId()) {
742 } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
743 AttributeRefAttrPtr aRefAttr =
744 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
745 if (aRefAttr.get() && !aRefAttr->isObject()) {
746 AttributePtr anAttribute = aRefAttr->attr();
747 aShape = theWorkshop->module()->findShape(anAttribute);
749 } else if (aType == ModelAPI_AttributeSelection::typeId()) {
750 AttributeSelectionPtr aSelectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
752 aShape = aSelectAttr->value();
754 else // Geom2D point processing
755 aShape = theWorkshop->module()->findShape(theAttribute);
759 void flushUpdated(ObjectPtr theObject)
761 blockUpdateViewer(true);
763 // Fix the problem of not previewed results of constraints applied. Flush Create/Delete
764 // (for the sketch result) to start processing of the sketch in the solver.
765 // TODO: these flushes should be moved in a separate method provided by Model
766 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
767 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES));
768 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
769 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_UPDATE_SELECTION));
770 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
772 blockUpdateViewer(false);
775 void blockUpdateViewer(const bool theValue)
777 // the viewer update should be blocked in order to avoid the temporary feature content
778 // when the solver processes the feature, the redisplay message can be flushed
779 // what caused the display in the viewer preliminary states of object
780 // e.g. fillet feature, angle value change
781 std::shared_ptr<Events_Message> aMsg;
783 aMsg = std::shared_ptr<Events_Message>(
784 new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)));
787 // the viewer update should be unblocked
788 aMsg = std::shared_ptr<Events_Message>(
789 new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)));
791 Events_Loop::loop()->send(aMsg);
794 QString wrapTextByWords(const QString& theValue, QWidget* theWidget,
795 int theMaxLineInPixels)
797 static QFontMetrics tfm(theWidget ? theWidget->font() : QApplication::font());
798 static qreal phi = 2.618;
800 QRect aBounds = tfm.boundingRect(theValue);
801 if(aBounds.width() <= theMaxLineInPixels)
804 qreal s = aBounds.width() * aBounds.height();
805 qreal aGoldWidth = sqrt(s*phi);
807 QStringList aWords = theValue.split(" ", QString::SkipEmptyParts);
809 int n = aWords.count();
811 for (int i = 0; i < n; i++) {
812 QString aLineExt = i == 0 ? aWords[i] : aLine + " " + aWords[i];
813 qreal anWidthNonExt = tfm.boundingRect(aLine).width();
814 qreal anWidthExt = tfm.boundingRect(aLineExt).width();
815 qreal aDeltaNonExt = fabs(anWidthNonExt-aGoldWidth);
816 qreal aDeltaExt = fabs(anWidthExt-aGoldWidth);
817 if(aDeltaNonExt < aDeltaExt) {
819 aLines.append(aLine);
827 aLines.append(aLine);
829 QString aResult = aLines.join("\n");
833 //**************************************************************
834 QLocale doubleLocale()
836 // VSR 01/07/2010: Disable thousands separator for spin box
837 // (to avoid inconsistency of double-2-string and string-2-double conversion)
839 aLocale.setNumberOptions(aLocale.numberOptions() |
840 QLocale::OmitGroupSeparator |
841 QLocale::RejectGroupSeparator);
845 //**************************************************************
846 void refsToFeatureInFeatureDocument(const ObjectPtr& theObject,
847 std::set<FeaturePtr>& theRefFeatures)
849 FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
850 if (aFeature.get()) {
851 DocumentPtr aFeatureDoc = aFeature->document();
852 // 1. find references in the current document
853 aFeatureDoc->refsToFeature(aFeature, theRefFeatures, false);
858 //**************************************************************
859 /*bool isSubOfComposite(const ObjectPtr& theObject)
862 std::set<FeaturePtr> aRefFeatures;
863 refsToFeatureInFeatureDocument(theObject, aRefFeatures);
864 std::set<FeaturePtr>::const_iterator anIt = aRefFeatures.begin(),
865 aLast = aRefFeatures.end();
866 for (; anIt != aLast && !isSub; anIt++) {
867 isSub = isSubOfComposite(theObject, *anIt);
872 //**************************************************************
873 /*bool isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature)
876 CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
877 if (aComposite.get()) {
878 isSub = aComposite->isSub(theObject);
879 // the recursive is possible, the parameters are sketch circle and extrusion cut. They are
880 // separated by composite sketch feature
882 int aNbSubs = aComposite->numberOfSubs();
883 for (int aSub = 0; aSub < aNbSubs && !isSub; aSub++) {
884 isSub = isSubOfComposite(theObject, aComposite->subFeature(aSub));
891 //**************************************************************
892 ResultPtr firstResult(const ObjectPtr& theObject)
894 ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
895 if (!aResult.get()) {
896 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
898 aResult = aFeature->firstResult();
903 //**************************************************************
904 bool isFeatureOfResult(const FeaturePtr& theFeature, const std::string& theGroupOfResult)
906 bool isResult = false;
908 if (!theFeature->data()->isValid())
911 ResultPtr aFirstResult = theFeature->firstResult();
912 if (!aFirstResult.get())
915 return aFirstResult->groupName() == theGroupOfResult;
918 //**************************************************************
919 bool hasModuleDocumentFeature(const std::set<FeaturePtr>& theFeatures)
921 bool aFoundModuleDocumentObject = false;
922 DocumentPtr aModuleDoc = ModelAPI_Session::get()->moduleDocument();
924 std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(), aLast = theFeatures.end();
925 for (; anIt != aLast && !aFoundModuleDocumentObject; anIt++) {
926 FeaturePtr aFeature = *anIt;
927 ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature);
928 if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group())
930 aFoundModuleDocumentObject = aFeature->document() == aModuleDoc;
933 return aFoundModuleDocumentObject;
936 //**************************************************************
937 bool askToDelete(const std::set<FeaturePtr> theFeatures,
938 const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
940 std::set<FeaturePtr>& theReferencesToDelete,
941 const std::string& thePrefixInfo)
943 QString aNotActivatedDocWrn;
944 std::wstring aNotActivatedNames;
945 if (!ModelAPI_Tools::allDocumentsActivated(aNotActivatedNames)) {
946 if (ModuleBase_Tools::hasModuleDocumentFeature(theFeatures))
947 aNotActivatedDocWrn =
948 QObject::tr("Selected objects can be used in Part documents which are not loaded: %1.\n")
949 .arg(QString::fromStdWString(aNotActivatedNames));
952 std::set<FeaturePtr> aFeaturesRefsTo;
953 std::set<FeaturePtr> aFeaturesRefsToParameter;
954 std::set<FeaturePtr> aParameterFeatures;
955 QStringList aPartFeatureNames;
956 std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),
957 aLast = theFeatures.end();
958 // separate features to references to parameter features and references to others
959 for (; anIt != aLast; anIt++) {
960 FeaturePtr aFeature = *anIt;
961 if (theReferences.find(aFeature) == theReferences.end())
964 if (isFeatureOfResult(aFeature, ModelAPI_ResultPart::group()))
965 aPartFeatureNames.append(QString::fromStdWString(aFeature->name()));
967 std::set<FeaturePtr> aRefFeatures;
968 std::set<FeaturePtr> aRefList = theReferences.at(aFeature);
969 std::set<FeaturePtr>::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end();
970 for (; aRefIt != aRefLast; aRefIt++) {
971 FeaturePtr aRefFeature = *aRefIt;
972 if (theFeatures.find(aRefFeature) == theFeatures.end() && // it is not selected
973 aRefFeatures.find(aRefFeature) == aRefFeatures.end()) // it is not added
974 aRefFeatures.insert(aRefFeature);
977 if (isFeatureOfResult(aFeature, ModelAPI_ResultParameter::group())) {
978 aFeaturesRefsToParameter.insert(aRefFeatures.begin(), aRefFeatures.end());
979 aParameterFeatures.insert(aFeature);
982 theReferencesToDelete.insert(aRefFeatures.begin(), aRefFeatures.end());
986 std::set<FeaturePtr> aFeaturesRefsToParameterOnly;
987 anIt = aFeaturesRefsToParameter.begin();
988 aLast = aFeaturesRefsToParameter.end();
989 // separate features to references to parameter features and references to others
990 QStringList aParamFeatureNames;
991 for (; anIt != aLast; anIt++) {
992 FeaturePtr aFeature = *anIt;
993 if (theReferencesToDelete.find(aFeature) == theReferencesToDelete.end()) {
994 aFeaturesRefsToParameterOnly.insert(aFeature);
995 aParamFeatureNames.append(QString::fromStdWString(aFeature->name()));
998 aParamFeatureNames.sort();
999 QStringList anOtherFeatureNames;
1000 anIt = theReferencesToDelete.begin();
1001 aLast = theReferencesToDelete.end();
1002 for (; anIt != aLast; anIt++) {
1003 FeaturePtr aFeature = *anIt;
1004 if (aFeature->getKind() == "RemoveResults")
1005 continue; // skip the remove results feature mentioning: result will be removed anyway
1006 if (isFeatureOfResult(aFeature, ModelAPI_ResultPart::group()))
1007 aPartFeatureNames.append(QString::fromStdWString(aFeature->name()));
1009 anOtherFeatureNames.append(QString::fromStdWString(aFeature->name()));
1011 aPartFeatureNames.sort();
1012 anOtherFeatureNames.sort();
1014 QMessageBox aMessageBox(theParent);
1015 aMessageBox.setWindowTitle(QObject::tr("Delete features"));
1016 aMessageBox.setIcon(QMessageBox::Warning);
1017 aMessageBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1018 aMessageBox.setDefaultButton(QMessageBox::No);
1020 QString aText, aDetailedText;
1021 if (!thePrefixInfo.empty())
1022 aText = thePrefixInfo.c_str();
1023 QString aSep = ", ";
1024 if (!aPartFeatureNames.empty()) {
1025 aText += QString(QObject::tr("The following parts will be deleted: %1.\n"))
1026 .arg(aPartFeatureNames.join(aSep));
1028 if (!aNotActivatedDocWrn.isEmpty())
1029 aText += aNotActivatedDocWrn;
1030 if (!anOtherFeatureNames.empty()) {
1031 const char* aMsg = "The selected features are used in some\n"
1032 "other features, which will also be deleted.\n";
1033 const char* aMsgDetails = "The selected features are used"
1034 " in the following features: %1.\n";
1035 aText += QString(QObject::tr(aMsg));
1036 aDetailedText += QString(QObject::tr(aMsgDetails))
1037 .arg(anOtherFeatureNames.join(aSep));
1039 if (!aParamFeatureNames.empty()) {
1040 const char* aMsg = "The selected parameters are used directly or through\n"
1041 "a sequence of dependencies in some features.\n"
1042 "These features will be deleted.\n"
1043 "Or parameters could be replaced by their values.\n";
1044 const char* aMsgDetails = "Parameters are used in the following features: %1.\n";
1045 aText += QString(QObject::tr(aMsg));
1046 aDetailedText += QString(QObject::tr(aMsgDetails))
1047 .arg(aParamFeatureNames.join(aSep));
1049 QPushButton *aReplaceButton =
1051 aMessageBox.addButton(QObject::tr("Replace"), QMessageBox::ActionRole);
1054 if (!aText.isEmpty()) {
1055 aMessageBox.setText(aText);
1056 aMessageBox.setInformativeText(QObject::tr("Would you like to continue?"));
1057 if (!aDetailedText.isEmpty())
1058 aMessageBox.setDetailedText(aDetailedText);
1060 QMessageBox::ButtonRole aButtonRole = aMessageBox.buttonRole(aMessageBox.clickedButton());
1062 if (aButtonRole == QMessageBox::NoRole)
1065 if (aButtonRole == QMessageBox::ActionRole) {
1066 foreach (FeaturePtr aObj, aParameterFeatures)
1067 ModelAPI_ReplaceParameterMessage::send(aObj, 0);
1070 theReferencesToDelete.insert(aFeaturesRefsToParameterOnly.begin(),
1071 aFeaturesRefsToParameterOnly.end());
1076 //**************************************************************
1077 void convertToFeatures(const QObjectPtrList& theObjects, std::set<FeaturePtr>& theFeatures)
1079 QObjectPtrList::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
1080 for(; anIt != aLast; anIt++) {
1081 ObjectPtr anObject = *anIt;
1082 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
1083 // for parameter result, use the corresponded reature to be removed
1084 if (!aFeature.get() && anObject->groupName() == ModelAPI_ResultParameter::group()) {
1085 aFeature = ModelAPI_Feature::feature(anObject);
1088 theFeatures.insert(aFeature);
1092 //**************************************************************
1093 void convertToFolders(const QObjectPtrList& theObjects,
1094 std::set<FolderPtr>& theFolders)
1096 QObjectPtrList::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
1097 for(; anIt != aLast; anIt++) {
1098 ObjectPtr anObject = *anIt;
1099 FolderPtr aFeature = std::dynamic_pointer_cast<ModelAPI_Folder>(anObject);
1101 theFolders.insert(aFeature);
1106 //**************************************************************
1107 QString translate(const Events_InfoMessage& theMessage)
1111 if (!theMessage.empty()) {
1112 std::string aStr = Config_Translator::translate(theMessage);
1113 if (!aStr.empty()) {
1114 std::string aCodec = Config_Translator::codec(theMessage);
1115 aMessage = QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str());
1122 QString translate(const std::string& theContext, const std::string& theMessage)
1126 if (!theMessage.empty()) {
1127 std::string aStr = Config_Translator::translate(theContext, theMessage);
1128 if (!aStr.empty()) {
1129 std::string aCodec = Config_Translator::codec(theContext);
1130 aMessage = QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str());
1137 void setPointBallHighlighting(AIS_InteractiveObject* theAIS)
1139 static Handle(Image_AlienPixMap) aPixMap;
1140 if(aPixMap.IsNull()) {
1141 // Load icon for the presentation
1143 char* anEnv = getenv("SHAPER_ROOT_DIR");
1145 aFile = std::string(anEnv) +
1146 FSEP + "share" + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
1148 anEnv = getenv("CADBUILDER_ROOT_DIR");
1150 aFile = std::string(anEnv) + FSEP + "resources";
1154 static const std::string aMarkerName = "marker_dot.png";
1155 aFile += aMarkerName;
1156 aPixMap = new Image_AlienPixMap();
1157 if(!aPixMap->Load(aFile.c_str())) {
1158 // The icon for constraint is not found
1159 static const std::string aMsg =
1160 "Error: Point market not found by path: \"" + aFile + "\". Falling back.";
1161 //Events_InfoMessage("ModuleBase_Tools::setPointBallHighlighting", aMsg).send();
1165 Handle(Graphic3d_AspectMarker3d) anAspect;
1166 Handle(Prs3d_Drawer) aDrawer = theAIS->DynamicHilightAttributes();
1167 if (aDrawer.IsNull()) {
1168 if (ModuleBase_IViewer::DefaultHighlightDrawer.IsNull())
1170 aDrawer = new Prs3d_Drawer(*ModuleBase_IViewer::DefaultHighlightDrawer);
1171 if (!aDrawer->HasOwnPointAspect()) {
1172 aDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_BALL, Quantity_NOC_BLACK, 2.0));
1175 if(aDrawer->HasOwnPointAspect()) {
1176 Handle(Prs3d_PointAspect) aPntAspect = aDrawer->PointAspect();
1177 if(aPixMap->IsEmpty()) {
1178 anAspect = aPntAspect->Aspect();
1179 anAspect->SetType(Aspect_TOM_BALL);
1181 if(aPixMap->Format() == Image_PixMap::ImgGray) {
1182 aPixMap->SetFormat (Image_PixMap::ImgAlpha);
1183 } else if(aPixMap->Format() == Image_PixMap::ImgGrayF) {
1184 aPixMap->SetFormat (Image_PixMap::ImgAlphaF);
1186 anAspect = new Graphic3d_AspectMarker3d(aPixMap);
1187 aPntAspect->SetAspect(anAspect);
1189 aDrawer->SetPointAspect(aPntAspect);
1190 theAIS->SetDynamicHilightAttributes(aDrawer);
1194 FeaturePtr createParameter(const QString& theText)
1196 FeaturePtr aParameter;
1197 QStringList aList = theText.split("=");
1198 if (aList.count() != 2) {
1201 QString aParamName = aList.at(0).trimmed();
1203 if (isNameExist(aParamName, FeaturePtr())) {
1207 if (!ModelAPI_Expression::isVariable(aParamName.toStdString())) {
1211 QString aExpression = aList.at(1).trimmed();
1212 if (aExpression.isEmpty()) {
1216 SessionPtr aMgr = ModelAPI_Session::get();
1217 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
1219 aParameter = aDoc->addFeature("Parameter", false);
1220 if (aParameter.get()) {
1221 AttributeStringPtr aNameAttr = aParameter->string("variable");
1222 aNameAttr->setValue(aParamName.toStdString());
1224 AttributeStringPtr aExprAttr = aParameter->string("expression");
1225 aExprAttr->setValue(aExpression.toStdString());
1226 aParameter->execute();
1228 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
1229 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
1234 void editParameter(FeaturePtr theParam, const QString& theText)
1236 QStringList aList = theText.split("=");
1237 QString aParamName = aList.at(0).trimmed();
1239 QString aExpression = aList.at(1).trimmed();
1240 if (aExpression.isEmpty()) {
1244 if (isNameExist(aParamName, theParam)) {
1247 AttributeStringPtr aNameAttr = theParam->string("variable");
1248 aNameAttr->setValue(aParamName.toStdString());
1250 AttributeStringPtr aExprAttr = theParam->string("expression");
1251 aExprAttr->setValue(aExpression.toStdString());
1252 theParam->execute();
1254 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
1257 bool isNameExist(const QString& theName, FeaturePtr theIgnoreParameter)
1259 SessionPtr aMgr = ModelAPI_Session::get();
1260 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
1261 FeaturePtr aParamFeature;
1262 int aNbFeatures = aDoc->numInternalFeatures();
1263 std::wstring aName = theName.toStdWString();
1264 for (int i = 0; i < aNbFeatures; i++) {
1265 aParamFeature = aDoc->internalFeature(i);
1266 if (aParamFeature && aParamFeature->getKind() == "Parameter") {
1267 if ((theIgnoreParameter != aParamFeature) && (aParamFeature->name() == aName))
1274 FeaturePtr findParameter(const QString& theName)
1276 SessionPtr aMgr = ModelAPI_Session::get();
1277 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
1278 FeaturePtr aParamFeature;
1279 int aNbFeatures = aDoc->numInternalFeatures();
1280 std::wstring aName = theName.toStdWString();
1281 for (int i = 0; i < aNbFeatures; i++) {
1282 aParamFeature = aDoc->internalFeature(i);
1283 if (aParamFeature && aParamFeature->getKind() == "Parameter") {
1284 if (aParamFeature->name() == aName)
1285 return aParamFeature;
1288 return FeaturePtr();
1292 //********************************************************************
1293 std::wstring generateName(const AttributePtr& theAttribute,
1294 ModuleBase_IWorkshop* theWorkshop)
1297 if (theAttribute.get() != NULL) {
1298 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
1299 if (aFeature.get()) {
1300 std::string aXmlCfg, aDescription;
1301 theWorkshop->module()->getXMLRepresentation(aFeature->getKind(), aXmlCfg, aDescription);
1303 ModuleBase_WidgetFactory aFactory(aXmlCfg, theWorkshop);
1304 std::string anAttributeTitle;
1305 aFactory.getAttributeTitle(theAttribute->id(), anAttributeTitle);
1307 std::wstringstream aStreamName;
1308 aStreamName << theAttribute->owner()->data()->name() << "/" << anAttributeTitle.c_str();
1309 aName = aStreamName.str();
1315 bool isSameShape(const TopoDS_Shape& theShape1, const TopoDS_Shape& theShape2)
1317 // In case of compound we cannot rely on simple comparison method.
1318 // If the compound is generated by Group feature then this compound is alwais new.
1319 // So, we have to compare content of these compounds
1320 if (theShape1.ShapeType() != theShape2.ShapeType())
1323 if (theShape1.ShapeType() != TopAbs_COMPOUND)
1324 return theShape1.IsSame(theShape2);
1326 TopoDS_Iterator aIt1(theShape1);
1327 TopoDS_Iterator aIt2(theShape2);
1329 for (; aIt1.More() && aIt2.More(); aIt1.Next(), aIt2.Next()) {
1330 if (!(aIt1.Value()).IsSame(aIt2.Value()))
1336 qreal currentPixelRatio()
1338 QWindowList aWnds = qApp->topLevelWindows();
1339 if (aWnds.size() > 0)
1340 return aWnds.first()->devicePixelRatio();
1341 return qApp->primaryScreen()->devicePixelRatio();
1345 } // namespace ModuleBase_Tools