File indexing completed on 2024-05-19 05:51:03
0001 /*************************************************************************** 0002 ** ** 0003 ** QcGauge, for instrumentation, and real time data measurement ** 0004 ** visualization widget for Qt. ** 0005 ** Copyright (C) 2015 Hadj Tahar Berrima ** 0006 ** ** 0007 ** This program is free software: you can redistribute it and/or modify ** 0008 ** it under the terms of the GNU Lesser General Public License as ** 0009 ** published by the Free Software Foundation, either version 3 of the ** 0010 ** License, or (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 Lesser General Public License for more details. ** 0016 ** ** 0017 ** You should have received a copy of the GNU Lesser General Public ** 0018 ** License along with this program. ** 0019 ** If not, see http://www.gnu.org/licenses/. ** 0020 ** ** 0021 **************************************************************************** 0022 ** Author: Hadj Tahar Berrima ** 0023 ** Website: http://pytricity.com/ ** 0024 ** Contact: berrima_tahar@yahoo.com ** 0025 ** Date: 1 dec 2014 ** 0026 ** Version: 1.0 ** 0027 **************************************************************************** 0028 ** Modified: Chris Rizzitello 2019 ** 0029 ** Website: http://atelier.kde.org ** 0030 ** Contact: rizzitello@kde.org ** 0031 ** Version: Atelier-Custom ** 0032 ****************************************************************************/ 0033 0034 #include "qcgaugewidget.h" 0035 #include <QPainterPath> 0036 0037 /////////////////////////////////////////////////////////////////////////////////////////// 0038 /////////////////////////////////////////////////////////////////////////////////////////// 0039 /////////////////////////////////////////////////////////////////////////////////////////// 0040 0041 QcGaugeWidget::QcGaugeWidget(QWidget *parent) 0042 : QWidget(parent) 0043 { 0044 setMinimumSize(250, 250); 0045 } 0046 0047 QcBackgroundItem *QcGaugeWidget::addBackground(float position) 0048 { 0049 QcBackgroundItem *item = new QcBackgroundItem(this); 0050 item->setPosition(position); 0051 mItems.append(item); 0052 return item; 0053 } 0054 0055 QcDegreesItem *QcGaugeWidget::addDegrees(float position) 0056 { 0057 QcDegreesItem *item = new QcDegreesItem(this); 0058 item->setPosition(position); 0059 0060 mItems.append(item); 0061 return item; 0062 } 0063 0064 QcValuesItem *QcGaugeWidget::addValues(float position) 0065 { 0066 auto *item = new QcValuesItem(this); 0067 item->setPosition(position); 0068 mItems.append(item); 0069 return item; 0070 } 0071 0072 QcArcItem *QcGaugeWidget::addArc(float position) 0073 { 0074 QcArcItem *item = new QcArcItem(this); 0075 item->setPosition(position); 0076 mItems.append(item); 0077 return item; 0078 } 0079 0080 QcNeedleItem *QcGaugeWidget::addNeedle(float position) 0081 { 0082 auto *item = new QcNeedleItem(this); 0083 item->setPosition(position); 0084 mItems.append(item); 0085 return item; 0086 } 0087 0088 QcLabelItem *QcGaugeWidget::addLabel(float position) 0089 { 0090 QcLabelItem *item = new QcLabelItem(this); 0091 item->setPosition(position); 0092 mItems.append(item); 0093 return item; 0094 } 0095 0096 void QcGaugeWidget::addItem(QcItem *item, float position) 0097 { 0098 // takes parentship of the item 0099 item->setParent(this); 0100 item->setPosition(position); 0101 mItems.append(item); 0102 } 0103 0104 int QcGaugeWidget::removeItem(QcItem *item) 0105 { 0106 return mItems.removeAll(item); 0107 } 0108 0109 QList<QcItem *> QcGaugeWidget::items() 0110 { 0111 return mItems; 0112 } 0113 0114 void QcGaugeWidget::paintEvent(QPaintEvent * /*paintEvt*/) 0115 { 0116 QPainter painter(this); 0117 painter.setRenderHint(QPainter::Antialiasing); 0118 0119 for (QcItem *item : qAsConst(mItems)) { 0120 item->draw(&painter); 0121 } 0122 } 0123 /////////////////////////////////////////////////////////////////////////////////////////// 0124 /////////////////////////////////////////////////////////////////////////////////////////// 0125 /////////////////////////////////////////////////////////////////////////////////////////// 0126 0127 QcItem::QcItem(QObject *parent) 0128 : QObject(parent) 0129 { 0130 parentWidget = qobject_cast<QWidget *>(parent); 0131 mPosition = 50; 0132 } 0133 0134 int QcItem::type() 0135 { 0136 return 50; 0137 } 0138 0139 void QcItem::update() 0140 { 0141 parentWidget->update(); 0142 } 0143 0144 float QcItem::position() 0145 { 0146 return mPosition; 0147 } 0148 0149 QRectF QcItem::rect() 0150 { 0151 return mRect; 0152 } 0153 0154 void QcItem::setPosition(float position) 0155 { 0156 if (position > 100) { 0157 mPosition = 100; 0158 } else if (position < 0) { 0159 mPosition = 0; 0160 } else { 0161 mPosition = position; 0162 } 0163 update(); 0164 } 0165 0166 QRectF QcItem::adjustRect(float percentage) 0167 { 0168 float r = getRadius(mRect); 0169 float offset = r - (percentage * r) / 100.0; 0170 QRectF tmpRect = mRect.adjusted(offset, offset, -offset, -offset); 0171 return tmpRect; 0172 } 0173 0174 float QcItem::getRadius(const QRectF &tmpRect) 0175 { 0176 float r = 0; 0177 if (tmpRect.width() < tmpRect.height()) { 0178 r = tmpRect.width() / 2.0; 0179 } else { 0180 r = tmpRect.height() / 2.0; 0181 } 0182 return r; 0183 } 0184 0185 QRectF QcItem::resetRect() 0186 { 0187 mRect = parentWidget->rect(); 0188 float r = getRadius(mRect); 0189 mRect.setWidth(2.0 * r); 0190 mRect.setHeight(2.0 * r); 0191 mRect.moveCenter(parentWidget->rect().center()); 0192 return mRect; 0193 } 0194 0195 QPointF QcItem::getPoint(float deg, const QRectF &tmpRect) 0196 { 0197 float r = getRadius(tmpRect); 0198 float xx = cos(qDegreesToRadians(deg)) * r; 0199 float yy = sin(qDegreesToRadians(deg)) * r; 0200 QPointF pt; 0201 xx = tmpRect.center().x() - xx; 0202 yy = tmpRect.center().y() - yy; 0203 pt.setX(xx); 0204 pt.setY(yy); 0205 return pt; 0206 } 0207 0208 float QcItem::getAngle(const QPointF &pt, const QRectF &tmpRect) 0209 { 0210 float xx = tmpRect.center().x() - pt.x(); 0211 float yy = tmpRect.center().y() - pt.y(); 0212 return qRadiansToDegrees(atan2(yy, xx)); 0213 } 0214 0215 /////////////////////////////////////////////////////////////////////////////////////////// 0216 /////////////////////////////////////////////////////////////////////////////////////////// 0217 /////////////////////////////////////////////////////////////////////////////////////////// 0218 0219 QcScaleItem::QcScaleItem(QObject *parent) 0220 : QcItem(parent) 0221 { 0222 mMinDegree = -45; 0223 mMaxDegree = 225; 0224 mMinValue = 0; 0225 mMaxValue = 100; 0226 } 0227 0228 void QcScaleItem::setValueRange(float minValue, float maxValue) 0229 { 0230 if (!(minValue < maxValue)) { 0231 mMaxValue = minValue; 0232 mMinValue = maxValue; 0233 } else { 0234 mMinValue = minValue; 0235 mMaxValue = maxValue; 0236 } 0237 } 0238 0239 void QcScaleItem::setDgereeRange(float minDegree, float maxDegree) 0240 { 0241 if (!(minDegree < maxDegree)) { 0242 mMinDegree = maxDegree; 0243 mMaxDegree = minDegree; 0244 } else { 0245 mMinDegree = minDegree; 0246 mMaxDegree = maxDegree; 0247 } 0248 } 0249 0250 float QcScaleItem::getDegFromValue(float v) 0251 { 0252 float a = (mMaxDegree - mMinDegree) / (mMaxValue - mMinValue); 0253 float b = -a * mMinValue + mMinDegree; 0254 return a * v + b; 0255 } 0256 0257 void QcScaleItem::setMinValue(float minValue) 0258 { 0259 if (minValue > mMaxValue) { 0260 return; 0261 } 0262 mMinValue = minValue; 0263 update(); 0264 } 0265 0266 void QcScaleItem::setMaxValue(float maxValue) 0267 { 0268 if (maxValue < mMinValue) { 0269 return; 0270 } 0271 mMaxValue = maxValue; 0272 update(); 0273 } 0274 0275 void QcScaleItem::setMinDegree(float minDegree) 0276 { 0277 if (minDegree > mMaxDegree) { 0278 return; 0279 } 0280 mMinDegree = minDegree; 0281 update(); 0282 } 0283 void QcScaleItem::setMaxDegree(float maxDegree) 0284 { 0285 if (maxDegree < mMinDegree) { 0286 return; 0287 } 0288 mMaxDegree = maxDegree; 0289 update(); 0290 } 0291 0292 float QcScaleItem::minValue() 0293 { 0294 return mMinValue; 0295 } 0296 0297 float QcScaleItem::maxValue() 0298 { 0299 return mMaxValue; 0300 } 0301 0302 float QcScaleItem::minDegree() 0303 { 0304 return mMinDegree; 0305 } 0306 0307 float QcScaleItem::maxDegree() 0308 { 0309 return mMaxDegree; 0310 } 0311 /////////////////////////////////////////////////////////////////////////////////////////// 0312 /////////////////////////////////////////////////////////////////////////////////////////// 0313 /////////////////////////////////////////////////////////////////////////////////////////// 0314 0315 QcBackgroundItem::QcBackgroundItem(QObject *parent) 0316 : QcItem(parent) 0317 { 0318 setPosition(88); 0319 mPen = Qt::NoPen; 0320 setPosition(88); 0321 0322 addColor(0.4, Qt::darkGray); 0323 addColor(0.8, Qt::black); 0324 } 0325 0326 void QcBackgroundItem::draw(QPainter *painter) 0327 { 0328 QRectF tmpRect = resetRect(); 0329 painter->setBrush(Qt::NoBrush); 0330 QLinearGradient linearGrad(tmpRect.topLeft(), tmpRect.bottomRight()); 0331 for (int i = 0; i < mColors.size(); i++) { 0332 linearGrad.setColorAt(mColors[i].first, mColors[i].second); 0333 } 0334 painter->setPen(mPen); 0335 painter->setBrush(linearGrad); 0336 painter->drawEllipse(adjustRect(position())); 0337 } 0338 0339 void QcBackgroundItem::addColor(float position, const QColor &color) 0340 { 0341 if (position < 0 || position > 1) { 0342 return; 0343 } 0344 QPair<float, QColor> pair; 0345 pair.first = position; 0346 pair.second = color; 0347 mColors.append(pair); 0348 update(); 0349 } 0350 0351 void QcBackgroundItem::clearrColors() 0352 { 0353 mColors.clear(); 0354 } 0355 0356 /////////////////////////////////////////////////////////////////////////////////////////// 0357 /////////////////////////////////////////////////////////////////////////////////////////// 0358 /////////////////////////////////////////////////////////////////////////////////////////// 0359 0360 QcLabelItem::QcLabelItem(QObject *parent) 0361 : QcItem(parent) 0362 { 0363 setPosition(50); 0364 mAngle = 270; 0365 mText = "%"; 0366 mColor = Qt::black; 0367 } 0368 0369 void QcLabelItem::draw(QPainter *painter) 0370 { 0371 resetRect(); 0372 QRectF tmpRect = adjustRect(position()); 0373 float r = getRadius(rect()); 0374 painter->setFont(mFont); 0375 painter->setPen(QPen(mColor)); 0376 0377 QPointF txtCenter = getPoint(mAngle, tmpRect); 0378 QFontMetrics fMetrics = painter->fontMetrics(); 0379 QSize sz = fMetrics.size(Qt::TextSingleLine, mText); 0380 QRectF txtRect(QPointF(0, 0), sz); 0381 txtRect.moveCenter(txtCenter); 0382 0383 painter->drawText(txtRect, Qt::TextSingleLine, mText); 0384 } 0385 0386 void QcLabelItem::setAngle(float a) 0387 { 0388 mAngle = a; 0389 update(); 0390 } 0391 0392 float QcLabelItem::angle() 0393 { 0394 return mAngle; 0395 } 0396 0397 void QcLabelItem::setFont(const QFont &font) 0398 { 0399 mFont = font; 0400 } 0401 0402 void QcLabelItem::setText(const QString &text, bool repaint) 0403 { 0404 mText = text; 0405 if (repaint) { 0406 update(); 0407 } 0408 } 0409 0410 QString QcLabelItem::text() 0411 { 0412 return mText; 0413 } 0414 0415 void QcLabelItem::setColor(const QColor &color) 0416 { 0417 mColor = color; 0418 update(); 0419 } 0420 0421 QColor QcLabelItem::color() 0422 { 0423 return mColor; 0424 } 0425 0426 /////////////////////////////////////////////////////////////////////////////////////////// 0427 /////////////////////////////////////////////////////////////////////////////////////////// 0428 /////////////////////////////////////////////////////////////////////////////////////////// 0429 0430 QcArcItem::QcArcItem(QObject *parent) 0431 : QcScaleItem(parent) 0432 { 0433 setPosition(80); 0434 mColor = Qt::black; 0435 } 0436 0437 void QcArcItem::draw(QPainter *painter) 0438 { 0439 resetRect(); 0440 QRectF tmpRect = adjustRect(position()); 0441 float r = getRadius(tmpRect); 0442 0443 QPen pen; 0444 pen.setColor(mColor); 0445 pen.setWidthF(r / 40); 0446 painter->setPen(pen); 0447 painter->drawArc(tmpRect, -16 * (minDegree() + 180), -16 * (maxDegree() - minDegree())); 0448 } 0449 0450 void QcArcItem::setColor(const QColor &color) 0451 { 0452 mColor = color; 0453 } 0454 0455 /////////////////////////////////////////////////////////////////////////////////////////// 0456 /////////////////////////////////////////////////////////////////////////////////////////// 0457 /////////////////////////////////////////////////////////////////////////////////////////// 0458 0459 QcDegreesItem::QcDegreesItem(QObject *parent) 0460 : QcScaleItem(parent) 0461 { 0462 mStep = 10; 0463 mColor = Qt::black; 0464 mSubDegree = false; 0465 setPosition(90); 0466 } 0467 0468 void QcDegreesItem::draw(QPainter *painter) 0469 { 0470 resetRect(); 0471 QRectF tmpRect = adjustRect(position()); 0472 0473 painter->setPen(mColor); 0474 float r = getRadius(tmpRect); 0475 for (float val = minValue(); val <= maxValue(); val += mStep) { 0476 float deg = getDegFromValue(val); 0477 QPointF pt = getPoint(deg, tmpRect); 0478 QPainterPath path; 0479 path.moveTo(pt); 0480 path.lineTo(tmpRect.center()); 0481 pt = path.pointAtPercent(0.03); 0482 QPointF newPt = path.pointAtPercent(0.13); 0483 0484 QPen pen; 0485 pen.setColor(mColor); 0486 if (!mSubDegree) { 0487 pen.setWidthF(r / 25.0); 0488 } 0489 0490 painter->setPen(pen); 0491 painter->drawLine(pt, newPt); 0492 } 0493 } 0494 0495 void QcDegreesItem::setStep(float step) 0496 { 0497 mStep = step; 0498 update(); 0499 } 0500 0501 void QcDegreesItem::setColor(const QColor &color) 0502 { 0503 mColor = color; 0504 update(); 0505 } 0506 0507 void QcDegreesItem::setSubDegree(bool b) 0508 { 0509 mSubDegree = b; 0510 update(); 0511 } 0512 0513 /////////////////////////////////////////////////////////////////////////////////////////// 0514 /////////////////////////////////////////////////////////////////////////////////////////// 0515 /////////////////////////////////////////////////////////////////////////////////////////// 0516 0517 QcNeedleItem::QcNeedleItem(QObject *parent) 0518 : QcScaleItem(parent) 0519 , mCurrentValue(0) 0520 , mColor(Qt::black) 0521 , mLabel(nullptr) 0522 { 0523 } 0524 0525 void QcNeedleItem::draw(QPainter *painter) 0526 { 0527 resetRect(); 0528 QRectF tmpRect = adjustRect(position()); 0529 painter->save(); 0530 painter->translate(tmpRect.center()); 0531 float deg = getDegFromValue(mCurrentValue); 0532 painter->rotate(deg + 90.0); 0533 painter->setBrush(QBrush(mColor)); 0534 painter->setPen(Qt::NoPen); 0535 0536 QLinearGradient grad; 0537 createDiamonNeedle(getRadius(tmpRect)); 0538 painter->drawConvexPolygon(mNeedlePoly); 0539 painter->restore(); 0540 } 0541 0542 void QcNeedleItem::setCurrentValue(float value) 0543 { 0544 if (value < minValue()) { 0545 mCurrentValue = minValue(); 0546 } else if (value > maxValue()) { 0547 mCurrentValue = maxValue(); 0548 } else { 0549 mCurrentValue = value; 0550 } 0551 0552 if (mLabel) { 0553 mLabel->setText(QString::number(mCurrentValue), false); 0554 } 0555 update(); 0556 } 0557 0558 float QcNeedleItem::currentValue() 0559 { 0560 return mCurrentValue; 0561 } 0562 0563 void QcNeedleItem::setColor(const QColor &color) 0564 { 0565 mColor = color; 0566 update(); 0567 } 0568 0569 QColor QcNeedleItem::color() 0570 { 0571 return mColor; 0572 } 0573 0574 void QcNeedleItem::setLabel(QcLabelItem *label) 0575 { 0576 mLabel = label; 0577 update(); 0578 } 0579 0580 QcLabelItem *QcNeedleItem::label() 0581 { 0582 return mLabel; 0583 } 0584 0585 void QcNeedleItem::createDiamonNeedle(float r) 0586 { 0587 QVector<QPointF> tmpPoints; 0588 tmpPoints.append(QPointF(0.0, 0.0)); 0589 tmpPoints.append(QPointF(-r / 20.0, r / 20.0)); 0590 tmpPoints.append(QPointF(0.0, r)); 0591 tmpPoints.append(QPointF(r / 20.0, r / 20.0)); 0592 mNeedlePoly = tmpPoints; 0593 } 0594 0595 /////////////////////////////////////////////////////////////////////////////////////////// 0596 /////////////////////////////////////////////////////////////////////////////////////////// 0597 /////////////////////////////////////////////////////////////////////////////////////////// 0598 0599 QcValuesItem::QcValuesItem(QObject *parent) 0600 : QcScaleItem(parent) 0601 , mStep(10) 0602 , mColor(Qt::black) 0603 { 0604 setPosition(70); 0605 } 0606 0607 void QcValuesItem::draw(QPainter *painter) 0608 { 0609 QRectF tmpRect = resetRect(); 0610 float r = getRadius(adjustRect(99)); 0611 painter->setFont(mFont); 0612 painter->setPen(mColor); 0613 for (float val = minValue(); val <= maxValue(); val += mStep) { 0614 float deg = getDegFromValue(val); 0615 QPointF pt = getPoint(deg, tmpRect); 0616 QPainterPath path; 0617 path.moveTo(pt); 0618 path.lineTo(tmpRect.center()); 0619 QString strVal = QString::number(val); 0620 QFontMetrics fMetrics = painter->fontMetrics(); 0621 QSize sz = fMetrics.size(Qt::TextSingleLine, strVal); 0622 QRectF txtRect(QPointF(0, 0), sz); 0623 QPointF textCenter = path.pointAtPercent(1.0 - position() / 100.0); 0624 txtRect.moveCenter(textCenter); 0625 0626 painter->drawText(txtRect, Qt::TextSingleLine, strVal); 0627 } 0628 } 0629 0630 void QcValuesItem::setFont(const QFont &font) 0631 { 0632 mFont = font; 0633 } 0634 0635 void QcValuesItem::setStep(float step) 0636 { 0637 mStep = step; 0638 } 0639 0640 void QcValuesItem::setColor(const QColor &color) 0641 { 0642 mColor = color; 0643 }