File indexing completed on 2024-05-19 05:51:04
0001 /* Atelier KDE Printer Host for 3D Printing 0002 Copyright (C) <2018> 0003 Author: Tomaz Canabrava - tcanabrava@kde.org 0004 Chris Rizzitello - rizzitello@kde.org 0005 Lays Rodrigues - lays.rodrigues@kde.org 0006 0007 This program is free software: you can redistribute it and/or modify 0008 it under the terms of the GNU General Public License as published by 0009 the Free Software Foundation, either version 3 of the License, or 0010 (at your option) any later version. 0011 0012 This program is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 GNU General Public License for more details. 0016 0017 You should have received a copy of the GNU General Public License 0018 along with this program. If not, see <http://www.gnu.org/licenses/>. 0019 */ 0020 #include "thermowidget.h" 0021 #include <QApplication> 0022 #include <QBrush> 0023 #include <QFocusEvent> 0024 #include <QKeyEvent> 0025 #include <QPaintEvent> 0026 #include <QPainter> 0027 #include <QPen> 0028 #include <QTimer> 0029 #include <QWheelEvent> 0030 0031 ThermoWidget::ThermoWidget(QWidget *parent, const QString &name) 0032 : QcGaugeWidget(parent) 0033 , m_tempChangedTimer(new QTimer(this)) 0034 , m_currentTemperature(0) 0035 , m_targetTemperature(0) 0036 { 0037 setFocusPolicy(Qt::StrongFocus); 0038 QcBackgroundItem *bkground = addBackground(100); 0039 bkground->clearrColors(); 0040 bkground->addColor(0.0, palette().light().color()); 0041 0042 auto bk2 = addBackground(98); 0043 bk2->clearrColors(); 0044 bk2->addColor(0.0, palette().dark().color()); 0045 0046 auto arc = addArc(70); 0047 arc->setColor(palette().midlight().color()); 0048 m_ticksItem = addDegrees(70); 0049 m_ticksItem->setColor(Qt::red); 0050 0051 m_subTicksItem = addDegrees(70); 0052 m_subTicksItem->setSubDegree(true); 0053 m_subTicksItem->setStep(5); 0054 m_subTicksItem->setColor(palette().text().color()); 0055 0056 m_nameLabel = addLabel(80); 0057 m_nameLabel->setFont(font()); 0058 m_nameLabel->setText(name); 0059 m_nameLabel->setColor(palette().text().color()); 0060 m_valueDisplay = addValues(85); 0061 m_valueDisplay->setFont(font()); 0062 m_valueDisplay->setColor(palette().text().color()); 0063 0064 m_targetTemperatureNeedle = addNeedle(60); 0065 m_targetTemperatureNeedle->setPosition(95); 0066 m_targetTemperatureNeedle->setColor(Qt::red); 0067 0068 QcLabelItem *lab = addLabel(60); 0069 lab->setText(QString::number(m_currentTemperature)); 0070 lab->setColor(palette().text().color()); 0071 0072 m_currentTemperatureNeedle = addNeedle(60); 0073 m_currentTemperatureNeedle->setPosition(65); 0074 m_currentTemperatureNeedle->setColor(palette().text().color()); 0075 m_currentTemperatureNeedle->setLabel(lab); 0076 addBackground(7); 0077 0078 m_cursorTimer = new QTimer(this); 0079 connect(m_cursorTimer, &QTimer::timeout, this, [this] { 0080 m_paintCursor = !m_paintCursor; 0081 update(); 0082 }); 0083 0084 m_tempChangedTimer->setSingleShot(true); 0085 connect(m_tempChangedTimer, &QTimer::timeout, this, [this] { emit targetTemperatureChanged(m_targetTemperature); }); 0086 } 0087 0088 void ThermoWidget::setRange(int min, int max) 0089 { 0090 m_maxValue = max; 0091 m_minValue = min; 0092 m_currentTemperatureNeedle->setValueRange(min, max); 0093 m_targetTemperatureNeedle->setValueRange(min, max); 0094 m_valueDisplay->setValueRange(min, max); 0095 int range = max - min; 0096 if (range <= 150) { 0097 m_valueDisplay->setStep(10); 0098 m_ticksItem->setStep(10); 0099 } else if (range <= 300) { 0100 m_valueDisplay->setStep(25); 0101 m_ticksItem->setStep(25); 0102 } else { 0103 m_valueDisplay->setStep((max - min) / 10); 0104 m_ticksItem->setStep((max - min) / 10); 0105 } 0106 m_ticksItem->setValueRange(min, max); 0107 } 0108 0109 void ThermoWidget::setName(const QString &name) 0110 { 0111 m_nameLabel->setText(name); 0112 } 0113 0114 void ThermoWidget::setCurrentTemperature(double temperature) 0115 { 0116 if (!isEqual(m_currentTemperature, temperature)) { 0117 m_currentTemperature = temperature; 0118 m_currentTemperatureNeedle->setCurrentValue(float(temperature)); 0119 update(); 0120 } 0121 } 0122 0123 void ThermoWidget::setTargetTemperature(int temperature) 0124 { 0125 if (m_targetTemperature != temperature) { 0126 m_targetTemperatureText = QString::number(temperature); 0127 m_targetTemperature = temperature; 0128 m_targetTemperatureNeedle->setCurrentValue(temperature); 0129 resetTimer(); 0130 update(); 0131 } 0132 } 0133 void ThermoWidget::keyPressEvent(QKeyEvent *event) 0134 { 0135 // set our target text length. 0136 int slen = m_targetTemperatureText.length() - 1; 0137 // be sure our cursor position is valid. 0138 if (slen < 0) { 0139 m_targetTemperatureText = QStringLiteral("0"); 0140 m_cursorPos = 0; 0141 } else if (slen > 2) { 0142 m_cursorPos = 2; 0143 } 0144 // parse the key events. 0145 if (event->key() >= Qt::Key_0 && event->key() <= Qt::Key_9) { 0146 auto tmp = QString::number(m_targetTemperature); 0147 0148 if (m_cursorPos == slen) { 0149 tmp.append(event->key()); 0150 } else { 0151 tmp.insert(m_cursorPos, event->key()); 0152 } 0153 0154 if (tmp.toInt() <= m_maxValue && tmp.toInt() >= m_minValue) { 0155 m_targetTemperatureText = tmp; 0156 if (m_cursorPos <= slen) { 0157 m_cursorPos++; 0158 } 0159 } 0160 } else if (event->key() == Qt::Key_Delete && m_targetTemperatureText.count()) { 0161 m_targetTemperatureText.remove(m_cursorPos, 1); 0162 if (m_cursorPos < slen) { 0163 m_cursorPos = slen; 0164 } 0165 m_cursorPos--; 0166 } else if (event->key() == Qt::Key_Backspace && m_targetTemperatureText.count()) { 0167 if (m_cursorPos <= slen) { 0168 m_cursorPos--; 0169 m_targetTemperatureText.remove(m_cursorPos, 1); 0170 } 0171 } else if (event->key() == Qt::Key_Enter) { 0172 m_targetTemperature = m_targetTemperatureText.toInt(); 0173 } else if (event->key() == Qt::Key_Escape) { 0174 m_targetTemperatureText = QString::number(m_targetTemperature); 0175 } else if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Plus) { 0176 if (!isEqual(m_targetTemperature, m_maxValue)) { 0177 m_targetTemperatureText = QString::number(m_targetTemperature + 1); 0178 } 0179 } else if (event->key() == Qt::Key_Down || event->key() == Qt::Key_Minus) { 0180 if (!isEqual(m_targetTemperature, m_minValue)) { 0181 m_targetTemperatureText = QString::number(m_targetTemperature - 1); 0182 } 0183 } else if (event->key() == Qt::Key_PageUp) { 0184 if (m_targetTemperature + 10 > m_maxValue) { 0185 m_targetTemperatureText = QString::number(m_maxValue); 0186 } else { 0187 m_targetTemperatureText = QString::number(m_targetTemperature + 10); 0188 } 0189 } else if (event->key() == Qt::Key_PageDown) { 0190 if (m_targetTemperature - 10 < m_minValue) { 0191 m_targetTemperatureText = QString::number(m_minValue); 0192 } else { 0193 m_targetTemperatureText = QString::number(m_targetTemperature - 10); 0194 } 0195 } else if (event->key() == Qt::Key_Right) { 0196 if (m_cursorPos < slen) { 0197 m_cursorPos++; 0198 } 0199 } else if (event->key() == Qt::Key_Left) { 0200 if (m_cursorPos > 0) { 0201 m_cursorPos--; 0202 } 0203 } else { 0204 QcGaugeWidget::keyPressEvent(event); 0205 } 0206 0207 if (m_cursorPos < 0) { 0208 m_cursorPos = 0; 0209 } else if (m_cursorPos > 2) { 0210 m_cursorPos = 2; 0211 } 0212 0213 if (m_targetTemperatureText.simplified().isEmpty()) { 0214 m_targetTemperatureText = QStringLiteral("0"); 0215 } 0216 0217 if (m_targetTemperature != m_targetTemperatureText.toInt()) { 0218 setTargetTemperature(m_targetTemperatureText.toInt()); 0219 resetTimer(); 0220 update(); 0221 } 0222 event->accept(); 0223 } 0224 0225 void ThermoWidget::wheelEvent(QWheelEvent *event) 0226 { 0227 if (event->angleDelta().y() > 0) { 0228 if (m_targetTemperature + 10 > m_maxValue) { 0229 m_targetTemperatureText = QString::number(m_maxValue); 0230 } else { 0231 m_targetTemperatureText = QString::number(m_targetTemperature + 10); 0232 } 0233 } else if (event->angleDelta().y() < 0) { 0234 if (m_targetTemperature - 10 < m_minValue) { 0235 m_targetTemperatureText = QString::number(m_minValue); 0236 } else { 0237 m_targetTemperatureText = QString::number(m_targetTemperature - 10); 0238 } 0239 } 0240 0241 if (m_targetTemperature != m_targetTemperatureText.toInt()) { 0242 setTargetTemperature(m_targetTemperatureText.toInt()); 0243 resetTimer(); 0244 update(); 0245 } 0246 event->accept(); 0247 } 0248 0249 void ThermoWidget::focusOutEvent(QFocusEvent *event) 0250 { 0251 if (m_targetTemperature != m_targetTemperatureText.toInt()) { 0252 setTargetTemperature(m_targetTemperatureText.toInt()); 0253 resetTimer(); 0254 event->accept(); 0255 } 0256 m_cursorTimer->stop(); 0257 m_paintCursor = false; 0258 update(); 0259 } 0260 0261 void ThermoWidget::focusInEvent(QFocusEvent *event) 0262 { 0263 m_cursorTimer->start(1000); 0264 event->accept(); 0265 } 0266 0267 void ThermoWidget::resetTimer() 0268 { 0269 m_tempChangedTimer->start(500); 0270 } 0271 0272 void ThermoWidget::paintEvent(QPaintEvent *event) 0273 { 0274 QcGaugeWidget::paintEvent(event); 0275 0276 int radiusAsInt = 0; 0277 if (rect().width() < rect().height()) { 0278 radiusAsInt = int(rect().width() / 2.0); 0279 } else { 0280 radiusAsInt = int(rect().height() / 2.0); 0281 } 0282 0283 QFont font(QApplication::font().family(), radiusAsInt / 10, QFont::Normal); 0284 QFontMetrics fm(font); 0285 const int targetWidth = fm.horizontalAdvance(m_targetTemperatureText); 0286 const int wWidth = fm.horizontalAdvance('W'); 0287 const int cursorWidth = fm.horizontalAdvance('0'); 0288 const int height = fm.height(); 0289 const int halfWidth = geometry().width() / 2; 0290 const int xposTarget = int(halfWidth - (targetWidth / 2)); 0291 const int xposCursor = xposTarget + (cursorWidth * m_cursorPos); 0292 int ypos = geometry().height() / 2 + height * 2; 0293 const double relativePercent = m_maxValue - m_minValue; 0294 const double targetTemperaturePercent = (m_targetTemperature - m_minValue) / relativePercent; 0295 const double targetTemperatureAngle = (225 - -45) * targetTemperaturePercent + -45; 0296 const int coolZone = int(-(targetTemperatureAngle - -45)); 0297 const int qtBeginAngle = -135; 0298 int PieYPos = geometry().height() / 2 - radiusAsInt; 0299 int PieXPos = geometry().width() / 2 - radiusAsInt; 0300 0301 QPainter p(this); 0302 p.setFont(font); 0303 // draw a box to put our target into as a user hint. 0304 p.fillRect(QRect(int(halfWidth - wWidth), int(ypos - (height * 1.2)), int(wWidth * 2), int(height * 0.8)), palette().color(QPalette::AlternateBase)); 0305 0306 if (m_paintCursor) { 0307 p.setPen(palette().color(QPalette::Text)); 0308 p.drawText(xposCursor, int(ypos - (height * 0.60)), QChar('_')); 0309 } 0310 0311 p.setPen(Qt::red); 0312 p.drawText(xposTarget, int(ypos - (height * 0.60)), m_targetTemperatureText); 0313 0314 QRadialGradient grad(rect().center(), radiusAsInt); 0315 grad.setColorAt(0.35, QColor(0, 0, 0, 0)); 0316 grad.setColorAt(0.45, QColor(255, 110, 60, 96)); 0317 grad.setColorAt(0.55, QColor(255, 0, 0, 96)); 0318 grad.setColorAt(0.70, QColor(0, 0, 0, 0)); 0319 p.setPen(Qt::transparent); 0320 p.setBrush(grad); 0321 p.drawPie(PieXPos, PieYPos, radiusAsInt * 2, radiusAsInt * 2, qtBeginAngle * 16, coolZone * 16); 0322 } 0323 0324 bool ThermoWidget::isEqual(double a, double b) 0325 { 0326 // qFuzzyCompare always returns false if a || b ==0 0327 if (qFuzzyIsNull(a) || qFuzzyIsNull(b)) { 0328 if (a < 0.0 || b < 0.0) { 0329 // One number is 0 and the other negative 0330 // to prevent a issue if a or b == -1 and the other 0 0331 // we will subtract one from each value 0332 a -= 1; 0333 b -= 1; 0334 } else { 0335 a += 1; 0336 b += 1; 0337 } 0338 } 0339 return qFuzzyCompare(a, b); 0340 }