Salome HOME
Using variables in WidgetDoubleValue
authorsbh <sergey.belash@opencascade.com>
Wed, 8 Apr 2015 18:00:32 +0000 (21:00 +0300)
committersbh <sergey.belash@opencascade.com>
Wed, 8 Apr 2015 18:00:32 +0000 (21:00 +0300)
13 files changed:
src/Model/Model_AttributeDouble.cpp
src/Model/Model_AttributeDouble.h
src/ModelAPI/ModelAPI_AttributeDouble.h
src/ModuleBase/CMakeLists.txt
src/ModuleBase/ModuleBase_DoubleSpinBox.h
src/ModuleBase/ModuleBase_ParamSpinBox.cpp [new file with mode: 0644]
src/ModuleBase/ModuleBase_ParamSpinBox.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp
src/ModuleBase/ModuleBase_WidgetDoubleValue.h
src/ModuleBase/ModuleBase_WidgetEditor.cpp
src/PartSet/PartSet_WidgetPoint2d.cpp
src/PartSet/PartSet_WidgetPoint2d.h
src/PartSet/PartSet_WidgetPoint2dDistance.cpp

index 4764420f7c515a0184b7471f416ae4a328e5bdaa..87bba89cfcb414356737172b932e57058adcf23c 100644 (file)
@@ -8,6 +8,9 @@
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Data.h>
 
+#include <TCollection_AsciiString.hxx>
+#include <TCollection_ExtendedString.hxx>
+
 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();
+}
index f04db7f88e9cdba0b4aef6b0fbd619e8cbfe08aa..951c99613ad1f0640acd05890c1c9607dc3841a6 100644 (file)
@@ -12,6 +12,8 @@
 #include <TDataStd_Real.hxx>
 #include <TDF_Label.hxx>
 
+#include <TDataStd_Name.hxx>
+
 /**\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);
index 291bc18831bc0e94509b34bd66356c0ee250a966..6ac965232fbf28b6a8c395f13a3068709e9fd42a 100644 (file)
@@ -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()
   {
index 3f5ba997f88d382f3d80ec29308c6b6c435a1a43..fd7878d103757eb542a6e5705a89b46c650ff25c 100644 (file)
@@ -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
index 11de54784dfbf2e450ba148094a9d01d1cbe7b20..347af2f49461d16ee029323ae620b6fd6352db8f 100644 (file)
@@ -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 (file)
index 0000000..cfcd5e6
--- /dev/null
@@ -0,0 +1,311 @@
+#include "ModuleBase_ParamSpinBox.h"
+
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_ResultParameter.h>
+#include <ModelAPI_AttributeDouble.h>
+
+#include <QKeyEvent>
+#include <QLineEdit>
+#include <QToolTip>
+#include <QRegExp>
+
+#include <string>
+
+/*!
+ \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<ModelAPI_ResultParameter>(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 (file)
index 0000000..5945dcb
--- /dev/null
@@ -0,0 +1,70 @@
+
+#ifndef ModuleBase_ParamSpinBox_H
+#define ModuleBase_ParamSpinBox_H
+
+#include "ModuleBase.h"
+
+#include <ModuleBase_DoubleSpinBox.h>
+
+#include <QValidator>
+
+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
index 4053a2a4b6c8d33f25b9c116462d7d9d3ca93555..0b5c4e681e8933da8ce7c8ef9ed67b56417d9281 100644 (file)
@@ -5,10 +5,11 @@
 // Author:      Vitaly Smetannikov
 
 #include <ModuleBase_WidgetDoubleValue.h>
-#include <ModuleBase_DoubleSpinBox.h>
+#include <ModuleBase_ParamSpinBox.h>
 #include <ModuleBase_Tools.h>
 
 #include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeString.h>
 #include <ModelAPI_Data.h>
 
 #include <Config_Keywords.h>
@@ -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;
 }
 
index a83292914eda6145fcb24f9927d021705793a708..228efa0d2602946fde74a1947b9616e589fb24cd 100644 (file)
@@ -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
index 8c3b74bdfd4f372db20791bea0838dd6aefc0502..c096d0b46dfc223a15960f913595cce8ad8c49de 100644 (file)
@@ -5,7 +5,7 @@
 // Author:      Natalia ERMOLAEVA
 
 #include <ModuleBase_WidgetEditor.h>
-#include <ModuleBase_DoubleSpinBox.h>
+#include <ModuleBase_ParamSpinBox.h>
 #include <ModuleBase_Tools.h>
 
 #include <Config_Keywords.h>
index 10f6de95fd65dc663d5e28d6d00fcbcab2f4ebed..d2c65a27f018a24c843d8e9a7c1fcc4d4b6f0b0f 100644 (file)
@@ -14,7 +14,7 @@
 #include <XGUI_Selection.h>
 #include <XGUI_OperationMgr.h>
 
-#include <ModuleBase_DoubleSpinBox.h>
+#include <ModuleBase_ParamSpinBox.h>
 #include <ModuleBase_Tools.h>
 #include <ModuleBase_IViewWindow.h>
 
@@ -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"));
index e39011c9054e32484b65472bdf9bdda846078354..133ac4fa6b28ca564c075b3bd92dcc6a12614cbc 100644 (file)
@@ -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
 
index 0e40984766fc5af49890a7b32df41b298958473a..e8d24eb51421f612c0b514c7d61b8263a460a667 100644 (file)
@@ -7,7 +7,7 @@
 #include "PartSet_WidgetPoint2dDistance.h"
 #include "PartSet_Tools.h"
 
-#include <ModuleBase_DoubleSpinBox.h>
+#include <ModuleBase_ParamSpinBox.h>
 #include <ModuleBase_IViewWindow.h>
 #include <ModuleBase_Tools.h>