1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: ModuleBase_ModelWidget.cpp
4 // Created: 25 Apr 2014
5 // Author: Natalia ERMOLAEVA
7 #include "ModuleBase_ModelWidget.h"
8 #include "ModuleBase_Tools.h"
10 #include <ModelAPI_Data.h>
11 #include <ModelAPI_Attribute.h>
12 #include <ModelAPI_Events.h>
13 #include <ModelAPI_Session.h>
14 #include <ModelAPI_Validator.h>
16 #include <Config_Keywords.h>
17 #include <Config_WidgetAPI.h>
19 #include <Events_Loop.h>
23 #include <QFocusEvent>
25 //#define DEBUG_VALUE_STATE
27 ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
28 const Config_WidgetAPI* theData,
29 const std::string& theParentId)
31 myParentId(theParentId),
34 myIsValueStateBlocked(false)
36 myIsInternal = theData->getBooleanAttribute(ATTR_INTERNAL, false);
38 myDefaultValue = theData->getProperty(ATTR_DEFAULT);
39 myUseReset = theData->getBooleanAttribute(ATTR_USE_RESET, true);
40 myIsComputedDefault = theData->getProperty(ATTR_DEFAULT) == DOUBLE_WDG_DEFAULT_COMPUTED;
41 myAttributeID = theData ? theData->widgetId() : "";
42 myIsObligatory = theData->getBooleanAttribute(ATTR_OBLIGATORY, true);
44 connect(this, SIGNAL(valuesChanged()), this, SLOT(onWidgetValuesChanged()));
45 connect(this, SIGNAL(valuesModified()), this, SLOT(onWidgetValuesModified()));
48 bool ModuleBase_ModelWidget::reset()
50 bool aResult = resetCustom();
57 bool ModuleBase_ModelWidget::isInitialized(ObjectPtr theObject) const
59 return theObject->data()->attribute(attributeID())->isInitialized();
62 QString ModuleBase_ModelWidget::getValueStateError() const
66 ModuleBase_ModelWidget::ValueState aState = getValueState();
67 if (aState != ModuleBase_ModelWidget::Stored) {
68 AttributePtr anAttr = feature()->attribute(attributeID());
70 QString anAttributeName = anAttr->id().c_str();
72 case ModuleBase_ModelWidget::ModifiedInViewer:
73 anError = "Attribute \"" + anAttributeName +
74 "\" is locked by modification value in the viewer.";
76 case ModuleBase_ModelWidget::Reset:
77 anError = "Attribute \"" + anAttributeName + "\" is not initialized.";
79 case ModuleBase_ModelWidget::ModifiedInPP: // Apply should be enabled in this mode
88 QString ModuleBase_ModelWidget::getError() const
95 std::string anAttributeID = attributeID();
96 AttributePtr anAttribute = feature()->attribute(anAttributeID);
97 if (!anAttribute.get())
100 std::string aValidatorID;
101 std::string anErrorMsg;
103 static ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
104 if (!aValidators->validate(anAttribute, aValidatorID, anErrorMsg)) {
105 if (anErrorMsg.empty())
106 anErrorMsg = "unknown error.";
107 anErrorMsg = anAttributeID + " - " + aValidatorID + ": " + anErrorMsg;
110 anError = QString::fromStdString(anErrorMsg);
111 if (anError.isEmpty())
112 anError = getValueStateError();
117 void ModuleBase_ModelWidget::enableFocusProcessing()
119 QList<QWidget*> aMyControls = getControls();
120 foreach(QWidget* eachControl, aMyControls) {
121 eachControl->setFocusPolicy(Qt::StrongFocus);
122 eachControl->installEventFilter(this);
126 void ModuleBase_ModelWidget::setHighlighted(bool isHighlighted)
128 QList<QWidget*> aWidgetList = getControls();
129 foreach(QWidget* aWidget, aWidgetList) {
130 QLabel* aLabel = qobject_cast<QLabel*>(aWidget);
131 // We won't set the effect to QLabels - it looks ugly
133 // If effect is the installed on a different widget, setGraphicsEffect() will
134 // remove the effect from the widget and install it on this widget.
135 // That's why we create a new effect for each widget
136 ModuleBase_Tools::setShadowEffect(aWidget, isHighlighted);
140 void ModuleBase_ModelWidget::setFeature(const FeaturePtr& theFeature, const bool theToStoreValue)
142 myFeature = theFeature;
147 bool ModuleBase_ModelWidget::focusTo()
149 QList<QWidget*> aControls = getControls();
150 QList<QWidget*>::const_iterator anIt = aControls.begin(), aLast = aControls.end();
151 bool isFocusAccepted = false;
152 for (; anIt != aLast && !isFocusAccepted; anIt++) {
153 QWidget* aWidget = *anIt;
154 if (aWidget && aWidget->focusPolicy() != Qt::NoFocus) {
155 ModuleBase_Tools::setFocus(aWidget, "ModuleBase_ModelWidget::focusTo()");
156 isFocusAccepted = true;
159 return isFocusAccepted;
162 void ModuleBase_ModelWidget::activate()
164 // the control value is stored to the mode by the focus in on the widget
165 // we need the value is initialized in order to enable the apply button in the property panel.
166 // It should happens in the creation mode only because all fields are filled in the edition mode
167 if (!isEditingMode()) {
168 AttributePtr anAttribute = myFeature->data()->attribute(myAttributeID);
169 if (anAttribute.get() != NULL && !anAttribute->isInitialized())
170 initializeValueByActivate();
175 void ModuleBase_ModelWidget::deactivate()
177 myIsValueStateBlocked = false;
178 if (myState == ModifiedInPP || myState == ModifiedInViewer)
183 void ModuleBase_ModelWidget::initializeValueByActivate()
185 if (isComputedDefault()) {
186 if (myFeature->compute(myAttributeID)) {
195 QWidget* ModuleBase_ModelWidget::getControlAcceptingFocus(const bool isFirst)
197 QWidget* aControl = 0;
199 QList<QWidget*> aControls = getControls();
200 int aSize = aControls.size();
203 for (int i = 0; i < aSize && !aControl; i++) {
204 if (aControls[i]->focusPolicy() != Qt::NoFocus)
205 aControl = aControls[i];
209 for (int i = aSize - 1; i >= 0 && !aControl; i--) {
210 if (aControls[i]->focusPolicy() != Qt::NoFocus)
211 aControl = aControls[i];
217 void ModuleBase_ModelWidget::setDefaultValue(const std::string& theValue)
219 myDefaultValue = theValue;
222 bool ModuleBase_ModelWidget::storeValue()
224 setValueState(Stored);
226 emit beforeValuesChanged();
227 bool isDone = storeValueCustom();
228 emit afterValuesChanged();
232 #ifdef DEBUG_VALUE_STATE
233 std::string getDebugInfo(const ModuleBase_ModelWidget::ValueState& theState)
237 case ModuleBase_ModelWidget::Stored: anInfo = "Stored "; break;
238 case ModuleBase_ModelWidget::ModifiedInPP: anInfo = "ModifiedInPP "; break;
239 case ModuleBase_ModelWidget::ModifiedInViewer: anInfo = "ModifiedInViewer"; break;
240 case ModuleBase_ModelWidget::Reset: anInfo = "Reset "; break;
247 ModuleBase_ModelWidget::ValueState ModuleBase_ModelWidget::setValueState
248 (const ModuleBase_ModelWidget::ValueState& theState)
250 ValueState aState = myState;
252 if (myState != theState && !myIsValueStateBlocked) {
253 #ifdef DEBUG_VALUE_STATE
254 qDebug(QString("setValueState: previous state = %1,\t new state = %2")
255 .arg(getDebugInfo(myState).c_str())
256 .arg(getDebugInfo(theState).c_str()).toStdString().c_str());
259 emit valueStateChanged(aState);
264 bool ModuleBase_ModelWidget::blockValueState(const bool theBlocked)
266 bool isBlocked = myIsValueStateBlocked;
267 myIsValueStateBlocked = theBlocked;
271 bool ModuleBase_ModelWidget::restoreValue()
273 emit beforeValuesRestored();
274 bool isDone = restoreValueCustom();
275 emit afterValuesRestored();
280 void ModuleBase_ModelWidget::updateObject(ObjectPtr theObj)
282 blockUpdateViewer(true);
284 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
286 blockUpdateViewer(false);
289 void ModuleBase_ModelWidget::moveObject(ObjectPtr theObj)
291 //blockUpdateViewer(true);
293 static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
294 ModelAPI_EventCreator::get()->sendUpdated(theObj, anEvent);
295 Events_Loop::loop()->flush(anEvent);
297 //blockUpdateViewer(false);
300 bool ModuleBase_ModelWidget::processEnter()
305 bool ModuleBase_ModelWidget::processDelete()
307 // we consider that model objects eats delete key in order to
308 // do nothing by for example symbol delete in line edit or spin box
312 bool ModuleBase_ModelWidget::eventFilter(QObject* theObject, QEvent *theEvent)
314 QWidget* aWidget = qobject_cast<QWidget*>(theObject);
315 if (theEvent->type() == QEvent::FocusIn) {
317 // The following two lines are for debugging purpose only
318 QFocusEvent* aFocusEvent = dynamic_cast<QFocusEvent*>(theEvent);
319 bool isWinFocus = aFocusEvent->reason() == Qt::ActiveWindowFocusReason;
321 if (getControls().contains(aWidget)) {
322 emit focusInWidget(this);
325 else if (theEvent->type() == QEvent::FocusOut) {
326 QFocusEvent* aFocusEvent = dynamic_cast<QFocusEvent*>(theEvent);
328 Qt::FocusReason aReason = aFocusEvent->reason();
329 bool aMouseOrKey = aReason == Qt::MouseFocusReason ||
330 aReason == Qt::TabFocusReason ||
331 aReason == Qt::BacktabFocusReason ||
332 aReason == Qt::OtherFocusReason; // to process widget->setFocus()
333 if (aMouseOrKey && getControls().contains(aWidget)) {
334 if (getValueState() == ModifiedInPP) {
339 // pass the event on to the parent class
341 return QObject::eventFilter(theObject, theEvent);
344 //**************************************************************
345 void ModuleBase_ModelWidget::onWidgetValuesChanged()
350 //**************************************************************
351 void ModuleBase_ModelWidget::onWidgetValuesModified()
353 setValueState(ModifiedInPP);
356 //**************************************************************
357 void ModuleBase_ModelWidget::blockUpdateViewer(const bool theValue)
359 // the viewer update should be blocked in order to avoid the temporary feature content
360 // when the solver processes the feature, the redisplay message can be flushed
361 // what caused the display in the viewer preliminary states of object
362 // e.g. fillet feature, angle value change
363 std::shared_ptr<Events_Message> aMsg;
365 aMsg = std::shared_ptr<Events_Message>(
366 new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)));
369 // the viewer update should be unblocked
370 aMsg = std::shared_ptr<Events_Message>(
371 new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)));
373 Events_Loop::loop()->send(aMsg);