From 3400f9977cb5bbc2c00d5d797b572acd083d1675 Mon Sep 17 00:00:00 2001 From: sbh Date: Wed, 8 Apr 2015 21:00:32 +0300 Subject: [PATCH] Using variables in WidgetDoubleValue --- src/Model/Model_AttributeDouble.cpp | 18 + src/Model/Model_AttributeDouble.h | 9 + src/ModelAPI/ModelAPI_AttributeDouble.h | 6 + src/ModuleBase/CMakeLists.txt | 2 + src/ModuleBase/ModuleBase_DoubleSpinBox.h | 2 +- src/ModuleBase/ModuleBase_ParamSpinBox.cpp | 311 ++++++++++++++++++ src/ModuleBase/ModuleBase_ParamSpinBox.h | 70 ++++ .../ModuleBase_WidgetDoubleValue.cpp | 19 +- src/ModuleBase/ModuleBase_WidgetDoubleValue.h | 4 +- src/ModuleBase/ModuleBase_WidgetEditor.cpp | 2 +- src/PartSet/PartSet_WidgetPoint2d.cpp | 6 +- src/PartSet/PartSet_WidgetPoint2d.h | 6 +- src/PartSet/PartSet_WidgetPoint2dDistance.cpp | 2 +- 13 files changed, 441 insertions(+), 16 deletions(-) create mode 100644 src/ModuleBase/ModuleBase_ParamSpinBox.cpp create mode 100644 src/ModuleBase/ModuleBase_ParamSpinBox.h diff --git a/src/Model/Model_AttributeDouble.cpp b/src/Model/Model_AttributeDouble.cpp index 4764420f7..87bba89cf 100644 --- a/src/Model/Model_AttributeDouble.cpp +++ b/src/Model/Model_AttributeDouble.cpp @@ -8,6 +8,9 @@ #include #include +#include +#include + using namespace std; void Model_AttributeDouble::setValue(const double theValue) @@ -30,5 +33,20 @@ Model_AttributeDouble::Model_AttributeDouble(TDF_Label& theLabel) if (!myIsInitialized) { // create attribute: not initialized by value yet, just zero myReal = TDataStd_Real::Set(theLabel, 0.); + myText = TDataStd_Name::Set(theLabel, TCollection_ExtendedString()); + } +} + +void Model_AttributeDouble::setText(const std::string& theValue) +{ + TCollection_ExtendedString aValue(theValue.c_str()); + if (myText->Get() != aValue) { + myText->Set(aValue); + //owner()->data()->sendAttributeUpdated(this); ? } } + +string Model_AttributeDouble::text() +{ + return TCollection_AsciiString(myText->Get()).ToCString(); +} diff --git a/src/Model/Model_AttributeDouble.h b/src/Model/Model_AttributeDouble.h index f04db7f88..951c99613 100644 --- a/src/Model/Model_AttributeDouble.h +++ b/src/Model/Model_AttributeDouble.h @@ -12,6 +12,8 @@ #include #include +#include + /**\class Model_AttributeDouble * \ingroup DataModel * \brief Attribute that contains real value with double precision. @@ -20,6 +22,7 @@ class Model_AttributeDouble : public ModelAPI_AttributeDouble { Handle_TDataStd_Real myReal; ///< double is Real attribute + Handle_TDataStd_Name myText; ///< Text representation of the attribute (may differ for parametres) public: /// Defines the double value MODEL_EXPORT virtual void setValue(const double theValue); @@ -27,6 +30,12 @@ class Model_AttributeDouble : public ModelAPI_AttributeDouble /// Returns the double value MODEL_EXPORT virtual double value(); + /// Defines the double value + MODEL_EXPORT virtual void setText(const std::string& theText); + + /// Returns the double value + MODEL_EXPORT virtual std::string text(); + protected: /// Initializes attibutes Model_AttributeDouble(TDF_Label& theLabel); diff --git a/src/ModelAPI/ModelAPI_AttributeDouble.h b/src/ModelAPI/ModelAPI_AttributeDouble.h index 291bc1883..6ac965232 100644 --- a/src/ModelAPI/ModelAPI_AttributeDouble.h +++ b/src/ModelAPI/ModelAPI_AttributeDouble.h @@ -23,6 +23,12 @@ class ModelAPI_AttributeDouble : public ModelAPI_Attribute /// Returns the double value MODELAPI_EXPORT virtual double value() = 0; + /// Defines the double value + MODELAPI_EXPORT virtual void setText(const std::string& theText) = 0; + + /// Returns the double value + MODELAPI_EXPORT virtual std::string text() = 0; + /// Returns the type of this class of attributes MODELAPI_EXPORT static std::string typeId() { diff --git a/src/ModuleBase/CMakeLists.txt b/src/ModuleBase/CMakeLists.txt index 3f5ba997f..fd7878d10 100644 --- a/src/ModuleBase/CMakeLists.txt +++ b/src/ModuleBase/CMakeLists.txt @@ -52,6 +52,7 @@ SET(PROJECT_HEADERS ModuleBase_WidgetToolbox.h ModuleBase_WidgetValidated.h ModuleBase_WidgetExprEditor.h + ModuleBase_ParamSpinBox.h ) SET(PROJECT_SOURCES @@ -94,6 +95,7 @@ SET(PROJECT_SOURCES ModuleBase_WidgetToolbox.cpp ModuleBase_WidgetValidated.cpp ModuleBase_WidgetExprEditor.cpp + ModuleBase_ParamSpinBox.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/ModuleBase/ModuleBase_DoubleSpinBox.h b/src/ModuleBase/ModuleBase_DoubleSpinBox.h index 11de54784..347af2f49 100644 --- a/src/ModuleBase/ModuleBase_DoubleSpinBox.h +++ b/src/ModuleBase/ModuleBase_DoubleSpinBox.h @@ -21,7 +21,7 @@ class MODULEBASE_EXPORT ModuleBase_DoubleSpinBox : public QDoubleSpinBox Q_OBJECT public: - ModuleBase_DoubleSpinBox(QWidget* theParent = 0, int thePrecision = 6); + explicit ModuleBase_DoubleSpinBox(QWidget* theParent = 0, int thePrecision = 6); virtual ~ModuleBase_DoubleSpinBox(); /// Returns true if the control is clear diff --git a/src/ModuleBase/ModuleBase_ParamSpinBox.cpp b/src/ModuleBase/ModuleBase_ParamSpinBox.cpp new file mode 100644 index 000000000..cfcd5e6e0 --- /dev/null +++ b/src/ModuleBase/ModuleBase_ParamSpinBox.cpp @@ -0,0 +1,311 @@ +#include "ModuleBase_ParamSpinBox.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/*! + \class ModuleBase_ParamSpinBox + */ + +/*! + \brief Constructor. + + Constructs a spin box with 0.0 as minimum value and 99.99 as maximum value, + a step value of 1.0 and a precision of 2 decimal places. + The value is initially set to 0.00. + + \param parent parent object + */ +ModuleBase_ParamSpinBox::ModuleBase_ParamSpinBox(QWidget* theParent, int thePrecision) + : ModuleBase_DoubleSpinBox(theParent, thePrecision), + myAcceptVariables(true), + myHasVariables(false), + myDefaultValue(0.) +{ + connectSignalsAndSlots(); +} + +/*! + \brief Destructor. + */ +ModuleBase_ParamSpinBox::~ModuleBase_ParamSpinBox() +{ +} + +/*! + \brief Perform \a steps increment/decrement steps. + + Re-implemented to handle cases when Notebook variable + name is specified by the user as the widget text. + Otherwise, simply calls the base implementation. + + \param steps number of increment/decrement steps + */ +void ModuleBase_ParamSpinBox::stepBy(int steps) +{ + QString str = text(); + QString pref = prefix(); + QString suff = suffix(); + + if (pref.length() && str.startsWith(pref)) + str = str.right(str.length() - pref.length()); + if (suff.length() && str.endsWith(suff)) + str = str.left(str.length() - suff.length()); + + QRegExp varNameMask("([a-z]|[A-Z]|_).*"); + if (varNameMask.exactMatch(str)) + return; + + ModuleBase_DoubleSpinBox::stepBy(steps); +} + +/*! + \brief Connect signals and slots. + */ +void ModuleBase_ParamSpinBox::connectSignalsAndSlots() +{ + connect(this, SIGNAL(editingFinished()), + this, SLOT(onEditingFinished())); + + connect(this, SIGNAL(valueChanged(const QString&)), + this, SLOT(onTextChanged(const QString&))); + + //connect(lineEdit(), SIGNAL(textChanged(const QString&)), + // this, SLOT(onTextChanged(const QString&))); + + //connect(lineEdit(), SIGNAL(textChanged(const QString&)), + // this, SIGNAL(textChanged(const QString&))); +} + +/*! + \brief This function is called when editing is finished. + */ +void ModuleBase_ParamSpinBox::onEditingFinished() +{ + if (myTextValue.isNull()) + myTextValue = text(); + + setText(myTextValue); +} + +/*! + \brief This function is called when value is changed. + */ +void ModuleBase_ParamSpinBox::onTextChanged(const QString& text) +{ + myTextValue = text; + + double value = 0; + if (isValid(text, value) == Acceptable) { + myCorrectValue = text; + myHasVariables = true; + } else { + myHasVariables = false; + } +} + +/*! + \brief Interpret text entered by the user as a value. + \param text text entered by the user + \return mapped value + \sa textFromValue() + */ +double ModuleBase_ParamSpinBox::valueFromText(const QString& theText) const +{ + double aValue = 0; + if (isValid(theText, aValue) == Acceptable) + return aValue; + + return defaultValue(); +} + +/*! + \brief This function is used by the spin box whenever it needs to display + the given value. + + \param val spin box value + \return text representation of the value + \sa valueFromText() + */ +QString ModuleBase_ParamSpinBox::textFromValue(double val) const +{ + return ModuleBase_DoubleSpinBox::textFromValue(val); +} + +/*! + \brief This function is used to determine whether input is valid. + \param str currently entered value + \param pos cursor position in the string + \return validating operation result + */ +QValidator::State ModuleBase_ParamSpinBox::validate(QString& str, int& pos) const +{ + QValidator::State res = QValidator::Invalid; + + // Considering the input text as a variable name + // Applying Python identifier syntax: + // either a string starting with a letter, or a string starting with + // an underscore followed by at least one alphanumeric character + if (isAcceptVariables()) { + QRegExp varNameMask("(([a-z]|[A-Z])([a-z]|[A-Z]|[0-9]|_)*)|" + "(_([a-z]|[A-Z]|[0-9])+([a-z]|[A-Z]|[0-9]|_)*)"); + if (varNameMask.exactMatch(str)) + res = QValidator::Acceptable; + + if (res == QValidator::Invalid) { + varNameMask.setPattern("_"); + if (varNameMask.exactMatch(str)) + res = QValidator::Intermediate; + } + } + + // Trying to interpret the current input text as a numeric value + if (res == QValidator::Invalid) + res = ModuleBase_DoubleSpinBox::validate(str, pos); + + return res; +} + +/*! + \brief This function is used to set a default value for this spinbox. + \param value default value + */ +void ModuleBase_ParamSpinBox::setDefaultValue(const double value) +{ + myDefaultValue = value; +} + +/*! + \brief This function is used to set a current value for this spinbox. + \param value current value + */ +void ModuleBase_ParamSpinBox::setValue(const double value) +{ + ModuleBase_DoubleSpinBox::setValue(value); + + myCorrectValue = ModuleBase_DoubleSpinBox::textFromValue(value); + myTextValue = myCorrectValue; +} + +/*! + \brief This function is used to set a text for this spinbox. + \param value current value + */ +void ModuleBase_ParamSpinBox::setText(const QString& value) +{ + lineEdit()->setText(value); +} + +/*! + \brief Enables or disables variable names in the spin box. + By default, variable names are enabled. + \param flag If true, variable names are enabled. + */ +void ModuleBase_ParamSpinBox::setAcceptVariables(const bool flag) +{ + myAcceptVariables = flag; +} + +/*! + \brief Returns true if the spin box accepts variable names. + */ +bool ModuleBase_ParamSpinBox::isAcceptVariables() const +{ + return myAcceptVariables; +} + +bool ModuleBase_ParamSpinBox::hasVariables() const +{ + return myHasVariables; +} + +/*! + \brief This function is used to determine whether input is valid. + \return validating operation result + */ +ModuleBase_ParamSpinBox::State ModuleBase_ParamSpinBox::isValid(const QString& theText, + double& theValue) const +{ + if (!findVariable(theText, theValue)) { + bool ok = false; + theValue = locale().toDouble(theText, &ok); + if (!ok) { + return NoVariable; + } + } + if (!checkRange(theValue)) { + return Invalid; + } + + return Acceptable; +} + +/*! + \brief This function return a default acceptable value (commonly, 0.0). + \return default acceptable value + */ +double ModuleBase_ParamSpinBox::defaultValue() const +{ + if (minimum() > myDefaultValue || maximum() < myDefaultValue) + return minimum(); + + return myDefaultValue; +} + +/*! + \brief This function is used to check that string value lies within predefined range. + \return check status + */ +bool ModuleBase_ParamSpinBox::checkRange(const double theValue) const +{ + return theValue >= minimum() && theValue <= maximum(); +} + +/*! + \brief This function is used to determine whether input is a variable name and to get its value. + \return status of search operation + */ +bool ModuleBase_ParamSpinBox::findVariable(const QString& theName, + double& outValue) const +{ + + SessionPtr aSession = ModelAPI_Session::get(); + DocumentPtr aDocument = aSession->activeDocument(); + ObjectPtr aParamObj = aDocument->objectByName(ModelAPI_ResultParameter::group(), + theName.toStdString()); + ResultParameterPtr aParam = std::dynamic_pointer_cast(aParamObj); + if(!aParam.get()) + return false; + AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE()); + outValue = aValueAttribute->value(); + return true; +} + +/*! + \brief This function is called when the spinbox recieves key press event. + */ +void ModuleBase_ParamSpinBox::keyPressEvent(QKeyEvent* e) +{ + if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { + QWidget::keyPressEvent(e); + } else { + ModuleBase_DoubleSpinBox::keyPressEvent(e); + } +} + +/*! + \brief This function is called when the spinbox recieves show event. + */ +void ModuleBase_ParamSpinBox::showEvent(QShowEvent*) +{ + setText(myTextValue); +} diff --git a/src/ModuleBase/ModuleBase_ParamSpinBox.h b/src/ModuleBase/ModuleBase_ParamSpinBox.h new file mode 100644 index 000000000..5945dcbd8 --- /dev/null +++ b/src/ModuleBase/ModuleBase_ParamSpinBox.h @@ -0,0 +1,70 @@ + +#ifndef ModuleBase_ParamSpinBox_H +#define ModuleBase_ParamSpinBox_H + +#include "ModuleBase.h" + +#include + +#include + +class MODULEBASE_EXPORT ModuleBase_ParamSpinBox : public ModuleBase_DoubleSpinBox +{ + Q_OBJECT + + enum State { Invalid = 0, NoVariable, Incompatible, Acceptable }; + +public: + explicit ModuleBase_ParamSpinBox(QWidget* theParent = 0, int thePrecision = 6); + virtual ~ModuleBase_ParamSpinBox(); + + virtual void stepBy(int); + + virtual double valueFromText(const QString&) const; + virtual QString textFromValue(double) const; + + virtual QValidator::State validate(QString&, int&) const; + + virtual void setDefaultValue(const double); + + virtual void setValue(double); + + virtual void setText(const QString&); + + void setAcceptVariables(const bool); + bool isAcceptVariables() const; + bool hasVariables() const; + +signals: + void textChanged(const QString&); + + protected: + State isValid(const QString&, double&) const; + + double defaultValue() const; + bool checkRange(const double) const; + + bool findVariable(const QString&, double&) const; + + protected: + virtual void keyPressEvent(QKeyEvent*); + virtual void showEvent(QShowEvent*); + + protected slots: + void onEditingFinished(); + void onTextChanged(const QString&); + + private: + void connectSignalsAndSlots(); + + private: + double myDefaultValue; + + QString myCorrectValue; + QString myTextValue; + + bool myAcceptVariables; + bool myHasVariables; +}; + +#endif diff --git a/src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp b/src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp index 4053a2a4b..0b5c4e681 100644 --- a/src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp +++ b/src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp @@ -5,10 +5,11 @@ // Author: Vitaly Smetannikov #include -#include +#include #include #include +#include #include #include @@ -46,7 +47,7 @@ ModuleBase_WidgetDoubleValue::ModuleBase_WidgetDoubleValue(QWidget* theParent, if (!aLabelIcon.isEmpty()) myLabel->setPixmap(QPixmap(aLabelIcon)); - mySpinBox = new ModuleBase_DoubleSpinBox(this); + mySpinBox = new ModuleBase_ParamSpinBox(this); QString anObjName = QString::fromStdString(attributeID()); mySpinBox->setObjectName(anObjName); @@ -113,6 +114,11 @@ bool ModuleBase_WidgetDoubleValue::storeValueCustom() const DataPtr aData = myFeature->data(); AttributeDoublePtr aReal = aData->real(attributeID()); aReal->setValue(mySpinBox->value()); + std::string aTextRepr; + if (mySpinBox->hasVariables()) { + aTextRepr = mySpinBox->text().toStdString(); + } + aReal->setText(aTextRepr); updateObject(myFeature); return true; } @@ -121,9 +127,12 @@ bool ModuleBase_WidgetDoubleValue::restoreValue() { DataPtr aData = myFeature->data(); AttributeDoublePtr aRef = aData->real(attributeID()); - - ModuleBase_Tools::setSpinValue(mySpinBox, aRef->value()); - + std::string aTextRepr = aRef->text(); + if (!aTextRepr.empty()) { + mySpinBox->setText(QString::fromStdString(aTextRepr)); + } else { + ModuleBase_Tools::setSpinValue(mySpinBox, aRef->value()); + } return true; } diff --git a/src/ModuleBase/ModuleBase_WidgetDoubleValue.h b/src/ModuleBase/ModuleBase_WidgetDoubleValue.h index a83292914..228efa0d2 100644 --- a/src/ModuleBase/ModuleBase_WidgetDoubleValue.h +++ b/src/ModuleBase/ModuleBase_WidgetDoubleValue.h @@ -10,7 +10,7 @@ #include "ModuleBase.h" #include "ModuleBase_ModelWidget.h" -class ModuleBase_DoubleSpinBox; +class ModuleBase_ParamSpinBox; class Config_WidgetAPI; class QWidget; class QLabel; @@ -63,7 +63,7 @@ protected: QLabel* myLabel; /// Input value control - ModuleBase_DoubleSpinBox* mySpinBox; + ModuleBase_ParamSpinBox* mySpinBox; }; #endif diff --git a/src/ModuleBase/ModuleBase_WidgetEditor.cpp b/src/ModuleBase/ModuleBase_WidgetEditor.cpp index 8c3b74bdf..c096d0b46 100644 --- a/src/ModuleBase/ModuleBase_WidgetEditor.cpp +++ b/src/ModuleBase/ModuleBase_WidgetEditor.cpp @@ -5,7 +5,7 @@ // Author: Natalia ERMOLAEVA #include -#include +#include #include #include diff --git a/src/PartSet/PartSet_WidgetPoint2d.cpp b/src/PartSet/PartSet_WidgetPoint2d.cpp index 10f6de95f..d2c65a27f 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.cpp +++ b/src/PartSet/PartSet_WidgetPoint2d.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include @@ -70,7 +70,7 @@ PartSet_WidgetPoint2D::PartSet_WidgetPoint2D(QWidget* theParent, aLabel->setPixmap(QPixmap(":pictures/x_point.png")); aGroupLay->addWidget(aLabel, 0, 0); - myXSpin = new ModuleBase_DoubleSpinBox(myGroupBox); + myXSpin = new ModuleBase_ParamSpinBox(myGroupBox); myXSpin->setMinimum(-DBL_MAX); myXSpin->setMaximum(DBL_MAX); myXSpin->setToolTip(tr("X")); @@ -84,7 +84,7 @@ PartSet_WidgetPoint2D::PartSet_WidgetPoint2D(QWidget* theParent, aLabel->setPixmap(QPixmap(":pictures/y_point.png")); aGroupLay->addWidget(aLabel, 1, 0); - myYSpin = new ModuleBase_DoubleSpinBox(myGroupBox); + myYSpin = new ModuleBase_ParamSpinBox(myGroupBox); myYSpin->setMinimum(-DBL_MAX); myYSpin->setMaximum(DBL_MAX); myYSpin->setToolTip(tr("Y")); diff --git a/src/PartSet/PartSet_WidgetPoint2d.h b/src/PartSet/PartSet_WidgetPoint2d.h index e39011c90..133ac4fa6 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.h +++ b/src/PartSet/PartSet_WidgetPoint2d.h @@ -18,7 +18,7 @@ class ModelAPI_Feature; class ModuleBase_IWorkshop; -class ModuleBase_DoubleSpinBox; +class ModuleBase_ParamSpinBox; class ModuleBase_IViewWindow; class GeomAPI_Pnt2d; class XGUI_Workshop; @@ -130,8 +130,8 @@ private slots: XGUI_Workshop* myWorkshop; QGroupBox* myGroupBox; ///< the parent group box for all intenal widgets - ModuleBase_DoubleSpinBox* myXSpin; ///< the spin box for the X coordinate - ModuleBase_DoubleSpinBox* myYSpin; ///< the spin box for the Y coordinate + ModuleBase_ParamSpinBox* myXSpin; ///< the spin box for the X coordinate + ModuleBase_ParamSpinBox* myYSpin; ///< the spin box for the Y coordinate //std::string myOptionParam; /// Parameter name which has to be taken from previous feature diff --git a/src/PartSet/PartSet_WidgetPoint2dDistance.cpp b/src/PartSet/PartSet_WidgetPoint2dDistance.cpp index 0e4098476..e8d24eb51 100644 --- a/src/PartSet/PartSet_WidgetPoint2dDistance.cpp +++ b/src/PartSet/PartSet_WidgetPoint2dDistance.cpp @@ -7,7 +7,7 @@ #include "PartSet_WidgetPoint2dDistance.h" #include "PartSet_Tools.h" -#include +#include #include #include -- 2.39.2