-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: ModuleBase_ModelWidget.cpp
-// Created: 25 Apr 2014
-// Author: Natalia ERMOLAEVA
+// Copyright (C) 2014-2024 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
#include "ModuleBase_ModelWidget.h"
+#include "ModuleBase_IPropertyPanel.h"
+#include "ModuleBase_ViewerPrs.h"
#include "ModuleBase_Tools.h"
+#include "ModuleBase_WidgetValidator.h"
+
+#include <Events_InfoMessage.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_Attribute.h>
#include <ModelAPI_Events.h>
#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
#include <Config_Keywords.h>
#include <Config_WidgetAPI.h>
+#include <Config_Translator.h>
+#include <Config_PropManager.h>
#include <Events_Loop.h>
#include <QEvent>
-#include <QGraphicsDropShadowEffect>
-#include <QColor>
#include <QLabel>
#include <QFocusEvent>
+#include <QTextCodec>
+
+//#define DEBUG_VALUE_STATE
+
+//#define DEBUG_WIDGET_INSTANCE
+//#define DEBUG_ENABLE_SKETCH_INPUT_FIELDS
+//**************************************************************
ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
- const Config_WidgetAPI* theData,
- const std::string& theParentId)
- : QWidget(theParent),
- myParentId(theParentId),
- myIsEditing(false),
- myState(Stored),
- myIsValueStateBlocked(false)
+ const Config_WidgetAPI* theData)
+ : QWidget(theParent),
+ myWidgetValidator(0),
+ myState(Stored),
+ myIsEditing(false),
+ myIsValueStateBlocked(false),
+ myFlushUpdateBlocked(false)
{
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::ModuleBase_ModelWidget");
+#endif
+
+ myFeatureId = theData->featureId();
+
+ myIsInternal = theData->getBooleanAttribute(ATTR_INTERNAL, false);
+ myUseExternalParts = theData->getBooleanAttribute("allow_parts_content", false);
+
+ myIsModifiedInEdit = theData->getProperty(ATTR_MODIFIED_IN_EDIT);
+
+ myUpdateVisualAttributes = theData->getBooleanAttribute(ATTR_VISUAL_CHANGED, false);
+
myDefaultValue = theData->getProperty(ATTR_DEFAULT);
myUseReset = theData->getBooleanAttribute(ATTR_USE_RESET, true);
myIsComputedDefault = theData->getProperty(ATTR_DEFAULT) == DOUBLE_WDG_DEFAULT_COMPUTED;
myAttributeID = theData ? theData->widgetId() : "";
myIsObligatory = theData->getBooleanAttribute(ATTR_OBLIGATORY, true);
+ myIsValueEnabled = On; // not defined or "true"
+ std::string anEnableValue = theData->getProperty(DOUBLE_WDG_ENABLE_VALUE);
+ if (anEnableValue == "false")
+ myIsValueEnabled = Off;
+ if (anEnableValue == DOUBLE_WDG_ENABLE_VALUE_BY_PREFERENCES)
+ myIsValueEnabled = DefinedInPreferences;
+
connect(this, SIGNAL(valuesChanged()), this, SLOT(onWidgetValuesChanged()));
connect(this, SIGNAL(valuesModified()), this, SLOT(onWidgetValuesModified()));
}
+//**************************************************************
+ModuleBase_ModelWidget::~ModuleBase_ModelWidget()
+{
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::~ModuleBase_ModelWidget");
+#endif
+}
+
+//**************************************************************
bool ModuleBase_ModelWidget::reset()
{
bool aResult = resetCustom();
return aResult;
}
+//**************************************************************
bool ModuleBase_ModelWidget::isInitialized(ObjectPtr theObject) const
{
return theObject->data()->attribute(attributeID())->isInitialized();
}
-QString ModuleBase_ModelWidget::getValueStateError() const
+//**************************************************************
+void ModuleBase_ModelWidget::selectionModes(int& theModuleSelectionModes, QIntList& theModes)
+{
+ theModuleSelectionModes = -1;
+ if (myWidgetValidator)
+ myWidgetValidator->selectionModes(theModuleSelectionModes, theModes);
+}
+
+//**************************************************************
+void ModuleBase_ModelWidget::selectionFilters(QIntList& theModuleSelectionFilters,
+ SelectMgr_ListOfFilter& theSelectionFilters)
+{
+ if (myWidgetValidator)
+ myWidgetValidator->selectionFilters(theModuleSelectionFilters, theSelectionFilters);
+}
+
+//**************************************************************
+bool ModuleBase_ModelWidget::isValueEnabled() const
+{
+ bool anEnabled = true;
+ if (myIsValueEnabled == DefinedInPreferences) {
+#ifdef DEBUG_ENABLE_SKETCH_INPUT_FIELDS
+ bool aCanDisable = false;
+#else
+ //Config_PropManager::boolean(SKETCH_TAB_NAME, "disable_input_fields", "true");
+ bool aCanDisable = true;
+#endif
+ if (aCanDisable)
+ anEnabled = false;
+ }
+ else if (myIsValueEnabled == Off)
+ anEnabled = false;
+ return anEnabled;
+}
+
+//**************************************************************
+void ModuleBase_ModelWidget::processValueState()
+{
+ if (myState == ModifiedInPP || myState == ModifiedInViewer)
+ storeValue();
+}
+
+//**************************************************************
+Events_InfoMessage ModuleBase_ModelWidget::getValueStateError() const
{
- QString anError = "";
+ Events_InfoMessage aMessage;
+ aMessage.setContext(context());
ModuleBase_ModelWidget::ValueState aState = getValueState();
if (aState != ModuleBase_ModelWidget::Stored) {
AttributePtr anAttr = feature()->attribute(attributeID());
if (anAttr.get()) {
- QString anAttributeName = anAttr->id().c_str();
+ const std::string& anAttributeName = anAttr->id();
switch (aState) {
- case ModuleBase_ModelWidget::ModifiedInPP:
- anError = "Attribute \"" + anAttributeName +
- "\" modification is not applyed. Please click \"Enter\" or \"Tab\".";
- break;
case ModuleBase_ModelWidget::ModifiedInViewer:
- anError = "Attribute \"" + anAttributeName +
- "\" is locked by modification value in the viewer.";
+ aMessage = "Attribute \"%1\" is locked by modification value in the viewer.";
+ aMessage.addParameter(anAttributeName);
break;
case ModuleBase_ModelWidget::Reset:
- anError = "Attribute \"" + anAttributeName + "\" is not initialized.";
+ aMessage = "Attribute \"%1\" is not initialized.";
+ aMessage.addParameter(anAttributeName);
+ break;
+ case ModuleBase_ModelWidget::ModifiedInPP: // Apply should be enabled in this mode
+ default:
break;
}
}
}
+ return aMessage;
+}
+
+//**************************************************************
+QString ModuleBase_ModelWidget::getError(const bool theValueStateChecked) const
+{
+ QString anError;
+
+ if (!feature().get())
+ return anError;
+
+ std::string anAttributeID = attributeID();
+ AttributePtr anAttribute = feature()->attribute(anAttributeID);
+ if (!anAttribute.get())
+ return anError;
+
+ std::string aValidatorID;
+ Events_InfoMessage anErrorMsg;
+
+ static ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
+ if (!aValidators->validate(anAttribute, aValidatorID, anErrorMsg)) {
+ if (anErrorMsg.empty())
+ anErrorMsg = "Unknown error.";
+
+ if (anErrorMsg.context().empty()) {
+ anErrorMsg.setContext(context() + ":" + aValidatorID);
+ }
+ }
+
+ if (anErrorMsg.empty() && theValueStateChecked) {
+ anErrorMsg = getValueStateError();
+ }
+
+ if (!anErrorMsg.empty()) {
+ anError = ModuleBase_Tools::translate(anErrorMsg);
+ }
+
return anError;
}
+//**************************************************************
void ModuleBase_ModelWidget::enableFocusProcessing()
{
QList<QWidget*> aMyControls = getControls();
foreach(QWidget* eachControl, aMyControls) {
- if (myIsObligatory) {
eachControl->setFocusPolicy(Qt::StrongFocus);
eachControl->installEventFilter(this);
- }
- else {
- eachControl->setFocusPolicy(Qt::NoFocus);
- }
}
}
+//**************************************************************
void ModuleBase_ModelWidget::setHighlighted(bool isHighlighted)
{
QList<QWidget*> aWidgetList = getControls();
QLabel* aLabel = qobject_cast<QLabel*>(aWidget);
// We won't set the effect to QLabels - it looks ugly
if(aLabel) continue;
- if(isHighlighted) {
- // If effect is the installed on a different widget, setGraphicsEffect() will
- // remove the effect from the widget and install it on this widget.
- // That's why we create a new effect for each widget
- QGraphicsDropShadowEffect* aGlowEffect = new QGraphicsDropShadowEffect();
- aGlowEffect->setOffset(.0);
- aGlowEffect->setBlurRadius(10.0);
- aGlowEffect->setColor(QColor(0, 170, 255)); // Light-blue color, #00AAFF
- aWidget->setGraphicsEffect(aGlowEffect);
- } else {
- QGraphicsEffect* anEffect = aWidget->graphicsEffect();
- if(anEffect)
- anEffect->deleteLater();
- aWidget->setGraphicsEffect(NULL);
- }
+ // If effect is the installed on a different widget, setGraphicsEffect() will
+ // remove the effect from the widget and install it on this widget.
+ // That's why we create a new effect for each widget
+ ModuleBase_Tools::setShadowEffect(aWidget, isHighlighted);
}
}
-void ModuleBase_ModelWidget::setFeature(const FeaturePtr& theFeature, const bool theToStoreValue)
+//**************************************************************
+void ModuleBase_ModelWidget::setFeature(const FeaturePtr& theFeature, const bool theToStoreValue,
+ const bool isUpdateFlushed)
{
+ /// it is possible to give this flag as parameter in storeValue/storeCustomValue
+ /// after debug, it may be corrected
+ myFlushUpdateBlocked = !isUpdateFlushed;
myFeature = theFeature;
- if (theToStoreValue)
- storeValue();
+ if (theToStoreValue) {
+ /// it is possible that the attribute is filled before the operation is started,
+ /// e.g. by reentrant operation case some attributes are filled by values of
+ /// feature of previous operation, we should not lost them here
+ if (!theFeature->data()->attribute(attributeID())->isInitialized())
+ storeValue();
+ }
+ myFlushUpdateBlocked = false;
}
+//**************************************************************
bool ModuleBase_ModelWidget::focusTo()
{
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::focusTo");
+#endif
QList<QWidget*> aControls = getControls();
QList<QWidget*>::const_iterator anIt = aControls.begin(), aLast = aControls.end();
bool isFocusAccepted = false;
return isFocusAccepted;
}
+//**************************************************************
void ModuleBase_ModelWidget::activate()
{
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::activate");
+#endif
// the control value is stored to the mode by the focus in on the widget
// we need the value is initialized in order to enable the apply button in the property panel.
// It should happens in the creation mode only because all fields are filled in the edition mode
activateCustom();
}
+//**************************************************************
void ModuleBase_ModelWidget::deactivate()
{
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::deactivate");
+#endif
myIsValueStateBlocked = false;
- if (myState == ModifiedInPP)
- storeValue();
myState = Stored;
+ if (myWidgetValidator)
+ myWidgetValidator->clearValidatedCash();
}
+//**************************************************************
void ModuleBase_ModelWidget::initializeValueByActivate()
{
if (isComputedDefault()) {
}
}
+//**************************************************************
QWidget* ModuleBase_ModelWidget::getControlAcceptingFocus(const bool isFirst)
{
QWidget* aControl = 0;
return aControl;
}
+//**************************************************************
void ModuleBase_ModelWidget::setDefaultValue(const std::string& theValue)
{
myDefaultValue = theValue;
}
+//**************************************************************
bool ModuleBase_ModelWidget::storeValue()
{
setValueState(Stored);
emit beforeValuesChanged();
- bool isDone = storeValueCustom();
+ bool isDone = false;
+ // value is stored only in creation mode and in edition if there is not
+ // XML flag prohibited modification in edit mode(macro feature circle/arc)
+ if (!isEditingMode() || isModifiedInEdit().empty())
+ isDone = storeValueCustom();
+ else {
+ /// store value in an alternative attribute if possible(attribute has the same type)
+ std::string aWidgetAttribute = attributeID();
+ myAttributeID = isModifiedInEdit();
+ storeValueCustom();
+ myAttributeID = aWidgetAttribute;
+ // operation will be restarted but if isDone == true, PagedContainer will try to set focus
+ // to the current widget, but will be already deleted
+ isDone = false;
+ }
+
emit afterValuesChanged();
return isDone;
}
+#ifdef DEBUG_VALUE_STATE
+
+//**************************************************************
+std::string getDebugInfo(const ModuleBase_ModelWidget::ValueState& theState)
+{
+ std::string anInfo;
+ switch (theState) {
+ case ModuleBase_ModelWidget::Stored: anInfo = "Stored "; break;
+ case ModuleBase_ModelWidget::ModifiedInPP: anInfo = "ModifiedInPP "; break;
+ case ModuleBase_ModelWidget::ModifiedInViewer: anInfo = "ModifiedInViewer"; break;
+ case ModuleBase_ModelWidget::Reset: anInfo = "Reset "; break;
+ default: break;
+ }
+ return anInfo;
+}
+#endif
-ModuleBase_ModelWidget::ValueState ModuleBase_ModelWidget::setValueState(const ModuleBase_ModelWidget::ValueState& theState)
+//**************************************************************
+ModuleBase_ModelWidget::ValueState ModuleBase_ModelWidget::setValueState
+ (const ModuleBase_ModelWidget::ValueState& theState)
{
ValueState aState = myState;
+
if (myState != theState && !myIsValueStateBlocked) {
+#ifdef DEBUG_VALUE_STATE
+ qDebug(QString("setValueState: previous state = %1,\t new state = %2")
+ .arg(getDebugInfo(myState).c_str())
+ .arg(getDebugInfo(theState).c_str()).toStdString().c_str());
+#endif
myState = theState;
emit valueStateChanged(aState);
}
return aState;
}
+//**************************************************************
bool ModuleBase_ModelWidget::blockValueState(const bool theBlocked)
{
bool isBlocked = myIsValueStateBlocked;
return isBlocked;
}
+//**************************************************************
bool ModuleBase_ModelWidget::restoreValue()
{
+ if (!isEnabled()) {
+ // This code works in inspection panel
+ ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
+ if (!aValidators->isCase(myFeature, attributeID()))
+ return false; // if it is not an active case for the widget
+ }
emit beforeValuesRestored();
bool isDone = restoreValueCustom();
emit afterValuesRestored();
return isDone;
}
-void ModuleBase_ModelWidget::updateObject(ObjectPtr theObj)
+//**************************************************************
+void ModuleBase_ModelWidget::updateObject(ObjectPtr theObject)
{
- blockUpdateViewer(true);
+ if (!myFlushUpdateBlocked) {
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::updateObject");
+#endif
+ if (myFeature.get() && myUpdateVisualAttributes) {
+ static const Events_ID anEvent = Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES);
+ ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent);
+ }
+ ModuleBase_Tools::flushUpdated(theObject);
+ emit objectUpdated();
+ }
+}
- Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+//**************************************************************
+bool ModuleBase_ModelWidget::canProcessAction(ModuleBase_ActionType theActionType,
+ bool& isActionEnabled)
+{
+ isActionEnabled = false;
+ switch (theActionType) {
+ case ActionEnter: return false;
+ case ActionEscape: return false;
+ case ActionDelete: return true;
+ case ActionSelection: return true;
+ case ActionUndo:
+ case ActionRedo:
+ default:
+ return false;
+ }
+}
- blockUpdateViewer(false);
+//**************************************************************
+bool ModuleBase_ModelWidget::processAction(ModuleBase_ActionType theActionType,
+ const ActionParamPtr& theParam)
+{
+ switch (theActionType) {
+ case ActionEnter:
+ return processEnter();
+ case ActionEscape:
+ return processEscape();
+ case ActionDelete:
+ return processDelete();
+ case ActionSelection:
+ processSelection();
+ case ActionUndo:
+ case ActionRedo:
+ default:
+ return false;
+ }
}
-void ModuleBase_ModelWidget::moveObject(ObjectPtr theObj)
+//**************************************************************
+bool ModuleBase_ModelWidget::processEnter()
{
- //blockUpdateViewer(true);
+ return false;
+}
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
- ModelAPI_EventCreator::get()->sendUpdated(theObj, anEvent);
- Events_Loop::loop()->flush(anEvent);
+//**************************************************************
+bool ModuleBase_ModelWidget::processEscape()
+{
+ return false;
+}
- //blockUpdateViewer(false);
+//**************************************************************
+bool ModuleBase_ModelWidget::processDelete()
+{
+ // we consider that model objects eats delete key in order to
+ // do nothing by for example symbol delete in line edit or spin box
+ return true;
}
-bool ModuleBase_ModelWidget::processEnter()
+//**************************************************************
+bool ModuleBase_ModelWidget::processSelection()
{
return false;
}
+//**************************************************************
bool ModuleBase_ModelWidget::eventFilter(QObject* theObject, QEvent *theEvent)
{
QWidget* aWidget = qobject_cast<QWidget*>(theObject);
if (theEvent->type() == QEvent::FocusIn) {
- #ifdef _DEBUG
- // The following two lines are for debugging purpose only
QFocusEvent* aFocusEvent = dynamic_cast<QFocusEvent*>(theEvent);
- bool isWinFocus = aFocusEvent->reason() == Qt::ActiveWindowFocusReason;
- #endif
- if (getControls().contains(aWidget)) {
- emit focusInWidget(this);
+ Qt::FocusReason aReason = aFocusEvent->reason();
+ bool aMouseOrKey = aReason == Qt::MouseFocusReason ||
+ /*aReason == Qt::TabFocusReason ||
+ //aReason == Qt::BacktabFocusReason ||*/
+ aReason == Qt::OtherFocusReason; // to process widget->setFocus()
+ if (aMouseOrKey && getControls().contains(aWidget)) {
+ //if (getControls().contains(aWidget)) {
+ emitFocusInWidget();
}
}
else if (theEvent->type() == QEvent::FocusOut) {
aReason == Qt::TabFocusReason ||
aReason == Qt::BacktabFocusReason ||
aReason == Qt::OtherFocusReason; // to process widget->setFocus()
- if (aMouseOrKey && getControls().contains(aWidget) && getValueState() == ModifiedInPP)
- storeValue();
+ if (aMouseOrKey && getControls().contains(aWidget)) {
+ if (getValueState() == ModifiedInPP) {
+ storeValue();
+ }
+ }
}
// pass the event on to the parent class
}
//**************************************************************
-void ModuleBase_ModelWidget::blockUpdateViewer(const bool theValue)
+QString ModuleBase_ModelWidget::translate(const std::string& theStr) const
{
- // the viewer update should be blocked in order to avoid the temporary feature content
- // when the solver processes the feature, the redisplay message can be flushed
- // what caused the display in the viewer preliminary states of object
- // e.g. fillet feature, angle value change
- std::shared_ptr<Events_Message> aMsg;
- if (theValue) {
- aMsg = std::shared_ptr<Events_Message>(
- new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)));
- }
- else {
- // the viewer update should be unblocked
- aMsg = std::shared_ptr<Events_Message>(
- new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)));
+ return ModuleBase_Tools::translate(context(), theStr);
+}
+
+//**************************************************************
+ModuleBase_ModelWidget* ModuleBase_ModelWidget::findModelWidget(ModuleBase_IPropertyPanel* theProp,
+ QWidget* theWidget)
+{
+ ModuleBase_ModelWidget* aModelWidget = 0;
+ if (!theWidget)
+ return aModelWidget;
+
+ QObject* aParent = theWidget->parent();
+ while (aParent) {
+ aModelWidget = qobject_cast<ModuleBase_ModelWidget*>(aParent);
+ if (aModelWidget)
+ break;
+ aParent = aParent->parent();
}
- Events_Loop::loop()->send(aMsg);
+ return aModelWidget;
}