1 /*
2 KSysGuard, the KDE System Guard
3
4 Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License or (at your option) version 3 or any later version
10 accepted by the membership of KDE e.V. (or its successor approved
11 by the membership of KDE e.V.), which shall act as a proxy
12 defined in Section 14 of version 3 of the license.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include <assert.h>
24 #include <string.h>
25
26 #include <QDebug>
27 #include <QPainter>
28
29 #include <KIconLoader>
30 #include <formatter/Formatter.h> // from libksysguard
31
32 #include "StyleEngine.h"
33
34 #include "BarGraph.h"
35
BarGraph(QWidget * parent)36 BarGraph::BarGraph( QWidget *parent )
37 : QWidget( parent )
38 {
39 bars = 0;
40 minValue = 0.0;
41 maxValue = 100.0;
42 lowerLimit = upperLimit = 0.0;
43 lowerLimitActive = upperLimitActive = false;
44
45 normalColor = KSGRD::Style->firstForegroundColor();
46 alarmColor = KSGRD::Style->alarmColor();
47 mBackgroundColor = KSGRD::Style->backgroundColor();
48 fontSize = KSGRD::Style->fontSize();
49
50 // Anything smaller than this does not make sense.
51 setMinimumSize( 16, 16 );
52 setSizePolicy( QSizePolicy( QSizePolicy::Expanding,
53 QSizePolicy::Expanding ) );
54 }
55
~BarGraph()56 BarGraph::~BarGraph()
57 {
58 }
59
addBar(const QString & footer)60 bool BarGraph::addBar( const QString &footer )
61 {
62 samples.resize( bars + 1 );
63 samples[ bars++ ] = 0.0;
64 footers.append( footer );
65
66 return true;
67 }
68
removeBar(uint idx)69 bool BarGraph::removeBar( uint idx )
70 {
71 if ( idx >= bars ) {
72 qDebug() << "BarGraph::removeBar: idx " << idx << " out of range "
73 << bars;
74 return false;
75 }
76
77 samples.resize( --bars );
78 footers.removeAt(idx);
79 update();
80
81 return true;
82 }
83
updateSamples(const QVector<double> & newSamples)84 void BarGraph::updateSamples( const QVector<double> &newSamples )
85 {
86 samples = newSamples;
87 update();
88 }
89
changeRange(double min,double max)90 void BarGraph::changeRange( double min, double max )
91 {
92 minValue = min;
93 maxValue = max;
94 }
95
paintEvent(QPaintEvent *)96 void BarGraph::paintEvent( QPaintEvent* )
97 {
98 int w = width();
99 int h = height();
100
101 QPainter p( this );
102
103 p.fillRect(0,0,w, h, mBackgroundColor);
104
105 p.setBrush( palette().color( QPalette::Light) );
106 p.setFont( QFont( p.font().family(), fontSize ) );
107 QFontMetrics fm( p.font() );
108
109 /* Draw white line along the bottom and the right side of the
110 * widget to create a 3D like look. */
111 p.drawLine( 0, h - 1, w - 1, h - 1 );
112 p.drawLine( w - 1, 0, w - 1, h - 1 );
113
114 p.setClipRect( 1, 1, w - 2, h - 2 );
115
116 if ( bars > 0 ) {
117 int barWidth = ( w - 2 ) / bars;
118 uint b;
119 /* Labels are only printed underneath the bars if the labels
120 * for all bars are smaller than the bar width. If a single
121 * label does not fit no label is shown. */
122 bool showLabels = true;
123 for ( b = 0; b < bars; b++ )
124 if ( fm.boundingRect( footers[ b ] ).width() > barWidth )
125 showLabels = false;
126
127 int barHeight;
128 if ( showLabels )
129 barHeight = h - 2 - ( 2 * fm.lineSpacing() ) - 2;
130 else
131 barHeight = h - 2;
132
133 for ( uint b = 0; b < bars; b++ ) {
134 int topVal = int( (maxValue == 0.0) ? 0.0 :
135 ( (float)barHeight / maxValue * ( samples[ b ] - minValue ) ) );
136 /* TODO: This widget does not handle negative values properly. */
137 if ( topVal < 0 )
138 topVal = 0;
139
140 for ( int i = 0; i < barHeight && i < topVal; i += 2 ) {
141 if ( ( upperLimitActive && samples[ b ] > upperLimit ) ||
142 ( lowerLimitActive && samples[ b ] < lowerLimit ) )
143 p.setPen( alarmColor.lighter( static_cast<int>( 30 + ( 70.0 /
144 ( barHeight + 1 ) * i ) ) ) );
145 else
146 p.setPen( normalColor.lighter( static_cast<int>( 30 + ( 70.0 /
147 ( barHeight + 1 ) * i ) ) ) );
148 p.drawLine( b * barWidth + 3, barHeight - i, ( b + 1 ) * barWidth - 3,
149 barHeight - i );
150 }
151
152 if ( ( upperLimitActive && samples[ b ] > upperLimit ) ||
153 ( lowerLimitActive && samples[ b ] < lowerLimit ) )
154 p.setPen( alarmColor );
155 else
156 p.setPen( normalColor );
157
158 if ( showLabels ) {
159 p.drawText( b * barWidth + 3, h - ( 2 * fm.lineSpacing() ) - 2,
160 barWidth - 2 * 3, fm.lineSpacing(), Qt::AlignCenter,
161 footers[ b ] );
162 p.drawText( b * barWidth + 3, h - fm.lineSpacing() - 2,
163 barWidth - 2 * 3, fm.lineSpacing(), Qt::AlignCenter,
164 KSysGuard::Formatter::formatValue( samples[b], KSysGuard::UnitNone ) );
165 }
166 }
167 }
168
169 p.end();
170 }
171
172
173