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 void QwtThermo::setScaleDraw(QwtScaleDraw *scaleDraw)
00130 {
00131 setAbstractScaleDraw(scaleDraw);
00132 }
00133
00134 const QwtScaleDraw *QwtThermo::scaleDraw() const
00135 {
00136 return (QwtScaleDraw *)abstractScaleDraw();
00137 }
00138
00139 QwtScaleDraw *QwtThermo::scaleDraw()
00140 {
00141 return (QwtScaleDraw *)abstractScaleDraw();
00142 }
00143
00145 void QwtThermo::paintEvent(QPaintEvent *e)
00146 {
00147
00148 const QRect &ur = e->rect();
00149 if ( ur.isValid() )
00150 {
00151 #if QT_VERSION < 0x040000
00152 QwtPaintBuffer paintBuffer(this, ur);
00153 draw(paintBuffer.painter(), ur);
00154 #else
00155 QPainter painter(this);
00156 draw(&painter, ur);
00157 #endif
00158 }
00159 }
00160
00162 void QwtThermo::draw(QPainter *p, const QRect& ur)
00163 {
00164 if ( !d_data->thermoRect.contains(ur) )
00165 {
00166 if (d_data->scalePos != None)
00167 {
00168 #if QT_VERSION < 0x040000
00169 scaleDraw()->draw(p, colorGroup());
00170 #else
00171 scaleDraw()->draw(p, palette());
00172 #endif
00173 }
00174
00175 qDrawShadePanel(p,
00176 d_data->thermoRect.x() - d_data->borderWidth,
00177 d_data->thermoRect.y() - d_data->borderWidth,
00178 d_data->thermoRect.width() + 2*d_data->borderWidth,
00179 d_data->thermoRect.height() + 2*d_data->borderWidth,
00180 #if QT_VERSION < 0x040000
00181 colorGroup(),
00182 #else
00183 palette(),
00184 #endif
00185 true, d_data->borderWidth,0);
00186 }
00187 drawThermo(p);
00188 }
00189
00191 void QwtThermo::resizeEvent(QResizeEvent *)
00192 {
00193 layoutThermo( false );
00194 }
00195
00202 void QwtThermo::layoutThermo( bool update_geometry )
00203 {
00204 QRect r = rect();
00205 int mbd = 0;
00206 if ( d_data->scalePos != None )
00207 {
00208 int d1, d2;
00209 scaleDraw()->getBorderDistHint(font(), d1, d2);
00210 mbd = qwtMax(d1, d2);
00211 }
00212
00213 if ( d_data->orientation == Qt::Horizontal )
00214 {
00215 switch ( d_data->scalePos )
00216 {
00217 case Top:
00218 {
00219 d_data->thermoRect.setRect(
00220 r.x() + mbd + d_data->borderWidth,
00221 r.y() + r.height()
00222 - d_data->thermoWidth - 2*d_data->borderWidth,
00223 r.width() - 2*(d_data->borderWidth + mbd),
00224 d_data->thermoWidth);
00225 scaleDraw()->setAlignment(QwtScaleDraw::TopScale);
00226 scaleDraw()->move( d_data->thermoRect.x(),
00227 d_data->thermoRect.y() - d_data->borderWidth
00228 - d_data->scaleDist);
00229 scaleDraw()->setLength(d_data->thermoRect.width());
00230 break;
00231 }
00232
00233 case Bottom:
00234 case None:
00235 default:
00236
00237
00238 {
00239 d_data->thermoRect.setRect(
00240 r.x() + mbd + d_data->borderWidth,
00241 r.y() + d_data->borderWidth,
00242 r.width() - 2*(d_data->borderWidth + mbd),
00243 d_data->thermoWidth);
00244 scaleDraw()->setAlignment(QwtScaleDraw::BottomScale);
00245 scaleDraw()->move(
00246 d_data->thermoRect.x(),
00247 d_data->thermoRect.y() + d_data->thermoRect.height()
00248 + d_data->borderWidth + d_data->scaleDist );
00249 scaleDraw()->setLength(d_data->thermoRect.width());
00250 break;
00251 }
00252 }
00253 d_data->map.setPaintInterval(d_data->thermoRect.x(),
00254 d_data->thermoRect.x() + d_data->thermoRect.width() - 1);
00255 }
00256 else
00257 {
00258 switch ( d_data->scalePos )
00259 {
00260 case Right:
00261 {
00262 d_data->thermoRect.setRect(
00263 r.x() + d_data->borderWidth,
00264 r.y() + mbd + d_data->borderWidth,
00265 d_data->thermoWidth,
00266 r.height() - 2*(d_data->borderWidth + mbd));
00267 scaleDraw()->setAlignment(QwtScaleDraw::RightScale);
00268 scaleDraw()->move(
00269 d_data->thermoRect.x() + d_data->thermoRect.width()
00270 + d_data->borderWidth + d_data->scaleDist,
00271 d_data->thermoRect.y());
00272 scaleDraw()->setLength(d_data->thermoRect.height());
00273 break;
00274 }
00275
00276 case Left:
00277 case None:
00278 default:
00279
00280
00281 {
00282 d_data->thermoRect.setRect(
00283 r.x() + r.width() - 2*d_data->borderWidth - d_data->thermoWidth,
00284 r.y() + mbd + d_data->borderWidth,
00285 d_data->thermoWidth,
00286 r.height() - 2*(d_data->borderWidth + mbd));
00287 scaleDraw()->setAlignment(QwtScaleDraw::LeftScale);
00288 scaleDraw()->move(
00289 d_data->thermoRect.x() - d_data->scaleDist
00290 - d_data->borderWidth,
00291 d_data->thermoRect.y() );
00292 scaleDraw()->setLength(d_data->thermoRect.height());
00293 break;
00294 }
00295 }
00296 d_data->map.setPaintInterval(
00297 d_data->thermoRect.y() + d_data->thermoRect.height() - 1,
00298 d_data->thermoRect.y());
00299 }
00300 if ( update_geometry )
00301 {
00302 updateGeometry();
00303 update();
00304 }
00305 }
00306
00323 void QwtThermo::setOrientation(Qt::Orientation o, ScalePos s)
00324 {
00325 if ( o == d_data->orientation )
00326 return;
00327
00328 switch(o)
00329 {
00330 case Qt::Horizontal:
00331 {
00332 d_data->orientation = Qt::Horizontal;
00333 if ((s == None) || (s == Bottom) || (s == Top))
00334 d_data->scalePos = s;
00335 else
00336 d_data->scalePos = None;
00337 break;
00338 }
00339 case Qt::Vertical:
00340 {
00341 d_data->orientation = Qt::Vertical;
00342 if ((s == None) || (s == Left) || (s == Right))
00343 d_data->scalePos = s;
00344 else
00345 d_data->scalePos = None;
00346 break;
00347 }
00348 }
00349
00350 #if QT_VERSION >= 0x040000
00351 if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
00352 #else
00353 if ( !testWState( WState_OwnSizePolicy ) )
00354 #endif
00355 {
00356 QSizePolicy sp = sizePolicy();
00357 sp.transpose();
00358 setSizePolicy(sp);
00359
00360 #if QT_VERSION >= 0x040000
00361 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00362 #else
00363 clearWState( WState_OwnSizePolicy );
00364 #endif
00365 }
00366
00367 layoutThermo();
00368 }
00369
00384 void QwtThermo::setScalePosition(ScalePos s)
00385 {
00386 if ((s == Bottom) || (s == Top))
00387 setOrientation(Qt::Horizontal, s);
00388 else if ((s == Left) || (s == Right))
00389 setOrientation(Qt::Vertical, s);
00390 else
00391 setOrientation(d_data->orientation, None);
00392 }
00393
00395 QwtThermo::ScalePos QwtThermo::scalePosition() const
00396 {
00397 return d_data->scalePos;
00398 }
00399
00401 void QwtThermo::fontChange(const QFont &f)
00402 {
00403 QWidget::fontChange( f );
00404 layoutThermo();
00405 }
00406
00408 void QwtThermo::scaleChange()
00409 {
00410 update();
00411 layoutThermo();
00412 }
00413
00415 void QwtThermo::drawThermo(QPainter *p)
00416 {
00417 int alarm = 0, taval = 0;
00418
00419 QRect fRect;
00420 QRect aRect;
00421 QRect bRect;
00422
00423 int inverted = ( d_data->maxValue < d_data->minValue );
00424
00425
00426
00427
00428
00429
00430 if (d_data->alarmEnabled)
00431 {
00432 if (inverted)
00433 {
00434 alarm = ((d_data->alarmLevel >= d_data->maxValue)
00435 && (d_data->alarmLevel <= d_data->minValue)
00436 && (d_data->value >= d_data->alarmLevel));
00437
00438 }
00439 else
00440 {
00441 alarm = (( d_data->alarmLevel >= d_data->minValue)
00442 && (d_data->alarmLevel <= d_data->maxValue)
00443 && (d_data->value >= d_data->alarmLevel));
00444 }
00445 }
00446
00447
00448
00449
00450 int tval = transform(d_data->value);
00451
00452 if (alarm)
00453 taval = transform(d_data->alarmLevel);
00454
00455
00456
00457
00458 if ( d_data->orientation == Qt::Horizontal )
00459 {
00460 if (inverted)
00461 {
00462 bRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00463 tval - d_data->thermoRect.x(),
00464 d_data->thermoRect.height());
00465
00466 if (alarm)
00467 {
00468 aRect.setRect(tval, d_data->thermoRect.y(),
00469 taval - tval + 1,
00470 d_data->thermoRect.height());
00471 fRect.setRect(taval + 1, d_data->thermoRect.y(),
00472 d_data->thermoRect.x() + d_data->thermoRect.width() - (taval + 1),
00473 d_data->thermoRect.height());
00474 }
00475 else
00476 {
00477 fRect.setRect(tval, d_data->thermoRect.y(),
00478 d_data->thermoRect.x() + d_data->thermoRect.width() - tval,
00479 d_data->thermoRect.height());
00480 }
00481 }
00482 else
00483 {
00484 bRect.setRect(tval + 1, d_data->thermoRect.y(),
00485 d_data->thermoRect.width() - (tval + 1 - d_data->thermoRect.x()),
00486 d_data->thermoRect.height());
00487
00488 if (alarm)
00489 {
00490 aRect.setRect(taval, d_data->thermoRect.y(),
00491 tval - taval + 1,
00492 d_data->thermoRect.height());
00493 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00494 taval - d_data->thermoRect.x(),
00495 d_data->thermoRect.height());
00496 }
00497 else
00498 {
00499 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00500 tval - d_data->thermoRect.x() + 1,
00501 d_data->thermoRect.height());
00502 }
00503
00504 }
00505 }
00506 else
00507 {
00508 if (tval < d_data->thermoRect.y())
00509 tval = d_data->thermoRect.y();
00510 else
00511 {
00512 if (tval > d_data->thermoRect.y() + d_data->thermoRect.height())
00513 tval = d_data->thermoRect.y() + d_data->thermoRect.height();
00514 }
00515
00516 if (inverted)
00517 {
00518 bRect.setRect(d_data->thermoRect.x(), tval + 1,
00519 d_data->thermoRect.width(),
00520 d_data->thermoRect.height() - (tval + 1 - d_data->thermoRect.y()));
00521
00522 if (alarm)
00523 {
00524 aRect.setRect(d_data->thermoRect.x(), taval,
00525 d_data->thermoRect.width(),
00526 tval - taval + 1);
00527 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00528 d_data->thermoRect.width(),
00529 taval - d_data->thermoRect.y());
00530 }
00531 else
00532 {
00533 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00534 d_data->thermoRect.width(),
00535 tval - d_data->thermoRect.y() + 1);
00536 }
00537 }
00538 else
00539 {
00540 bRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00541 d_data->thermoRect.width(),
00542 tval - d_data->thermoRect.y());
00543 if (alarm)
00544 {
00545 aRect.setRect(d_data->thermoRect.x(),tval,
00546 d_data->thermoRect.width(),
00547 taval - tval + 1);
00548 fRect.setRect(d_data->thermoRect.x(),taval + 1,
00549 d_data->thermoRect.width(),
00550 d_data->thermoRect.y() + d_data->thermoRect.height() - (taval + 1));
00551 }
00552 else
00553 {
00554 fRect.setRect(d_data->thermoRect.x(),tval,
00555 d_data->thermoRect.width(),
00556 d_data->thermoRect.y() + d_data->thermoRect.height() - tval);
00557 }
00558 }
00559 }
00560
00561
00562
00563
00564 const QColor bgColor =
00565 #if QT_VERSION < 0x040000
00566 colorGroup().color(QColorGroup::Background);
00567 #else
00568 palette().color(QPalette::Background);
00569 #endif
00570 p->fillRect(bRect, bgColor);
00571
00572 if (alarm)
00573 p->fillRect(aRect, d_data->alarmBrush);
00574
00575 p->fillRect(fRect, d_data->fillBrush);
00576 }
00577
00579 void QwtThermo::setBorderWidth(int w)
00580 {
00581 if ((w >= 0) && (w < (qwtMin(d_data->thermoRect.width(),
00582 d_data->thermoRect.height()) + d_data->borderWidth) / 2 - 1))
00583 {
00584 d_data->borderWidth = w;
00585 layoutThermo();
00586 }
00587 }
00588
00590 int QwtThermo::borderWidth() const
00591 {
00592 return d_data->borderWidth;
00593 }
00594
00601 void QwtThermo::setRange(double vmin, double vmax, bool logarithmic)
00602 {
00603 d_data->minValue = vmin;
00604 d_data->maxValue = vmax;
00605
00606 if ( logarithmic )
00607 setScaleEngine(new QwtLog10ScaleEngine);
00608 else
00609 setScaleEngine(new QwtLinearScaleEngine);
00610
00611
00612
00613
00614
00615
00616
00617 d_data->map.setTransformation(scaleEngine()->transformation());
00618 d_data->map.setScaleInterval(d_data->minValue, d_data->maxValue);
00619
00620 if (autoScale())
00621 rescale(d_data->minValue, d_data->maxValue);
00622
00623 layoutThermo();
00624 }
00625
00630 void QwtThermo::setFillBrush(const QBrush& brush)
00631 {
00632 d_data->fillBrush = brush;
00633 update();
00634 }
00635
00637 const QBrush& QwtThermo::fillBrush() const
00638 {
00639 return d_data->fillBrush;
00640 }
00641
00646 void QwtThermo::setFillColor(const QColor &c)
00647 {
00648 d_data->fillBrush.setColor(c);
00649 update();
00650 }
00651
00653 const QColor &QwtThermo::fillColor() const
00654 {
00655 return d_data->fillBrush.color();
00656 }
00657
00662 void QwtThermo::setAlarmBrush(const QBrush& brush)
00663 {
00664 d_data->alarmBrush = brush;
00665 update();
00666 }
00667
00669 const QBrush& QwtThermo::alarmBrush() const
00670 {
00671 return d_data->alarmBrush;
00672 }
00673
00678 void QwtThermo::setAlarmColor(const QColor &c)
00679 {
00680 d_data->alarmBrush.setColor(c);
00681 update();
00682 }
00683
00685 const QColor &QwtThermo::alarmColor() const
00686 {
00687 return d_data->alarmBrush.color();
00688 }
00689
00691 void QwtThermo::setAlarmLevel(double v)
00692 {
00693 d_data->alarmLevel = v;
00694 d_data->alarmEnabled = 1;
00695 update();
00696 }
00697
00699 double QwtThermo::alarmLevel() const
00700 {
00701 return d_data->alarmLevel;
00702 }
00703
00705 void QwtThermo::setPipeWidth(int w)
00706 {
00707 if (w > 0)
00708 {
00709 d_data->thermoWidth = w;
00710 layoutThermo();
00711 }
00712 }
00713
00715 int QwtThermo::pipeWidth() const
00716 {
00717 return d_data->thermoWidth;
00718 }
00719
00720
00735 void QwtThermo::setMargin(int)
00736 {
00737 }
00738
00739
00744 void QwtThermo::setAlarmEnabled(bool tf)
00745 {
00746 d_data->alarmEnabled = tf;
00747 update();
00748 }
00749
00751 bool QwtThermo::alarmEnabled() const
00752 {
00753 return d_data->alarmEnabled;
00754 }
00755
00760 QSize QwtThermo::sizeHint() const
00761 {
00762 return minimumSizeHint();
00763 }
00764
00770 QSize QwtThermo::minimumSizeHint() const
00771 {
00772 int w = 0, h = 0;
00773
00774 if ( d_data->scalePos != None )
00775 {
00776 const int sdExtent = scaleDraw()->extent( QPen(), font() );
00777 const int sdLength = scaleDraw()->minLength( QPen(), font() );
00778
00779 w = sdLength;
00780 h = d_data->thermoWidth + sdExtent +
00781 d_data->borderWidth + d_data->scaleDist;
00782
00783 }
00784 else
00785 {
00786 w = 200;
00787 h = d_data->thermoWidth;
00788 }
00789
00790 if ( d_data->orientation == Qt::Vertical )
00791 qSwap(w, h);
00792
00793 w += 2 * d_data->borderWidth;
00794 h += 2 * d_data->borderWidth;
00795
00796 return QSize( w, h );
00797 }
00798
00799 int QwtThermo::transform(double value) const
00800 {
00801 const double min = qwtMin(d_data->map.s1(), d_data->map.s2());
00802 const double max = qwtMax(d_data->map.s1(), d_data->map.s2());
00803
00804 if ( value > max )
00805 value = max;
00806 if ( value < min )
00807 value = min;
00808
00809 return d_data->map.transform(value);
00810 }