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