44 , m_lineEdit(m_q->lineEdit())
46 m_q->installEventFilter(
this);
48 m_lineEdit->setAutoFillBackground(
false);
49 m_lineEdit->installEventFilter(
this);
53 m_timerShowWarning.setSingleShot(
true);
55 if (m_warningIcon.isNull() && QFile(
":/./16_light_warning.svg").exists()) {
56 m_warningIcon = QIcon(
":/./16_light_warning.svg");
58 m_warningAnimation.setStartValue(0.0);
59 m_warningAnimation.setEndValue(1.0);
60 m_warningAnimation.setEasingCurve(QEasingCurve(QEasingCurve::InOutCubic));
61 connect(&m_warningAnimation, &QVariantAnimation::valueChanged, m_lineEdit, QOverload<>::of(&QLineEdit::update));
79 if (!m_q->hasFocus() || m_lineEdit->isReadOnly()) {
80 overwriteExpression =
true;
84 if (overwriteExpression) {
85 m_lastExpressionParsed = QString();
91 if (
value != m_q->value() || overwriteExpression) {
92 m_q->BaseSpinBoxType::setValue(
value);
96 Q_EMIT m_q->noMoreParsingError();
119 template <typename U = SpinBoxTypeTP, typename = typename std::enable_if<std::is_same<ValueType, int>::value, U>::type>
126 template <typename U = SpinBoxTypeTP, typename = typename std::enable_if<std::is_same<ValueType, double>::value, U>::type>
141 m_lastExpressionParsed = text;
142 if (m_lastExpressionParsed.endsWith(m_q->suffix())) {
143 m_lastExpressionParsed.remove(m_lastExpressionParsed.size() - m_q->suffix().size(), m_q->suffix().size());
145 if(m_lastExpressionParsed.startsWith(m_q->prefix())){
146 m_lastExpressionParsed.remove(0, m_q->prefix().size());
150 ValueType value = parseMathExpression(m_lastExpressionParsed, &ok);
153 m_isLastValid =
false;
154 value = m_q->value();
155 showWarning(showWarningInterval);
156 Q_EMIT m_q->errorWhileParsing(text);
158 if (!m_isLastValid) {
159 m_isLastValid =
true;
160 Q_EMIT m_q->noMoreParsingError();
184 if (m_lineEdit->selectedText().isEmpty()) {
187 const int suffixStart = m_q->text().length() - m_q->suffix().length();
188 const int newStart = qBound(m_q->prefix().length(), m_lineEdit->selectionStart(), suffixStart);
189 const int newEnd = qBound(m_q->prefix().length(), m_lineEdit->selectionStart() + m_lineEdit->selectedText().length(), suffixStart);
190 if (m_lineEdit->cursorPosition() == m_lineEdit->selectionStart()) {
191 m_lineEdit->setSelection(newEnd, -(newEnd - newStart));
193 m_lineEdit->setSelection(newStart, newEnd - newStart);
215 if (m_isWarningActive && m_warningAnimation.state() == QVariantAnimation::Running) {
218 m_timerShowWarning.stop();
219 m_warningAnimation.stop();
220 m_isWarningActive =
true;
221 if (!m_warningIcon.isNull()) {
222 QFontMetricsF fm(m_lineEdit->font());
223#if QT_VERSION >= QT_VERSION_CHECK(5,11,0)
224 const qreal textWidth = fm.horizontalAdvance(m_lineEdit->text());
226 const qreal textWidth = fm.width(m_lineEdit->text());
228 const int minimumWidth =
231 textWidth + (m_q->alignment() == Qt::AlignCenter ? 2.0 : 1.0) * widthOfWarningIconArea + 4
234 if (m_lineEdit->width() >= minimumWidth) {
235 m_showWarningIcon =
true;
237 m_showWarningIcon =
false;
241 const int animationDuration =
242 static_cast<int>(std::round((1.0 - m_warningAnimation.currentValue().toReal()) * warningAnimationDuration));
243 m_warningAnimation.setStartValue(m_warningAnimation.currentValue());
244 m_warningAnimation.setEndValue(1.0);
245 m_warningAnimation.setDuration(animationDuration);
246 m_warningAnimation.start();
265 m_timerShowWarning.stop();
266 m_warningAnimation.stop();
267 m_isWarningActive =
false;
269 const int animationDuration =
270 static_cast<int>(std::round(m_warningAnimation.currentValue().toReal() * warningAnimationDuration));
271 m_warningAnimation.setStartValue(m_warningAnimation.currentValue());
272 m_warningAnimation.setEndValue(0.0);
273 m_warningAnimation.setDuration(animationDuration);
274 m_warningAnimation.start();
366 QPainter painter(m_lineEdit);
367 painter.setRenderHint(QPainter::Antialiasing,
true);
368 QPalette pal = m_lineEdit->palette();
370 QColor color(255, 48, 0, 0);
371 constexpr int maxOpacity = 160;
373 const qreal warningAnimationPos = m_warningAnimation.currentValue().toReal();
375 if (m_warningAnimation.state() == QVariantAnimation::Running) {
376 color.setAlpha(
static_cast<int>(std::round(
KisAlgebra2D::lerp(0.0,
static_cast<double>(maxOpacity), warningAnimationPos))));
379 if (m_isWarningActive) {
380 color.setAlpha(maxOpacity);
381 textColor = Qt::white;
383 textColor = m_q->palette().text().color();
387 const QRect
rect = m_lineEdit->rect();
388 painter.setBrush(color);
389 painter.setPen(Qt::NoPen);
391 if (style ==
"fusion") {
392 painter.drawRoundedRect(
rect, 1, 1);
394 painter.drawRoundedRect(
rect, 0, 0);
397 if (m_showWarningIcon) {
398 constexpr qreal warningIconMargin = 4.0;
399 const qreal warningIconSize = widthOfWarningIconArea - 2.0 * warningIconMargin;
400 if (m_warningAnimation.state() == QVariantAnimation::Running) {
401 qreal warningIconPos =
403 m_lineEdit->alignment() & Qt::AlignRight ? -warningIconMargin :
rect.width() - warningIconSize + warningIconMargin,
404 m_lineEdit->alignment() & Qt::AlignRight ? warningIconMargin :
rect.width() - warningIconSize - warningIconMargin,
407 painter.setOpacity(warningAnimationPos);
409 warningIconPos, (
static_cast<qreal
>(
rect.height()) - warningIconSize) / 2.0,
410 m_warningIcon.pixmap(warningIconSize, warningIconSize)
412 }
else if (m_isWarningActive) {
414 m_lineEdit->alignment() & Qt::AlignRight ? warningIconMargin :
rect.width() - warningIconSize - warningIconMargin,
415 (
static_cast<qreal
>(
rect.height()) - warningIconSize) / 2.0,
416 m_warningIcon.pixmap(warningIconSize, warningIconSize)
421 pal.setBrush(QPalette::Text, textColor);
424 pal.setBrush(QPalette::Base, Qt::transparent);
425 pal.setBrush(QPalette::Button, Qt::transparent);
426 m_lineEdit->setPalette(pal);