00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <qpainter.h>
00011 #include <qevent.h>
00012 #include <qstyle.h>
00013 #include <qpixmap.h>
00014 #include <qdrawutil.h>
00015 #include "qwt_math.h"
00016 #include "qwt_scale_engine.h"
00017 #include "qwt_scale_draw.h"
00018 #include "qwt_scale_map.h"
00019 #include "qwt_paint_buffer.h"
00020 #include "qwt_thermo.h"
00021
00022 class QwtThermo::PrivateData
00023 {
00024 public:
00025 PrivateData():
00026 fillBrush(Qt::black),
00027 alarmBrush(Qt::white),
00028 orientation(Qt::Vertical),
00029 scalePos(QwtThermo::Left),
00030 borderWidth(2),
00031 scaleDist(3),
00032 thermoWidth(10),
00033 minValue(0.0),
00034 maxValue(1.0),
00035 value(0.0),
00036 alarmLevel(0.0),
00037 alarmEnabled(false)
00038 {
00039 map.setScaleInterval(minValue, maxValue);
00040 }
00041
00042 QwtScaleMap map;
00043 QRect thermoRect;
00044 QBrush fillBrush;
00045 QBrush alarmBrush;
00046
00047 Qt::Orientation orientation;
00048 ScalePos scalePos;
00049 int borderWidth;
00050 int scaleDist;
00051 int thermoWidth;
00052
00053 double minValue;
00054 double maxValue;
00055 double value;
00056 double alarmLevel;
00057 bool alarmEnabled;
00058 };
00059
00061 QwtThermo::QwtThermo(QWidget *parent):
00062 QWidget(parent)
00063 {
00064 #if QT_VERSION < 0x040000
00065 setWFlags(Qt::WNoAutoErase);
00066 #endif
00067 d_data = new PrivateData;
00068 setRange(d_data->minValue, d_data->maxValue, false);
00069
00070 QSizePolicy policy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
00071 if (d_data->orientation == Qt::Vertical)
00072 policy.transpose();
00073
00074 setSizePolicy(policy);
00075
00076 #if QT_VERSION >= 0x040000
00077 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00078 #else
00079 clearWState( WState_OwnSizePolicy );
00080 #endif
00081 }
00082
00084 QwtThermo::~QwtThermo()
00085 {
00086 delete d_data;
00087 }
00088
00090 void QwtThermo::setMaxValue(double v)
00091 {
00092 setRange(d_data->minValue, v);
00093 }
00094
00096 double QwtThermo::maxValue() const
00097 {
00098 return d_data->maxValue;
00099 }
00100
00102 void QwtThermo::setMinValue(double v)
00103 {
00104 setRange(v, d_data->maxValue);
00105 }
00106
00108 double QwtThermo::minValue() const
00109 {
00110 return d_data->minValue;
00111 }
00112
00114 void QwtThermo::setValue(double v)
00115 {
00116 if (d_data->value != v)
00117 {
00118 d_data->value = v;
00119 update();
00120 }
00121 }
00122
00124 double QwtThermo::value() const
00125 {
00126 return d_data->value;
00127 }
00128
00129
00131 void QwtThermo::paintEvent(QPaintEvent *e)
00132 {
00133
00134 const QRect &ur = e->rect();
00135 if ( ur.isValid() )
00136 {
00137 #if QT_VERSION < 0x040000
00138 QwtPaintBuffer paintBuffer(this, ur);
00139 draw(paintBuffer.painter(), ur);
00140 #else
00141 QPainter painter(this);
00142 draw(&painter, ur);
00143 #endif
00144 }
00145 }
00146
00148 void QwtThermo::draw(QPainter *p, const QRect& ur)
00149 {
00150 if ( !d_data->thermoRect.contains(ur) )
00151 {
00152 if (d_data->scalePos != None)
00153 {
00154 #if QT_VERSION < 0x040000
00155 scaleDraw()->draw(p, colorGroup());
00156 #else
00157 scaleDraw()->draw(p, palette());
00158 #endif
00159 }
00160
00161 qDrawShadePanel(p,
00162 d_data->thermoRect.x() - d_data->borderWidth,
00163 d_data->thermoRect.y() - d_data->borderWidth,
00164 d_data->thermoRect.width() + 2*d_data->borderWidth,
00165 d_data->thermoRect.height() + 2*d_data->borderWidth,
00166 #if QT_VERSION < 0x040000
00167 colorGroup(),
00168 #else
00169 palette(),
00170 #endif
00171 true, d_data->borderWidth,0);
00172 }
00173 drawThermo(p);
00174 }
00175
00177 void QwtThermo::resizeEvent(QResizeEvent *)
00178 {
00179 layoutThermo( false );
00180 }
00181
00188 void QwtThermo::layoutThermo( bool update_geometry )
00189 {
00190 QRect r = rect();
00191 int mbd = 0;
00192 if ( d_data->scalePos != None )
00193 {
00194 int d1, d2;
00195 scaleDraw()->minBorderDist(font(), d1, d2);
00196 mbd = qwtMax(d1, d2);
00197 }
00198
00199 if ( d_data->orientation == Qt::Horizontal )
00200 {
00201 switch ( d_data->scalePos )
00202 {
00203 case Top:
00204 d_data->thermoRect.setRect(
00205 r.x() + mbd + d_data->borderWidth,
00206 r.y() + r.height()
00207 - d_data->thermoWidth - 2*d_data->borderWidth,
00208 r.width() - 2*(d_data->borderWidth + mbd),
00209 d_data->thermoWidth);
00210 scaleDraw()->setGeometry(
00211 d_data->thermoRect.x(),
00212 d_data->thermoRect.y() - d_data->borderWidth - d_data->scaleDist,
00213 d_data->thermoRect.width(),
00214 QwtScaleDraw::Top);
00215 break;
00216
00217 case Bottom:
00218 case None:
00219 default:
00220
00221
00222 d_data->thermoRect.setRect(
00223 r.x() + mbd + d_data->borderWidth,
00224 r.y() + d_data->borderWidth,
00225 r.width() - 2*(d_data->borderWidth + mbd),
00226 d_data->thermoWidth);
00227 scaleDraw()->setGeometry(
00228 d_data->thermoRect.x(),
00229 d_data->thermoRect.y() + d_data->thermoRect.height()
00230 + d_data->borderWidth + d_data->scaleDist,
00231 d_data->thermoRect.width(),
00232 QwtScaleDraw::Bottom);
00233 break;
00234 }
00235 d_data->map.setPaintInterval(d_data->thermoRect.x(),
00236 d_data->thermoRect.x() + d_data->thermoRect.width() - 1);
00237 }
00238 else
00239 {
00240 switch ( d_data->scalePos )
00241 {
00242 case Right:
00243 d_data->thermoRect.setRect(
00244 r.x() + d_data->borderWidth,
00245 r.y() + mbd + d_data->borderWidth,
00246 d_data->thermoWidth,
00247 r.height() - 2*(d_data->borderWidth + mbd));
00248 scaleDraw()->setGeometry(
00249 d_data->thermoRect.x() + d_data->thermoRect.width()
00250 + d_data->borderWidth + d_data->scaleDist,
00251 d_data->thermoRect.y(),
00252 d_data->thermoRect.height(),
00253 QwtScaleDraw::Right);
00254 break;
00255
00256 case Left:
00257 case None:
00258 default:
00259
00260
00261 d_data->thermoRect.setRect(
00262 r.x() + r.width() - 2*d_data->borderWidth - d_data->thermoWidth,
00263 r.y() + mbd + d_data->borderWidth,
00264 d_data->thermoWidth,
00265 r.height() - 2*(d_data->borderWidth + mbd));
00266 scaleDraw()->setGeometry(
00267 d_data->thermoRect.x() - d_data->scaleDist - d_data->borderWidth,
00268 d_data->thermoRect.y(),
00269 d_data->thermoRect.height(),
00270 QwtScaleDraw::Left);
00271 break;
00272 }
00273 d_data->map.setPaintInterval(d_data->thermoRect.y() + d_data->thermoRect.height() - 1,
00274 d_data->thermoRect.y());
00275 }
00276 if ( update_geometry )
00277 {
00278 updateGeometry();
00279 update();
00280 }
00281 }
00282
00299 void QwtThermo::setOrientation(Qt::Orientation o, ScalePos s)
00300 {
00301 if ( o == d_data->orientation )
00302 return;
00303
00304 switch(o)
00305 {
00306 case Qt::Horizontal:
00307 {
00308 d_data->orientation = Qt::Horizontal;
00309 if ((s == None) || (s == Bottom) || (s == Top))
00310 d_data->scalePos = s;
00311 else
00312 d_data->scalePos = None;
00313 break;
00314 }
00315 case Qt::Vertical:
00316 {
00317 d_data->orientation = Qt::Vertical;
00318 if ((s == None) || (s == Left) || (s == Right))
00319 d_data->scalePos = s;
00320 else
00321 d_data->scalePos = None;
00322 break;
00323 }
00324 }
00325
00326 #if QT_VERSION >= 0x040000
00327 if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
00328 #else
00329 if ( !testWState( WState_OwnSizePolicy ) )
00330 #endif
00331 {
00332 QSizePolicy sp = sizePolicy();
00333 sp.transpose();
00334 setSizePolicy(sp);
00335
00336 #if QT_VERSION >= 0x040000
00337 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00338 #else
00339 clearWState( WState_OwnSizePolicy );
00340 #endif
00341 }
00342
00343 layoutThermo();
00344 }
00345
00360 void QwtThermo::setScalePosition(ScalePos s)
00361 {
00362 if ((s == Bottom) || (s == Top))
00363 setOrientation(Qt::Horizontal, s);
00364 else if ((s == Left) || (s == Right))
00365 setOrientation(Qt::Vertical, s);
00366 else
00367 setOrientation(d_data->orientation, None);
00368 }
00369
00371 QwtThermo::ScalePos QwtThermo::scalePosition() const
00372 {
00373 return d_data->scalePos;
00374 }
00375
00377 void QwtThermo::fontChange(const QFont &f)
00378 {
00379 QWidget::fontChange( f );
00380 layoutThermo();
00381 }
00382
00384 void QwtThermo::scaleChange()
00385 {
00386 update();
00387 layoutThermo();
00388 }
00389
00391 void QwtThermo::drawThermo(QPainter *p)
00392 {
00393 int alarm = 0, taval = 0;
00394
00395 QRect fRect;
00396 QRect aRect;
00397 QRect bRect;
00398
00399 int inverted = ( d_data->maxValue < d_data->minValue );
00400
00401
00402
00403
00404
00405
00406 if (d_data->alarmEnabled)
00407 {
00408 if (inverted)
00409 {
00410 alarm = ((d_data->alarmLevel >= d_data->maxValue)
00411 && (d_data->alarmLevel <= d_data->minValue)
00412 && (d_data->value >= d_data->alarmLevel));
00413
00414 }
00415 else
00416 {
00417 alarm = (( d_data->alarmLevel >= d_data->minValue)
00418 && (d_data->alarmLevel <= d_data->maxValue)
00419 && (d_data->value >= d_data->alarmLevel));
00420 }
00421 }
00422
00423
00424
00425
00426 int tval = transform(d_data->value);
00427
00428 if (alarm)
00429 taval = transform(d_data->alarmLevel);
00430
00431
00432
00433
00434 if ( d_data->orientation == Qt::Horizontal )
00435 {
00436 if (inverted)
00437 {
00438 bRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00439 tval - d_data->thermoRect.x(),
00440 d_data->thermoRect.height());
00441
00442 if (alarm)
00443 {
00444 aRect.setRect(tval, d_data->thermoRect.y(),
00445 taval - tval + 1,
00446 d_data->thermoRect.height());
00447 fRect.setRect(taval + 1, d_data->thermoRect.y(),
00448 d_data->thermoRect.x() + d_data->thermoRect.width() - (taval + 1),
00449 d_data->thermoRect.height());
00450 }
00451 else
00452 {
00453 fRect.setRect(tval, d_data->thermoRect.y(),
00454 d_data->thermoRect.x() + d_data->thermoRect.width() - tval,
00455 d_data->thermoRect.height());
00456 }
00457 }
00458 else
00459 {
00460 bRect.setRect(tval + 1, d_data->thermoRect.y(),
00461 d_data->thermoRect.width() - (tval + 1 - d_data->thermoRect.x()),
00462 d_data->thermoRect.height());
00463
00464 if (alarm)
00465 {
00466 aRect.setRect(taval, d_data->thermoRect.y(),
00467 tval - taval + 1,
00468 d_data->thermoRect.height());
00469 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00470 taval - d_data->thermoRect.x(),
00471 d_data->thermoRect.height());
00472 }
00473 else
00474 {
00475 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00476 tval - d_data->thermoRect.x() + 1,
00477 d_data->thermoRect.height());
00478 }
00479
00480 }
00481 }
00482 else
00483 {
00484 if (tval < d_data->thermoRect.y())
00485 tval = d_data->thermoRect.y();
00486 else
00487 {
00488 if (tval > d_data->thermoRect.y() + d_data->thermoRect.height())
00489 tval = d_data->thermoRect.y() + d_data->thermoRect.height();
00490 }
00491
00492 if (inverted)
00493 {
00494 bRect.setRect(d_data->thermoRect.x(), tval + 1,
00495 d_data->thermoRect.width(),
00496 d_data->thermoRect.height() - (tval + 1 - d_data->thermoRect.y()));
00497
00498 if (alarm)
00499 {
00500 aRect.setRect(d_data->thermoRect.x(), taval,
00501 d_data->thermoRect.width(),
00502 tval - taval + 1);
00503 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00504 d_data->thermoRect.width(),
00505 taval - d_data->thermoRect.y());
00506 }
00507 else
00508 {
00509 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00510 d_data->thermoRect.width(),
00511 tval - d_data->thermoRect.y() + 1);
00512 }
00513 }
00514 else
00515 {
00516 bRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00517 d_data->thermoRect.width(),
00518 tval - d_data->thermoRect.y());
00519 if (alarm)
00520 {
00521 aRect.setRect(d_data->thermoRect.x(),tval,
00522 d_data->thermoRect.width(),
00523 taval - tval + 1);
00524 fRect.setRect(d_data->thermoRect.x(),taval + 1,
00525 d_data->thermoRect.width(),
00526 d_data->thermoRect.y() + d_data->thermoRect.height() - (taval + 1));
00527 }
00528 else
00529 {
00530 fRect.setRect(d_data->thermoRect.x(),tval,
00531 d_data->thermoRect.width(),
00532 d_data->thermoRect.y() + d_data->thermoRect.height() - tval);
00533 }
00534 }
00535 }
00536
00537
00538
00539
00540 const QColor bgColor =
00541 #if QT_VERSION < 0x040000
00542 colorGroup().color(QColorGroup::Background);
00543 #else
00544 palette().color(QPalette::Background);
00545 #endif
00546 p->fillRect(bRect, bgColor);
00547
00548 if (alarm)
00549 p->fillRect(aRect, d_data->alarmBrush);
00550
00551 p->fillRect(fRect, d_data->fillBrush);
00552 }
00553
00555 void QwtThermo::setBorderWidth(int w)
00556 {
00557 if ((w >= 0) && (w < (qwtMin(d_data->thermoRect.width(),
00558 d_data->thermoRect.height()) + d_data->borderWidth) / 2 - 1))
00559 {
00560 d_data->borderWidth = w;
00561 layoutThermo();
00562 }
00563 }
00564
00566 int QwtThermo::borderWidth() const
00567 {
00568 return d_data->borderWidth;
00569 }
00570
00577 void QwtThermo::setRange(double vmin, double vmax, bool logarithmic)
00578 {
00579 d_data->minValue = vmin;
00580 d_data->maxValue = vmax;
00581
00582 if ( logarithmic )
00583 setScaleEngine(new QwtLog10ScaleEngine);
00584 else
00585 setScaleEngine(new QwtLinearScaleEngine);
00586
00587
00588
00589
00590
00591
00592
00593 d_data->map.setTransformation(scaleEngine()->transformation());
00594 d_data->map.setScaleInterval(d_data->minValue, d_data->maxValue);
00595
00596 if (autoScale())
00597 rescale(d_data->minValue, d_data->maxValue);
00598
00599 layoutThermo();
00600 }
00601
00606 void QwtThermo::setFillBrush(const QBrush& b)
00607 {
00608 d_data->fillBrush = b;
00609 update();
00610 }
00611
00613 const QBrush& QwtThermo::fillBrush() const
00614 {
00615 return d_data->fillBrush;
00616 }
00617
00622 void QwtThermo::setFillColor(const QColor &c)
00623 {
00624 d_data->fillBrush.setColor(c);
00625 update();
00626 }
00627
00629 const QColor &QwtThermo::fillColor() const
00630 {
00631 return d_data->fillBrush.color();
00632 }
00633
00638 void QwtThermo::setAlarmBrush(const QBrush& b)
00639 {
00640 d_data->alarmBrush = b;
00641 update();
00642 }
00643
00645 const QBrush& QwtThermo::alarmBrush() const
00646 {
00647 return d_data->alarmBrush;
00648 }
00649
00654 void QwtThermo::setAlarmColor(const QColor &c)
00655 {
00656 d_data->alarmBrush.setColor(c);
00657 update();
00658 }
00659
00661 const QColor &QwtThermo::alarmColor() const
00662 {
00663 return d_data->alarmBrush.color();
00664 }
00665
00667 void QwtThermo::setAlarmLevel(double v)
00668 {
00669 d_data->alarmLevel = v;
00670 d_data->alarmEnabled = 1;
00671 update();
00672 }
00673
00675 double QwtThermo::alarmLevel() const
00676 {
00677 return d_data->alarmLevel;
00678 }
00679
00681 void QwtThermo::setPipeWidth(int w)
00682 {
00683 if (w > 0)
00684 {
00685 d_data->thermoWidth = w;
00686 layoutThermo();
00687 }
00688 }
00689
00691 int QwtThermo::pipeWidth() const
00692 {
00693 return d_data->thermoWidth;
00694 }
00695
00696
00711 void QwtThermo::setMargin(int)
00712 {
00713 }
00714
00715
00720 void QwtThermo::setAlarmEnabled(bool tf)
00721 {
00722 d_data->alarmEnabled = tf;
00723 update();
00724 }
00725
00727 bool QwtThermo::alarmEnabled() const
00728 {
00729 return d_data->alarmEnabled;
00730 }
00731
00736 QSize QwtThermo::sizeHint() const
00737 {
00738 return minimumSizeHint();
00739 }
00740
00746 QSize QwtThermo::minimumSizeHint() const
00747 {
00748 int w = 0, h = 0;
00749
00750 if ( d_data->scalePos != None )
00751 {
00752 int smw = scaleDraw()->minWidth( QPen(), font() );
00753 int smh = scaleDraw()->minHeight( QPen(), font() );
00754
00755 if ( d_data->orientation == Qt::Vertical )
00756 {
00757 w = d_data->thermoWidth + smw + 3 * d_data->borderWidth + d_data->scaleDist;
00758 h = smh + 2 * d_data->borderWidth;
00759 }
00760 else
00761 {
00762 w = smw + 2 * d_data->borderWidth;
00763 h = d_data->thermoWidth + smh + 3 * d_data->borderWidth + d_data->scaleDist;
00764 }
00765
00766 }
00767 else
00768 {
00769 if ( d_data->orientation == Qt::Vertical )
00770 {
00771 w = d_data->thermoWidth + 2 * d_data->borderWidth;
00772 h = 200 + 2 * d_data->borderWidth;
00773 }
00774 else
00775 {
00776 w = 200 + 2 * d_data->borderWidth;
00777 h = d_data->thermoWidth + 2 * d_data->borderWidth;
00778 }
00779 }
00780 return QSize( w, h );
00781 }
00782
00783 int QwtThermo::transform(double value) const
00784 {
00785 const double min = qwtMin(d_data->map.s1(), d_data->map.s2());
00786 const double max = qwtMax(d_data->map.s1(), d_data->map.s2());
00787
00788 if ( value > max )
00789 value = max;
00790 if ( value < min )
00791 value = min;
00792
00793 return d_data->map.transform(value);
00794 }