Salome HOME
5e0cd3e9837fce05a1d1cca2d2c49c42cc2bb396
[modules/shaper.git] / src / ModuleBase / ModuleBase_WidgetSelector.cpp
1 // File:        ModuleBase_WidgetSelector.h
2 // Created:     2 June 2014
3 // Author:      Vitaly Smetannikov
4
5
6 #include "ModuleBase_WidgetSelector.h"
7 #include "ModuleBase_IWorkshop.h"
8 #include "ModuleBase_Tools.h"
9
10 #include <Events_Loop.h>
11 #include <ModelAPI_Events.h>
12
13 #include <ModelAPI_Data.h>
14 #include <ModelAPI_Object.h>
15 #include <ModelAPI_Result.h>
16 #include <ModelAPI_AttributeReference.h>
17 #include <Config_WidgetAPI.h>
18
19 #include <GeomAPI_Shape.h>
20
21 #include <TopoDS_Shape.hxx>
22 #include <TopExp_Explorer.hxx>
23
24 #include <QWidget>
25 #include <QLayout>
26 #include <QLabel>
27 #include <QLineEdit>
28 #include <QToolButton>
29 #include <QString>
30 #include <QEvent>
31 #include <QDockWidget>
32
33 #include <stdexcept>
34
35
36 typedef QMap<QString, TopAbs_ShapeEnum> ShapeTypes;
37 static ShapeTypes MyShapeTypes;
38
39 TopAbs_ShapeEnum ModuleBase_WidgetSelector::shapeType(const QString& theType)
40 {
41   if (MyShapeTypes.count() == 0) {
42     MyShapeTypes["face"] = TopAbs_FACE;
43     MyShapeTypes["vertex"] = TopAbs_VERTEX;
44     MyShapeTypes["wire"] = TopAbs_WIRE;
45     MyShapeTypes["edge"] = TopAbs_EDGE;
46     MyShapeTypes["shell"] = TopAbs_SHELL;
47     MyShapeTypes["solid"] = TopAbs_SOLID;
48   }
49   if (MyShapeTypes.contains(theType)) 
50     return MyShapeTypes[theType];
51   throw std::invalid_argument("Shape type defined in XML is not implemented!");
52 }
53
54
55
56
57 ModuleBase_WidgetSelector::ModuleBase_WidgetSelector(QWidget* theParent, 
58                                                      ModuleBase_IWorkshop* theWorkshop, 
59                                                      const Config_WidgetAPI* theData)
60 : ModuleBase_ModelWidget(theParent, theData), myWorkshop(theWorkshop), myActivateOnStart(false)
61 {
62   myContainer = new QWidget(theParent);
63   QHBoxLayout* aLayout = new QHBoxLayout(myContainer);
64
65   aLayout->setContentsMargins(0, 0, 0, 0);
66   QString aLabelText = QString::fromStdString(theData->widgetLabel());
67   QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
68   myLabel = new QLabel(aLabelText, myContainer);
69   myLabel->setPixmap(QPixmap(aLabelIcon));
70
71   aLayout->addWidget(myLabel);
72
73   QString aToolTip = QString::fromStdString(theData->widgetTooltip());
74   myTextLine = new QLineEdit(myContainer);
75   myTextLine->setReadOnly(true);
76   myTextLine->setToolTip(aToolTip);
77   myTextLine->installEventFilter(this);
78
79   aLayout->addWidget(myTextLine);
80
81   myActivateBtn = new QToolButton(myContainer);
82   myActivateBtn->setIcon(QIcon(":icons/hand_point.png"));
83   myActivateBtn->setCheckable(true);
84   myActivateBtn->setToolTip(tr("Activate/Deactivate selection"));
85   connect(myActivateBtn, SIGNAL(toggled(bool)), this, SLOT(activateSelection(bool)));
86
87   aLayout->addWidget(myActivateBtn);
88
89   QString aActivateTxt = QString::fromStdString(theData->getProperty("activate"));
90   if (!aActivateTxt.isNull()) {
91     myActivateOnStart = (aActivateTxt == "true");
92   }
93
94   std::string aTypes = theData->getProperty("shape_types");
95   myShapeTypes = QString(aTypes.c_str()).split(',');
96 }
97
98 //********************************************************************
99 ModuleBase_WidgetSelector::~ModuleBase_WidgetSelector()
100 {
101 }
102
103 //********************************************************************
104 bool ModuleBase_WidgetSelector::storeValue(ObjectPtr theObject) const
105 {
106   DataPtr aData = theObject->data();
107   boost::shared_ptr<ModelAPI_AttributeReference> aRef = 
108     boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(aData->attribute(attributeID()));
109
110   ObjectPtr aObject = aRef->value();
111   if (!(aObject && aObject->isSame(mySelectedObject))) {
112     aRef->setValue(mySelectedObject);
113     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
114   }
115   return true;
116 }
117
118 //********************************************************************
119 bool ModuleBase_WidgetSelector::restoreValue(ObjectPtr theObject)
120 {
121   DataPtr aData = theObject->data();
122   boost::shared_ptr<ModelAPI_AttributeReference> aRef = aData->reference(attributeID());
123
124   bool isBlocked = this->blockSignals(true);
125   mySelectedObject = aRef->value();
126   updateSelectionName(); 
127
128   this->blockSignals(isBlocked);
129   return true;
130 }
131
132 //********************************************************************
133 QList<QWidget*> ModuleBase_WidgetSelector::getControls() const
134 {
135   QList<QWidget*> aControls;
136   aControls.append(myLabel);
137   aControls.append(myTextLine);
138   aControls.append(myActivateBtn);
139   return aControls;
140 }
141
142 //********************************************************************
143 void ModuleBase_WidgetSelector::onSelectionChanged()
144 {
145   QList<ObjectPtr> aObjects = myWorkshop->selectedObjects();
146   if (aObjects.size() > 0) {
147     ObjectPtr aObject = aObjects.first();
148     if ((!mySelectedObject) && (!aObject))
149       return;
150     if (mySelectedObject && aObject && mySelectedObject->isSame(aObject))
151       return;
152
153     // Check that the selection corresponds to selection type
154     if (!isAccepted(aObject)) return;
155
156     mySelectedObject = aObject;
157     if (mySelectedObject) {
158       updateSelectionName();
159       activateSelection(false);
160       raisePanel();
161     } else {
162       myTextLine->setText("");
163     }
164     emit valuesChanged();
165   }
166 }
167
168 //********************************************************************
169 bool ModuleBase_WidgetSelector::isAccepted(const ObjectPtr theResult) const
170 {
171   ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(theResult);
172   boost::shared_ptr<GeomAPI_Shape> aShapePtr = ModuleBase_Tools::shape(aResult);
173   if (!aShapePtr) return false;
174   TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
175   if (aShape.IsNull()) return false;
176
177   TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
178   if (aShapeType == TopAbs_COMPOUND) {
179     foreach (QString aType, myShapeTypes) {
180       TopExp_Explorer aEx(aShape, shapeType(aType));
181       if (aEx.More())
182         return true;
183     }
184   } else {
185     foreach (QString aType, myShapeTypes) {
186       if (shapeType(aType) == aShapeType)
187         return true;
188     }
189   }
190   return false;
191 }
192
193 //********************************************************************
194 void ModuleBase_WidgetSelector::updateSelectionName()
195 {
196   if (mySelectedObject) {
197     std::string aName = mySelectedObject->data()->name();
198  
199     myTextLine->setText(QString::fromStdString(aName));
200   } else 
201     myTextLine->setText("");
202 }
203
204 //********************************************************************
205 bool ModuleBase_WidgetSelector::eventFilter(QObject* theObj, QEvent* theEvent)
206 {
207   if (theObj == myTextLine) {
208     if (theEvent->type() == QEvent::Polish) {
209       activateSelection(myActivateOnStart);
210       onSelectionChanged();
211     }
212   }
213   return ModuleBase_ModelWidget::eventFilter(theObj, theEvent);
214 }
215
216 //********************************************************************
217 void ModuleBase_WidgetSelector::enableOthersControls(bool toEnable) const
218 {
219   QWidget* aParent = myContainer->parentWidget();
220   QList<QWidget*> aChldList = aParent->findChildren<QWidget*>();
221   foreach(QWidget* aWgt, aChldList) {
222     if ((aWgt != myLabel) && (aWgt != myActivateBtn) && (aWgt != myTextLine) && (aWgt != myContainer))
223       aWgt->setEnabled(toEnable);
224   }
225 }
226
227 //********************************************************************
228 void ModuleBase_WidgetSelector::activateSelection(bool toActivate)
229 {
230   enableOthersControls(!toActivate);
231   myTextLine->setEnabled(toActivate);
232
233   if (toActivate)
234     connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
235   else
236     disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
237
238   myActivateBtn->setDown(toActivate);
239 }
240
241 //********************************************************************
242 void ModuleBase_WidgetSelector::raisePanel() const
243 {
244   QWidget* aParent = myContainer->parentWidget();
245   QWidget* aLastPanel = 0;
246   while (!aParent->inherits("QDockWidget")) {
247     aLastPanel = aParent;
248     aParent = aParent->parentWidget();
249     if (!aParent) return;
250   }
251   if (aParent->inherits("QDockWidget")) {
252     QDockWidget* aTabWgt = (QDockWidget*) aParent;
253     aTabWgt->raise();
254   }
255 }