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>
37 ModuleBase_ParamSpinBox::ModuleBase_ParamSpinBox(QWidget* theParent, int thePrecision)
38 : QAbstractSpinBox(theParent),
39 myPrecision(thePrecision),
41 myAcceptVariables(true),
46 myCompleter = new QCompleter(this);
47 myCompleter->setWidget(lineEdit());
48 myCompleter->setCompletionMode(QCompleter::PopupCompletion);
50 myCompleterModel = new QStringListModel(this);
51 myCompleter->setModel(myCompleterModel);
52 // Use sorted model to accelerate completion (QCompleter will use binary search)
53 myCompleter->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
54 myCompleter->setCaseSensitivity(Qt::CaseInsensitive);
55 connect(myCompleter, SIGNAL(highlighted(const QString&)),
56 this, SLOT(insertCompletion(const QString&)));
58 // connectSignalsAndSlots();
59 myEnabledBaseColor = palette().color(QPalette::Active, QPalette::Base);
60 connect(lineEdit(), SIGNAL(textChanged(const QString&)),
61 this, SLOT(onTextChanged(const QString&)));
63 setLocale(QLocale::c());
65 myValidator = new QDoubleValidator(this);
66 myValidator->setLocale(locale());
67 myValidator->setRange(myMinimum, myMaximum);
68 myValidator->setDecimals(3);
71 void ModuleBase_ParamSpinBox::setCompletionList(QStringList& theList)
74 theList.removeDuplicates();
75 myCompleterModel->setStringList(theList);
81 ModuleBase_ParamSpinBox::~ModuleBase_ParamSpinBox()
87 \brief Perform \a steps increment/decrement steps.
89 Re-implemented to handle cases when Notebook variable
90 name is specified by the user as the widget text.
91 Otherwise, simply calls the base implementation.
93 \param steps number of increment/decrement steps
95 void ModuleBase_ParamSpinBox::stepBy(int steps)
100 double aVal = lineEdit()->text().toDouble();
101 aVal += steps * mySingleStep;
103 QAbstractSpinBox::stepBy(steps);
106 void ModuleBase_ParamSpinBox::onTextChanged(const QString& theText)
108 myIsEquation = hasVariable(theText);
109 emit textChanged(theText);
114 \brief This function is used to determine whether input is valid.
115 \param str currently entered value
116 \param pos cursor position in the string
117 \return validating operation result
119 QValidator::State ModuleBase_ParamSpinBox::validate(QString& str, int& pos) const
121 // Trying to interpret the current input text as a numeric value
122 if (!hasVariable(str)) {
123 /// If decimals = 0 do not accept '.' (interpret as int)
124 if ((myValidator->decimals() == 0) && str.endsWith('.'))
125 return QValidator::Invalid;
126 return myValidator->validate(str, pos);
129 return isAcceptVariables() ? QValidator::Acceptable : QValidator::Invalid;
133 \brief This function is used to set a current value for this spinbox.
134 \param value current value
136 The new value is ignored if the spinbox has a variable.
138 void ModuleBase_ParamSpinBox::setValue(double value)
140 myIsEquation = false;
142 if (aVal < myMinimum)
144 else if (aVal > myMaximum)
146 QString aText = QString::number(aVal, 'g', decimals());
147 lineEdit()->setText(aText);
148 emit textChanged(aText);
151 double ModuleBase_ParamSpinBox::value() const
153 return lineEdit()->text().toDouble();
157 \brief This function is used to set a text for this spinbox.
158 \param value current value
160 void ModuleBase_ParamSpinBox::setText(const QString& value)
162 myIsEquation = hasVariable(value);
163 if (myAcceptVariables && myIsEquation) {
164 lineEdit()->setText(value);
165 emit textChanged(value);
170 \brief Enables or disables variable names in the spin box.
171 By default, variable names are enabled.
172 \param flag If true, variable names are enabled.
174 void ModuleBase_ParamSpinBox::setAcceptVariables(const bool flag)
176 myAcceptVariables = flag;
177 if ((!myAcceptVariables) && myIsEquation) {
183 \brief Returns true if the spin box accepts variable names.
185 bool ModuleBase_ParamSpinBox::isAcceptVariables() const
187 return myAcceptVariables;
190 bool ModuleBase_ParamSpinBox::hasVariable() const
195 bool ModuleBase_ParamSpinBox::hasVariable(const QString& theText) const
197 bool isDouble = false;
198 QLocale::c().toDouble(theText, &isDouble);
202 void ModuleBase_ParamSpinBox::keyReleaseEvent(QKeyEvent* e)
208 if (myCompleter->popup()->isVisible()) {
209 myCompleter->popup()->hide();
212 emit textChanged(lineEdit()->text());
216 if (e->modifiers() & Qt::ControlModifier) {
217 myCompletePos = lineEdit()->cursorPosition();
219 QString aPrefix = getPrefix(aStart, aEnd);
220 myCompleter->setCompletionPrefix(aPrefix);
221 myCompleter->complete();
225 QAbstractSpinBox::keyReleaseEvent(e);
230 QString ModuleBase_ParamSpinBox::getPrefix(int& theStart, int& theEnd) const
233 QString aText = lineEdit()->text();
234 theStart = theEnd = myCompletePos;
235 const int aLen = aText.length();
237 if (myCompletePos > 0) {
238 int aLastChar = myCompletePos - 1;
239 QChar aChar = aText.at(aLastChar);
240 while (aChar.isLetter() || aChar.isDigit()) {
241 aPrefix.prepend(aText.at(aLastChar));
245 aChar = aText.at(aLastChar);
247 theStart = aLastChar + 1;
249 if (myCompletePos < aLen) {
250 int aLastChar = myCompletePos;
251 QChar aChar = aText.at(aLastChar);
252 while (aChar.isLetter() || aChar.isDigit()) {
253 aPrefix.append(aText.at(aLastChar));
255 if (aLastChar >= aLen)
257 aChar = aText.at(aLastChar);
266 void ModuleBase_ParamSpinBox::insertCompletion(const QString& theText)
268 QString aText = lineEdit()->text();
270 QString aPrefix = getPrefix(aStart, aEnd);
273 int aPrefLen = aPrefix.length();
275 aResult = aText.insert(myCompletePos, theText);
277 aResult = aText.left(aStart) + theText + aText.right(aText.length() - aEnd);
279 lineEdit()->setText(aResult);
284 void ModuleBase_ParamSpinBox::setValueEnabled(bool theEnable)
286 setReadOnly(!theEnable);
288 QPalette aPal = palette();
289 aPal.setColor(QPalette::All, QPalette::Base,
290 theEnable ? myEnabledBaseColor : aPal.color(QPalette::Disabled, QPalette::Base));