1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
20 #include "ModuleBase_ModelWidget.h"
21 #include "ModuleBase_IPropertyPanel.h"
22 #include "ModuleBase_ViewerPrs.h"
23 #include "ModuleBase_Tools.h"
24 #include "ModuleBase_WidgetValidator.h"
26 #include <Events_InfoMessage.h>
28 #include <ModelAPI_Data.h>
29 #include <ModelAPI_Attribute.h>
30 #include <ModelAPI_Events.h>
31 #include <ModelAPI_Session.h>
32 #include <ModelAPI_Validator.h>
34 #include <Config_Keywords.h>
35 #include <Config_WidgetAPI.h>
36 #include <Config_Translator.h>
37 #include <Config_PropManager.h>
39 #include <Events_Loop.h>
43 #include <QFocusEvent>
46 //#define DEBUG_VALUE_STATE
48 //#define DEBUG_WIDGET_INSTANCE
49 //#define DEBUG_ENABLE_SKETCH_INPUT_FIELDS
51 ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
52 const Config_WidgetAPI* theData)
56 myIsValueStateBlocked(false),
57 myFlushUpdateBlocked(false),
60 #ifdef DEBUG_WIDGET_INSTANCE
61 qDebug("ModuleBase_ModelWidget::ModuleBase_ModelWidget");
64 myFeatureId = theData->featureId();
66 myIsInternal = theData->getBooleanAttribute(ATTR_INTERNAL, false);
68 myIsModifiedInEdit = theData->getProperty(ATTR_MODIFIED_IN_EDIT);
70 myDefaultValue = theData->getProperty(ATTR_DEFAULT);
71 myUseReset = theData->getBooleanAttribute(ATTR_USE_RESET, true);
72 myIsComputedDefault = theData->getProperty(ATTR_DEFAULT) == DOUBLE_WDG_DEFAULT_COMPUTED;
73 myAttributeID = theData ? theData->widgetId() : "";
74 myIsObligatory = theData->getBooleanAttribute(ATTR_OBLIGATORY, true);
76 myIsValueEnabled = On; // not defined or "true"
77 std::string anEnableValue = theData->getProperty(DOUBLE_WDG_ENABLE_VALUE);
78 if (anEnableValue == "false")
79 myIsValueEnabled = Off;
80 if (anEnableValue == DOUBLE_WDG_ENABLE_VALUE_BY_PREFERENCES)
81 myIsValueEnabled = DefinedInPreferences;
83 connect(this, SIGNAL(valuesChanged()), this, SLOT(onWidgetValuesChanged()));
84 connect(this, SIGNAL(valuesModified()), this, SLOT(onWidgetValuesModified()));
87 ModuleBase_ModelWidget::~ModuleBase_ModelWidget()
89 #ifdef DEBUG_WIDGET_INSTANCE
90 qDebug("ModuleBase_ModelWidget::~ModuleBase_ModelWidget");
94 bool ModuleBase_ModelWidget::reset()
96 bool aResult = resetCustom();
103 bool ModuleBase_ModelWidget::isInitialized(ObjectPtr theObject) const
105 return theObject->data()->attribute(attributeID())->isInitialized();
108 bool ModuleBase_ModelWidget::isValueEnabled() const
110 bool anEnabled = true;
111 if (myIsValueEnabled == DefinedInPreferences) {
112 #ifdef DEBUG_ENABLE_SKETCH_INPUT_FIELDS
113 bool aCanDisable = false;
115 //Config_PropManager::boolean(SKETCH_TAB_NAME, "disable_input_fields", "true");
116 bool aCanDisable = true;
121 else if (myIsValueEnabled == Off)
126 void ModuleBase_ModelWidget::processValueState()
128 if (myState == ModifiedInPP || myState == ModifiedInViewer)
132 Events_InfoMessage ModuleBase_ModelWidget::getValueStateError() const
134 Events_InfoMessage aMessage;
136 ModuleBase_ModelWidget::ValueState aState = getValueState();
137 if (aState != ModuleBase_ModelWidget::Stored) {
138 AttributePtr anAttr = feature()->attribute(attributeID());
140 const std::string& anAttributeName = anAttr->id();
142 case ModuleBase_ModelWidget::ModifiedInViewer:
143 aMessage = "Attribute \"%1\" is locked by modification value in the viewer.";
144 aMessage.addParameter(anAttributeName);
146 case ModuleBase_ModelWidget::Reset:
147 aMessage = "Attribute \"%1\" is not initialized.";
148 aMessage.addParameter(anAttributeName);
150 case ModuleBase_ModelWidget::ModifiedInPP: // Apply should be enabled in this mode
159 QString ModuleBase_ModelWidget::getError(const bool theValueStateChecked) const
163 if (!feature().get())
166 std::string aFeatureID = feature()->getKind();
167 std::string anAttributeID = attributeID();
168 AttributePtr anAttribute = feature()->attribute(anAttributeID);
169 if (!anAttribute.get())
172 std::string aValidatorID;
173 Events_InfoMessage anErrorMsg;
175 static ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
176 if (!aValidators->validate(anAttribute, aValidatorID, anErrorMsg)) {
177 if (anErrorMsg.empty())
178 anErrorMsg = "Unknown error.";
180 if (anErrorMsg.context().empty()) {
181 anErrorMsg.setContext(aFeatureID + ":" + anAttributeID + ":" + aValidatorID);
185 if (anErrorMsg.empty() && theValueStateChecked) {
186 anErrorMsg = getValueStateError();
189 if (!anErrorMsg.empty()) {
190 anError = ModuleBase_Tools::translate(anErrorMsg);
196 void ModuleBase_ModelWidget::enableFocusProcessing()
198 QList<QWidget*> aMyControls = getControls();
199 foreach(QWidget* eachControl, aMyControls) {
200 eachControl->setFocusPolicy(Qt::StrongFocus);
201 eachControl->installEventFilter(this);
205 void ModuleBase_ModelWidget::setHighlighted(bool isHighlighted)
207 QList<QWidget*> aWidgetList = getControls();
208 foreach(QWidget* aWidget, aWidgetList) {
209 QLabel* aLabel = qobject_cast<QLabel*>(aWidget);
210 // We won't set the effect to QLabels - it looks ugly
212 // If effect is the installed on a different widget, setGraphicsEffect() will
213 // remove the effect from the widget and install it on this widget.
214 // That's why we create a new effect for each widget
215 ModuleBase_Tools::setShadowEffect(aWidget, isHighlighted);
219 void ModuleBase_ModelWidget::setFeature(const FeaturePtr& theFeature, const bool theToStoreValue,
220 const bool isUpdateFlushed)
222 /// it is possible to give this flag as parameter in storeValue/storeCustomValue
223 /// after debug, it may be corrected
224 myFlushUpdateBlocked = !isUpdateFlushed;
225 myFeature = theFeature;
226 if (theToStoreValue) {
227 /// it is possible that the attribute is filled before the operation is started,
228 /// e.g. by reentrant operation case some attributes are filled by values of
229 /// feature of previous operation, we should not lost them here
230 if (!theFeature->data()->attribute(attributeID())->isInitialized())
233 myFlushUpdateBlocked = false;
236 bool ModuleBase_ModelWidget::focusTo()
238 #ifdef DEBUG_WIDGET_INSTANCE
239 qDebug("ModuleBase_ModelWidget::focusTo");
241 QList<QWidget*> aControls = getControls();
242 QList<QWidget*>::const_iterator anIt = aControls.begin(), aLast = aControls.end();
243 bool isFocusAccepted = false;
244 for (; anIt != aLast && !isFocusAccepted; anIt++) {
245 QWidget* aWidget = *anIt;
246 if (aWidget && aWidget->focusPolicy() != Qt::NoFocus) {
247 ModuleBase_Tools::setFocus(aWidget, "ModuleBase_ModelWidget::focusTo()");
248 isFocusAccepted = true;
251 return isFocusAccepted;
254 void ModuleBase_ModelWidget::activate()
256 #ifdef DEBUG_WIDGET_INSTANCE
257 qDebug("ModuleBase_ModelWidget::activate");
259 // the control value is stored to the mode by the focus in on the widget
260 // we need the value is initialized in order to enable the apply button in the property panel.
261 // It should happens in the creation mode only because all fields are filled in the edition mode
262 if (!isEditingMode()) {
263 AttributePtr anAttribute = myFeature->data()->attribute(myAttributeID);
264 if (anAttribute.get() != NULL && !anAttribute->isInitialized())
265 initializeValueByActivate();
268 if (myWidgetValidator)
269 myWidgetValidator->activateFilters(true);
274 void ModuleBase_ModelWidget::deactivate()
276 #ifdef DEBUG_WIDGET_INSTANCE
277 qDebug("ModuleBase_ModelWidget::deactivate");
279 myIsValueStateBlocked = false;
281 if (myWidgetValidator)
282 myWidgetValidator->activateFilters(false);
285 void ModuleBase_ModelWidget::initializeValueByActivate()
287 if (isComputedDefault()) {
288 if (myFeature->compute(myAttributeID)) {
297 QWidget* ModuleBase_ModelWidget::getControlAcceptingFocus(const bool isFirst)
299 QWidget* aControl = 0;
301 QList<QWidget*> aControls = getControls();
302 int aSize = aControls.size();
305 for (int i = 0; i < aSize && !aControl; i++) {
306 if (aControls[i]->focusPolicy() != Qt::NoFocus)
307 aControl = aControls[i];
311 for (int i = aSize - 1; i >= 0 && !aControl; i--) {
312 if (aControls[i]->focusPolicy() != Qt::NoFocus)
313 aControl = aControls[i];
319 void ModuleBase_ModelWidget::setDefaultValue(const std::string& theValue)
321 myDefaultValue = theValue;
324 bool ModuleBase_ModelWidget::storeValue()
326 setValueState(Stored);
328 emit beforeValuesChanged();
330 // value is stored only in creation mode and in edition if there is not
331 // XML flag prohibited modification in edit mode(macro feature circle/arc)
332 if (!isEditingMode() || isModifiedInEdit().empty())
333 isDone = storeValueCustom();
335 /// store value in an alternative attribute if possible(attribute has the same type)
336 std::string aWidgetAttribute = attributeID();
337 myAttributeID = isModifiedInEdit();
339 myAttributeID = aWidgetAttribute;
340 // operation will be restarted but if isDone == true, PagedContainer will try to set focus
341 // to the current widget, but will be already deleted
345 emit afterValuesChanged();
349 #ifdef DEBUG_VALUE_STATE
350 std::string getDebugInfo(const ModuleBase_ModelWidget::ValueState& theState)
354 case ModuleBase_ModelWidget::Stored: anInfo = "Stored "; break;
355 case ModuleBase_ModelWidget::ModifiedInPP: anInfo = "ModifiedInPP "; break;
356 case ModuleBase_ModelWidget::ModifiedInViewer: anInfo = "ModifiedInViewer"; break;
357 case ModuleBase_ModelWidget::Reset: anInfo = "Reset "; break;
364 ModuleBase_ModelWidget::ValueState ModuleBase_ModelWidget::setValueState
365 (const ModuleBase_ModelWidget::ValueState& theState)
367 ValueState aState = myState;
369 if (myState != theState && !myIsValueStateBlocked) {
370 #ifdef DEBUG_VALUE_STATE
371 qDebug(QString("setValueState: previous state = %1,\t new state = %2")
372 .arg(getDebugInfo(myState).c_str())
373 .arg(getDebugInfo(theState).c_str()).toStdString().c_str());
376 emit valueStateChanged(aState);
381 bool ModuleBase_ModelWidget::blockValueState(const bool theBlocked)
383 bool isBlocked = myIsValueStateBlocked;
384 myIsValueStateBlocked = theBlocked;
388 bool ModuleBase_ModelWidget::restoreValue()
390 emit beforeValuesRestored();
391 bool isDone = restoreValueCustom();
392 emit afterValuesRestored();
397 void ModuleBase_ModelWidget::updateObject(ObjectPtr theObject)
399 if (!myFlushUpdateBlocked) {
400 #ifdef DEBUG_WIDGET_INSTANCE
401 qDebug("ModuleBase_ModelWidget::updateObject");
403 ModuleBase_Tools::flushUpdated(theObject);
404 emit objectUpdated();
408 void ModuleBase_ModelWidget::moveObject(ObjectPtr theObj)
410 //blockUpdateViewer(true);
411 #ifdef DEBUG_WIDGET_INSTANCE
412 qDebug("ModuleBase_ModelWidget::moveObject");
415 static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
416 ModelAPI_EventCreator::get()->sendUpdated(theObj, anEvent);
417 Events_Loop::loop()->flush(anEvent);
419 //blockUpdateViewer(false);
422 bool ModuleBase_ModelWidget::processEnter()
427 bool ModuleBase_ModelWidget::processDelete()
429 // we consider that model objects eats delete key in order to
430 // do nothing by for example symbol delete in line edit or spin box
434 bool ModuleBase_ModelWidget::eventFilter(QObject* theObject, QEvent *theEvent)
436 QWidget* aWidget = qobject_cast<QWidget*>(theObject);
437 if (theEvent->type() == QEvent::FocusIn) {
438 QFocusEvent* aFocusEvent = dynamic_cast<QFocusEvent*>(theEvent);
439 Qt::FocusReason aReason = aFocusEvent->reason();
440 bool aMouseOrKey = aReason == Qt::MouseFocusReason ||
441 /*aReason == Qt::TabFocusReason ||
442 //aReason == Qt::BacktabFocusReason ||*/
443 aReason == Qt::OtherFocusReason; // to process widget->setFocus()
444 if (aMouseOrKey && getControls().contains(aWidget)) {
445 //if (getControls().contains(aWidget)) {
449 else if (theEvent->type() == QEvent::FocusOut) {
450 QFocusEvent* aFocusEvent = dynamic_cast<QFocusEvent*>(theEvent);
452 Qt::FocusReason aReason = aFocusEvent->reason();
453 bool aMouseOrKey = aReason == Qt::MouseFocusReason ||
454 aReason == Qt::TabFocusReason ||
455 aReason == Qt::BacktabFocusReason ||
456 aReason == Qt::OtherFocusReason; // to process widget->setFocus()
457 if (aMouseOrKey && getControls().contains(aWidget)) {
458 if (getValueState() == ModifiedInPP) {
463 // pass the event on to the parent class
465 return QObject::eventFilter(theObject, theEvent);
468 //**************************************************************
469 void ModuleBase_ModelWidget::onWidgetValuesChanged()
474 //**************************************************************
475 void ModuleBase_ModelWidget::onWidgetValuesModified()
477 setValueState(ModifiedInPP);
480 //**************************************************************
481 QString ModuleBase_ModelWidget::translate(const std::string& theStr) const
483 return ModuleBase_Tools::translate(context(), theStr);
486 //**************************************************************
487 ModuleBase_ModelWidget* ModuleBase_ModelWidget::findModelWidget(ModuleBase_IPropertyPanel* theProp,
490 ModuleBase_ModelWidget* aModelWidget = 0;
494 QObject* aParent = theWidget->parent();
496 aModelWidget = qobject_cast<ModuleBase_ModelWidget*>(aParent);
499 aParent = aParent->parent();