Salome HOME
Issue #1158: To use parameters in integer attributes -- GUI
authorspo <sergey.pokhodenko@opencascade.com>
Thu, 24 Dec 2015 09:18:46 +0000 (12:18 +0300)
committerspo <sergey.pokhodenko@opencascade.com>
Thu, 24 Dec 2015 13:27:53 +0000 (16:27 +0300)
src/ModuleBase/CMakeLists.txt
src/ModuleBase/ModuleBase_ParamIntSpinBox.cpp [new file with mode: 0644]
src/ModuleBase/ModuleBase_ParamIntSpinBox.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_Tools.cpp
src/ModuleBase/ModuleBase_Tools.h
src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp
src/ModuleBase/ModuleBase_WidgetIntValue.cpp
src/ModuleBase/ModuleBase_WidgetIntValue.h

index 48c904e16dd9106faf7355a2f22b0c43c4f8db3f..bc1ab4e90e709c80162feb4751acebe39bec323f 100644 (file)
@@ -30,6 +30,7 @@ SET(PROJECT_HEADERS
   ModuleBase_PageGroupBox.h
   ModuleBase_PageWidget.h      
   ModuleBase_PagedContainer.h
+  ModuleBase_ParamIntSpinBox.h
   ModuleBase_ParamSpinBox.h
   ModuleBase_Preferences.h
   ModuleBase_ResultPrs.h
@@ -85,6 +86,7 @@ SET(PROJECT_SOURCES
   ModuleBase_PageGroupBox.cpp
   ModuleBase_PageWidget.cpp
   ModuleBase_PagedContainer.cpp
+  ModuleBase_ParamIntSpinBox.cpp
   ModuleBase_ParamSpinBox.cpp
   ModuleBase_Preferences.cpp
   ModuleBase_ResultPrs.cpp
diff --git a/src/ModuleBase/ModuleBase_ParamIntSpinBox.cpp b/src/ModuleBase/ModuleBase_ParamIntSpinBox.cpp
new file mode 100644 (file)
index 0000000..b3f286d
--- /dev/null
@@ -0,0 +1,208 @@
+#include "ModuleBase_ParamIntSpinBox.h"
+
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_ResultParameter.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_Tools.h>
+
+#include <QKeyEvent>
+#include <QLineEdit>
+#include <QLocale>
+#include <QRegExp>
+#include <QToolTip>
+#include <QApplication>
+
+#include <string>
+#include <iostream>
+
+
+ModuleBase_ParamIntSpinBox::ModuleBase_ParamIntSpinBox(QWidget* theParent)
+    : ModuleBase_IntSpinBox(theParent),
+      myAcceptVariables(true)
+{
+  connectSignalsAndSlots();
+}
+
+/*!
+ \brief Destructor.
+ */
+ModuleBase_ParamIntSpinBox::~ModuleBase_ParamIntSpinBox()
+{
+}
+
+/*!
+ \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_ParamIntSpinBox::stepBy(int steps)
+{
+  if ((!myTextValue.isEmpty()) && hasVariable())
+    return;
+
+  ModuleBase_IntSpinBox::stepBy(steps);
+}
+
+/*!
+ \brief Connect signals and slots.
+ */
+void ModuleBase_ParamIntSpinBox::connectSignalsAndSlots()
+{
+  connect(this, SIGNAL(valueChanged(const QString&)),
+          this, SLOT(onTextChanged(const QString&)));
+}
+
+void ModuleBase_ParamIntSpinBox::onTextChanged(const QString& text)
+{
+  myTextValue = text;
+}
+
+int ModuleBase_ParamIntSpinBox::valueFromText(const QString& theText) const
+{
+  if (!hasVariable(theText))
+    return ModuleBase_IntSpinBox::valueFromText(theText);
+
+  // small hack: return hash of the string to initiate valuesChanged signal
+  return qHash(theText);
+}
+
+QString ModuleBase_ParamIntSpinBox::textFromValue(int theValue) const
+{
+  if ((!myTextValue.isEmpty()) && hasVariable(myTextValue)){
+    return myTextValue;
+  }
+  return ModuleBase_IntSpinBox::textFromValue(theValue);
+}
+
+/*!
+ \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_ParamIntSpinBox::validate(QString& str, int& pos) const
+{
+  // Trying to interpret the current input text as a numeric value
+  if (!hasVariable(str))
+    return ModuleBase_IntSpinBox::validate(str, pos);
+
+  QValidator::State res = QValidator::Invalid;
+  if (isAcceptVariables()) {
+    res = QValidator::Acceptable;
+  }
+  return res;
+}
+
+/*!
+ \brief This function is used to set a current value for this spinbox.
+ \param value current value
+
+ The new value is ignored if the spinbox has a variable.
+ */
+void ModuleBase_ParamIntSpinBox::setValue(int value)
+{
+  if (hasVariable())
+    return;
+
+  myTextValue = ModuleBase_IntSpinBox::textFromValue(value);
+  ModuleBase_IntSpinBox::setValue(value);
+}
+
+/*!
+ \brief This function is used to set a text for this spinbox.
+ \param value current value
+ */
+void ModuleBase_ParamIntSpinBox::setText(const QString& value)
+{
+  myTextValue = 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_ParamIntSpinBox::setAcceptVariables(const bool flag)
+{
+  myAcceptVariables = flag;
+}
+
+/*!
+ \brief Returns true if the spin box accepts variable names.
+ */
+bool ModuleBase_ParamIntSpinBox::isAcceptVariables() const
+{
+  return myAcceptVariables;
+}
+
+bool ModuleBase_ParamIntSpinBox::hasVariable() const
+{
+  if (myTextValue.isEmpty())
+    return false;
+  return hasVariable(myTextValue);
+}
+
+bool ModuleBase_ParamIntSpinBox::hasVariable(const QString& theText) const
+{
+  bool ok = false;
+  QLocale::c().toInt(theText, &ok);
+  return !ok;
+}
+
+/*!
+ \brief This function is used to determine whether input is valid.
+ \return validating operation result
+ */
+ModuleBase_ParamIntSpinBox::State ModuleBase_ParamIntSpinBox::isValid(
+    const QString& theText, double& theValue) const
+{
+  if (hasVariable() && !findVariable(theText, theValue)) {
+    bool ok = false;
+    theValue = locale().toInt(theText, &ok);
+    if (!ok) {
+      return NoVariable;
+    }
+  }
+  if (!checkRange(theValue)) {
+    return Invalid;
+  }
+
+  return Acceptable;
+}
+
+/*!
+ \brief This function is used to check that string value lies within predefined range.
+ \return check status
+ */
+bool ModuleBase_ParamIntSpinBox::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_ParamIntSpinBox::findVariable(const QString& theName,
+                                              double& outValue) const
+{
+  ResultParameterPtr aParam;
+  return ModelAPI_Tools::findVariable(theName.toStdString(), outValue, aParam);
+}
+
+/*!
+ \brief This function is called when the spinbox receives show event.
+ */
+void ModuleBase_ParamIntSpinBox::showEvent(QShowEvent* theEvent)
+{
+  ModuleBase_IntSpinBox::showEvent(theEvent);
+  if ((!myTextValue.isEmpty()) && hasVariable(myTextValue)) {
+    setText(myTextValue);
+  }
+}
diff --git a/src/ModuleBase/ModuleBase_ParamIntSpinBox.h b/src/ModuleBase/ModuleBase_ParamIntSpinBox.h
new file mode 100644 (file)
index 0000000..d728953
--- /dev/null
@@ -0,0 +1,87 @@
+
+#ifndef ModuleBase_ParamIntSpinBox_H
+#define ModuleBase_ParamIntSpinBox_H
+
+#include "ModuleBase.h"
+
+#include <ModuleBase_IntSpinBox.h>
+
+#include <QValidator>
+
+/**
+* \ingroup GUI
+* An extension of a double spin box which let to use parameters and expressions for value definition
+*/
+class MODULEBASE_EXPORT ModuleBase_ParamIntSpinBox : public ModuleBase_IntSpinBox
+{
+  Q_OBJECT
+
+  enum State { Invalid = 0, NoVariable, Incompatible, Acceptable };
+
+public:
+  /*!
+   \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 theParent a parent object
+   \param thePrecision a precision of values display
+   */
+  explicit ModuleBase_ParamIntSpinBox(QWidget* theParent = 0);
+  virtual ~ModuleBase_ParamIntSpinBox();
+
+  virtual void stepBy(int);
+
+  virtual int valueFromText(const QString&) const;
+  virtual QString textFromValue(int value) const;
+
+  virtual QValidator::State validate(QString&, int&) const;
+
+  virtual void setValue(int);
+
+  virtual void setText(const QString&);
+
+  /// Set a flag about accepted variable
+  void setAcceptVariables(const bool);
+
+  /// Returns accepted variables flag
+  bool isAcceptVariables() const;
+
+  /// Returns True if the input value contains variable
+  bool hasVariable() const;
+
+ protected:
+   /// Returns True if the given text contains variable
+   /// \param theText a text string
+  bool hasVariable(const QString& theText) const;
+
+  /// Returns state of the control
+  State isValid(const QString&, double&) const;
+
+  /// Returns True if the given value is within min and max of the control
+  bool checkRange(const double) const;
+
+  /// Finds a variable by its name. Returns true in success
+  /// \param theName a name of variable
+  /// \param outValue an output value of the variable
+  bool findVariable(const QString& theName, double& outValue) const;
+
+ protected:
+  virtual void showEvent(QShowEvent*);
+
+ protected slots:
+   /// A slot called on text change
+  void onTextChanged(const QString&);
+
+ private:
+  void connectSignalsAndSlots();
+
+ private:
+  QString myTextValue;
+
+  bool myAcceptVariables;
+};
+
+#endif
index 66f2979fa4dd03f45a2383900d285b7c89fd4230..6cbbe1c80c3361ba65c7009a2b57c7ac62f63f77 100755 (executable)
@@ -5,6 +5,8 @@
 // Author:      Vitaly Smetannikov
 
 #include "ModuleBase_Tools.h"
+
+#include <ModuleBase_ParamIntSpinBox.h>
 #include <ModuleBase_ParamSpinBox.h>
 
 #include <ModelAPI_Attribute.h>
@@ -190,6 +192,26 @@ void setSpinValue(ModuleBase_ParamSpinBox* theSpin, double theValue)
   theSpin->blockSignals(isBlocked);
 }
 
+void setSpinText(ModuleBase_ParamIntSpinBox* theSpin, const QString& theText)
+{
+  // In order to avoid extra text setting because it will
+  // reset cursor position in control
+  if (theSpin->text() == theText)
+    return;
+  bool isBlocked = theSpin->blockSignals(true);
+  theSpin->setText(theText);
+  theSpin->blockSignals(isBlocked);
+}
+
+void setSpinValue(ModuleBase_ParamIntSpinBox* theSpin, int theValue)
+{
+  if (theSpin->value() == theValue)
+    return;
+  bool isBlocked = theSpin->blockSignals(true);
+  theSpin->setValue(theValue);
+  theSpin->blockSignals(isBlocked);
+}
+
 QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo)
 {
   QString aFeatureStr = "feature";
index c8d3c6afa7655b63bd716ddafa9d2a5423342172..31556d8d822f88e79558e10ee7926a4cf6d7f7c0 100755 (executable)
@@ -24,6 +24,7 @@
 class QWidget;
 class QLayout;
 class QDoubleSpinBox;
+class ModuleBase_ParamIntSpinBox;
 class ModuleBase_ParamSpinBox;
 
 namespace ModuleBase_Tools {
@@ -102,6 +103,16 @@ MODULEBASE_EXPORT void setSpinValue(ModuleBase_ParamSpinBox* theSpin, double the
 /// \param theText a new value
 MODULEBASE_EXPORT void setSpinText(ModuleBase_ParamSpinBox* theSpin, const QString& theText);
 
+/// Sets programmatically the value to the spin box without emitting any signals(e.g. valueChanged)
+/// \param theSpin a ModuleBase_ParamIntSpinBox object
+/// \param theValue a new value
+MODULEBASE_EXPORT void setSpinValue(ModuleBase_ParamIntSpinBox* theSpin, int theValue);
+
+/// Sets programmatically the value to the spin box without emitting any signals(e.g. valueChanged)
+/// \param theSpin a SpinBox that accepts text
+/// \param theText a new value
+MODULEBASE_EXPORT void setSpinText(ModuleBase_ParamIntSpinBox* theSpin, const QString& theText);
+
 /// Converts the object to the feature or a result and generate information string
 /// \param theObj an object
 /// \param isUseAttributesInfo a flag whether the attribute values information is used
index 141abdd39f2902731bc583403242e592988f8457..fbe80ec1897a1c38369dcd1da4b4595c6d209573 100644 (file)
@@ -105,7 +105,7 @@ bool ModuleBase_WidgetDoubleValue::resetCustom()
     bool isOk;
     double aDefValue = QString::fromStdString(getDefaultValue()).toDouble(&isOk);
     // reset the value just if there is a default value definition in the XML definition
-    // if the double value can not be found by the default value, do nothing
+    // if the value can not be found by the default value, do nothing
     if (isOk) {
       ModuleBase_Tools::setSpinValue(mySpinBox, aDefValue);
       storeValue();
index 308aef0ff7f2dc46f576e137a4c473ddc28f0098..6056ca2e061ad93b4f1b0f6b852ac90478cc59db 100644 (file)
@@ -7,7 +7,7 @@
 #include <ModuleBase_WidgetIntValue.h>
 #include <ModuleBase_ParamSpinBox.h>
 #include <ModuleBase_Tools.h>
-#include <ModuleBase_IntSpinBox.h>
+#include <ModuleBase_ParamIntSpinBox.h>
 
 #include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_Data.h>
@@ -48,7 +48,7 @@ ModuleBase_WidgetIntValue::ModuleBase_WidgetIntValue(QWidget* theParent,
   if (!aLabelIcon.isEmpty())
     myLabel->setPixmap(QPixmap(aLabelIcon));
 
-  mySpinBox = new ModuleBase_IntSpinBox(this);
+  mySpinBox = new ModuleBase_ParamIntSpinBox(this);
   QString anObjName = QString::fromStdString(attributeID());
   mySpinBox->setObjectName(anObjName);
 
@@ -95,18 +95,16 @@ ModuleBase_WidgetIntValue::~ModuleBase_WidgetIntValue()
 bool ModuleBase_WidgetIntValue::resetCustom()
 {
   bool aDone = false;
-  if (!isUseReset() || isComputedDefault()) {
+  if (!isUseReset() || isComputedDefault() || mySpinBox->hasVariable()) {
     aDone = false;
   } else {
     bool isOk;
     int aDefValue = QString::fromStdString(getDefaultValue()).toInt(&isOk);
     // reset the value just if there is a default value definition in the XML definition
-    // if the double value can not be found by the default value, do nothing
+    // if the value can not be found by the default value, do nothing
     if (isOk) {
-      bool isBlocked = mySpinBox->blockSignals(true);
-      mySpinBox->setValue(isOk ? aDefValue : 0);
-      mySpinBox->blockSignals(isBlocked);
-      storeValueCustom();
+      ModuleBase_Tools::setSpinValue(mySpinBox, aDefValue);
+      storeValue();
       aDone = true;
     }
   }
@@ -116,9 +114,18 @@ bool ModuleBase_WidgetIntValue::resetCustom()
 bool ModuleBase_WidgetIntValue::storeValueCustom() const
 {
   DataPtr aData = myFeature->data();
-  AttributeIntegerPtr aIntVal = aData->integer(attributeID());
-  int aVal = mySpinBox->value();
-  aIntVal->setValue(mySpinBox->value());
+  AttributeIntegerPtr anAttribute = aData->integer(attributeID());
+  if (mySpinBox->hasVariable()) {
+    // Here is a text of a real value or an expression.
+    std::string aText = mySpinBox->text().toStdString();
+    anAttribute->setText(aText);
+  } else {
+    // it is important to set the empty text value to the attribute before set the value
+    // because setValue tries to calculate the attribute value according to the
+    // attribute current text
+    anAttribute->setText("");
+    anAttribute->setValue(mySpinBox->value());
+  }
   updateObject(myFeature);
   return true;
 }
@@ -126,13 +133,21 @@ bool ModuleBase_WidgetIntValue::storeValueCustom() const
 bool ModuleBase_WidgetIntValue::restoreValueCustom()
 {
   DataPtr aData = myFeature->data();
-  AttributeIntegerPtr aRef = aData->integer(attributeID());
-  bool isBlocked = mySpinBox->blockSignals(true);
-  mySpinBox->setValue(aRef->value());
-  mySpinBox->blockSignals(isBlocked);
+  AttributeIntegerPtr anAttribute = aData->integer(attributeID());
+  std::string aTextRepr = anAttribute->text();
+  if (!aTextRepr.empty()) {
+    ModuleBase_Tools::setSpinText(mySpinBox, QString::fromStdString(aTextRepr));
+  } else {
+    ModuleBase_Tools::setSpinValue(mySpinBox, anAttribute->value());
+  }
   return true;
 }
 
+void ModuleBase_WidgetIntValue::selectContent()
+{
+  mySpinBox->selectAll();
+}
+
 QList<QWidget*> ModuleBase_WidgetIntValue::getControls() const
 {
   QList<QWidget*> aList;
index 3eaf0e52bf22c37c34645abbb6b61f85c4806b12..1268a5592ebea580e1913851b10fe4c001d007cb 100644 (file)
@@ -10,7 +10,7 @@
 #include "ModuleBase.h"
 #include "ModuleBase_ModelWidget.h"
 
-class ModuleBase_IntSpinBox;
+class ModuleBase_ParamIntSpinBox;
 class Config_WidgetAPI;
 class QWidget;
 class QLabel;
@@ -37,6 +37,9 @@ Q_OBJECT
 
   virtual ~ModuleBase_WidgetIntValue();
 
+  /// Select the internal content if it can be selected. It is empty in the default realization
+  virtual void selectContent();
+
   /// Returns list of widget controls
   /// \return a control list
   virtual QList<QWidget*> getControls() const;
@@ -62,7 +65,7 @@ protected:
   QLabel* myLabel;
 
   /// Input value control
-  ModuleBase_IntSpinBox* mySpinBox;
+  ModuleBase_ParamIntSpinBox* mySpinBox;
 };
 
 #endif