]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModuleBase/ModuleBase_ModelWidget.cpp
Salome HOME
#1112 tab key doesn't work on the last field of left panels
[modules/shaper.git] / src / ModuleBase / ModuleBase_ModelWidget.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        ModuleBase_ModelWidget.cpp
4 // Created:     25 Apr 2014
5 // Author:      Natalia ERMOLAEVA
6
7 #include "ModuleBase_ModelWidget.h"
8 #include "ModuleBase_Tools.h"
9
10 #include <ModelAPI_Data.h>
11 #include <ModelAPI_Attribute.h>
12 #include <ModelAPI_Events.h>
13 #include <ModelAPI_Session.h>
14
15 #include <Config_Keywords.h>
16 #include <Config_WidgetAPI.h>
17
18 #include <Events_Loop.h>
19
20 #include <QEvent>
21 #include <QLabel>
22 #include <QFocusEvent>
23
24 ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
25                                                const Config_WidgetAPI* theData,
26                                                const std::string& theParentId)
27     : QWidget(theParent),
28       myParentId(theParentId),
29       myIsEditing(false),
30       myState(Stored),
31       myIsValueStateBlocked(false)
32 {
33   myDefaultValue = theData->getProperty(ATTR_DEFAULT);
34   myUseReset = theData->getBooleanAttribute(ATTR_USE_RESET, true);
35   myIsComputedDefault = theData->getProperty(ATTR_DEFAULT) == DOUBLE_WDG_DEFAULT_COMPUTED;
36   myAttributeID = theData ? theData->widgetId() : "";
37   myIsObligatory = theData->getBooleanAttribute(ATTR_OBLIGATORY, true);
38
39   connect(this, SIGNAL(valuesChanged()), this, SLOT(onWidgetValuesChanged()));
40   connect(this, SIGNAL(valuesModified()), this, SLOT(onWidgetValuesModified()));
41 }
42
43 bool ModuleBase_ModelWidget::reset()
44 {
45   bool aResult = resetCustom();
46   if (aResult)
47     setValueState(Reset);
48
49   return aResult;
50 }
51
52 bool ModuleBase_ModelWidget::isInitialized(ObjectPtr theObject) const
53 {
54   return theObject->data()->attribute(attributeID())->isInitialized();
55 }
56
57 QString ModuleBase_ModelWidget::getValueStateError() const
58 {
59   QString anError = "";
60
61   ModuleBase_ModelWidget::ValueState aState = getValueState();
62   if (aState != ModuleBase_ModelWidget::Stored) {
63     AttributePtr anAttr = feature()->attribute(attributeID());
64     if (anAttr.get()) {
65       QString anAttributeName = anAttr->id().c_str();
66       switch (aState) {
67         case ModuleBase_ModelWidget::ModifiedInViewer:
68           anError = "Attribute \"" + anAttributeName +
69                     "\" is locked by modification value in the viewer.";
70           break;
71         case ModuleBase_ModelWidget::Reset:
72           anError = "Attribute \"" + anAttributeName + "\" is not initialized.";
73           break;
74         case ModuleBase_ModelWidget::ModifiedInPP: // Apply should be enabled in this mode
75         default:
76           break;
77       }
78     }
79   }
80   return anError;
81 }
82
83 void ModuleBase_ModelWidget::enableFocusProcessing()
84 {
85   QList<QWidget*> aMyControls = getControls();
86   foreach(QWidget*  eachControl, aMyControls) {
87     if (myIsObligatory) {
88       eachControl->setFocusPolicy(Qt::StrongFocus);
89       eachControl->installEventFilter(this);
90     }
91     else {
92       eachControl->setFocusPolicy(Qt::NoFocus);
93     }
94   }
95 }
96
97 void ModuleBase_ModelWidget::setHighlighted(bool isHighlighted)
98 {
99   QList<QWidget*> aWidgetList = getControls();
100   foreach(QWidget* aWidget, aWidgetList) {
101     QLabel* aLabel = qobject_cast<QLabel*>(aWidget);
102     // We won't set the effect to QLabels - it looks ugly
103     if(aLabel) continue;
104     // If effect is the installed on a different widget, setGraphicsEffect() will
105     // remove the effect from the widget and install it on this widget.
106     // That's why we create a new effect for each widget
107     ModuleBase_Tools::setShadowEffect(aWidget, isHighlighted);
108   }
109 }
110
111 void ModuleBase_ModelWidget::setFeature(const FeaturePtr& theFeature, const bool theToStoreValue)
112 {
113   myFeature = theFeature;
114   if (theToStoreValue)
115     storeValue();
116 }
117
118 bool ModuleBase_ModelWidget::focusTo()
119 {
120   QList<QWidget*> aControls = getControls();
121   QList<QWidget*>::const_iterator anIt = aControls.begin(), aLast = aControls.end();
122   bool isFocusAccepted = false;
123   for (; anIt != aLast && !isFocusAccepted; anIt++) {
124     QWidget* aWidget = *anIt;
125     if (aWidget && aWidget->focusPolicy() != Qt::NoFocus) {
126       ModuleBase_Tools::setFocus(aWidget, "ModuleBase_ModelWidget::focusTo()");
127       isFocusAccepted = true;
128     }
129   }
130   return isFocusAccepted;
131 }
132
133 void ModuleBase_ModelWidget::activate()
134 {
135   // the control value is stored to the mode by the focus in on the widget
136   // we need the value is initialized in order to enable the apply button in the property panel.
137   // It should happens in the creation mode only because all fields are filled in the edition mode
138   if (!isEditingMode()) {
139     AttributePtr anAttribute = myFeature->data()->attribute(myAttributeID);
140     if (anAttribute.get() != NULL && !anAttribute->isInitialized())
141       initializeValueByActivate();
142   }
143   activateCustom();
144 }
145
146 void ModuleBase_ModelWidget::deactivate()
147 {
148   myIsValueStateBlocked = false;
149   if (myState == ModifiedInPP)
150     storeValue();
151   myState = Stored;
152 }
153
154 void ModuleBase_ModelWidget::initializeValueByActivate()
155 {
156   if (isComputedDefault()) {
157     if (myFeature->compute(myAttributeID)) {
158       restoreValue();
159     }
160   }
161   else {
162     storeValue();
163   }
164 }
165
166 QWidget* ModuleBase_ModelWidget::getControlAcceptingFocus(const bool isFirst)
167 {
168   QWidget* aControl = 0;
169
170   QList<QWidget*> aControls = getControls();
171   int aSize = aControls.size();
172
173   if (isFirst) {
174     for (int i = 0; i < aSize && !aControl; i++)  {
175       if (aControls[i]->focusPolicy() != Qt::NoFocus)
176         aControl = aControls[i];
177     }
178   }
179   else {
180     for (int i = aSize - 1; i >= 0 && !aControl; i--)  {
181       if (aControls[i]->focusPolicy() != Qt::NoFocus)
182         aControl = aControls[i];
183     }
184   }
185   return aControl;
186 }
187
188 void ModuleBase_ModelWidget::setDefaultValue(const std::string& theValue)
189 {
190   myDefaultValue = theValue;
191 }
192
193 bool ModuleBase_ModelWidget::storeValue()
194 {
195   setValueState(Stored);
196
197   emit beforeValuesChanged();
198   bool isDone = storeValueCustom();
199   emit afterValuesChanged();
200
201   return isDone;
202 }
203
204 ModuleBase_ModelWidget::ValueState ModuleBase_ModelWidget::setValueState(const ModuleBase_ModelWidget::ValueState& theState)
205 {
206   ValueState aState = myState;
207   if (myState != theState && !myIsValueStateBlocked) {
208     myState = theState;
209     emit valueStateChanged(aState);
210   }
211   return aState;
212 }
213
214 bool ModuleBase_ModelWidget::blockValueState(const bool theBlocked)
215 {
216   bool isBlocked = myIsValueStateBlocked;
217   myIsValueStateBlocked = theBlocked;
218   return isBlocked;
219 }
220
221 bool ModuleBase_ModelWidget::restoreValue()
222 {
223   emit beforeValuesRestored();
224   bool isDone = restoreValueCustom();
225   emit afterValuesRestored();
226
227   return isDone;
228 }
229
230 void ModuleBase_ModelWidget::updateObject(ObjectPtr theObj)
231 {
232   blockUpdateViewer(true);
233
234   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
235
236   blockUpdateViewer(false);
237 }
238
239 void ModuleBase_ModelWidget::moveObject(ObjectPtr theObj)
240 {
241   //blockUpdateViewer(true);
242
243   static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
244   ModelAPI_EventCreator::get()->sendUpdated(theObj, anEvent);
245   Events_Loop::loop()->flush(anEvent);
246
247   //blockUpdateViewer(false);
248 }
249
250 bool ModuleBase_ModelWidget::processEnter()
251 {
252   return false;
253 }
254
255 bool ModuleBase_ModelWidget::eventFilter(QObject* theObject, QEvent *theEvent)
256 {
257   QWidget* aWidget = qobject_cast<QWidget*>(theObject);
258   if (theEvent->type() == QEvent::FocusIn) {
259     #ifdef _DEBUG
260     // The following two lines are for debugging purpose only
261     QFocusEvent* aFocusEvent = dynamic_cast<QFocusEvent*>(theEvent);
262     bool isWinFocus = aFocusEvent->reason() == Qt::ActiveWindowFocusReason;
263     #endif
264     if (getControls().contains(aWidget)) {
265       emit focusInWidget(this);
266     }
267   }
268   else if (theEvent->type() == QEvent::FocusOut) {
269     QFocusEvent* aFocusEvent = dynamic_cast<QFocusEvent*>(theEvent);
270
271     Qt::FocusReason aReason = aFocusEvent->reason();
272     bool aMouseOrKey = aReason == Qt::MouseFocusReason ||
273                         aReason == Qt::TabFocusReason ||
274                         aReason == Qt::BacktabFocusReason ||
275                         aReason == Qt::OtherFocusReason; // to process widget->setFocus()
276     if (aMouseOrKey && getControls().contains(aWidget) && getValueState() == ModifiedInPP)
277       storeValue();
278   }
279   // pass the event on to the parent class
280
281   return QObject::eventFilter(theObject, theEvent);
282 }
283
284 //**************************************************************
285 void ModuleBase_ModelWidget::onWidgetValuesChanged()
286 {
287   storeValue();
288 }
289
290 //**************************************************************
291 void ModuleBase_ModelWidget::onWidgetValuesModified()
292 {
293   setValueState(ModifiedInPP);
294 }
295
296 //**************************************************************
297 void ModuleBase_ModelWidget::blockUpdateViewer(const bool theValue)
298 {
299   // the viewer update should be blocked in order to avoid the temporary feature content
300   // when the solver processes the feature, the redisplay message can be flushed
301   // what caused the display in the viewer preliminary states of object
302   // e.g. fillet feature, angle value change
303   std::shared_ptr<Events_Message> aMsg;
304   if (theValue) {
305     aMsg = std::shared_ptr<Events_Message>(
306         new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)));
307   }
308   else {
309     // the viewer update should be unblocked
310     aMsg = std::shared_ptr<Events_Message>(
311         new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)));
312   }
313   Events_Loop::loop()->send(aMsg);
314 }