Salome HOME
Fix sketcher bugs
[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                                                      const std::string& theParentId)
61 : ModuleBase_ModelWidget(theParent, theData, theParentId), myWorkshop(theWorkshop), myActivateOnStart(false)
62 {
63   myContainer = new QWidget(theParent);
64   QHBoxLayout* aLayout = new QHBoxLayout(myContainer);
65
66   aLayout->setContentsMargins(0, 0, 0, 0);
67   QString aLabelText = QString::fromStdString(theData->widgetLabel());
68   QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
69   myLabel = new QLabel(aLabelText, myContainer);
70   myLabel->setPixmap(QPixmap(aLabelIcon));
71
72   aLayout->addWidget(myLabel);
73
74   QString aToolTip = QString::fromStdString(theData->widgetTooltip());
75   myTextLine = new QLineEdit(myContainer);
76   myTextLine->setReadOnly(true);
77   myTextLine->setToolTip(aToolTip);
78   myTextLine->installEventFilter(this);
79
80   aLayout->addWidget(myTextLine);
81
82   myActivateBtn = new QToolButton(myContainer);
83   myActivateBtn->setIcon(QIcon(":icons/hand_point.png"));
84   myActivateBtn->setCheckable(true);
85   myActivateBtn->setToolTip(tr("Activate/Deactivate selection"));
86   connect(myActivateBtn, SIGNAL(toggled(bool)), this, SLOT(activateSelection(bool)));
87
88   aLayout->addWidget(myActivateBtn);
89
90   QString aActivateTxt = QString::fromStdString(theData->getProperty("activate"));
91   if (!aActivateTxt.isNull()) {
92     myActivateOnStart = (aActivateTxt == "true");
93   }
94
95   std::string aTypes = theData->getProperty("shape_types");
96   myShapeTypes = QString(aTypes.c_str()).split(',');
97 }
98
99 //********************************************************************
100 ModuleBase_WidgetSelector::~ModuleBase_WidgetSelector()
101 {
102 }
103
104 //********************************************************************
105 bool ModuleBase_WidgetSelector::storeValue(ObjectPtr theObject) const
106 {
107   DataPtr aData = theObject->data();
108   boost::shared_ptr<ModelAPI_AttributeReference> aRef = 
109     boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(aData->attribute(attributeID()));
110
111   ObjectPtr aObject = aRef->value();
112   if (!(aObject && aObject->isSame(mySelectedObject))) {
113     aRef->setValue(mySelectedObject);
114     updateObject(theObject);
115   }
116   return true;
117 }
118
119 //********************************************************************
120 bool ModuleBase_WidgetSelector::restoreValue(ObjectPtr theObject)
121 {
122   DataPtr aData = theObject->data();
123   boost::shared_ptr<ModelAPI_AttributeReference> aRef = aData->reference(attributeID());
124
125   bool isBlocked = this->blockSignals(true);
126   mySelectedObject = aRef->value();
127   updateSelectionName(); 
128
129   this->blockSignals(isBlocked);
130   return true;
131 }
132
133 //********************************************************************
134 QList<QWidget*> ModuleBase_WidgetSelector::getControls() const
135 {
136   QList<QWidget*> aControls;
137   aControls.append(myLabel);
138   aControls.append(myTextLine);
139   aControls.append(myActivateBtn);
140   return aControls;
141 }
142
143 //********************************************************************
144 void ModuleBase_WidgetSelector::onSelectionChanged()
145 {
146   QList<ObjectPtr> aObjects = myWorkshop->selectedObjects();
147   if (aObjects.size() > 0) {
148     ObjectPtr aObject = aObjects.first();
149     if ((!mySelectedObject) && (!aObject))
150       return;
151     if (mySelectedObject && aObject && mySelectedObject->isSame(aObject))
152       return;
153
154     // Check that the selection corresponds to selection type
155     if (!isAccepted(aObject)) return;
156
157     mySelectedObject = aObject;
158     if (mySelectedObject) {
159       updateSelectionName();
160       activateSelection(false);
161       raisePanel();
162     } else {
163       myTextLine->setText("");
164     }
165     emit valuesChanged();
166   }
167 }
168
169 //********************************************************************
170 bool ModuleBase_WidgetSelector::isAccepted(const ObjectPtr theResult) const
171 {
172   ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(theResult);
173   boost::shared_ptr<GeomAPI_Shape> aShapePtr = ModuleBase_Tools::shape(aResult);
174   if (!aShapePtr) return false;
175   TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
176   if (aShape.IsNull()) return false;
177
178   TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
179   if (aShapeType == TopAbs_COMPOUND) {
180     foreach (QString aType, myShapeTypes) {
181       TopExp_Explorer aEx(aShape, shapeType(aType));
182       if (aEx.More())
183         return true;
184     }
185   } else {
186     foreach (QString aType, myShapeTypes) {
187       if (shapeType(aType) == aShapeType)
188         return true;
189     }
190   }
191   return false;
192 }
193
194 //********************************************************************
195 void ModuleBase_WidgetSelector::updateSelectionName()
196 {
197   if (mySelectedObject) {
198     std::string aName = mySelectedObject->data()->name();
199  
200     myTextLine->setText(QString::fromStdString(aName));
201   } else 
202     myTextLine->setText("");
203 }
204
205 //********************************************************************
206 bool ModuleBase_WidgetSelector::eventFilter(QObject* theObj, QEvent* theEvent)
207 {
208   if (theObj == myTextLine) {
209     if (theEvent->type() == QEvent::Polish) {
210       activateSelection(myActivateOnStart);
211       onSelectionChanged();
212     }
213   }
214   return ModuleBase_ModelWidget::eventFilter(theObj, theEvent);
215 }
216
217 //********************************************************************
218 void ModuleBase_WidgetSelector::enableOthersControls(bool toEnable) const
219 {
220   QWidget* aParent = myContainer->parentWidget();
221   QList<QWidget*> aChldList = aParent->findChildren<QWidget*>();
222   foreach(QWidget* aWgt, aChldList) {
223     if ((aWgt != myLabel) && (aWgt != myActivateBtn) && (aWgt != myTextLine) && (aWgt != myContainer))
224       aWgt->setEnabled(toEnable);
225   }
226 }
227
228 //********************************************************************
229 void ModuleBase_WidgetSelector::activateSelection(bool toActivate)
230 {
231   enableOthersControls(!toActivate);
232   myTextLine->setEnabled(toActivate);
233
234   if (toActivate)
235     connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
236   else
237     disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
238
239   myActivateBtn->setDown(toActivate);
240 }
241
242 //********************************************************************
243 void ModuleBase_WidgetSelector::raisePanel() const
244 {
245   QWidget* aParent = myContainer->parentWidget();
246   QWidget* aLastPanel = 0;
247   while (!aParent->inherits("QDockWidget")) {
248     aLastPanel = aParent;
249     aParent = aParent->parentWidget();
250     if (!aParent) return;
251   }
252   if (aParent->inherits("QDockWidget")) {
253     QDockWidget* aTabWgt = (QDockWidget*) aParent;
254     aTabWgt->raise();
255   }
256 }