Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / ksysguard / gui / SensorDisplayLib / DancingBars.cc
blob082312106a9fae5967664f680bd3ccda6bf00ef4
1 /*
2 KSysGuard, the KDE System Guard
4 Copyright (c) 1999, 2000, 2001 Chris Schlaeger <cs@kde.org>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public
8 License version 2 or at your option version 3 as published by
9 the Free Software Foundation.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include <QCheckBox>
23 #include <QtXml/qdom.h>
24 #include <QLineEdit>
25 #include <QPushButton>
26 #include <QSpinBox>
27 #include <QHBoxLayout>
29 #include <kdebug.h>
30 #include <klocale.h>
31 #include <knumvalidator.h>
32 #include <ksgrd/SensorManager.h>
33 #include "StyleEngine.h"
35 #include "BarGraph.h"
36 #include "DancingBarsSettings.h"
38 #include "DancingBars.h"
40 DancingBars::DancingBars( QWidget *parent, const QString &title, SharedSettings *workSheetSettings)
41 : KSGRD::SensorDisplay( parent, title, workSheetSettings)
43 mBars = 0;
44 mFlags = QBitArray( 100 );
45 mFlags.fill( false );
47 QLayout *layout = new QHBoxLayout(this);
48 mPlotter = new BarGraph( this );
49 layout->addWidget(mPlotter);
51 setMinimumSize( sizeHint() );
53 /* All RMB clicks to the mPlotter widget will be handled by
54 * SensorDisplay::eventFilter. */
55 mPlotter->installEventFilter( this );
57 setPlotterWidget( mPlotter );
61 DancingBars::~DancingBars()
65 void DancingBars::configureSettings()
67 DancingBarsSettings dlg( this );
69 dlg.setTitle( title() );
70 dlg.setMinValue( mPlotter->getMin() );
71 dlg.setMaxValue( mPlotter->getMax() );
73 double l, u;
74 bool la, ua;
75 mPlotter->getLimits( l, la, u, ua );
77 dlg.setUseUpperLimit( ua );
78 dlg.setUpperLimit( u );
80 dlg.setUseLowerLimit( la );
81 dlg.setLowerLimit( l );
83 dlg.setForegroundColor( mPlotter->normalColor );
84 dlg.setAlarmColor( mPlotter->alarmColor );
85 dlg.setBackgroundColor( mPlotter->mBackgroundColor );
86 dlg.setFontSize( mPlotter->fontSize );
88 SensorModelEntry::List list;
89 for ( uint i = mBars - 1; i < mBars; i-- ) {
90 SensorModelEntry entry;
91 entry.setId( i );
92 entry.setHostName( sensors().at( i )->hostName() );
93 entry.setSensorName( KSGRD::SensorMgr->translateSensor( sensors().at( i )->name() ) );
94 entry.setLabel( mPlotter->footers[ i ] );
95 entry.setUnit( KSGRD::SensorMgr->translateUnit( sensors().at( i )->unit() ) );
96 entry.setStatus( sensors().at( i )->isOk() ? i18n( "OK" ) : i18n( "Error" ) );
98 list.append( entry );
100 dlg.setSensors( list );
102 if ( !dlg.exec() )
103 return;
105 setTitle( dlg.title() );
106 mPlotter->changeRange( dlg.minValue(), dlg.maxValue() );
107 mPlotter->setLimits( dlg.useLowerLimit() ?
108 dlg.lowerLimit() : 0,
109 dlg.useLowerLimit(),
110 dlg.useUpperLimit() ?
111 dlg.upperLimit() : 0,
112 dlg.useUpperLimit() );
114 mPlotter->normalColor = dlg.foregroundColor();
115 mPlotter->alarmColor = dlg.alarmColor();
116 mPlotter->mBackgroundColor = dlg.backgroundColor();
117 mPlotter->fontSize = dlg.fontSize();
119 uint delCount = 0;
121 list = dlg.sensors();
123 for ( int i = 0; i < sensors().count(); ++i ) {
124 bool found = false;
125 for ( int j = 0; j < list.count(); ++j ) {
126 if ( list[ j ].id() == (int)( i + delCount ) ) {
127 mPlotter->footers[ i ] = list[ j ].label();
128 found = true;
129 if ( delCount > 0 )
130 list[ j ].setId( i );
132 continue;
136 if ( !found ) {
137 if ( removeSensor(i) ) {
138 i--;
139 delCount++;
144 repaint();
147 void DancingBars::applyStyle()
149 mPlotter->normalColor = KSGRD::Style->firstForegroundColor();
150 mPlotter->alarmColor = KSGRD::Style->alarmColor();
151 mPlotter->mBackgroundColor = KSGRD::Style->backgroundColor();
152 mPlotter->fontSize = KSGRD::Style->fontSize();
154 repaint();
157 bool DancingBars::addSensor( const QString &hostName, const QString &name,
158 const QString &type, const QString &title )
160 if ( type != "integer" && type != "float" )
161 return false;
163 if ( mBars >= 32 )
164 return false;
166 if ( !mPlotter->addBar( title ) )
167 return false;
169 registerSensor( new KSGRD::SensorProperties( hostName, name, type, title ) );
171 /* To differentiate between answers from value requests and info
172 * requests we add 100 to the beam index for info requests. */
173 sendRequest( hostName, name + '?', mBars + 100 );
174 ++mBars;
175 mSampleBuffer.resize( mBars );
177 QString tooltip;
178 for ( uint i = 0; i < mBars; ++i ) {
179 tooltip += QString( "%1%2:%3" ).arg( i != 0 ? "\n" : "" )
180 .arg( sensors().at( i )->hostName() )
181 .arg( sensors().at( i )->name() );
183 mPlotter->setToolTip( tooltip );
185 return true;
188 bool DancingBars::removeSensor( uint pos )
190 if ( pos >= mBars ) {
191 kDebug(1215) << "DancingBars::removeSensor: idx out of range ("
192 << pos << ")" << endl;
193 return false;
196 mPlotter->removeBar( pos );
197 mBars--;
198 KSGRD::SensorDisplay::removeSensor( pos );
200 QString tooltip;
201 for ( uint i = 0; i < mBars; ++i ) {
202 tooltip += QString( "%1%2:%3" ).arg( i != 0 ? "\n" : "" )
203 .arg( sensors().at( i )->hostName() )
204 .arg( sensors().at( i )->name() );
206 mPlotter->setToolTip( tooltip );
208 return true;
211 void DancingBars::updateSamples( const QVector<double> &samples )
213 mPlotter->updateSamples( samples );
216 void DancingBars::answerReceived( int id, const QList<QByteArray> &answerlist )
218 /* We received something, so the sensor is probably ok. */
219 sensorError( id, false );
220 QByteArray answer;
221 if(!answerlist.isEmpty()) answer = answerlist[0];
222 if ( id < 100 ) {
223 if(id >= mSampleBuffer.count()) {
224 kDebug(1215) << "ERROR: DancingBars received invalid data";
225 sensorError(id, true);
226 return;
228 mSampleBuffer[ id ] = answer.toDouble();
229 if ( mFlags.testBit( id ) == true ) {
230 kDebug(1215) << "ERROR: DancingBars lost sample (" << mFlags
231 << ", " << mBars << ")" << endl;
232 sensorError( id, true );
233 return;
235 mFlags.setBit( id, true );
237 bool allBitsAvailable = true;
238 for ( uint i = 0; i < mBars; ++i )
239 allBitsAvailable &= mFlags.testBit( i );
241 if ( allBitsAvailable ) {
242 mPlotter->updateSamples( mSampleBuffer );
243 mFlags.fill( false );
245 } else if ( id >= 100 ) {
246 KSGRD::SensorIntegerInfo info( answer );
247 if ( id == 100 )
248 if ( mPlotter->getMin() == 0.0 && mPlotter->getMax() == 0.0 ) {
249 /* We only use this information from the sensor when the
250 * display is still using the default values. If the
251 * sensor has been restored we don't touch the already set
252 * values. */
253 mPlotter->changeRange( info.min(), info.max() );
256 sensors().at( id - 100 )->setUnit( info.unit() );
260 bool DancingBars::restoreSettings( QDomElement &element )
262 SensorDisplay::restoreSettings( element );
264 mPlotter->changeRange( element.attribute( "min", "0" ).toDouble(),
265 element.attribute( "max", "0" ).toDouble() );
267 mPlotter->setLimits( element.attribute( "lowlimit", "0" ).toDouble(),
268 element.attribute( "lowlimitactive", "0" ).toInt(),
269 element.attribute( "uplimit", "0" ).toDouble(),
270 element.attribute( "uplimitactive", "0" ).toInt() );
272 mPlotter->normalColor = restoreColor( element, "normalColor",
273 KSGRD::Style->firstForegroundColor() );
274 mPlotter->alarmColor = restoreColor( element, "alarmColor",
275 KSGRD::Style->alarmColor() );
276 mPlotter->mBackgroundColor = restoreColor( element, "backgroundColor",
277 KSGRD::Style->backgroundColor() );
278 mPlotter->fontSize = element.attribute( "fontSize", QString( "%1" ).arg(
279 KSGRD::Style->fontSize() ) ).toInt();
281 QDomNodeList dnList = element.elementsByTagName( "beam" );
282 for ( int i = 0; i < dnList.count(); ++i ) {
283 QDomElement el = dnList.item( i ).toElement();
284 addSensor( el.attribute( "hostName" ), el.attribute( "sensorName" ),
285 ( el.attribute( "sensorType" ).isEmpty() ? "integer" :
286 el.attribute( "sensorType" ) ), el.attribute( "sensorDescr" ) );
290 return true;
293 bool DancingBars::saveSettings( QDomDocument &doc, QDomElement &element)
295 element.setAttribute( "min", mPlotter->getMin() );
296 element.setAttribute( "max", mPlotter->getMax() );
297 double l, u;
298 bool la, ua;
299 mPlotter->getLimits( l, la, u, ua );
300 element.setAttribute( "lowlimit", l );
301 element.setAttribute( "lowlimitactive", la );
302 element.setAttribute( "uplimit", u );
303 element.setAttribute( "uplimitactive", ua );
305 saveColor( element, "normalColor", mPlotter->normalColor );
306 saveColor( element, "alarmColor", mPlotter->alarmColor );
307 saveColor( element, "backgroundColor", mPlotter->mBackgroundColor );
308 element.setAttribute( "fontSize", mPlotter->fontSize );
310 for ( uint i = 0; i < mBars; ++i ) {
311 QDomElement beam = doc.createElement( "beam" );
312 element.appendChild( beam );
313 beam.setAttribute( "hostName", sensors().at( i )->hostName() );
314 beam.setAttribute( "sensorName", sensors().at( i )->name() );
315 beam.setAttribute( "sensorType", sensors().at( i )->type() );
316 beam.setAttribute( "sensorDescr", mPlotter->footers[ i ] );
319 SensorDisplay::saveSettings( doc, element );
321 return true;
324 bool DancingBars::hasSettingsDialog() const
326 return true;
329 #include "DancingBars.moc"