Salome HOME
Translation of sketch operations
[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_ViewerPrs.h"
9 #include "ModuleBase_Tools.h"
10 #include "ModuleBase_WidgetValidator.h"
11
12 #include <ModelAPI_Data.h>
13 #include <ModelAPI_Attribute.h>
14 #include <ModelAPI_Events.h>
15 #include <ModelAPI_Session.h>
16 #include <ModelAPI_Validator.h>
17
18 #include <Config_Keywords.h>
19 #include <Config_WidgetAPI.h>
20 #include <Config_Translator.h>
21
22 #include <Events_Loop.h>
23
24 #include <QEvent>
25 #include <QLabel>
26 #include <QFocusEvent>
27 #include <QTextCodec>
28
29 //#define DEBUG_VALUE_STATE
30
31 //#define DEBUG_WIDGET_INSTANCE
32
33 ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
34                                                const Config_WidgetAPI* theData)
35     : QWidget(theParent),
36       myIsEditing(false),
37       myState(Stored),
38       myIsValueStateBlocked(false),
39       myFlushUpdateBlocked(false),
40       myWidgetValidator(0)
41 {
42 #ifdef DEBUG_WIDGET_INSTANCE
43   qDebug("ModuleBase_ModelWidget::ModuleBase_ModelWidget");
44 #endif
45
46   myIsInternal = theData->getBooleanAttribute(ATTR_INTERNAL, false);
47
48   myDefaultValue = theData->getProperty(ATTR_DEFAULT);
49   myUseReset = theData->getBooleanAttribute(ATTR_USE_RESET, true);
50   myIsComputedDefault = theData->getProperty(ATTR_DEFAULT) == DOUBLE_WDG_DEFAULT_COMPUTED;
51   myAttributeID = theData ? theData->widgetId() : "";
52   myIsObligatory = theData->getBooleanAttribute(ATTR_OBLIGATORY, true);
53
54   connect(this, SIGNAL(valuesChanged()), this, SLOT(onWidgetValuesChanged()));
55   connect(this, SIGNAL(valuesModified()), this, SLOT(onWidgetValuesModified()));
56 }
57
58 ModuleBase_ModelWidget::~ModuleBase_ModelWidget()
59 {
60 #ifdef DEBUG_WIDGET_INSTANCE
61   qDebug("ModuleBase_ModelWidget::~ModuleBase_ModelWidget");
62 #endif
63 }
64
65 bool ModuleBase_ModelWidget::reset()
66 {
67   bool aResult = resetCustom();
68   if (aResult)
69     setValueState(Reset);
70
71   return aResult;
72 }
73
74 bool ModuleBase_ModelWidget::isInitialized(ObjectPtr theObject) const
75 {
76   return theObject->data()->attribute(attributeID())->isInitialized();
77 }
78
79 void ModuleBase_ModelWidget::processValueState()
80 {
81   if (myState == ModifiedInPP || myState == ModifiedInViewer)
82     storeValue();
83 }
84
85 QString ModuleBase_ModelWidget::getValueStateError() const
86 {
87   QString anError = "";
88
89   ModuleBase_ModelWidget::ValueState aState = getValueState();
90   if (aState != ModuleBase_ModelWidget::Stored) {
91     AttributePtr anAttr = feature()->attribute(attributeID());
92     if (anAttr.get()) {
93       QString anAttributeName = anAttr->id().c_str();
94       switch (aState) {
95         case ModuleBase_ModelWidget::ModifiedInViewer:
96           anError = "Attribute \"" + anAttributeName +
97                     "\" is locked by modification value in the viewer.";
98           break;
99         case ModuleBase_ModelWidget::Reset:
100           anError = "Attribute \"" + anAttributeName + "\" is not initialized.";
101           break;
102         case ModuleBase_ModelWidget::ModifiedInPP: // Apply should be enabled in this mode
103         default:
104           break;
105       }
106     }
107   }
108   return anError;
109 }
110
111 QString ModuleBase_ModelWidget::getError(const bool theValueStateChecked) const
112 {
113   QString anError;
114
115   if (!feature().get())
116     return anError;
117
118   std::string anAttributeID = attributeID();
119   AttributePtr anAttribute = feature()->attribute(anAttributeID);
120   if (!anAttribute.get())
121     return anError;
122
123   std::string aValidatorID;
124   std::string anErrorMsg;
125
126   static ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
127   if (!aValidators->validate(anAttribute, aValidatorID, anErrorMsg)) {
128     if (anErrorMsg.empty())
129       anErrorMsg = "unknown error.";
130     anErrorMsg = anAttributeID + " - " + aValidatorID + ": " + anErrorMsg;
131   }
132
133   anError = QString::fromStdString(anErrorMsg);
134   if (anError.isEmpty() && theValueStateChecked)
135     anError = getValueStateError();
136
137   anError = translateString(anError);
138   return anError;
139 }
140
141
142 QString ModuleBase_ModelWidget::translateString(const QString& theMsg) const
143 {
144   if (!theMsg.isEmpty()) {
145     std::string aContext = feature()->getKind();
146     std::string aStr = Config_Translator::translate(aContext, theMsg.toStdString().c_str());
147     std::string aCodec = Config_Translator::codec(aContext);
148     return QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str());
149   }
150   return theMsg;
151 }
152
153
154 void ModuleBase_ModelWidget::enableFocusProcessing()
155 {
156   QList<QWidget*> aMyControls = getControls();
157   foreach(QWidget*  eachControl, aMyControls) {
158       eachControl->setFocusPolicy(Qt::StrongFocus);
159       eachControl->installEventFilter(this);
160   }
161 }
162
163 void ModuleBase_ModelWidget::setHighlighted(bool isHighlighted)
164 {
165   QList<QWidget*> aWidgetList = getControls();
166   foreach(QWidget* aWidget, aWidgetList) {
167     QLabel* aLabel = qobject_cast<QLabel*>(aWidget);
168     // We won't set the effect to QLabels - it looks ugly
169     if(aLabel) continue;
170     // If effect is the installed on a different widget, setGraphicsEffect() will
171     // remove the effect from the widget and install it on this widget.
172     // That's why we create a new effect for each widget
173     ModuleBase_Tools::setShadowEffect(aWidget, isHighlighted);
174   }
175 }
176
177 void ModuleBase_ModelWidget::setFeature(const FeaturePtr& theFeature, const bool theToStoreValue,
178                                         const bool isUpdateFlushed)
179 {
180   /// it is possible to give this flag as parameter in storeValue/storeCustomValue
181   /// after debug, it may be corrected
182   myFlushUpdateBlocked = !isUpdateFlushed;
183   myFeature = theFeature;
184   if (theToStoreValue)
185     storeValue();
186   myFlushUpdateBlocked = false;
187 }
188
189 bool ModuleBase_ModelWidget::focusTo()
190 {
191 #ifdef DEBUG_WIDGET_INSTANCE
192   qDebug("ModuleBase_ModelWidget::focusTo");
193 #endif
194   QList<QWidget*> aControls = getControls();
195   QList<QWidget*>::const_iterator anIt = aControls.begin(), aLast = aControls.end();
196   bool isFocusAccepted = false;
197   for (; anIt != aLast && !isFocusAccepted; anIt++) {
198     QWidget* aWidget = *anIt;
199     if (aWidget && aWidget->focusPolicy() != Qt::NoFocus) {
200       ModuleBase_Tools::setFocus(aWidget, "ModuleBase_ModelWidget::focusTo()");
201       isFocusAccepted = true;
202     }
203   }
204   return isFocusAccepted;
205 }
206
207 void ModuleBase_ModelWidget::activate()
208 {
209 #ifdef DEBUG_WIDGET_INSTANCE
210   qDebug("ModuleBase_ModelWidget::activate");
211 #endif
212   // the control value is stored to the mode by the focus in on the widget
213   // we need the value is initialized in order to enable the apply button in the property panel.
214   // It should happens in the creation mode only because all fields are filled in the edition mode
215   if (!isEditingMode()) {
216     AttributePtr anAttribute = myFeature->data()->attribute(myAttributeID);
217     if (anAttribute.get() != NULL && !anAttribute->isInitialized())
218       initializeValueByActivate();
219   }
220
221   if (myWidgetValidator)
222     myWidgetValidator->activateFilters(true);
223
224   activateCustom();
225 }
226
227 void ModuleBase_ModelWidget::deactivate()
228 {
229 #ifdef DEBUG_WIDGET_INSTANCE
230   qDebug("ModuleBase_ModelWidget::deactivate");
231 #endif
232   myIsValueStateBlocked = false;
233   myState = Stored;
234   if (myWidgetValidator)
235     myWidgetValidator->activateFilters(false);
236 }
237
238 void ModuleBase_ModelWidget::initializeValueByActivate()
239 {
240   if (isComputedDefault()) {
241     if (myFeature->compute(myAttributeID)) {
242       restoreValue();
243     }
244   }
245   else {
246     storeValue();
247   }
248 }
249
250 QWidget* ModuleBase_ModelWidget::getControlAcceptingFocus(const bool isFirst)
251 {
252   QWidget* aControl = 0;
253
254   QList<QWidget*> aControls = getControls();
255   int aSize = aControls.size();
256
257   if (isFirst) {
258     for (int i = 0; i < aSize && !aControl; i++)  {
259       if (aControls[i]->focusPolicy() != Qt::NoFocus)
260         aControl = aControls[i];
261     }
262   }
263   else {
264     for (int i = aSize - 1; i >= 0 && !aControl; i--)  {
265       if (aControls[i]->focusPolicy() != Qt::NoFocus)
266         aControl = aControls[i];
267     }
268   }
269   return aControl;
270 }
271
272 void ModuleBase_ModelWidget::setDefaultValue(const std::string& theValue)
273 {
274   myDefaultValue = theValue;
275 }
276
277 bool ModuleBase_ModelWidget::storeValue()
278 {
279   setValueState(Stored);
280
281   emit beforeValuesChanged();
282   bool isDone = storeValueCustom();
283   emit afterValuesChanged();
284
285   return isDone;
286 }
287 #ifdef DEBUG_VALUE_STATE
288 std::string getDebugInfo(const ModuleBase_ModelWidget::ValueState& theState)
289 {
290   std::string anInfo;
291   switch (theState) {
292     case ModuleBase_ModelWidget::Stored:           anInfo = "Stored          "; break;
293     case ModuleBase_ModelWidget::ModifiedInPP:     anInfo = "ModifiedInPP    "; break;
294     case ModuleBase_ModelWidget::ModifiedInViewer: anInfo = "ModifiedInViewer"; break;
295     case ModuleBase_ModelWidget::Reset:            anInfo = "Reset           "; break;
296     default: break;
297   }
298   return anInfo;
299 }
300
301 #endif
302 ModuleBase_ModelWidget::ValueState ModuleBase_ModelWidget::setValueState
303                                          (const ModuleBase_ModelWidget::ValueState& theState)
304 {
305   ValueState aState = myState;
306
307   if (myState != theState && !myIsValueStateBlocked) {
308 #ifdef DEBUG_VALUE_STATE
309     qDebug(QString("setValueState: previous state = %1,\t new state = %2")
310            .arg(getDebugInfo(myState).c_str())
311            .arg(getDebugInfo(theState).c_str()).toStdString().c_str());
312 #endif
313     myState = theState;
314     emit valueStateChanged(aState);
315   }
316   return aState;
317 }
318
319 bool ModuleBase_ModelWidget::blockValueState(const bool theBlocked)
320 {
321   bool isBlocked = myIsValueStateBlocked;
322   myIsValueStateBlocked = theBlocked;
323   return isBlocked;
324 }
325
326 bool ModuleBase_ModelWidget::restoreValue()
327 {
328   emit beforeValuesRestored();
329   bool isDone = restoreValueCustom();
330   emit afterValuesRestored();
331
332   return isDone;
333 }
334
335 void ModuleBase_ModelWidget::updateObject(ObjectPtr theObject)
336 {
337   if (!myFlushUpdateBlocked) {
338 #ifdef DEBUG_WIDGET_INSTANCE
339     qDebug("ModuleBase_ModelWidget::updateObject");
340 #endif
341     ModuleBase_Tools::flushUpdated(theObject);
342     emit objectUpdated();
343   }
344 }
345
346 void ModuleBase_ModelWidget::moveObject(ObjectPtr theObj)
347 {
348   //blockUpdateViewer(true);
349 #ifdef DEBUG_WIDGET_INSTANCE
350   qDebug("ModuleBase_ModelWidget::moveObject");
351 #endif
352
353   static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
354   ModelAPI_EventCreator::get()->sendUpdated(theObj, anEvent);
355   Events_Loop::loop()->flush(anEvent);
356
357   //blockUpdateViewer(false);
358 }
359
360 bool ModuleBase_ModelWidget::processEnter()
361 {
362   return false;
363 }
364
365 bool ModuleBase_ModelWidget::processDelete()
366 {
367   // we consider that model objects eats delete key in order to
368   // do nothing by for example symbol delete in line edit or spin box
369   return true;
370 }
371
372 bool ModuleBase_ModelWidget::eventFilter(QObject* theObject, QEvent *theEvent)
373 {
374   QWidget* aWidget = qobject_cast<QWidget*>(theObject);
375   if (theEvent->type() == QEvent::FocusIn) {
376     #ifdef _DEBUG
377     // The following two lines are for debugging purpose only
378     QFocusEvent* aFocusEvent = dynamic_cast<QFocusEvent*>(theEvent);
379     bool isWinFocus = aFocusEvent->reason() == Qt::ActiveWindowFocusReason;
380     #endif
381     if (getControls().contains(aWidget)) {
382       emit focusInWidget(this);
383     }
384   }
385   else if (theEvent->type() == QEvent::FocusOut) {
386     QFocusEvent* aFocusEvent = dynamic_cast<QFocusEvent*>(theEvent);
387
388     Qt::FocusReason aReason = aFocusEvent->reason();
389     bool aMouseOrKey = aReason == Qt::MouseFocusReason ||
390                         aReason == Qt::TabFocusReason ||
391                         aReason == Qt::BacktabFocusReason ||
392                         aReason == Qt::OtherFocusReason; // to process widget->setFocus()
393     if (aMouseOrKey && getControls().contains(aWidget)) {
394       if (getValueState() == ModifiedInPP) {
395         storeValue();
396       }
397     }
398   }
399   // pass the event on to the parent class
400
401   return QObject::eventFilter(theObject, theEvent);
402 }
403
404 //**************************************************************
405 void ModuleBase_ModelWidget::onWidgetValuesChanged()
406 {
407   storeValue();
408 }
409
410 //**************************************************************
411 void ModuleBase_ModelWidget::onWidgetValuesModified()
412 {
413   setValueState(ModifiedInPP);
414 }