1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include "ModuleBase_ParamSpinBox.h"
27 #include <QApplication>
29 #include <QStringListModel>
31 #include <QAbstractItemView>
38 ModuleBase_ParamSpinBox::ModuleBase_ParamSpinBox(QWidget* theParent, int thePrecision)
39 : QAbstractSpinBox(theParent),
40 myPrecision(thePrecision),
42 myAcceptVariables(true),
47 myCompleter = new QCompleter(this);
48 myCompleter->setWidget(lineEdit());
49 myCompleter->setCompletionMode(QCompleter::PopupCompletion);
51 myCompleterModel = new QStringListModel(this);
52 myCompleter->setModel(myCompleterModel);
53 // Use sorted model to accelerate completion (QCompleter will use binary search)
54 myCompleter->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
55 myCompleter->setCaseSensitivity(Qt::CaseInsensitive);
56 connect(myCompleter, SIGNAL(highlighted(const QString&)),
57 this, SLOT(insertCompletion(const QString&)));
59 // connectSignalsAndSlots();
60 myEnabledBaseColor = palette().color(QPalette::Active, QPalette::Base);
61 connect(lineEdit(), SIGNAL(textChanged(const QString&)),
62 this, SLOT(onTextChanged(const QString&)));
64 setLocale(QLocale::c());
66 myValidator = new QDoubleValidator(this);
67 myValidator->setLocale(locale());
68 myValidator->setRange(myMinimum, myMaximum);
69 myValidator->setDecimals(myPrecision);
72 void ModuleBase_ParamSpinBox::setCompletionList(QStringList& theList)
75 theList.removeDuplicates();
76 myCompleterModel->setStringList(theList);
82 ModuleBase_ParamSpinBox::~ModuleBase_ParamSpinBox()
88 \brief Perform \a steps increment/decrement steps.
90 Re-implemented to handle cases when Notebook variable
91 name is specified by the user as the widget text.
92 Otherwise, simply calls the base implementation.
94 \param steps number of increment/decrement steps
96 void ModuleBase_ParamSpinBox::stepBy(int steps)
101 double aVal = lineEdit()->text().toDouble();
102 aVal += steps * mySingleStep;
104 QAbstractSpinBox::stepBy(steps);
107 void ModuleBase_ParamSpinBox::onTextChanged(const QString& theText)
109 myIsEquation = hasVariable(theText);
110 emit textChanged(theText);
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
120 QValidator::State ModuleBase_ParamSpinBox::validate(QString& str, int& pos) const
122 // Trying to interpret the current input text as a numeric value
123 if (!hasVariable(str)) {
124 /// If decimals = 0 do not accept '.' (interpret as int)
125 if ((myValidator->decimals() == 0) && str.endsWith('.'))
126 return QValidator::Invalid;
127 return myValidator->validate(str, pos);
130 return isAcceptVariables() ? QValidator::Acceptable : QValidator::Invalid;
134 \brief This function is used to set a current value for this spinbox.
135 \param value current value
137 The new value is ignored if the spinbox has a variable.
139 void ModuleBase_ParamSpinBox::setValue(double value)
141 myIsEquation = false;
143 if (aVal < myMinimum)
145 else if (aVal > myMaximum)
147 QString aText = QString::number(aVal, 'g', decimals());
148 lineEdit()->setText(aText);
149 emit textChanged(aText);
152 double ModuleBase_ParamSpinBox::value() const
154 std::string aa = lineEdit()->text().toStdString();
155 return lineEdit()->text().toDouble();
159 \brief This function is used to set a text for this spinbox.
160 \param value current value
162 void ModuleBase_ParamSpinBox::setText(const QString& value)
164 myIsEquation = hasVariable(value);
165 if (myAcceptVariables && myIsEquation) {
166 lineEdit()->setText(value);
167 emit textChanged(value);
172 \brief Enables or disables variable names in the spin box.
173 By default, variable names are enabled.
174 \param flag If true, variable names are enabled.
176 void ModuleBase_ParamSpinBox::setAcceptVariables(const bool flag)
178 myAcceptVariables = flag;
179 if ((!myAcceptVariables) && myIsEquation) {
185 \brief Returns true if the spin box accepts variable names.
187 bool ModuleBase_ParamSpinBox::isAcceptVariables() const
189 return myAcceptVariables;
192 bool ModuleBase_ParamSpinBox::hasVariable() const
197 bool ModuleBase_ParamSpinBox::hasVariable(const QString& theText) const
199 bool isDouble = false;
200 QLocale::c().toDouble(theText, &isDouble);
204 void ModuleBase_ParamSpinBox::keyReleaseEvent(QKeyEvent* e)
210 if (myCompleter->popup()->isVisible()) {
211 myCompleter->popup()->hide();
214 emit textChanged(lineEdit()->text());
218 if (e->modifiers() & Qt::ControlModifier) {
219 myCompletePos = lineEdit()->cursorPosition();
221 QString aPrefix = getPrefix(aStart, aEnd);
222 myCompleter->setCompletionPrefix(aPrefix);
223 myCompleter->complete();
227 QAbstractSpinBox::keyReleaseEvent(e);
232 QString ModuleBase_ParamSpinBox::getPrefix(int& theStart, int& theEnd) const
235 QString aText = lineEdit()->text();
236 theStart = theEnd = myCompletePos;
237 const int aLen = aText.length();
239 if (myCompletePos > 0) {
240 int aLastChar = myCompletePos - 1;
241 QChar aChar = aText.at(aLastChar);
242 while (aChar.isLetter() || aChar.isDigit()) {
243 aPrefix.prepend(aText.at(aLastChar));
247 aChar = aText.at(aLastChar);
249 theStart = aLastChar + 1;
251 if (myCompletePos < aLen) {
252 int aLastChar = myCompletePos;
253 QChar aChar = aText.at(aLastChar);
254 while (aChar.isLetter() || aChar.isDigit()) {
255 aPrefix.append(aText.at(aLastChar));
257 if (aLastChar >= aLen)
259 aChar = aText.at(aLastChar);
268 void ModuleBase_ParamSpinBox::insertCompletion(const QString& theText)
270 QString aText = lineEdit()->text();
272 QString aPrefix = getPrefix(aStart, aEnd);
275 int aPrefLen = aPrefix.length();
277 aResult = aText.insert(myCompletePos, theText);
279 aResult = aText.left(aStart) + theText + aText.right(aText.length() - aEnd);
281 lineEdit()->setText(aResult);
286 void ModuleBase_ParamSpinBox::setValueEnabled(bool theEnable)
288 setReadOnly(!theEnable);
290 QPalette aPal = palette();
291 aPal.setColor(QPalette::All, QPalette::Base,
292 theEnable ? myEnabledBaseColor : aPal.color(QPalette::Disabled, QPalette::Base));