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>
39 bool isVariableSymbol(const QChar& theChar) {
40 if (theChar.isLetterOrNumber())
47 ModuleBase_ParamSpinBox::ModuleBase_ParamSpinBox(QWidget* theParent, int thePrecision)
48 : QAbstractSpinBox(theParent),
50 myAcceptVariables(true),
55 myCompleter = new QCompleter(this);
56 myCompleter->setWidget(lineEdit());
57 myCompleter->setCompletionMode(QCompleter::PopupCompletion);
59 myCompleterModel = new QStringListModel(this);
60 myCompleter->setModel(myCompleterModel);
61 connect(myCompleter, SIGNAL(highlighted(const QString&)),
62 this, SLOT(insertCompletion(const QString&)));
64 QAbstractItemView* aPopup = myCompleter->popup();
65 aPopup->installEventFilter(this);
67 // connectSignalsAndSlots();
68 myEnabledBaseColor = palette().color(QPalette::Active, QPalette::Base);
69 connect(lineEdit(), SIGNAL(textChanged(const QString&)),
70 this, SLOT(onTextChanged(const QString&)));
72 setLocale(QLocale::c());
74 myValidator = new QDoubleValidator(this);
75 myValidator->setLocale(locale());
76 myValidator->setRange(myMinimum, myMaximum);
77 myValidator->setDecimals(thePrecision);
80 void ModuleBase_ParamSpinBox::setCompletionList(QStringList& theList)
82 theList.removeDuplicates();
84 myCompleterModel->setStringList(theList);
90 ModuleBase_ParamSpinBox::~ModuleBase_ParamSpinBox()
96 \brief Perform \a steps increment/decrement steps.
98 Re-implemented to handle cases when Notebook variable
99 name is specified by the user as the widget text.
100 Otherwise, simply calls the base implementation.
102 \param steps number of increment/decrement steps
104 void ModuleBase_ParamSpinBox::stepBy(int steps)
109 double aVal = lineEdit()->text().toDouble();
110 aVal += steps * mySingleStep;
112 //QAbstractSpinBox::stepBy(steps);
115 void ModuleBase_ParamSpinBox::onTextChanged(const QString& theText)
117 myIsEquation = hasVariable(theText);
118 emit textChanged(theText);
123 \brief This function is used to determine whether input is valid.
124 \param str currently entered value
125 \param pos cursor position in the string
126 \return validating operation result
128 QValidator::State ModuleBase_ParamSpinBox::validate(QString& str, int& pos) const
130 // Trying to interpret the current input text as a numeric value
131 if (!hasVariable(str)) {
132 /// If decimals = 0 do not accept '.' (interpret as int)
133 if ((myValidator->decimals() == 0) && str.endsWith('.'))
134 return QValidator::Invalid;
135 return myValidator->validate(str, pos);
138 return isAcceptVariables() ? QValidator::Acceptable : QValidator::Invalid;
142 \brief This function is used to set a current value for this spinbox.
143 \param value current value
145 The new value is ignored if the spinbox has a variable.
147 void ModuleBase_ParamSpinBox::setValue(double value)
149 myIsEquation = false;
151 if (aVal < myMinimum)
153 else if (aVal > myMaximum)
155 QString aText = (myValidator->decimals() == 0) ? QString::number((int)aVal) :
156 QString::number(aVal, 'g', decimals());
157 lineEdit()->blockSignals(true);
158 lineEdit()->setText(aText);
159 lineEdit()->blockSignals(false);
160 emit textChanged(aText);
163 double ModuleBase_ParamSpinBox::value() const
165 std::string aa = lineEdit()->text().toStdString();
166 return lineEdit()->text().toDouble();
170 \brief This function is used to set a text for this spinbox.
171 \param value current value
173 void ModuleBase_ParamSpinBox::setText(const QString& value)
175 myIsEquation = hasVariable(value);
176 if (myAcceptVariables && myIsEquation) {
177 lineEdit()->setText(value);
178 emit textChanged(value);
182 double aVal = value.toDouble(&isConv);
189 \brief Enables or disables variable names in the spin box.
190 By default, variable names are enabled.
191 \param flag If true, variable names are enabled.
193 void ModuleBase_ParamSpinBox::setAcceptVariables(const bool flag)
195 myAcceptVariables = flag;
196 if ((!myAcceptVariables) && myIsEquation) {
202 \brief Returns true if the spin box accepts variable names.
204 bool ModuleBase_ParamSpinBox::isAcceptVariables() const
206 return myAcceptVariables;
209 bool ModuleBase_ParamSpinBox::hasVariable() const
214 bool ModuleBase_ParamSpinBox::hasVariable(const QString& theText) const
216 bool isDouble = false;
217 QLocale::c().toDouble(theText, &isDouble);
221 void ModuleBase_ParamSpinBox::showCompletion(bool checkPrefix)
223 myCompletePos = lineEdit()->cursorPosition();
226 aPrefix = getPrefix(aStart, aEnd);
228 if (aPrefix.length() > 0) {
229 myCompleter->setCompletionPrefix(aPrefix);
230 myCompleter->complete();
233 myCompleter->setCompletionPrefix(aPrefix);
234 myCompleter->complete();
238 void ModuleBase_ParamSpinBox::keyReleaseEvent(QKeyEvent* e)
243 case Qt::Key_Backspace:
244 if (myCompleter->popup()->isVisible()) {
245 myCompleter->popup()->hide();
247 showCompletion(true);
251 if (myCompleter->popup()->isVisible()) {
252 myCompleter->popup()->hide();
255 emit textChanged(lineEdit()->text());
258 if (e->modifiers() & Qt::ControlModifier) {
259 showCompletion(false);
263 if (aText.length() == 1) {
264 QChar aChar = aText.at(0);
265 if (isVariableSymbol(aChar)) {
266 showCompletion(true);
270 QAbstractSpinBox::keyReleaseEvent(e);
273 bool ModuleBase_ParamSpinBox::eventFilter(QObject* theObj, QEvent* theEvent)
275 if (theEvent->type() == QEvent::KeyRelease) {
276 keyReleaseEvent((QKeyEvent*)theEvent);
278 return QAbstractSpinBox::eventFilter(theObj, theEvent);
282 QString ModuleBase_ParamSpinBox::getPrefix(int& theStart, int& theEnd) const
285 QString aText = lineEdit()->text();
286 theStart = theEnd = myCompletePos;
287 const int aLen = aText.length();
289 if (myCompletePos > 0) {
290 int aLastChar = myCompletePos - 1;
291 QChar aChar = aText.at(aLastChar);
292 while (isVariableSymbol(aChar)) {
293 aPrefix.prepend(aText.at(aLastChar));
297 aChar = aText.at(aLastChar);
299 theStart = aLastChar + 1;
301 if (myCompletePos < aLen) {
302 int aLastChar = myCompletePos;
303 QChar aChar = aText.at(aLastChar);
304 while (isVariableSymbol(aChar)) {
305 aPrefix.append(aText.at(aLastChar));
307 if (aLastChar >= aLen)
309 aChar = aText.at(aLastChar);
318 void ModuleBase_ParamSpinBox::insertCompletion(const QString& theText)
320 QString aText = lineEdit()->text();
322 QString aPrefix = getPrefix(aStart, aEnd);
325 int aPrefLen = aPrefix.length();
327 aResult = aText.insert(myCompletePos, theText);
329 aResult = aText.left(aStart) + theText + aText.right(aText.length() - aEnd);
331 lineEdit()->setText(aResult);
336 void ModuleBase_ParamSpinBox::setValueEnabled(bool theEnable)
338 setReadOnly(!theEnable);
340 QPalette aPal = palette();
341 aPal.setColor(QPalette::All, QPalette::Base,
342 theEnable ? myEnabledBaseColor : aPal.color(QPalette::Disabled, QPalette::Base));