]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModuleBase/ModuleBase_ParamSpinBox.cpp
Salome HOME
#2027 Sketcher Trim Feature: 1. preview/selected attributes in trim; 2. avoid includi...
[modules/shaper.git] / src / ModuleBase / ModuleBase_ParamSpinBox.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 #include "ModuleBase_ParamSpinBox.h"
4
5 #include <ModelAPI_Session.h>
6 #include <ModelAPI_Document.h>
7 #include <ModelAPI_Feature.h>
8 #include <ModelAPI_ResultParameter.h>
9 #include <ModelAPI_AttributeDouble.h>
10 #include <ModelAPI_Tools.h>
11
12 #include <QKeyEvent>
13 #include <QLineEdit>
14 #include <QLocale>
15 #include <QRegExp>
16 #include <QToolTip>
17 #include <QApplication>
18
19 #include <QStringListModel>
20 #include <QCompleter>
21 #include <QShortcut>
22
23 #include <string>
24 #include <iostream>
25
26 //#define DEBUG_COMPLETE_WITH_PARAMETERS
27
28 ModuleBase_ParamSpinBox::ModuleBase_ParamSpinBox(QWidget* theParent, int thePrecision)
29     : ModuleBase_DoubleSpinBox(theParent, thePrecision),
30       myAcceptVariables(true)
31 {
32 #ifdef DEBUG_COMPLETE_WITH_PARAMETERS
33   myCompleter = new QCompleter(this);
34   myCompleter->setWidget(this);
35   myCompleter->setCompletionMode(QCompleter::PopupCompletion);
36
37   myCompleterModel = new QStringListModel(this);
38   myCompleter->setModel(myCompleterModel);
39   // Use sorted model to accelerate completion (QCompleter will use binary search)
40   myCompleter->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
41   myCompleter->setCaseSensitivity(Qt::CaseInsensitive);
42
43   lineEdit()->setCompleter(myCompleter);
44 #endif
45
46   connectSignalsAndSlots();
47 }
48
49 void ModuleBase_ParamSpinBox::setCompletionList(QStringList& theList)
50 {
51 #ifdef DEBUG_COMPLETE_WITH_PARAMETERS
52   theList.sort();
53   theList.removeDuplicates();
54   myCompleterModel->setStringList(theList);
55 #endif
56 }
57
58 /*!
59  \brief Destructor.
60  */
61 ModuleBase_ParamSpinBox::~ModuleBase_ParamSpinBox()
62 {
63 }
64
65 /*!
66  \brief Perform \a steps increment/decrement steps.
67
68  Re-implemented to handle cases when Notebook variable
69  name is specified by the user as the widget text.
70  Otherwise, simply calls the base implementation.
71
72  \param steps number of increment/decrement steps
73  */
74 void ModuleBase_ParamSpinBox::stepBy(int steps)
75 {
76   if ((!myTextValue.isEmpty()) && hasVariable())
77     return;
78
79   ModuleBase_DoubleSpinBox::stepBy(steps);
80 }
81
82 /*!
83  \brief Connect signals and slots.
84  */
85 void ModuleBase_ParamSpinBox::connectSignalsAndSlots()
86 {
87   connect(this, SIGNAL(valueChanged(const QString&)),
88           this, SLOT(onTextChanged(const QString&)));
89 }
90
91 void ModuleBase_ParamSpinBox::onTextChanged(const QString& text)
92 {
93   myTextValue = text;
94   emit textChanged(text);
95 }
96
97 double ModuleBase_ParamSpinBox::valueFromText(const QString& theText) const
98 {
99   if (!hasVariable(theText))
100     return ModuleBase_DoubleSpinBox::valueFromText(theText);
101
102   // small hack: return hash of the string to initiate valuesChanged signal
103   return qHash(theText);
104 }
105
106 QString ModuleBase_ParamSpinBox::textFromValue (double theValue) const
107 {
108   if ((!myTextValue.isEmpty()) && hasVariable(myTextValue)){
109     return myTextValue;
110   }
111   return ModuleBase_DoubleSpinBox::textFromValue(theValue);
112 }
113
114 /*!
115  \brief This function is used to determine whether input is valid.
116  \param str currently entered value
117  \param pos cursor position in the string
118  \return validating operation result
119  */
120 QValidator::State ModuleBase_ParamSpinBox::validate(QString& str, int& pos) const
121 {
122   // Trying to interpret the current input text as a numeric value
123   if (!hasVariable(str))
124     return ModuleBase_DoubleSpinBox::validate(str, pos);
125
126   QValidator::State res = QValidator::Invalid;
127   if (isAcceptVariables()) {
128     res = QValidator::Acceptable;
129   }
130   return res;
131 }
132
133 /*!
134  \brief This function is used to set a current value for this spinbox.
135  \param value current value
136
137  The new value is ignored if the spinbox has a variable.
138  */
139 void ModuleBase_ParamSpinBox::setValue(const double value)
140 {
141   if (hasVariable())
142     return;
143
144   myTextValue = ModuleBase_DoubleSpinBox::textFromValue(value);
145   ModuleBase_DoubleSpinBox::setValue(value);
146 }
147
148 /*!
149  \brief This function is used to set a text for this spinbox.
150  \param value current value
151  */
152 void ModuleBase_ParamSpinBox::setText(const QString& value)
153 {
154   myTextValue = value;
155   lineEdit()->setText(value);
156 }
157
158 /*!
159  \brief Enables or disables variable names in the spin box.
160  By default, variable names are enabled.
161  \param flag If true, variable names are enabled.
162  */
163 void ModuleBase_ParamSpinBox::setAcceptVariables(const bool flag)
164 {
165   myAcceptVariables = flag;
166 }
167
168 /*!
169  \brief Returns true if the spin box accepts variable names.
170  */
171 bool ModuleBase_ParamSpinBox::isAcceptVariables() const
172 {
173   return myAcceptVariables;
174 }
175
176 bool ModuleBase_ParamSpinBox::hasVariable() const
177 {
178   if (myTextValue.isEmpty())
179     return false;
180   return hasVariable(myTextValue);
181 }
182
183 bool ModuleBase_ParamSpinBox::hasVariable(const QString& theText) const
184 {
185   //const QString aDigitPattern = QString("[-+]?[0-9]*[%1]?[0-9]*([eE][-+]?[0-9]+)?");
186
187   //bool aHasDigit = false;
188   //{
189   //  QRegExp varNameMask(aDigitPattern.arg("."));
190   //  aHasDigit = varNameMask.exactMatch(theText);
191   //}
192   //if (!aHasDigit)
193   //{
194   //  QRegExp varNameMask(aDigitPattern.arg(","));
195   //  aHasDigit = varNameMask.exactMatch(theText);
196   //}
197   bool isDouble = false;
198   QLocale::c().toDouble(theText, &isDouble);
199
200 //  theText.toDouble(&isDouble);
201 //  if (isDouble) {
202 //    QLocale aLoc; // create default locale
203 //    QChar aDecPnt = aLoc.decimalPoint();
204 //    if (aDecPnt == '.')
205 //      isDouble = theText.contains(aDecPnt) || (!theText.contains(','));
206 //    else if (aDecPnt == ',')
207 //      isDouble = theText.contains(aDecPnt) || (!theText.contains('.'));
208 //  }
209   return !isDouble;
210 }
211
212 /*!
213  \brief This function is used to determine whether input is valid.
214  \return validating operation result
215  */
216 ModuleBase_ParamSpinBox::State ModuleBase_ParamSpinBox::isValid(const QString& theText,
217                                                                 double& theValue) const
218 {
219   if (hasVariable() && !findVariable(theText, theValue)) {
220     bool ok = false;
221     theValue = locale().toDouble(theText, &ok);
222     if (!ok) {
223       return NoVariable;
224     }
225   }
226   if (!checkRange(theValue)) {
227     return Invalid;
228   }
229
230   return Acceptable;
231 }
232
233 /*!
234  \brief This function is used to check that string value lies within predefined range.
235  \return check status
236  */
237 bool ModuleBase_ParamSpinBox::checkRange(const double theValue) const
238 {
239   return theValue >= minimum() && theValue <= maximum();
240 }
241
242 /*!
243  \brief This function is used to determine whether input is a variable name and to get its value.
244  \return status of search operation
245  */
246 bool ModuleBase_ParamSpinBox::findVariable(const QString& theName,
247                                            double& outValue) const
248 {
249   ResultParameterPtr aParam;
250   return ModelAPI_Tools::findVariable(FeaturePtr(), theName.toStdString(), outValue, aParam);
251 }
252
253 /*!
254  \brief This function is called when the spinbox receives key press event.
255  */
256 //void ModuleBase_ParamSpinBox::keyPressEvent(QKeyEvent* e)
257 //{
258 //  if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
259 //    QWidget::keyPressEvent(e);
260 //  } else {
261 //    ModuleBase_DoubleSpinBox::keyPressEvent(e);
262 //  }
263 //}
264
265 /*!
266  \brief This function is called when the spinbox receives show event.
267  */
268 void ModuleBase_ParamSpinBox::showEvent(QShowEvent* theEvent)
269 {
270   ModuleBase_DoubleSpinBox::showEvent(theEvent);
271   if ((!myTextValue.isEmpty()) && hasVariable(myTextValue)) {
272     setText(myTextValue);
273   }
274 }