source: ntrip/trunk/BNC/qwt/qwt_thermo.cpp@ 8486

Last change on this file since 8486 was 8127, checked in by stoecker, 8 years ago

update qwt and qwtpolar, many QT5 fixes (unfinished)

File size: 22.6 KB
Line 
1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_thermo.h"
11#include "qwt_scale_engine.h"
12#include "qwt_scale_draw.h"
13#include "qwt_scale_map.h"
14#include "qwt_color_map.h"
15#include <qpainter.h>
16#include <qevent.h>
17#include <qdrawutil.h>
18#include <qstyle.h>
19#include <qstyleoption.h>
20#include <qmath.h>
21
22static inline void qwtDrawLine( QPainter *painter, int pos,
23 const QColor &color, const QRect &pipeRect, const QRect &liquidRect,
24 Qt::Orientation orientation )
25{
26 painter->setPen( color );
27 if ( orientation == Qt::Horizontal )
28 {
29 if ( pos >= liquidRect.left() && pos < liquidRect.right() )
30 painter->drawLine( pos, pipeRect.top(), pos, pipeRect.bottom() );
31 }
32 else
33 {
34 if ( pos >= liquidRect.top() && pos < liquidRect.bottom() )
35 painter->drawLine( pipeRect.left(), pos, pipeRect.right(), pos );
36 }
37}
38
39QVector<double> qwtTickList( const QwtScaleDiv &scaleDiv )
40{
41 QVector<double> values;
42
43 double lowerLimit = scaleDiv.interval().minValue();
44 double upperLimit = scaleDiv.interval().maxValue();
45
46 if ( upperLimit < lowerLimit )
47 qSwap( lowerLimit, upperLimit );
48
49 values += lowerLimit;
50
51 for ( int tickType = QwtScaleDiv::MinorTick;
52 tickType < QwtScaleDiv::NTickTypes; tickType++ )
53 {
54 const QList<double> ticks = scaleDiv.ticks( tickType );
55
56 for ( int i = 0; i < ticks.count(); i++ )
57 {
58 const double v = ticks[i];
59 if ( v > lowerLimit && v < upperLimit )
60 values += v;
61 }
62 }
63
64 values += upperLimit;
65
66 return values;
67}
68
69class QwtThermo::PrivateData
70{
71public:
72 PrivateData():
73 orientation( Qt::Vertical ),
74 scalePosition( QwtThermo::TrailingScale ),
75 spacing( 3 ),
76 borderWidth( 2 ),
77 pipeWidth( 10 ),
78 alarmLevel( 0.0 ),
79 alarmEnabled( false ),
80 autoFillPipe( true ),
81 originMode( QwtThermo::OriginMinimum ),
82 origin( 0.0 ),
83 colorMap( NULL ),
84 value( 0.0 )
85 {
86 rangeFlags = QwtInterval::IncludeBorders;
87 }
88
89 ~PrivateData()
90 {
91 delete colorMap;
92 }
93
94 Qt::Orientation orientation;
95 QwtThermo::ScalePosition scalePosition;
96
97 int spacing;
98 int borderWidth;
99 int pipeWidth;
100
101 QwtInterval::BorderFlags rangeFlags;
102 double alarmLevel;
103 bool alarmEnabled;
104 bool autoFillPipe;
105 QwtThermo::OriginMode originMode;
106 double origin;
107
108 QwtColorMap *colorMap;
109
110 double value;
111};
112
113/*!
114 Constructor
115 \param parent Parent widget
116*/
117QwtThermo::QwtThermo( QWidget *parent ):
118 QwtAbstractScale( parent )
119{
120 d_data = new PrivateData;
121
122 QSizePolicy policy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
123 if ( d_data->orientation == Qt::Vertical )
124 policy.transpose();
125
126 setSizePolicy( policy );
127
128 setAttribute( Qt::WA_WState_OwnSizePolicy, false );
129 layoutThermo( true );
130}
131
132//! Destructor
133QwtThermo::~QwtThermo()
134{
135 delete d_data;
136}
137
138/*!
139 \brief Exclude/Include min/max values
140
141 According to the flags minValue() and maxValue()
142 are included/excluded from the pipe. In case of an
143 excluded value the corresponding tick is painted
144 1 pixel off of the pipeRect().
145
146 F.e. when a minimum
147 of 0.0 has to be displayed as an empty pipe the minValue()
148 needs to be excluded.
149
150 \param flags Range flags
151 \sa rangeFlags()
152*/
153void QwtThermo::setRangeFlags( QwtInterval::BorderFlags flags )
154{
155 if ( d_data->rangeFlags != flags )
156 {
157 d_data->rangeFlags = flags;
158 update();
159 }
160}
161
162/*!
163 \return Range flags
164 \sa setRangeFlags()
165*/
166QwtInterval::BorderFlags QwtThermo::rangeFlags() const
167{
168 return d_data->rangeFlags;
169}
170
171/*!
172 Set the current value.
173
174 \param value New Value
175 \sa value()
176*/
177void QwtThermo::setValue( double value )
178{
179 if ( d_data->value != value )
180 {
181 d_data->value = value;
182 update();
183 }
184}
185
186//! Return the value.
187double QwtThermo::value() const
188{
189 return d_data->value;
190}
191
192/*!
193 \brief Set a scale draw
194
195 For changing the labels of the scales, it
196 is necessary to derive from QwtScaleDraw and
197 overload QwtScaleDraw::label().
198
199 \param scaleDraw ScaleDraw object, that has to be created with
200 new and will be deleted in ~QwtThermo() or the next
201 call of setScaleDraw().
202*/
203void QwtThermo::setScaleDraw( QwtScaleDraw *scaleDraw )
204{
205 setAbstractScaleDraw( scaleDraw );
206 layoutThermo( true );
207}
208
209/*!
210 \return the scale draw of the thermo
211 \sa setScaleDraw()
212*/
213const QwtScaleDraw *QwtThermo::scaleDraw() const
214{
215 return static_cast<const QwtScaleDraw *>( abstractScaleDraw() );
216}
217
218/*!
219 \return the scale draw of the thermo
220 \sa setScaleDraw()
221*/
222QwtScaleDraw *QwtThermo::scaleDraw()
223{
224 return static_cast<QwtScaleDraw *>( abstractScaleDraw() );
225}
226
227/*!
228 Paint event handler
229 \param event Paint event
230*/
231void QwtThermo::paintEvent( QPaintEvent *event )
232{
233 QPainter painter( this );
234 painter.setClipRegion( event->region() );
235
236 QStyleOption opt;
237 opt.init(this);
238 style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
239
240 const QRect tRect = pipeRect();
241
242 if ( !tRect.contains( event->rect() ) )
243 {
244 if ( d_data->scalePosition != QwtThermo::NoScale )
245 scaleDraw()->draw( &painter, palette() );
246 }
247
248 const int bw = d_data->borderWidth;
249
250 const QBrush brush = palette().brush( QPalette::Base );
251 qDrawShadePanel( &painter,
252 tRect.adjusted( -bw, -bw, bw, bw ),
253 palette(), true, bw,
254 d_data->autoFillPipe ? &brush : NULL );
255
256 drawLiquid( &painter, tRect );
257}
258
259/*!
260 Resize event handler
261 \param event Resize event
262*/
263void QwtThermo::resizeEvent( QResizeEvent *event )
264{
265 Q_UNUSED( event );
266 layoutThermo( false );
267}
268
269/*!
270 Qt change event handler
271 \param event Event
272*/
273void QwtThermo::changeEvent( QEvent *event )
274{
275 switch( event->type() )
276 {
277 case QEvent::StyleChange:
278 case QEvent::FontChange:
279 {
280 layoutThermo( true );
281 break;
282 }
283 default:
284 break;
285 }
286}
287
288/*!
289 Recalculate the QwtThermo geometry and layout based on
290 pipeRect() and the fonts.
291
292 \param update_geometry notify the layout system and call update
293 to redraw the scale
294*/
295void QwtThermo::layoutThermo( bool update_geometry )
296{
297 const QRect tRect = pipeRect();
298 const int bw = d_data->borderWidth + d_data->spacing;
299 const bool inverted = ( upperBound() < lowerBound() );
300
301 int from, to;
302
303 if ( d_data->orientation == Qt::Horizontal )
304 {
305 from = tRect.left();
306 to = tRect.right();
307
308 if ( d_data->rangeFlags & QwtInterval::ExcludeMinimum )
309 {
310 if ( inverted )
311 to++;
312 else
313 from--;
314 }
315 if ( d_data->rangeFlags & QwtInterval::ExcludeMaximum )
316 {
317 if ( inverted )
318 from--;
319 else
320 to++;
321 }
322
323 if ( d_data->scalePosition == QwtThermo::TrailingScale )
324 {
325 scaleDraw()->setAlignment( QwtScaleDraw::TopScale );
326 scaleDraw()->move( from, tRect.top() - bw );
327 }
328 else
329 {
330 scaleDraw()->setAlignment( QwtScaleDraw::BottomScale );
331 scaleDraw()->move( from, tRect.bottom() + bw );
332 }
333
334 scaleDraw()->setLength( qMax( to - from, 0 ) );
335 }
336 else // Qt::Vertical
337 {
338 from = tRect.top();
339 to = tRect.bottom();
340
341 if ( d_data->rangeFlags & QwtInterval::ExcludeMinimum )
342 {
343 if ( inverted )
344 from--;
345 else
346 to++;
347 }
348 if ( d_data->rangeFlags & QwtInterval::ExcludeMaximum )
349 {
350 if ( inverted )
351 to++;
352 else
353 from--;
354 }
355
356 if ( d_data->scalePosition == QwtThermo::LeadingScale )
357 {
358 scaleDraw()->setAlignment( QwtScaleDraw::RightScale );
359 scaleDraw()->move( tRect.right() + bw, from );
360 }
361 else
362 {
363 scaleDraw()->setAlignment( QwtScaleDraw::LeftScale );
364 scaleDraw()->move( tRect.left() - bw, from );
365 }
366
367 scaleDraw()->setLength( qMax( to - from, 0 ) );
368 }
369
370 if ( update_geometry )
371 {
372 updateGeometry();
373 update();
374 }
375}
376
377/*!
378 \return Bounding rectangle of the pipe ( without borders )
379 in widget coordinates
380*/
381QRect QwtThermo::pipeRect() const
382{
383 int mbd = 0;
384 if ( d_data->scalePosition != QwtThermo::NoScale )
385 {
386 int d1, d2;
387 scaleDraw()->getBorderDistHint( font(), d1, d2 );
388 mbd = qMax( d1, d2 );
389 }
390 const int bw = d_data->borderWidth;
391 const int scaleOff = bw + mbd;
392
393 const QRect cr = contentsRect();
394
395 QRect pipeRect = cr;
396 if ( d_data->orientation == Qt::Horizontal )
397 {
398 pipeRect.adjust( scaleOff, 0, -scaleOff, 0 );
399
400 if ( d_data->scalePosition == QwtThermo::TrailingScale )
401 pipeRect.setTop( cr.top() + cr.height() - bw - d_data->pipeWidth );
402 else
403 pipeRect.setTop( bw );
404
405 pipeRect.setHeight( d_data->pipeWidth );
406 }
407 else // Qt::Vertical
408 {
409 pipeRect.adjust( 0, scaleOff, 0, -scaleOff );
410
411 if ( d_data->scalePosition == QwtThermo::LeadingScale )
412 pipeRect.setLeft( bw );
413 else
414 pipeRect.setLeft( cr.left() + cr.width() - bw - d_data->pipeWidth );
415
416 pipeRect.setWidth( d_data->pipeWidth );
417 }
418
419 return pipeRect;
420}
421
422/*!
423 \brief Set the orientation.
424 \param orientation Allowed values are Qt::Horizontal and Qt::Vertical.
425
426 \sa orientation(), scalePosition()
427*/
428void QwtThermo::setOrientation( Qt::Orientation orientation )
429{
430 if ( orientation == d_data->orientation )
431 return;
432
433 d_data->orientation = orientation;
434
435 if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) )
436 {
437 QSizePolicy sp = sizePolicy();
438 sp.transpose();
439 setSizePolicy( sp );
440
441 setAttribute( Qt::WA_WState_OwnSizePolicy, false );
442 }
443
444 layoutThermo( true );
445}
446
447/*!
448 \return Orientation
449 \sa setOrientation()
450*/
451Qt::Orientation QwtThermo::orientation() const
452{
453 return d_data->orientation;
454}
455
456/*!
457 \brief Change how the origin is determined.
458 \sa originMode(), serOrigin(), origin()
459 */
460void QwtThermo::setOriginMode( OriginMode m )
461{
462 if ( m == d_data->originMode )
463 return;
464
465 d_data->originMode = m;
466 update();
467}
468
469/*!
470 \return Mode, how the origin is determined.
471 \sa setOriginMode(), serOrigin(), origin()
472 */
473QwtThermo::OriginMode QwtThermo::originMode() const
474{
475 return d_data->originMode;
476}
477
478/*!
479 \brief Specifies the custom origin.
480
481 If originMode is set to OriginCustom this property controls where the
482 liquid starts.
483
484 \param origin New origin level
485 \sa setOriginMode(), originMode(), origin()
486 */
487void QwtThermo::setOrigin( double origin )
488{
489 if ( origin == d_data->origin )
490 return;
491
492 d_data->origin = origin;
493 update();
494}
495
496/*!
497 \return Origin of the thermo, when OriginCustom is enabled
498 \sa setOrigin(), setOriginMode(), originMode()
499 */
500double QwtThermo::origin() const
501{
502 return d_data->origin;
503}
504
505/*!
506 \brief Change the position of the scale
507 \param scalePosition Position of the scale.
508
509 \sa ScalePosition, scalePosition()
510*/
511void QwtThermo::setScalePosition( ScalePosition scalePosition )
512{
513 if ( d_data->scalePosition == scalePosition )
514 return;
515
516 d_data->scalePosition = scalePosition;
517
518 if ( testAttribute( Qt::WA_WState_Polished ) )
519 layoutThermo( true );
520}
521
522/*!
523 \return Scale position.
524 \sa setScalePosition()
525*/
526QwtThermo::ScalePosition QwtThermo::scalePosition() const
527{
528 return d_data->scalePosition;
529}
530
531//! Notify a scale change.
532void QwtThermo::scaleChange()
533{
534 layoutThermo( true );
535}
536
537/*!
538 Redraw the liquid in thermometer pipe.
539 \param painter Painter
540 \param pipeRect Bounding rectangle of the pipe without borders
541*/
542void QwtThermo::drawLiquid(
543 QPainter *painter, const QRect &pipeRect ) const
544{
545 painter->save();
546 painter->setClipRect( pipeRect, Qt::IntersectClip );
547 painter->setPen( Qt::NoPen );
548
549 const QwtScaleMap scaleMap = scaleDraw()->scaleMap();
550
551 QRect liquidRect = fillRect( pipeRect );
552
553 if ( d_data->colorMap != NULL )
554 {
555 const QwtInterval interval = scaleDiv().interval().normalized();
556
557 // Because the positions of the ticks are rounded
558 // we calculate the colors for the rounded tick values
559
560 QVector<double> values = qwtTickList( scaleDraw()->scaleDiv() );
561
562 if ( scaleMap.isInverting() )
563 qSort( values.begin(), values.end(), qGreater<double>() );
564 else
565 qSort( values.begin(), values.end(), qLess<double>() );
566
567 int from;
568 if ( !values.isEmpty() )
569 {
570 from = qRound( scaleMap.transform( values[0] ) );
571 qwtDrawLine( painter, from,
572 d_data->colorMap->color( interval, values[0] ),
573 pipeRect, liquidRect, d_data->orientation );
574 }
575
576 for ( int i = 1; i < values.size(); i++ )
577 {
578 const int to = qRound( scaleMap.transform( values[i] ) );
579
580 for ( int pos = from + 1; pos < to; pos++ )
581 {
582 const double v = scaleMap.invTransform( pos );
583
584 qwtDrawLine( painter, pos,
585 d_data->colorMap->color( interval, v ),
586 pipeRect, liquidRect, d_data->orientation );
587 }
588
589 qwtDrawLine( painter, to,
590 d_data->colorMap->color( interval, values[i] ),
591 pipeRect, liquidRect, d_data->orientation );
592
593 from = to;
594 }
595 }
596 else
597 {
598 if ( !liquidRect.isEmpty() && d_data->alarmEnabled )
599 {
600 const QRect r = alarmRect( liquidRect );
601 if ( !r.isEmpty() )
602 {
603 painter->fillRect( r, palette().brush( QPalette::Highlight ) );
604 liquidRect = QRegion( liquidRect ).subtracted( r ).boundingRect();
605 }
606 }
607
608 painter->fillRect( liquidRect, palette().brush( QPalette::ButtonText ) );
609 }
610
611 painter->restore();
612}
613
614/*!
615 \brief Change the spacing between pipe and scale
616
617 A spacing of 0 means, that the backbone of the scale is below
618 the pipe.
619
620 The default setting is 3 pixels.
621
622 \param spacing Number of pixels
623 \sa spacing();
624*/
625void QwtThermo::setSpacing( int spacing )
626{
627 if ( spacing <= 0 )
628 spacing = 0;
629
630 if ( spacing != d_data->spacing )
631 {
632 d_data->spacing = spacing;
633 layoutThermo( true );
634 }
635}
636
637/*!
638 \return Number of pixels between pipe and scale
639 \sa setSpacing()
640*/
641int QwtThermo::spacing() const
642{
643 return d_data->spacing;
644}
645
646/*!
647 Set the border width of the pipe.
648 \param width Border width
649 \sa borderWidth()
650*/
651void QwtThermo::setBorderWidth( int width )
652{
653 if ( width <= 0 )
654 width = 0;
655
656 if ( width != d_data->borderWidth )
657 {
658 d_data->borderWidth = width;
659 layoutThermo( true );
660 }
661}
662
663/*!
664 \return Border width of the thermometer pipe.
665 \sa setBorderWidth()
666*/
667int QwtThermo::borderWidth() const
668{
669 return d_data->borderWidth;
670}
671
672/*!
673 \brief Assign a color map for the fill color
674
675 \param colorMap Color map
676 \warning The alarm threshold has no effect, when
677 a color map has been assigned
678*/
679void QwtThermo::setColorMap( QwtColorMap *colorMap )
680{
681 if ( colorMap != d_data->colorMap )
682 {
683 delete d_data->colorMap;
684 d_data->colorMap = colorMap;
685 }
686}
687
688/*!
689 \return Color map for the fill color
690 \warning The alarm threshold has no effect, when
691 a color map has been assigned
692*/
693QwtColorMap *QwtThermo::colorMap()
694{
695 return d_data->colorMap;
696}
697
698/*!
699 \return Color map for the fill color
700 \warning The alarm threshold has no effect, when
701 a color map has been assigned
702*/
703const QwtColorMap *QwtThermo::colorMap() const
704{
705 return d_data->colorMap;
706}
707
708/*!
709 \brief Change the brush of the liquid.
710
711 Changes the QPalette::ButtonText brush of the palette.
712
713 \param brush New brush.
714 \sa fillBrush(), QWidget::setPalette()
715*/
716void QwtThermo::setFillBrush( const QBrush& brush )
717{
718 QPalette pal = palette();
719 pal.setBrush( QPalette::ButtonText, brush );
720 setPalette( pal );
721}
722
723/*!
724 \return Liquid ( QPalette::ButtonText ) brush.
725 \sa setFillBrush(), QWidget::palette()
726*/
727QBrush QwtThermo::fillBrush() const
728{
729 return palette().brush( QPalette::ButtonText );
730}
731
732/*!
733 \brief Specify the liquid brush above the alarm threshold
734
735 Changes the QPalette::Highlight brush of the palette.
736
737 \param brush New brush.
738 \sa alarmBrush(), QWidget::setPalette()
739
740 \warning The alarm threshold has no effect, when
741 a color map has been assigned
742*/
743void QwtThermo::setAlarmBrush( const QBrush& brush )
744{
745 QPalette pal = palette();
746 pal.setBrush( QPalette::Highlight, brush );
747 setPalette( pal );
748}
749
750/*!
751 \return Liquid brush ( QPalette::Highlight ) above the alarm threshold.
752 \sa setAlarmBrush(), QWidget::palette()
753
754 \warning The alarm threshold has no effect, when
755 a color map has been assigned
756*/
757QBrush QwtThermo::alarmBrush() const
758{
759 return palette().brush( QPalette::Highlight );
760}
761
762/*!
763 Specify the alarm threshold.
764
765 \param level Alarm threshold
766 \sa alarmLevel()
767
768 \warning The alarm threshold has no effect, when
769 a color map has been assigned
770*/
771void QwtThermo::setAlarmLevel( double level )
772{
773 d_data->alarmLevel = level;
774 d_data->alarmEnabled = 1;
775 update();
776}
777
778/*!
779 \return Alarm threshold.
780 \sa setAlarmLevel()
781
782 \warning The alarm threshold has no effect, when
783 a color map has been assigned
784*/
785double QwtThermo::alarmLevel() const
786{
787 return d_data->alarmLevel;
788}
789
790/*!
791 Change the width of the pipe.
792
793 \param width Width of the pipe
794 \sa pipeWidth()
795*/
796void QwtThermo::setPipeWidth( int width )
797{
798 if ( width > 0 )
799 {
800 d_data->pipeWidth = width;
801 layoutThermo( true );
802 }
803}
804
805/*!
806 \return Width of the pipe.
807 \sa setPipeWidth()
808*/
809int QwtThermo::pipeWidth() const
810{
811 return d_data->pipeWidth;
812}
813
814/*!
815 \brief Enable or disable the alarm threshold
816 \param on true (disabled) or false (enabled)
817
818 \warning The alarm threshold has no effect, when
819 a color map has been assigned
820*/
821void QwtThermo::setAlarmEnabled( bool on )
822{
823 d_data->alarmEnabled = on;
824 update();
825}
826
827/*!
828 \return True, when the alarm threshold is enabled.
829
830 \warning The alarm threshold has no effect, when
831 a color map has been assigned
832*/
833bool QwtThermo::alarmEnabled() const
834{
835 return d_data->alarmEnabled;
836}
837
838/*!
839 \return the minimum size hint
840 \sa minimumSizeHint()
841*/
842QSize QwtThermo::sizeHint() const
843{
844 return minimumSizeHint();
845}
846
847/*!
848 \return Minimum size hint
849 \warning The return value depends on the font and the scale.
850 \sa sizeHint()
851*/
852QSize QwtThermo::minimumSizeHint() const
853{
854 int w = 0, h = 0;
855
856 if ( d_data->scalePosition != NoScale )
857 {
858 const int sdExtent = qCeil( scaleDraw()->extent( font() ) );
859 const int sdLength = scaleDraw()->minLength( font() );
860
861 w = sdLength;
862 h = d_data->pipeWidth + sdExtent + d_data->spacing;
863
864 }
865 else // no scale
866 {
867 w = 200;
868 h = d_data->pipeWidth;
869 }
870
871 if ( d_data->orientation == Qt::Vertical )
872 qSwap( w, h );
873
874 w += 2 * d_data->borderWidth;
875 h += 2 * d_data->borderWidth;
876
877 // finally add the margins
878 int left, right, top, bottom;
879 getContentsMargins( &left, &top, &right, &bottom );
880 w += left + right;
881 h += top + bottom;
882
883 return QSize( w, h );
884}
885
886/*!
887 \brief Calculate the filled rectangle of the pipe
888
889 \param pipeRect Rectangle of the pipe
890 \return Rectangle to be filled ( fill and alarm brush )
891
892 \sa pipeRect(), alarmRect()
893 */
894QRect QwtThermo::fillRect( const QRect &pipeRect ) const
895{
896 double origin;
897 if ( d_data->originMode == OriginMinimum )
898 {
899 origin = qMin( lowerBound(), upperBound() );
900 }
901 else if ( d_data->originMode == OriginMaximum )
902 {
903 origin = qMax( lowerBound(), upperBound() );
904 }
905 else // OriginCustom
906 {
907 origin = d_data->origin;
908 }
909
910 const QwtScaleMap scaleMap = scaleDraw()->scaleMap();
911
912 int from = qRound( scaleMap.transform( d_data->value ) );
913 int to = qRound( scaleMap.transform( origin ) );
914
915 if ( to < from )
916 qSwap( from, to );
917
918 QRect fillRect = pipeRect;
919 if ( d_data->orientation == Qt::Horizontal )
920 {
921 fillRect.setLeft( from );
922 fillRect.setRight( to );
923 }
924 else // Qt::Vertical
925 {
926 fillRect.setTop( from );
927 fillRect.setBottom( to );
928 }
929
930 return fillRect.normalized();
931}
932
933/*!
934 \brief Calculate the alarm rectangle of the pipe
935
936 \param fillRect Filled rectangle in the pipe
937 \return Rectangle to be filled with the alarm brush
938
939 \sa pipeRect(), fillRect(), alarmLevel(), alarmBrush()
940 */
941QRect QwtThermo::alarmRect( const QRect &fillRect ) const
942{
943 QRect alarmRect( 0, 0, -1, -1); // something invalid
944
945 if ( !d_data->alarmEnabled )
946 return alarmRect;
947
948 const bool inverted = ( upperBound() < lowerBound() );
949
950 bool increasing;
951 if ( d_data->originMode == OriginCustom )
952 {
953 increasing = d_data->value > d_data->origin;
954 }
955 else
956 {
957 increasing = d_data->originMode == OriginMinimum;
958 }
959
960 const QwtScaleMap map = scaleDraw()->scaleMap();
961 const int alarmPos = qRound( map.transform( d_data->alarmLevel ) );
962 const int valuePos = qRound( map.transform( d_data->value ) );
963
964 if ( d_data->orientation == Qt::Horizontal )
965 {
966 int v1, v2;
967 if ( inverted )
968 {
969 v1 = fillRect.left();
970
971 v2 = alarmPos - 1;
972 v2 = qMin( v2, increasing ? fillRect.right() : valuePos );
973 }
974 else
975 {
976 v1 = alarmPos + 1;
977 v1 = qMax( v1, increasing ? fillRect.left() : valuePos );
978
979 v2 = fillRect.right();
980
981 }
982 alarmRect.setRect( v1, fillRect.top(), v2 - v1 + 1, fillRect.height() );
983 }
984 else
985 {
986 int v1, v2;
987 if ( inverted )
988 {
989 v1 = alarmPos + 1;
990 v1 = qMax( v1, increasing ? fillRect.top() : valuePos );
991
992 v2 = fillRect.bottom();
993 }
994 else
995 {
996 v1 = fillRect.top();
997
998 v2 = alarmPos - 1;
999 v2 = qMin( v2, increasing ? fillRect.bottom() : valuePos );
1000 }
1001 alarmRect.setRect( fillRect.left(), v1, fillRect.width(), v2 - v1 + 1 );
1002 }
1003
1004 return alarmRect;
1005}
Note: See TracBrowser for help on using the repository browser.