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 return lineEdit()->text().toDouble();
158 \brief This function is used to set a text for this spinbox.
159 \param value current value
161 void ModuleBase_ParamSpinBox::setText(const QString& value)
163 myIsEquation = hasVariable(value);
164 if (myAcceptVariables && myIsEquation) {
165 lineEdit()->setText(value);
166 emit textChanged(value);
171 \brief Enables or disables variable names in the spin box.
172 By default, variable names are enabled.
173 \param flag If true, variable names are enabled.
175 void ModuleBase_ParamSpinBox::setAcceptVariables(const bool flag)
177 myAcceptVariables = flag;
178 if ((!myAcceptVariables) && myIsEquation) {
184 \brief Returns true if the spin box accepts variable names.
186 bool ModuleBase_ParamSpinBox::isAcceptVariables() const
188 return myAcceptVariables;
191 bool ModuleBase_ParamSpinBox::hasVariable() const
196 bool ModuleBase_ParamSpinBox::hasVariable(const QString& theText) const
198 bool isDouble = false;
199 QLocale::c().toDouble(theText, &isDouble);
203 void ModuleBase_ParamSpinBox::keyReleaseEvent(QKeyEvent* e)
209 if (myCompleter->popup()->isVisible()) {
210 myCompleter->popup()->hide();
213 emit textChanged(lineEdit()->text());
217 if (e->modifiers() & Qt::ControlModifier) {
218 myCompletePos = lineEdit()->cursorPosition();
220 QString aPrefix = getPrefix(aStart, aEnd);
221 myCompleter->setCompletionPrefix(aPrefix);
222 myCompleter->complete();
226 QAbstractSpinBox::keyReleaseEvent(e);
231 QString ModuleBase_ParamSpinBox::getPrefix(int& theStart, int& theEnd) const
234 QString aText = lineEdit()->text();
235 theStart = theEnd = myCompletePos;
236 const int aLen = aText.length();
238 if (myCompletePos > 0) {
239 int aLastChar = myCompletePos - 1;
240 QChar aChar = aText.at(aLastChar);
241 while (aChar.isLetter() || aChar.isDigit()) {
242 aPrefix.prepend(aText.at(aLastChar));
246 aChar = aText.at(aLastChar);
248 theStart = aLastChar + 1;
250 if (myCompletePos < aLen) {
251 int aLastChar = myCompletePos;
252 QChar aChar = aText.at(aLastChar);
253 while (aChar.isLetter() || aChar.isDigit()) {
254 aPrefix.append(aText.at(aLastChar));
256 if (aLastChar >= aLen)
258 aChar = aText.at(aLastChar);
267 void ModuleBase_ParamSpinBox::insertCompletion(const QString& theText)
269 QString aText = lineEdit()->text();
271 QString aPrefix = getPrefix(aStart, aEnd);
274 int aPrefLen = aPrefix.length();
276 aResult = aText.insert(myCompletePos, theText);
278 aResult = aText.left(aStart) + theText + aText.right(aText.length() - aEnd);
280 lineEdit()->setText(aResult);
285 void ModuleBase_ParamSpinBox::setValueEnabled(bool theEnable)
287 setReadOnly(!theEnable);
289 QPalette aPal = palette();
290 aPal.setColor(QPalette::All, QPalette::Base,
291 theEnable ? myEnabledBaseColor : aPal.color(QPalette::Disabled, QPalette::Base));