summaryrefslogtreecommitdiffstats
path: root/ksysguard/gui/SensorDisplayLib
diff options
context:
space:
mode:
Diffstat (limited to 'ksysguard/gui/SensorDisplayLib')
-rw-r--r--ksysguard/gui/SensorDisplayLib/BarGraph.cc177
-rw-r--r--ksysguard/gui/SensorDisplayLib/BarGraph.h94
-rw-r--r--ksysguard/gui/SensorDisplayLib/DancingBars.cc353
-rw-r--r--ksysguard/gui/SensorDisplayLib/DancingBars.h90
-rw-r--r--ksysguard/gui/SensorDisplayLib/DancingBarsSettings.cc398
-rw-r--r--ksysguard/gui/SensorDisplayLib/DancingBarsSettings.h106
-rw-r--r--ksysguard/gui/SensorDisplayLib/DummyDisplay.cc58
-rw-r--r--ksysguard/gui/SensorDisplayLib/DummyDisplay.h44
-rw-r--r--ksysguard/gui/SensorDisplayLib/FancyPlotter.cc457
-rw-r--r--ksysguard/gui/SensorDisplayLib/FancyPlotter.h103
-rw-r--r--ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.cc637
-rw-r--r--ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.h143
-rw-r--r--ksysguard/gui/SensorDisplayLib/ListView.cc371
-rw-r--r--ksysguard/gui/SensorDisplayLib/ListView.h112
-rw-r--r--ksysguard/gui/SensorDisplayLib/ListViewSettings.cc77
-rw-r--r--ksysguard/gui/SensorDisplayLib/ListViewSettings.h57
-rw-r--r--ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui178
-rw-r--r--ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui.h56
-rw-r--r--ksysguard/gui/SensorDisplayLib/LogFile.cc285
-rw-r--r--ksysguard/gui/SensorDisplayLib/LogFile.h85
-rw-r--r--ksysguard/gui/SensorDisplayLib/LogFileSettings.ui345
-rw-r--r--ksysguard/gui/SensorDisplayLib/Makefile.am39
-rw-r--r--ksysguard/gui/SensorDisplayLib/MultiMeter.cc258
-rw-r--r--ksysguard/gui/SensorDisplayLib/MultiMeter.h79
-rw-r--r--ksysguard/gui/SensorDisplayLib/MultiMeterSettings.cc127
-rw-r--r--ksysguard/gui/SensorDisplayLib/MultiMeterSettings.h68
-rw-r--r--ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui475
-rw-r--r--ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui.h123
-rw-r--r--ksysguard/gui/SensorDisplayLib/ProcessController.cc472
-rw-r--r--ksysguard/gui/SensorDisplayLib/ProcessController.h154
-rw-r--r--ksysguard/gui/SensorDisplayLib/ProcessList.cc941
-rw-r--r--ksysguard/gui/SensorDisplayLib/ProcessList.h270
-rw-r--r--ksysguard/gui/SensorDisplayLib/ReniceDlg.cc66
-rw-r--r--ksysguard/gui/SensorDisplayLib/ReniceDlg.h61
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorDisplay.cc611
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorDisplay.h331
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLogger.cc437
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLogger.h184
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.cc106
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.h62
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui263
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui.h89
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.cc77
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.h57
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui180
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui.h56
-rw-r--r--ksysguard/gui/SensorDisplayLib/SignalPlotter.cc648
-rw-r--r--ksysguard/gui/SensorDisplayLib/SignalPlotter.h147
48 files changed, 10607 insertions, 0 deletions
diff --git a/ksysguard/gui/SensorDisplayLib/BarGraph.cc b/ksysguard/gui/SensorDisplayLib/BarGraph.cc
new file mode 100644
index 000000000..f6dc741cb
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/BarGraph.cc
@@ -0,0 +1,177 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <assert.h>
+#include <string.h>
+
+#include <qpainter.h>
+
+#include <kdebug.h>
+#include <kiconloader.h>
+
+#include <ksgrd/StyleEngine.h>
+
+#include "BarGraph.h"
+
+BarGraph::BarGraph( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ // paintEvent covers whole widget so we use no background to avoid flicker
+ setBackgroundMode( NoBackground );
+
+ bars = 0;
+ minValue = 0.0;
+ maxValue = 100.0;
+ lowerLimit = upperLimit = 0.0;
+ lowerLimitActive = upperLimitActive = false;
+
+ normalColor = KSGRD::Style->firstForegroundColor();
+ alarmColor = KSGRD::Style->alarmColor();
+ backgroundColor = KSGRD::Style->backgroundColor();
+ fontSize = KSGRD::Style->fontSize();
+
+ // Anything smaller than this does not make sense.
+ setMinimumSize( 16, 16 );
+ setSizePolicy( QSizePolicy( QSizePolicy::Expanding,
+ QSizePolicy::Expanding, false ) );
+}
+
+BarGraph::~BarGraph()
+{
+}
+
+bool BarGraph::addBar( const QString &footer )
+{
+ samples.resize( bars + 1 );
+ samples[ bars++ ] = 0.0;
+ footers.append( footer );
+
+ return true;
+}
+
+bool BarGraph::removeBar( uint idx )
+{
+ if ( idx >= bars ) {
+ kdDebug(1215) << "BarGraph::removeBar: idx " << idx << " out of range "
+ << bars << endl;
+ return false;
+ }
+
+ samples.resize( --bars );
+ footers.remove( footers.at( idx ) );
+ update();
+
+ return true;
+}
+
+void BarGraph::updateSamples( const QMemArray<double> &newSamples )
+{
+ samples = newSamples;
+ update();
+}
+
+void BarGraph::changeRange( double min, double max )
+{
+ minValue = min;
+ maxValue = max;
+}
+
+void BarGraph::paintEvent( QPaintEvent* )
+{
+ int w = width();
+ int h = height();
+
+ QPixmap pm( w, h );
+ QPainter p;
+ p.begin( &pm, this );
+ p.setFont( QFont( p.font().family(), fontSize ) );
+ QFontMetrics fm( p.font() );
+
+ pm.fill( backgroundColor );
+
+ /* Draw white line along the bottom and the right side of the
+ * widget to create a 3D like look. */
+ p.setPen( QColor( colorGroup().light() ) );
+ p.drawLine( 0, h - 1, w - 1, h - 1 );
+ p.drawLine( w - 1, 0, w - 1, h - 1 );
+
+ p.setClipRect( 1, 1, w - 2, h - 2 );
+
+ if ( bars > 0 ) {
+ int barWidth = ( w - 2 ) / bars;
+ uint b;
+ /* Labels are only printed underneath the bars if the labels
+ * for all bars are smaller than the bar width. If a single
+ * label does not fit no label is shown. */
+ bool showLabels = true;
+ for ( b = 0; b < bars; b++ )
+ if ( fm.width( footers[ b ] ) > barWidth )
+ showLabels = false;
+
+ int barHeight;
+ if ( showLabels )
+ barHeight = h - 2 - ( 2 * fm.lineSpacing() ) - 2;
+ else
+ barHeight = h - 2;
+
+ for ( uint b = 0; b < bars; b++ ) {
+ int topVal = (int) ( (float)barHeight / maxValue *
+ ( samples[ b ] - minValue ) );
+ /* TODO: This widget does not handle negative values properly. */
+ if ( topVal < 0 )
+ topVal = 0;
+
+ for ( int i = 0; i < barHeight && i < topVal; i += 2 ) {
+ if ( ( upperLimitActive && samples[ b ] > upperLimit ) ||
+ ( lowerLimitActive && samples[ b ] < lowerLimit ) )
+ p.setPen( alarmColor.light( static_cast<int>( 30 + ( 70.0 /
+ ( barHeight + 1 ) * i ) ) ) );
+ else
+ p.setPen( normalColor.light( static_cast<int>( 30 + ( 70.0 /
+ ( barHeight + 1 ) * i ) ) ) );
+ p.drawLine( b * barWidth + 3, barHeight - i, ( b + 1 ) * barWidth - 3,
+ barHeight - i );
+ }
+
+ if ( ( upperLimitActive && samples[ b ] > upperLimit ) ||
+ ( lowerLimitActive && samples[ b ] < lowerLimit ) )
+ p.setPen( alarmColor );
+ else
+ p.setPen( normalColor );
+
+ if ( showLabels ) {
+ p.drawText( b * barWidth + 3, h - ( 2 * fm.lineSpacing() ) - 2,
+ barWidth - 2 * 3, fm.lineSpacing(), Qt::AlignCenter,
+ footers[ b ] );
+ p.drawText( b * barWidth + 3, h - fm.lineSpacing() - 2,
+ barWidth - 2 * 3, fm.lineSpacing(), Qt::AlignCenter,
+ QString( "%1" ).arg( samples[ b ] ) );
+ }
+ }
+ }
+
+ p.end();
+ bitBlt( this, 0, 0, &pm );
+}
+
+#include "BarGraph.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/BarGraph.h b/ksysguard/gui/SensorDisplayLib/BarGraph.h
new file mode 100644
index 000000000..aca20c629
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/BarGraph.h
@@ -0,0 +1,94 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_BARGRAPH_H
+#define KSG_BARGRAPH_H
+
+#include <qmemarray.h>
+#include <qptrvector.h>
+#include <qwidget.h>
+
+class BarGraph : public QWidget
+{
+ Q_OBJECT
+
+ friend class DancingBars;
+
+ public:
+ BarGraph( QWidget *parent, const char *name = 0 );
+ ~BarGraph();
+
+ bool addBar( const QString &footer );
+ bool removeBar( uint idx );
+
+ void updateSamples( const QMemArray<double> &newSamples );
+
+ double getMin() const
+ {
+ return minValue;
+ }
+
+ double getMax() const
+ {
+ return maxValue;
+ }
+
+ void getLimits( double &l, bool &la, double &u, bool &ua ) const
+ {
+ l = lowerLimit;
+ la = lowerLimitActive;
+ u = upperLimit;
+ ua = upperLimitActive;
+ }
+
+ void setLimits( double l, bool la, double u, bool ua )
+ {
+ lowerLimit = l;
+ lowerLimitActive = la;
+ upperLimit = u;
+ upperLimitActive = ua;
+ }
+
+ void changeRange( double min, double max );
+
+ protected:
+ virtual void paintEvent( QPaintEvent* );
+
+ private:
+ double minValue;
+ double maxValue;
+ double lowerLimit;
+ double lowerLimitActive;
+ double upperLimit;
+ bool upperLimitActive;
+ bool autoRange;
+ QMemArray<double> samples;
+ QStringList footers;
+ uint bars;
+ QColor normalColor;
+ QColor alarmColor;
+ QColor backgroundColor;
+ int fontSize;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/DancingBars.cc b/ksysguard/gui/SensorDisplayLib/DancingBars.cc
new file mode 100644
index 000000000..48c360713
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/DancingBars.cc
@@ -0,0 +1,353 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000, 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <qcheckbox.h>
+#include <qdom.h>
+#include <qlineedit.h>
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qspinbox.h>
+#include <qtooltip.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <knumvalidator.h>
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+
+#include "BarGraph.h"
+#include "DancingBarsSettings.h"
+
+#include "DancingBars.h"
+
+DancingBars::DancingBars( QWidget *parent, const char *name, const QString &title,
+ int, int, bool noFrame_, bool isApplet )
+ : KSGRD::SensorDisplay( parent, name, title, noFrame_, isApplet )
+{
+ mBars = 0;
+ mFlags = QBitArray(100);
+ mFlags.fill( false );
+
+ if ( noFrame() )
+ mPlotter = new BarGraph( this );
+ else
+ mPlotter = new BarGraph( frame() );
+
+ setMinimumSize( sizeHint() );
+
+ /* All RMB clicks to the mPlotter widget will be handled by
+ * SensorDisplay::eventFilter. */
+ mPlotter->installEventFilter( this );
+
+ setPlotterWidget( mPlotter );
+
+ setModified( false );
+}
+
+DancingBars::~DancingBars()
+{
+}
+
+void DancingBars::configureSettings()
+{
+ mSettingsDialog = new DancingBarsSettings( this );
+
+ mSettingsDialog->setTitle( title() );
+ mSettingsDialog->setMinValue( mPlotter->getMin() );
+ mSettingsDialog->setMaxValue( mPlotter->getMax() );
+
+ double l, u;
+ bool la, ua;
+ mPlotter->getLimits( l, la, u, ua );
+
+ mSettingsDialog->setUseUpperLimit( ua );
+ mSettingsDialog->setUpperLimit( u );
+
+ mSettingsDialog->setUseLowerLimit( la );
+ mSettingsDialog->setLowerLimit( l );
+
+ mSettingsDialog->setForegroundColor( mPlotter->normalColor );
+ mSettingsDialog->setAlarmColor( mPlotter->alarmColor );
+ mSettingsDialog->setBackgroundColor( mPlotter->backgroundColor );
+ mSettingsDialog->setFontSize( mPlotter->fontSize );
+
+ QValueList< QStringList > list;
+ for ( uint i = mBars - 1; i < mBars; i-- ) {
+ QStringList entry;
+ entry << sensors().at( i )->hostName();
+ entry << KSGRD::SensorMgr->translateSensor( sensors().at( i )->name() );
+ entry << mPlotter->footers[ i ];
+ entry << KSGRD::SensorMgr->translateUnit( sensors().at( i )->unit() );
+ entry << ( sensors().at( i )->isOk() ? i18n( "OK" ) : i18n( "Error" ) );
+
+ list.append( entry );
+ }
+ mSettingsDialog->setSensors( list );
+
+ connect( mSettingsDialog, SIGNAL( applyClicked() ), SLOT( applySettings() ) );
+
+ if ( mSettingsDialog->exec() )
+ applySettings();
+
+ delete mSettingsDialog;
+ mSettingsDialog = 0;
+}
+
+void DancingBars::applySettings()
+{
+ setTitle( mSettingsDialog->title() );
+ mPlotter->changeRange( mSettingsDialog->minValue(), mSettingsDialog->maxValue() );
+ mPlotter->setLimits( mSettingsDialog->useLowerLimit() ?
+ mSettingsDialog->lowerLimit() : 0,
+ mSettingsDialog->useLowerLimit(),
+ mSettingsDialog->useUpperLimit() ?
+ mSettingsDialog->upperLimit() : 0,
+ mSettingsDialog->useUpperLimit() );
+
+ mPlotter->normalColor = mSettingsDialog->foregroundColor();
+ mPlotter->alarmColor = mSettingsDialog->alarmColor();
+ mPlotter->backgroundColor = mSettingsDialog->backgroundColor();
+ mPlotter->fontSize = mSettingsDialog->fontSize();
+
+ QValueList< QStringList > list = mSettingsDialog->sensors();
+ QValueList< QStringList >::Iterator it;
+
+ for ( uint i = 0; i < sensors().count(); i++ ) {
+ bool found = false;
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ if ( (*it)[ 0 ] == sensors().at( i )->hostName() &&
+ (*it)[ 1 ] == KSGRD::SensorMgr->translateSensor( sensors().at( i )->name() ) ) {
+ mPlotter->footers[ i ] = (*it)[ 2 ];
+ found = true;
+ break;
+ }
+ }
+
+ if ( !found )
+ removeSensor( i );
+ }
+
+ repaint();
+ setModified( true );
+}
+
+void DancingBars::applyStyle()
+{
+ mPlotter->normalColor = KSGRD::Style->firstForegroundColor();
+ mPlotter->alarmColor = KSGRD::Style->alarmColor();
+ mPlotter->backgroundColor = KSGRD::Style->backgroundColor();
+ mPlotter->fontSize = KSGRD::Style->fontSize();
+
+ repaint();
+ setModified( true );
+}
+
+bool DancingBars::addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &title )
+{
+ if ( type != "integer" && type != "float" )
+ return false;
+
+ if ( mBars >= 32 )
+ return false;
+
+ if ( !mPlotter->addBar( title ) )
+ return false;
+
+ registerSensor( new KSGRD::SensorProperties( hostName, name, type, title ) );
+
+ /* To differentiate between answers from value requests and info
+ * requests we add 100 to the beam index for info requests. */
+ sendRequest( hostName, name + "?", mBars + 100 );
+ ++mBars;
+ mSampleBuffer.resize( mBars );
+
+ QString tooltip;
+ for ( uint i = 0; i < mBars; ++i ) {
+ tooltip += QString( "%1%2:%3" ).arg( i != 0 ? "\n" : "" )
+ .arg( sensors().at( i )->hostName() )
+ .arg( sensors().at( i )->name() );
+ }
+ QToolTip::remove( mPlotter );
+ QToolTip::add( mPlotter, tooltip );
+
+ return true;
+}
+
+bool DancingBars::removeSensor( uint pos )
+{
+ if ( pos >= mBars ) {
+ kdDebug(1215) << "DancingBars::removeSensor: idx out of range ("
+ << pos << ")" << endl;
+ return false;
+ }
+
+ mPlotter->removeBar( pos );
+ mBars--;
+ KSGRD::SensorDisplay::removeSensor( pos );
+
+ QString tooltip;
+ for ( uint i = 0; i < mBars; ++i ) {
+ tooltip += QString( "%1%2:%3" ).arg( i != 0 ? "\n" : "" )
+ .arg( sensors().at( i )->hostName() )
+ .arg( sensors().at( i )->name() );
+ }
+ QToolTip::remove( mPlotter );
+ QToolTip::add( mPlotter, tooltip );
+
+ return true;
+}
+
+void DancingBars::updateSamples( const QMemArray<double> &samples )
+{
+ mPlotter->updateSamples( samples );
+}
+
+void DancingBars::resizeEvent( QResizeEvent* )
+{
+ if ( noFrame() )
+ mPlotter->setGeometry( 0, 0, width(), height() );
+ else
+ frame()->setGeometry( 0, 0, width(), height() );
+}
+
+QSize DancingBars::sizeHint()
+{
+ if ( noFrame() )
+ return ( mPlotter->sizeHint() );
+ else
+ return ( frame()->sizeHint() );
+}
+
+void DancingBars::answerReceived( int id, const QString &answer )
+{
+ /* We received something, so the sensor is probably ok. */
+ sensorError( id, false );
+
+ if ( id < 100 ) {
+ mSampleBuffer[ id ] = answer.toDouble();
+ if ( mFlags.testBit( id ) == true ) {
+ kdDebug(1215) << "ERROR: DancingBars lost sample (" << mFlags
+ << ", " << mBars << ")" << endl;
+ sensorError( id, true );
+ }
+ mFlags.setBit( id, true );
+
+ bool allBitsAvailable = true;
+ for ( uint i = 0; i < mBars; ++i )
+ allBitsAvailable &= mFlags.testBit( i );
+
+ if ( allBitsAvailable ) {
+ mPlotter->updateSamples( mSampleBuffer );
+ mFlags.fill( false );
+ }
+ } else if ( id >= 100 ) {
+ KSGRD::SensorIntegerInfo info( answer );
+ if ( id == 100 )
+ if ( mPlotter->getMin() == 0.0 && mPlotter->getMax() == 0.0 ) {
+ /* We only use this information from the sensor when the
+ * display is still using the default values. If the
+ * sensor has been restored we don't touch the already set
+ * values. */
+ mPlotter->changeRange( info.min(), info.max() );
+ }
+
+ sensors().at( id - 100 )->setUnit( info.unit() );
+ }
+}
+
+bool DancingBars::restoreSettings( QDomElement &element )
+{
+ SensorDisplay::restoreSettings( element );
+
+ mPlotter->changeRange( element.attribute( "min", "0" ).toDouble(),
+ element.attribute( "max", "0" ).toDouble() );
+
+ mPlotter->setLimits( element.attribute( "lowlimit", "0" ).toDouble(),
+ element.attribute( "lowlimitactive", "0" ).toInt(),
+ element.attribute( "uplimit", "0" ).toDouble(),
+ element.attribute( "uplimitactive", "0" ).toInt() );
+
+ mPlotter->normalColor = restoreColor( element, "normalColor",
+ KSGRD::Style->firstForegroundColor() );
+ mPlotter->alarmColor = restoreColor( element, "alarmColor",
+ KSGRD::Style->alarmColor() );
+ mPlotter->backgroundColor = restoreColor( element, "backgroundColor",
+ KSGRD::Style->backgroundColor() );
+ mPlotter->fontSize = element.attribute( "fontSize", QString( "%1" ).arg(
+ KSGRD::Style->fontSize() ) ).toInt();
+
+ QDomNodeList dnList = element.elementsByTagName( "beam" );
+ for ( uint i = 0; i < dnList.count(); ++i ) {
+ QDomElement el = dnList.item( i ).toElement();
+ addSensor( el.attribute( "hostName" ), el.attribute( "sensorName" ),
+ ( el.attribute( "sensorType" ).isEmpty() ? "integer" :
+ el.attribute( "sensorType" ) ), el.attribute( "sensorDescr" ) );
+ }
+
+ setModified( false );
+
+ return true;
+}
+
+bool DancingBars::saveSettings( QDomDocument &doc, QDomElement &element,
+ bool save )
+{
+ element.setAttribute( "min", mPlotter->getMin() );
+ element.setAttribute( "max", mPlotter->getMax() );
+ double l, u;
+ bool la, ua;
+ mPlotter->getLimits( l, la, u, ua );
+ element.setAttribute( "lowlimit", l );
+ element.setAttribute( "lowlimitactive", la );
+ element.setAttribute( "uplimit", u );
+ element.setAttribute( "uplimitactive", ua );
+
+ saveColor( element, "normalColor", mPlotter->normalColor );
+ saveColor( element, "alarmColor", mPlotter->alarmColor );
+ saveColor( element, "backgroundColor", mPlotter->backgroundColor );
+ element.setAttribute( "fontSize", mPlotter->fontSize );
+
+ for ( uint i = 0; i < mBars; ++i ) {
+ QDomElement beam = doc.createElement( "beam" );
+ element.appendChild( beam );
+ beam.setAttribute( "hostName", sensors().at( i )->hostName() );
+ beam.setAttribute( "sensorName", sensors().at( i )->name() );
+ beam.setAttribute( "sensorType", sensors().at( i )->type() );
+ beam.setAttribute( "sensorDescr", mPlotter->footers[ i ] );
+ }
+
+ SensorDisplay::saveSettings( doc, element );
+
+ if ( save )
+ setModified( false );
+
+ return true;
+}
+
+bool DancingBars::hasSettingsDialog() const
+{
+ return true;
+}
+
+#include "DancingBars.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/DancingBars.h b/ksysguard/gui/SensorDisplayLib/DancingBars.h
new file mode 100644
index 000000000..ad671dfe7
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/DancingBars.h
@@ -0,0 +1,90 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_DANCINGBARS_H
+#define KSG_DANCINGBARS_H
+
+#include <SensorDisplay.h>
+#include <qbitarray.h>
+
+class KIntNumInput;
+
+class QGroupBox;
+class QLineEdit;
+class QListViewItem;
+
+class BarGraph;
+class DancingBarsSettings;
+
+class DancingBars : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+
+ public:
+ DancingBars( QWidget *parent = 0, const char *name = 0,
+ const QString &title = QString::null, int min = 0,
+ int max = 100, bool noFrame = false, bool isApplet = false );
+ virtual ~DancingBars();
+
+ void configureSettings();
+
+ bool addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &title );
+ bool removeSensor( uint pos );
+
+ void updateSamples( const QMemArray<double> &samples );
+
+ virtual QSize sizeHint();
+
+ virtual void answerReceived( int id, const QString &answer );
+
+ bool restoreSettings( QDomElement& );
+ bool saveSettings( QDomDocument&, QDomElement&, bool save = true );
+
+ virtual bool hasSettingsDialog() const;
+
+ public slots:
+ void applySettings();
+ virtual void applyStyle();
+
+ protected:
+ virtual void resizeEvent( QResizeEvent* );
+
+ private:
+ uint mBars;
+
+ BarGraph* mPlotter;
+
+ DancingBarsSettings* mSettingsDialog;
+
+ /**
+ The sample buffer and the flags are needed to store the incoming
+ samples for each beam until all samples of the period have been
+ received. The flags variable is used to ensure that all samples have
+ been received.
+ */
+ QMemArray<double> mSampleBuffer;
+ QBitArray mFlags;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/DancingBarsSettings.cc b/ksysguard/gui/SensorDisplayLib/DancingBarsSettings.cc
new file mode 100644
index 000000000..15e6b6ec3
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/DancingBarsSettings.cc
@@ -0,0 +1,398 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <kaccelmanager.h>
+#include <kcolorbutton.h>
+#include <klineedit.h>
+#include <kinputdialog.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include <qcheckbox.h>
+#include <qframe.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qwhatsthis.h>
+
+#include "DancingBarsSettings.h"
+
+DancingBarsSettings::DancingBarsSettings( QWidget* parent, const char* name )
+ : KDialogBase( Tabbed, i18n( "Edit BarGraph Preferences" ),
+ Ok | Apply | Cancel, Ok, parent, name, true, true )
+{
+ // Range page
+ QFrame *page = addPage( i18n( "Range" ) );
+ QGridLayout *pageLayout = new QGridLayout( page, 3, 1, 0, spacingHint() );
+
+ QGroupBox *groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Title" ), page );
+ QGridLayout *boxLayout = new QGridLayout( groupBox->layout(), 1, 1 );
+
+ mTitle = new KLineEdit( groupBox );
+ QWhatsThis::add( mTitle, i18n( "Enter the title of the display here." ) );
+ boxLayout->addWidget( mTitle, 0, 0 );
+
+ pageLayout->addWidget( groupBox, 0, 0 );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Display Range" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 1, 5 );
+ boxLayout->setColStretch( 2, 1 );
+
+ QLabel *label = new QLabel( i18n( "Minimum value:" ), groupBox );
+ boxLayout->addWidget( label, 0, 0 );
+
+ mMinValue = new KDoubleSpinBox( 0, 100, 0.5, 0, 2, groupBox );
+ QWhatsThis::add( mMinValue, i18n( "Enter the minimum value for the display here. If both values are 0, automatic range detection is enabled." ) );
+ boxLayout->addWidget( mMinValue, 0, 1 );
+ label->setBuddy( mMinValue );
+
+ label = new QLabel( i18n( "Maximum value:" ), groupBox );
+ boxLayout->addWidget( label, 0, 3 );
+
+ mMaxValue = new KDoubleSpinBox( 0, 10000, 0.5, 100, 2, groupBox );
+ QWhatsThis::add( mMaxValue, i18n( "Enter the maximum value for the display here. If both values are 0, automatic range detection is enabled." ) );
+ boxLayout->addWidget( mMaxValue, 0, 4 );
+ label->setBuddy( mMaxValue );
+
+ pageLayout->addWidget( groupBox, 1, 0 );
+
+ pageLayout->setRowStretch( 2, 1 );
+
+ // Alarm page
+ page = addPage( i18n( "Alarms" ) );
+ pageLayout = new QGridLayout( page, 3, 1, 0, spacingHint() );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Alarm for Minimum Value" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 1, 4 );
+ boxLayout->setColStretch( 1, 1 );
+
+ mUseLowerLimit = new QCheckBox( i18n( "Enable alarm" ), groupBox );
+ QWhatsThis::add( mUseLowerLimit, i18n( "Enable the minimum value alarm." ) );
+ boxLayout->addWidget( mUseLowerLimit, 0, 0 );
+
+ label = new QLabel( i18n( "Lower limit:" ), groupBox );
+ boxLayout->addWidget( label, 0, 2 );
+
+ mLowerLimit = new KDoubleSpinBox( 0, 100, 0.5, 0, 2, groupBox );
+ mLowerLimit->setEnabled( false );
+ boxLayout->addWidget( mLowerLimit, 0, 3 );
+ label->setBuddy( mLowerLimit );
+
+ pageLayout->addWidget( groupBox, 0, 0 );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Alarm for Maximum Value" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 1, 4 );
+ boxLayout->setColStretch( 1, 1 );
+
+ mUseUpperLimit = new QCheckBox( i18n( "Enable alarm" ), groupBox );
+ QWhatsThis::add( mUseUpperLimit, i18n( "Enable the maximum value alarm." ) );
+ boxLayout->addWidget( mUseUpperLimit, 0, 0 );
+
+ label = new QLabel( i18n( "Upper limit:" ), groupBox );
+ boxLayout->addWidget( label, 0, 2 );
+
+ mUpperLimit = new KDoubleSpinBox( 0, 100, 0.5, 0, 2, groupBox );
+ mUpperLimit->setEnabled( false );
+ boxLayout->addWidget( mUpperLimit, 0, 3 );
+ label->setBuddy( mUpperLimit );
+
+ pageLayout->addWidget( groupBox, 1, 0 );
+
+ pageLayout->setRowStretch( 2, 1 );
+
+ // Look page
+ page = addPage( i18n( "Look" ) );
+ pageLayout = new QGridLayout( page, 5, 2, 0, spacingHint() );
+
+ label = new QLabel( i18n( "Normal bar color:" ), page );
+ pageLayout->addWidget( label, 0, 0 );
+
+ mForegroundColor = new KColorButton( page );
+ pageLayout->addWidget( mForegroundColor, 0, 1 );
+ label->setBuddy( mForegroundColor );
+
+ label = new QLabel( i18n( "Out-of-range color:" ), page );
+ pageLayout->addWidget( label, 1, 0 );
+
+ mAlarmColor = new KColorButton( page );
+ pageLayout->addWidget( mAlarmColor, 1, 1 );
+ label->setBuddy( mAlarmColor );
+
+ label = new QLabel( i18n( "Background color:" ), page );
+ pageLayout->addWidget( label, 2, 0 );
+
+ mBackgroundColor = new KColorButton( page );
+ pageLayout->addWidget( mBackgroundColor, 2, 1 );
+ label->setBuddy( mBackgroundColor );
+
+ label = new QLabel( i18n( "Font size:" ), page );
+ pageLayout->addWidget( label, 3, 0 );
+
+ mFontSize = new KIntNumInput( 9, page );
+ QWhatsThis::add( mFontSize, i18n( "This determines the size of the font used to print a label underneath the bars. Bars are automatically suppressed if text becomes too large, so it is advisable to use a small font size here." ) );
+ pageLayout->addWidget( mFontSize, 3, 1 );
+ label->setBuddy( mFontSize );
+
+ pageLayout->setRowStretch( 4, 1 );
+
+ // Sensor page
+ page = addPage( i18n( "Sensors" ) );
+ pageLayout = new QGridLayout( page, 3, 2, 0, spacingHint() );
+ pageLayout->setRowStretch( 2, 1 );
+
+ mSensorView = new KListView( page );
+ mSensorView->addColumn( i18n( "Host" ) );
+ mSensorView->addColumn( i18n( "Sensor" ) );
+ mSensorView->addColumn( i18n( "Label" ) );
+ mSensorView->addColumn( i18n( "Unit" ) );
+ mSensorView->addColumn( i18n( "Status" ) );
+ mSensorView->setAllColumnsShowFocus( true );
+ pageLayout->addMultiCellWidget( mSensorView, 0, 2, 0, 0 );
+
+ mEditButton = new QPushButton( i18n( "Edit..." ), page );
+ mEditButton->setEnabled( false );
+ QWhatsThis::add( mEditButton, i18n( "Push this button to configure the label." ) );
+ pageLayout->addWidget( mEditButton, 0, 1 );
+
+ mRemoveButton = new QPushButton( i18n( "Delete" ), page );
+ mRemoveButton->setEnabled( false );
+ QWhatsThis::add( mRemoveButton, i18n( "Push this button to delete the sensor." ) );
+ pageLayout->addWidget( mRemoveButton, 1, 1 );
+
+ connect( mUseLowerLimit, SIGNAL( toggled( bool ) ),
+ mLowerLimit, SLOT( setEnabled( bool ) ) );
+ connect( mUseUpperLimit, SIGNAL( toggled( bool ) ),
+ mUpperLimit, SLOT( setEnabled( bool ) ) );
+
+ connect( mSensorView, SIGNAL( selectionChanged( QListViewItem* ) ),
+ SLOT( selectionChanged( QListViewItem* ) ) );
+ connect( mEditButton, SIGNAL( clicked() ), SLOT( editSensor() ) );
+ connect( mRemoveButton, SIGNAL( clicked() ), SLOT( removeSensor() ) );
+
+ KAcceleratorManager::manage( this );
+
+ mTitle->setFocus();
+}
+
+DancingBarsSettings::~DancingBarsSettings()
+{
+}
+
+void DancingBarsSettings::setTitle( const QString& title )
+{
+ mTitle->setText( title );
+}
+
+QString DancingBarsSettings::title() const
+{
+ return mTitle->text();
+}
+
+void DancingBarsSettings::setMinValue( double min )
+{
+ mMinValue->setValue( min );
+}
+
+double DancingBarsSettings::minValue() const
+{
+ return mMinValue->value();
+}
+
+void DancingBarsSettings::setMaxValue( double max )
+{
+ mMaxValue->setValue( max );
+}
+
+double DancingBarsSettings::maxValue() const
+{
+ return mMaxValue->value();
+}
+
+void DancingBarsSettings::setUseLowerLimit( bool value )
+{
+ mUseLowerLimit->setChecked( value );
+}
+
+bool DancingBarsSettings::useLowerLimit() const
+{
+ return mUseLowerLimit->isChecked();
+}
+
+void DancingBarsSettings::setLowerLimit( double limit )
+{
+ mLowerLimit->setValue( limit );
+}
+
+double DancingBarsSettings::lowerLimit() const
+{
+ return mLowerLimit->value();
+}
+
+void DancingBarsSettings::setUseUpperLimit( bool value )
+{
+ mUseUpperLimit->setChecked( value );
+}
+
+bool DancingBarsSettings::useUpperLimit() const
+{
+ return mUseUpperLimit->isChecked();
+}
+
+void DancingBarsSettings::setUpperLimit( double limit )
+{
+ mUpperLimit->setValue( limit );
+}
+
+double DancingBarsSettings::upperLimit() const
+{
+ return mUpperLimit->value();
+}
+
+void DancingBarsSettings::setForegroundColor( const QColor &color )
+{
+ mForegroundColor->setColor( color );
+}
+
+QColor DancingBarsSettings::foregroundColor() const
+{
+ return mForegroundColor->color();
+}
+
+void DancingBarsSettings::setAlarmColor( const QColor &color )
+{
+ mAlarmColor->setColor( color );
+}
+
+QColor DancingBarsSettings::alarmColor() const
+{
+ return mAlarmColor->color();
+}
+
+void DancingBarsSettings::setBackgroundColor( const QColor &color )
+{
+ mBackgroundColor->setColor( color );
+}
+
+QColor DancingBarsSettings::backgroundColor() const
+{
+ return mBackgroundColor->color();
+}
+
+void DancingBarsSettings::setFontSize( int size )
+{
+ mFontSize->setValue( size );
+}
+
+int DancingBarsSettings::fontSize() const
+{
+ return mFontSize->value();
+}
+
+void DancingBarsSettings::setSensors( const QValueList< QStringList > &list )
+{
+ mSensorView->clear();
+
+ QValueList< QStringList >::ConstIterator it;
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ new QListViewItem( mSensorView,
+ (*it)[ 0 ], // host name
+ (*it)[ 1 ], // sensor name
+ (*it)[ 2 ], // footer title
+ (*it)[ 3 ], // unit
+ (*it)[ 4 ] ); // status
+ }
+}
+
+QValueList< QStringList > DancingBarsSettings::sensors() const
+{
+ QValueList< QStringList > list;
+
+ QListViewItemIterator it( mSensorView );
+ while ( it.current() && !it.current()->text( 0 ).isEmpty() ) {
+ QStringList entry;
+ entry << it.current()->text( 0 );
+ entry << it.current()->text( 1 );
+ entry << it.current()->text( 2 );
+ entry << it.current()->text( 3 );
+ entry << it.current()->text( 4 );
+
+ list.append( entry );
+ ++it;
+ }
+
+ return list;
+}
+
+void DancingBarsSettings::editSensor()
+{
+ QListViewItem *lvi = mSensorView->currentItem();
+
+ if ( !lvi )
+ return;
+
+ bool ok;
+ QString str = KInputDialog::getText( i18n( "Label of Bar Graph" ),
+ i18n( "Enter new label:" ), lvi->text( 2 ), &ok, this );
+ if ( ok )
+ lvi->setText( 2, str );
+}
+
+void DancingBarsSettings::removeSensor()
+{
+ QListViewItem *lvi = mSensorView->currentItem();
+
+ if ( lvi ) {
+ /* Before we delete the currently selected item, we determine a
+ * new item to be selected. That way we can ensure that multiple
+ * items can be deleted without forcing the user to select a new
+ * item between the deletes. If all items are deleted, the buttons
+ * are disabled again. */
+ QListViewItem* newSelected = 0;
+ if ( lvi->itemBelow() ) {
+ lvi->itemBelow()->setSelected( true );
+ newSelected = lvi->itemBelow();
+ } else if ( lvi->itemAbove() ) {
+ lvi->itemAbove()->setSelected( true );
+ newSelected = lvi->itemAbove();
+ } else
+ selectionChanged( 0 );
+
+ delete lvi;
+
+ if ( newSelected )
+ mSensorView->ensureItemVisible( newSelected );
+ }
+}
+
+void DancingBarsSettings::selectionChanged( QListViewItem* lvi )
+{
+ bool state = ( lvi != 0 );
+
+ mEditButton->setEnabled( state );
+ mRemoveButton->setEnabled( state );
+}
+
+
+#include "DancingBarsSettings.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/DancingBarsSettings.h b/ksysguard/gui/SensorDisplayLib/DancingBarsSettings.h
new file mode 100644
index 000000000..12e559dc0
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/DancingBarsSettings.h
@@ -0,0 +1,106 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_DANCINGBARSSETTINGS_H
+#define KSG_DANCINGBARSSETTINGS_H
+
+#include <kdialogbase.h>
+
+class KColorButton;
+class KDoubleSpinBox;
+class KIntNumInput;
+class KLineEdit;
+class KListView;
+
+class QCheckBox;
+class QListViewItem;
+class QPushButton;
+
+class DancingBarsSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ DancingBarsSettings( QWidget* parent = 0, const char* name = 0 );
+ ~DancingBarsSettings();
+
+ void setTitle( const QString& title );
+ QString title() const;
+
+ void setMinValue( double min );
+ double minValue() const;
+
+ void setMaxValue( double max );
+ double maxValue() const;
+
+ void setUseLowerLimit( bool value );
+ bool useLowerLimit() const;
+
+ void setLowerLimit( double limit );
+ double lowerLimit() const;
+
+ void setUseUpperLimit( bool value );
+ bool useUpperLimit() const;
+
+ void setUpperLimit( double limit );
+ double upperLimit() const;
+
+ void setForegroundColor( const QColor &color );
+ QColor foregroundColor() const;
+
+ void setAlarmColor( const QColor &color );
+ QColor alarmColor() const;
+
+ void setBackgroundColor( const QColor &color );
+ QColor backgroundColor() const;
+
+ void setFontSize( int size );
+ int fontSize() const;
+
+ void setSensors( const QValueList< QStringList > &list );
+ QValueList< QStringList > sensors() const;
+
+ private slots:
+ void editSensor();
+ void removeSensor();
+ void selectionChanged( QListViewItem* );
+
+ private:
+ KColorButton *mForegroundColor;
+ KColorButton *mAlarmColor;
+ KColorButton *mBackgroundColor;
+ KDoubleSpinBox *mMinValue;
+ KDoubleSpinBox *mMaxValue;
+ KDoubleSpinBox *mLowerLimit;
+ KDoubleSpinBox *mUpperLimit;
+ KLineEdit *mTitle;
+ KListView *mSensorView;
+ KIntNumInput *mFontSize;
+
+ QCheckBox *mUseLowerLimit;
+ QCheckBox *mUseUpperLimit;
+ QPushButton *mEditButton;
+ QPushButton *mRemoveButton;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/DummyDisplay.cc b/ksysguard/gui/SensorDisplayLib/DummyDisplay.cc
new file mode 100644
index 000000000..a4ea6afb4
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/DummyDisplay.cc
@@ -0,0 +1,58 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000, 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <klocale.h>
+#include <ksgrd/SensorManager.h>
+
+#include <qwhatsthis.h>
+
+#include "DummyDisplay.h"
+
+DummyDisplay::DummyDisplay( QWidget* parent, const char* name,
+ const QString&, double, double )
+ : KSGRD::SensorDisplay( parent, name, i18n( "Drop Sensor Here" ) )
+{
+ setMinimumSize( 16, 16 );
+
+ QWhatsThis::add( this, i18n(
+ "This is an empty space in a worksheet. Drag a sensor from "
+ "the Sensor Browser and drop it here. A sensor display will "
+ "appear that allows you to monitor the values of the sensor "
+ "over time." ) );
+}
+
+void DummyDisplay::resizeEvent( QResizeEvent* )
+{
+ frame()->setGeometry( 0, 0, width(), height() );
+}
+
+bool DummyDisplay::eventFilter( QObject* object, QEvent* event )
+{
+ if ( event->type() == QEvent::MouseButtonRelease &&
+ ( (QMouseEvent*)event)->button() == LeftButton )
+ setFocus();
+
+ return QWidget::eventFilter( object, event );
+}
+
+#include "DummyDisplay.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/DummyDisplay.h b/ksysguard/gui/SensorDisplayLib/DummyDisplay.h
new file mode 100644
index 000000000..53098fa0c
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/DummyDisplay.h
@@ -0,0 +1,44 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_DUMMYDISPLAY_H
+#define KSG_DUMMYDISPLAY_H
+
+#include <SensorDisplay.h>
+
+class DummyDisplay : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+
+ public:
+ DummyDisplay( QWidget* parent = 0, const char* name = 0,
+ const QString& = QString::null, double min = 0,
+ double max = 0 );
+ virtual ~DummyDisplay() {}
+
+ void resizeEvent( QResizeEvent* );
+
+ virtual bool eventFilter( QObject*, QEvent* );
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/FancyPlotter.cc b/ksysguard/gui/SensorDisplayLib/FancyPlotter.cc
new file mode 100644
index 000000000..361ce16e7
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/FancyPlotter.cc
@@ -0,0 +1,457 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2002 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <qdom.h>
+#include <qimage.h>
+#include <qtooltip.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+#include "SensorDisplay.h"
+#include "FancyPlotterSettings.h"
+
+#include "FancyPlotter.h"
+
+FancyPlotter::FancyPlotter( QWidget* parent, const char* name,
+ const QString &title, double, double,
+ bool nf, bool isApplet)
+ : KSGRD::SensorDisplay( parent, name, title, nf, isApplet )
+{
+ mBeams = 0;
+ mSettingsDialog = 0;
+
+ if ( noFrame() ) {
+ mPlotter = new SignalPlotter( this );
+ mPlotter->setShowTopBar( true );
+ } else
+ mPlotter = new SignalPlotter( frame() );
+ mPlotter->setTitle( title );
+ mPlotter->setThinFrame(!isApplet); //if we aren't an applet, draw a thin white frame on the left and bottom, for a 3d effect
+
+ setMinimumSize( sizeHint() );
+
+ /* All RMB clicks to the mPlotter widget will be handled by
+ * SensorDisplay::eventFilter. */
+ mPlotter->installEventFilter( this );
+
+ setPlotterWidget( mPlotter );
+
+ setModified( false );
+}
+
+FancyPlotter::~FancyPlotter()
+{
+}
+
+void FancyPlotter::configureSettings()
+{
+ if(mSettingsDialog) {
+ return;
+ }
+ mSettingsDialog = new FancyPlotterSettings( this );
+
+ mSettingsDialog->setTitle( title() );
+ mSettingsDialog->setUseAutoRange( mPlotter->useAutoRange() );
+ mSettingsDialog->setMinValue( mPlotter->minValue() );
+ mSettingsDialog->setMaxValue( mPlotter->maxValue() );
+
+ mSettingsDialog->setUsePolygonStyle( mPlotter->graphStyle() == GRAPH_POLYGON );
+ mSettingsDialog->setHorizontalScale( mPlotter->horizontalScale() );
+
+ mSettingsDialog->setShowVerticalLines( mPlotter->showVerticalLines() );
+ mSettingsDialog->setVerticalLinesColor( mPlotter->verticalLinesColor() );
+ mSettingsDialog->setVerticalLinesDistance( mPlotter->verticalLinesDistance() );
+ mSettingsDialog->setVerticalLinesScroll( mPlotter->verticalLinesScroll() );
+
+ mSettingsDialog->setShowHorizontalLines( mPlotter->showHorizontalLines() );
+ mSettingsDialog->setHorizontalLinesColor( mPlotter->horizontalLinesColor() );
+ mSettingsDialog->setHorizontalLinesCount( mPlotter->horizontalLinesCount() );
+
+ mSettingsDialog->setShowLabels( mPlotter->showLabels() );
+ mSettingsDialog->setShowTopBar( mPlotter->showTopBar() );
+ mSettingsDialog->setFontSize( mPlotter->fontSize() );
+
+ mSettingsDialog->setBackgroundColor( mPlotter->backgroundColor() );
+
+ QValueList< QStringList > list;
+ for ( uint i = 0; i < mBeams; ++i ) {
+ QStringList entry;
+ entry << QString::number(i);
+ entry << sensors().at( i )->hostName();
+ entry << KSGRD::SensorMgr->translateSensor( sensors().at( i )->name() );
+ entry << KSGRD::SensorMgr->translateUnit( sensors().at( i )->unit() );
+ entry << ( sensors().at( i )->isOk() ? i18n( "OK" ) : i18n( "Error" ) );
+ entry << ( mPlotter->beamColors()[ i ].name() );
+
+ list.append( entry );
+ }
+ mSettingsDialog->setSensors( list );
+
+ connect( mSettingsDialog, SIGNAL( applyClicked() ), SLOT( applySettings() ) );
+ connect( mSettingsDialog, SIGNAL( okClicked() ), SLOT( applySettings() ) );
+ connect( mSettingsDialog, SIGNAL( finished() ), SLOT( killDialog() ) );
+
+ mSettingsDialog->show();
+}
+
+void FancyPlotter::killDialog() {
+ mSettingsDialog->delayedDestruct();
+ mSettingsDialog = 0;
+}
+
+void FancyPlotter::applySettings()
+{
+ setTitle( mSettingsDialog->title() );
+ mPlotter->setTitle( title() );
+
+ if ( mSettingsDialog->useAutoRange() )
+ mPlotter->setUseAutoRange( true );
+ else {
+ mPlotter->setUseAutoRange( false );
+ mPlotter->changeRange( 0, mSettingsDialog->minValue(),
+ mSettingsDialog->maxValue() );
+ }
+
+ if ( mSettingsDialog->usePolygonStyle() )
+ mPlotter->setGraphStyle( GRAPH_POLYGON );
+ else
+ mPlotter->setGraphStyle( GRAPH_ORIGINAL );
+
+ if ( mPlotter->horizontalScale() != mSettingsDialog->horizontalScale() ) {
+ mPlotter->setHorizontalScale( mSettingsDialog->horizontalScale() );
+ // Can someone think of a useful QResizeEvent to pass?
+ // It doesn't really matter anyway because it's not used.
+ emit resizeEvent( 0 );
+ }
+
+ mPlotter->setShowVerticalLines( mSettingsDialog->showVerticalLines() );
+ mPlotter->setVerticalLinesColor( mSettingsDialog->verticalLinesColor() );
+ mPlotter->setVerticalLinesDistance( mSettingsDialog->verticalLinesDistance() );
+ mPlotter->setVerticalLinesScroll( mSettingsDialog->verticalLinesScroll() );
+
+ mPlotter->setShowHorizontalLines( mSettingsDialog->showHorizontalLines() );
+ mPlotter->setHorizontalLinesColor( mSettingsDialog->horizontalLinesColor() );
+ mPlotter->setHorizontalLinesCount( mSettingsDialog->horizontalLinesCount() );
+
+ mPlotter->setShowLabels( mSettingsDialog->showLabels() );
+ mPlotter->setShowTopBar( mSettingsDialog->showTopBar() );
+ mPlotter->setFontSize( mSettingsDialog->fontSize() );
+
+ mPlotter->setBackgroundColor( mSettingsDialog->backgroundColor() );
+
+
+ QValueList<int> orderOfSensors = mSettingsDialog->order();
+ QValueList<int> deletedSensors = mSettingsDialog->deleted();
+ mSettingsDialog->clearDeleted();
+ mSettingsDialog->resetOrder();
+ QValueList< int >::Iterator itDelete;
+ for ( itDelete = deletedSensors.begin(); itDelete != deletedSensors.end(); ++itDelete )
+ removeSensor(*itDelete);
+
+ QValueList< int >::Iterator itOrder;
+ mPlotter->reorderBeams(orderOfSensors);
+ reorderSensors(orderOfSensors);
+
+ QValueList< QStringList > list = mSettingsDialog->sensors();
+ QValueList< QStringList >::Iterator it;
+
+ for ( uint i = 0; i < sensors().count(); ++i )
+ mPlotter->beamColors()[ i ] = QColor( list[i][ 5 ] );
+
+ mPlotter->repaint();
+ setModified( true );
+}
+
+void FancyPlotter::applyStyle()
+{
+ mPlotter->setVerticalLinesColor( KSGRD::Style->firstForegroundColor() );
+ mPlotter->setHorizontalLinesColor( KSGRD::Style->secondForegroundColor() );
+ mPlotter->setBackgroundColor( KSGRD::Style->backgroundColor() );
+ mPlotter->setFontSize( KSGRD::Style->fontSize() );
+ for ( uint i = 0; i < mPlotter->beamColors().count() &&
+ i < KSGRD::Style->numSensorColors(); ++i )
+ mPlotter->beamColors()[ i ] = KSGRD::Style->sensorColor( i );
+
+ mPlotter->update();
+ setModified( true );
+}
+
+bool FancyPlotter::addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &title )
+{
+ return addSensor( hostName, name, type, title,
+ KSGRD::Style->sensorColor( mBeams ) );
+}
+
+bool FancyPlotter::addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &title,
+ const QColor &color )
+{
+ if ( type != "integer" && type != "float" )
+ return false;
+
+ if ( mBeams > 0 && hostName != sensors().at( 0 )->hostName() ) {
+ KMessageBox::sorry( this, QString( "All sensors of this display need "
+ "to be from the host %1!" )
+ .arg( sensors().at( 0 )->hostName() ) );
+
+ /* We have to enforce this since the answers to value requests
+ * need to be received in order. */
+ return false;
+ }
+
+ if ( !mPlotter->addBeam( color ) )
+ return false;
+
+ registerSensor( new FPSensorProperties( hostName, name, type, title, color ) );
+
+ /* To differentiate between answers from value requests and info
+ * requests we add 100 to the beam index for info requests. */
+ sendRequest( hostName, name + "?", mBeams + 100 );
+
+ ++mBeams;
+
+ QString tooltip;
+ for ( uint i = 0; i < mBeams; ++i ) {
+ tooltip += QString( "%1%2:%3" ).arg( i != 0 ? "\n" : "" )
+ .arg( sensors().at( mBeams - i - 1 )->hostName() )
+ .arg( sensors().at( mBeams - i - 1 )->name() );
+ }
+
+ QToolTip::remove( mPlotter );
+ QToolTip::add( mPlotter, tooltip );
+
+ return true;
+}
+
+bool FancyPlotter::removeSensor( uint pos )
+{
+ if ( pos >= mBeams ) {
+ kdDebug(1215) << "FancyPlotter::removeSensor: idx out of range ("
+ << pos << ")" << endl;
+ return false;
+ }
+
+ mPlotter->removeBeam( pos );
+ mBeams--;
+ KSGRD::SensorDisplay::removeSensor( pos );
+
+ QString tooltip;
+ for ( uint i = 0; i < mBeams; ++i ) {
+ tooltip += QString( "%1%2:%3" ).arg( i != 0 ? "\n" : "" )
+ .arg( sensors().at( mBeams - i - 1 )->hostName() )
+ .arg( sensors().at( mBeams - i - 1 )->name() );
+ }
+
+ QToolTip::remove( mPlotter );
+ QToolTip::add( mPlotter, tooltip );
+
+ return true;
+}
+
+void FancyPlotter::resizeEvent( QResizeEvent* )
+{
+ if ( noFrame() )
+ mPlotter->setGeometry( 0, 0, width(), height() );
+ else
+ frame()->setGeometry( 0, 0, width(), height() );
+}
+
+QSize FancyPlotter::sizeHint()
+{
+ if ( noFrame() )
+ return mPlotter->sizeHint();
+ else
+ return frame()->sizeHint();
+}
+
+void FancyPlotter::answerReceived( int id, const QString &answer )
+{
+ if ( (uint)id < mBeams ) {
+ if ( id != (int)mSampleBuf.count() ) {
+ if ( id == 0 )
+ sensorError( mBeams - 1, true );
+ else
+ sensorError( id - 1, true );
+ }
+ mSampleBuf.append( answer.toDouble() );
+
+ /* We received something, so the sensor is probably ok. */
+ sensorError( id, false );
+
+ if ( id == (int)mBeams - 1 ) {
+ mPlotter->addSample( mSampleBuf );
+ mSampleBuf.clear();
+ }
+ } else if ( id >= 100 ) {
+ KSGRD::SensorFloatInfo info( answer );
+ if ( !mPlotter->useAutoRange() && mPlotter->minValue() == 0.0 &&
+ mPlotter->maxValue() == 0.0 ) {
+ /* We only use this information from the sensor when the
+ * display is still using the default values. If the
+ * sensor has been restored we don't touch the already set
+ * values. */
+ mPlotter->changeRange( id - 100, info.min(), info.max() );
+ if ( info.min() == 0.0 && info.max() == 0.0 )
+ mPlotter->setUseAutoRange( true );
+ }
+ sensors().at( id - 100 )->setUnit( info.unit() );
+ }
+}
+
+bool FancyPlotter::restoreSettings( QDomElement &element )
+{
+ /* autoRage was added after KDE 2.x and was brokenly emulated by
+ * min == 0.0 and max == 0.0. Since we have to be able to read old
+ * files as well we have to emulate the old behaviour as well. */
+ double min = element.attribute( "min", "0.0" ).toDouble();
+ double max = element.attribute( "max", "0.0" ).toDouble();
+ if ( element.attribute( "autoRange", min == 0.0 && max == 0.0 ? "1" : "0" ).toInt() )
+ mPlotter->setUseAutoRange( true );
+ else {
+ mPlotter->setUseAutoRange( false );
+ mPlotter->changeRange( 0, element.attribute( "min" ).toDouble(),
+ element.attribute( "max" ).toDouble() );
+ }
+
+ mPlotter->setShowVerticalLines( element.attribute( "vLines", "1" ).toUInt() );
+ mPlotter->setVerticalLinesColor( restoreColor( element, "vColor",
+ KSGRD::Style->firstForegroundColor() ) );
+ mPlotter->setVerticalLinesDistance( element.attribute( "vDistance", "30" ).toUInt() );
+ mPlotter->setVerticalLinesScroll( element.attribute( "vScroll", "1" ).toUInt() );
+ mPlotter->setGraphStyle( element.attribute( "graphStyle", "0" ).toUInt() );
+ mPlotter->setHorizontalScale( element.attribute( "hScale", "1" ).toUInt() );
+
+ mPlotter->setShowHorizontalLines( element.attribute( "hLines", "1" ).toUInt() );
+ mPlotter->setHorizontalLinesColor( restoreColor( element, "hColor",
+ KSGRD::Style->secondForegroundColor() ) );
+ mPlotter->setHorizontalLinesCount( element.attribute( "hCount", "5" ).toUInt() );
+
+ mPlotter->setShowLabels( element.attribute( "labels", "1" ).toUInt() );
+ mPlotter->setShowTopBar( element.attribute( "topBar", "0" ).toUInt() );
+ mPlotter->setFontSize( element.attribute( "fontSize",
+ QString( "%1" ).arg( KSGRD::Style->fontSize() ) ).toUInt() );
+
+ mPlotter->setBackgroundColor( restoreColor( element, "bColor",
+ KSGRD::Style->backgroundColor() ) );
+
+ QDomNodeList dnList = element.elementsByTagName( "beam" );
+ for ( uint i = 0; i < dnList.count(); ++i ) {
+ QDomElement el = dnList.item( i ).toElement();
+ addSensor( el.attribute( "hostName" ), el.attribute( "sensorName" ),
+ ( el.attribute( "sensorType" ).isEmpty() ? "integer" :
+ el.attribute( "sensorType" ) ), "", restoreColor( el, "color",
+ KSGRD::Style->sensorColor( i ) ) );
+ }
+
+ SensorDisplay::restoreSettings( element );
+
+ if ( !title().isEmpty() )
+ mPlotter->setTitle( title() );
+
+ setModified( false );
+
+ return true;
+}
+
+bool FancyPlotter::saveSettings( QDomDocument &doc, QDomElement &element,
+ bool save )
+{
+ element.setAttribute( "min", mPlotter->minValue() );
+ element.setAttribute( "max", mPlotter->maxValue() );
+ element.setAttribute( "autoRange", mPlotter->useAutoRange() );
+ element.setAttribute( "vLines", mPlotter->showVerticalLines() );
+ saveColor( element, "vColor", mPlotter->verticalLinesColor() );
+ element.setAttribute( "vDistance", mPlotter->verticalLinesDistance() );
+ element.setAttribute( "vScroll", mPlotter->verticalLinesScroll() );
+
+ element.setAttribute( "graphStyle", mPlotter->graphStyle() );
+ element.setAttribute( "hScale", mPlotter->horizontalScale() );
+
+ element.setAttribute( "hLines", mPlotter->showHorizontalLines() );
+ saveColor( element, "hColor", mPlotter->horizontalLinesColor() );
+ element.setAttribute( "hCount", mPlotter->horizontalLinesCount() );
+
+ element.setAttribute( "labels", mPlotter->showLabels() );
+ element.setAttribute( "topBar", mPlotter->showTopBar() );
+ element.setAttribute( "fontSize", mPlotter->fontSize() );
+
+ saveColor( element, "bColor", mPlotter->backgroundColor() );
+
+ for ( uint i = 0; i < mBeams; ++i ) {
+ QDomElement beam = doc.createElement( "beam" );
+ element.appendChild( beam );
+ beam.setAttribute( "hostName", sensors().at( i )->hostName() );
+ beam.setAttribute( "sensorName", sensors().at( i )->name() );
+ beam.setAttribute( "sensorType", sensors().at( i )->type() );
+ saveColor( beam, "color", mPlotter->beamColors()[ i ] );
+ }
+
+ SensorDisplay::saveSettings( doc, element );
+
+ if ( save )
+ setModified( false );
+
+ return true;
+}
+
+bool FancyPlotter::hasSettingsDialog() const
+{
+ return true;
+}
+
+
+
+FPSensorProperties::FPSensorProperties()
+{
+}
+
+FPSensorProperties::FPSensorProperties( const QString &hostName,
+ const QString &name,
+ const QString &type,
+ const QString &description,
+ const QColor &color )
+ : KSGRD::SensorProperties( hostName, name, type, description ),
+ mColor( color )
+{
+}
+
+FPSensorProperties::~FPSensorProperties()
+{
+}
+
+void FPSensorProperties::setColor( const QColor &color )
+{
+ mColor = color;
+}
+
+QColor FPSensorProperties::color() const
+{
+ return mColor;
+}
+
+#include "FancyPlotter.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/FancyPlotter.h b/ksysguard/gui/SensorDisplayLib/FancyPlotter.h
new file mode 100644
index 000000000..d19c28760
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/FancyPlotter.h
@@ -0,0 +1,103 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_FANCYPLOTTER_H
+#define KSG_FANCYPLOTTER_H
+
+#include <kdialogbase.h>
+
+#include <SensorDisplay.h>
+
+#include "SignalPlotter.h"
+
+class QListViewItem;
+class FancyPlotterSettings;
+
+class FPSensorProperties : public KSGRD::SensorProperties
+{
+ public:
+ FPSensorProperties();
+ FPSensorProperties( const QString &hostName, const QString &name,
+ const QString &type, const QString &description,
+ const QColor &color );
+ ~FPSensorProperties();
+
+ void setColor( const QColor &color );
+ QColor color() const;
+
+ private:
+ QColor mColor;
+};
+
+class FancyPlotter : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+
+ public:
+ FancyPlotter( QWidget* parent = 0, const char* name = 0,
+ const QString& title = QString::null, double min = 0,
+ double max = 100, bool noFrame = false, bool isApplet = false );
+ virtual ~FancyPlotter();
+
+ void configureSettings();
+
+ bool addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &title );
+ bool addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &title,
+ const QColor &color );
+
+ bool removeSensor( uint pos );
+
+ virtual QSize sizeHint(void);
+
+ virtual void answerReceived( int id, const QString &answer );
+
+ virtual bool restoreSettings( QDomElement &element );
+ virtual bool saveSettings( QDomDocument &doc, QDomElement &element,
+ bool save = true );
+
+ virtual bool hasSettingsDialog() const;
+
+ public slots:
+ void applySettings();
+ virtual void applyStyle();
+ void killDialog();
+
+ protected:
+ virtual void resizeEvent( QResizeEvent* );
+
+ private:
+ uint mBeams;
+
+ SignalPlotter* mPlotter;
+
+ FancyPlotterSettings* mSettingsDialog;
+
+ /**
+ The sample buffer and the flags are needed to store the incoming
+ samples for each beam until all samples of the period have been
+ received. The flags variable is used to ensure that all samples have
+ been received.
+ */
+ QValueList<double> mSampleBuf;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.cc b/ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.cc
new file mode 100644
index 000000000..9d4114bd3
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.cc
@@ -0,0 +1,637 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <kaccelmanager.h>
+#include <kcolorbutton.h>
+#include <kcolordialog.h>
+#include <klineedit.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include <qcheckbox.h>
+#include <qbuttongroup.h>
+#include <qgroupbox.h>
+#include <qimage.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+#include <qwhatsthis.h>
+#include <qheader.h>
+
+#include "FancyPlotterSettings.h"
+
+FancyPlotterSettings::FancyPlotterSettings( QWidget* parent, const char* name )
+ : KDialogBase( Tabbed, i18n( "Signal Plotter Settings" ), Ok | Apply | Cancel,
+ Ok, parent, name, false, true )
+{
+ QFrame *page = 0;
+ QGridLayout *pageLayout = 0;
+ QGridLayout *boxLayout = 0;
+ QGroupBox *groupBox = 0;
+ QLabel *label = 0;
+
+ // Style page
+ page = addPage( i18n( "Style" ) );
+ pageLayout = new QGridLayout( page, 3, 2, 0, spacingHint() );
+
+ label = new QLabel( i18n( "Title:" ), page );
+ pageLayout->addWidget( label, 0, 0 );
+
+ mTitle = new KLineEdit( page );
+ QWhatsThis::add( mTitle, i18n( "Enter the title of the display here." ) );
+ pageLayout->addWidget( mTitle, 0, 1 );
+ label->setBuddy( mTitle );
+
+ QButtonGroup *buttonBox = new QButtonGroup( 2, Qt::Vertical,
+ i18n( "Graph Drawing Style" ), page );
+
+ mUsePolygonStyle = new QRadioButton( i18n( "Basic polygons" ), buttonBox );
+ mUsePolygonStyle->setChecked( true );
+ mUseOriginalStyle = new QRadioButton( i18n( "Original - single line per data point" ), buttonBox );
+
+ pageLayout->addMultiCellWidget( buttonBox, 1, 1, 0, 1 );
+
+ // Scales page
+ page = addPage( i18n( "Scales" ) );
+ pageLayout = new QGridLayout( page, 2, 1, 0, spacingHint() );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Vertical Scale" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 2, 5, spacingHint() );
+ boxLayout->setColStretch( 2, 1 );
+
+ mUseAutoRange = new QCheckBox( i18n( "Automatic range detection" ), groupBox );
+ QWhatsThis::add( mUseAutoRange, i18n( "Check this box if you want the display range to adapt dynamically to the currently displayed values; if you do not check this, you have to specify the range you want in the fields below." ) );
+ boxLayout->addMultiCellWidget( mUseAutoRange, 0, 0, 0, 4 );
+
+ label = new QLabel( i18n( "Minimum value:" ), groupBox );
+ boxLayout->addWidget( label, 1, 0 );
+
+ mMinValue = new KLineEdit( groupBox );
+ mMinValue->setAlignment( AlignRight );
+ mMinValue->setEnabled( false );
+ QWhatsThis::add( mMinValue, i18n( "Enter the minimum value for the display here. If both values are 0, automatic range detection is enabled." ) );
+ boxLayout->addWidget( mMinValue, 1, 1 );
+ label->setBuddy( mMinValue );
+
+ label = new QLabel( i18n( "Maximum value:" ), groupBox );
+ boxLayout->addWidget( label, 1, 3 );
+
+ mMaxValue = new KLineEdit( groupBox );
+ mMaxValue->setAlignment( AlignRight );
+ mMaxValue->setEnabled( false );
+ QWhatsThis::add( mMaxValue, i18n( "Enter the maximum value for the display here. If both values are 0, automatic range detection is enabled." ) );
+ boxLayout->addWidget( mMaxValue, 1, 4 );
+ label->setBuddy( mMaxValue );
+
+ pageLayout->addWidget( groupBox, 0, 0 );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Horizontal Scale" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 2, 2, spacingHint() );
+ boxLayout->setRowStretch( 1, 1 );
+
+ mHorizontalScale = new KIntNumInput( 1, groupBox );
+ mHorizontalScale->setMinValue( 1 );
+ mHorizontalScale->setMaxValue( 50 );
+ boxLayout->addWidget( mHorizontalScale, 0, 0 );
+
+ label = new QLabel( i18n( "pixel(s) per time period" ), groupBox );
+ boxLayout->addWidget( label, 0, 1 );
+
+ pageLayout->addWidget( groupBox, 1, 0 );
+
+ // Grid page
+ page = addPage( i18n( "Grid" ) );
+ pageLayout = new QGridLayout( page, 3, 2, 0, spacingHint() );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Lines" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 2, 5, spacingHint() );
+ boxLayout->setColStretch( 1, 1 );
+
+ mShowVerticalLines = new QCheckBox( i18n( "Vertical lines" ), groupBox );
+ QWhatsThis::add( mShowVerticalLines, i18n( "Check this to activate the vertical lines if display is large enough." ) );
+ boxLayout->addWidget( mShowVerticalLines, 0, 0 );
+
+ label = new QLabel( i18n( "Distance:" ), groupBox );
+ boxLayout->addWidget( label, 0, 2 );
+
+ mVerticalLinesDistance = new KIntNumInput( 0, groupBox );
+ mVerticalLinesDistance->setMinValue( 10 );
+ mVerticalLinesDistance->setMaxValue( 120 );
+ QWhatsThis::add( mVerticalLinesDistance, i18n( "Enter the distance between two vertical lines here." ) );
+ boxLayout->addWidget( mVerticalLinesDistance , 0, 3 );
+ label->setBuddy( mVerticalLinesDistance );
+
+ mVerticalLinesScroll = new QCheckBox( i18n( "Vertical lines scroll" ), groupBox );
+ boxLayout->addWidget( mVerticalLinesScroll, 0, 4 );
+
+ mShowHorizontalLines = new QCheckBox( i18n( "Horizontal lines" ), groupBox );
+ QWhatsThis::add( mShowHorizontalLines, i18n( "Check this to enable horizontal lines if display is large enough." ) );
+ boxLayout->addWidget( mShowHorizontalLines, 1, 0 );
+
+ label = new QLabel( i18n( "Count:" ), groupBox );
+ boxLayout->addWidget( label, 1, 2 );
+
+ mHorizontalLinesCount = new KIntNumInput( 0, groupBox );
+ mHorizontalLinesCount->setMinValue( 1 );
+ mHorizontalLinesCount->setMaxValue( 100 );
+ QWhatsThis::add( mHorizontalLinesCount, i18n( "Enter the number of horizontal lines here." ) );
+ boxLayout->addWidget( mHorizontalLinesCount , 1, 3 );
+ label->setBuddy( mHorizontalLinesCount );
+
+ boxLayout->setRowStretch( 2, 1 );
+
+ pageLayout->addMultiCellWidget( groupBox, 0, 0, 0, 1 );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Text" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 3, 4, spacingHint() );
+ boxLayout->setColStretch( 1, 1 );
+
+ mShowLabels = new QCheckBox( i18n( "Labels" ), groupBox );
+ QWhatsThis::add( mShowLabels, i18n( "Check this box if horizontal lines should be decorated with the values they mark." ) );
+ boxLayout->addWidget( mShowLabels, 0, 0 );
+
+ label = new QLabel( i18n( "Font size:" ), groupBox );
+ boxLayout->addWidget( label, 0, 2 );
+
+ mFontSize = new KIntNumInput( 9, groupBox );
+ mFontSize->setMinValue( 5 );
+ mFontSize->setMaxValue( 24 );
+ boxLayout->addWidget( mFontSize, 0, 3 );
+ label->setBuddy( mFontSize );
+
+ mShowTopBar = new QCheckBox( i18n( "Top bar" ), groupBox );
+ QWhatsThis::add( mShowTopBar, i18n( "Check this to active the display title bar. This is probably only useful for applet displays. The bar is only visible if the display is large enough." ) );
+ boxLayout->addWidget( mShowTopBar, 1, 0 );
+
+ boxLayout->setRowStretch( 2, 1 );
+
+ pageLayout->addWidget( groupBox, 1, 0 );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Colors" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 4, 2, spacingHint() );
+
+ label = new QLabel( i18n( "Vertical lines:" ), groupBox );
+ boxLayout->addWidget( label, 0, 0 );
+
+ mVerticalLinesColor = new KColorButton( groupBox );
+ boxLayout->addWidget( mVerticalLinesColor, 0, 1 );
+ label->setBuddy( mVerticalLinesColor );
+
+ label = new QLabel( i18n( "Horizontal lines:" ), groupBox );
+ boxLayout->addWidget( label, 1, 0 );
+
+ mHorizontalLinesColor = new KColorButton( groupBox );
+ boxLayout->addWidget( mHorizontalLinesColor, 1, 1 );
+ label->setBuddy( mHorizontalLinesColor );
+
+ label = new QLabel( i18n( "Background:" ), groupBox );
+ boxLayout->addWidget( label, 2, 0 );
+
+ mBackgroundColor = new KColorButton( groupBox );
+ boxLayout->addWidget( mBackgroundColor, 2, 1 );
+ label->setBuddy( mBackgroundColor );
+
+ boxLayout->setRowStretch( 3, 1 );
+
+ pageLayout->addWidget( groupBox, 1, 1 );
+
+ pageLayout->setRowStretch( 2, 1 );
+
+ // Sensors page
+ page = addPage( i18n( "Sensors" ) );
+ pageLayout = new QGridLayout( page, 6, 2, 0, spacingHint() );
+ pageLayout->setRowStretch( 2, 1 );
+ pageLayout->setRowStretch( 5, 1 );
+
+ mSensorView = new KListView( page );
+ mSensorView->addColumn("" , 0);
+ mSensorView->addColumn( i18n( "Host" ) );
+ mSensorView->addColumn( i18n( "Sensor" ) );
+ mSensorView->addColumn( i18n( "Unit" ) );
+ mSensorView->addColumn( i18n( "Status" ) );
+ mSensorView->setResizeMode(QListView::LastColumn);
+ mSensorView->header()->setResizeEnabled(false, 0);
+ mSensorView->hideColumn(0);
+ mSensorView->header()->resizeSection(0, 0);
+ mSensorView->setAllColumnsShowFocus( true );
+ pageLayout->addMultiCellWidget( mSensorView, 0, 5, 0, 0 );
+ mSensorView->setSortColumn ( -1 );
+ mEditButton = new QPushButton( i18n( "Set Color..." ), page );
+ mEditButton->setEnabled( false );
+ QWhatsThis::add( mEditButton, i18n( "Push this button to configure the color of the sensor in the diagram." ) );
+ pageLayout->addWidget( mEditButton, 0, 1 );
+
+ mRemoveButton = new QPushButton( i18n( "Delete" ), page );
+ mRemoveButton->setEnabled( false );
+ QWhatsThis::add( mRemoveButton, i18n( "Push this button to delete the sensor." ) );
+ pageLayout->addWidget( mRemoveButton, 1, 1 );
+
+ mMoveUpButton = new QPushButton( i18n( "Move Up" ), page );
+ mMoveUpButton->setEnabled( false );
+ pageLayout->addWidget( mMoveUpButton, 3, 1 );
+
+ mMoveDownButton = new QPushButton( i18n( "Move Down" ), page );
+ mMoveDownButton->setEnabled( false );
+ pageLayout->addWidget( mMoveDownButton, 4, 1 );
+
+ connect( mUseAutoRange, SIGNAL( toggled( bool ) ), mMinValue,
+ SLOT( setDisabled( bool ) ) );
+ connect( mUseAutoRange, SIGNAL( toggled( bool ) ), mMaxValue,
+ SLOT( setDisabled( bool ) ) );
+ connect( mShowVerticalLines, SIGNAL( toggled( bool ) ), mVerticalLinesDistance,
+ SLOT( setEnabled( bool ) ) );
+ connect( mShowVerticalLines, SIGNAL( toggled( bool ) ), mVerticalLinesScroll,
+ SLOT( setEnabled( bool ) ) );
+ connect( mShowVerticalLines, SIGNAL( toggled( bool ) ), mVerticalLinesColor,
+ SLOT( setEnabled( bool ) ) );
+ connect( mShowHorizontalLines, SIGNAL( toggled( bool ) ), mHorizontalLinesCount,
+ SLOT( setEnabled( bool ) ) );
+ connect( mShowHorizontalLines, SIGNAL( toggled( bool ) ), mHorizontalLinesColor,
+ SLOT( setEnabled( bool ) ) );
+ connect( mShowHorizontalLines, SIGNAL( toggled( bool ) ), mShowLabels,
+ SLOT( setEnabled( bool ) ) );
+ connect( mSensorView, SIGNAL( selectionChanged( QListViewItem* ) ),
+ SLOT( selectionChanged( QListViewItem* ) ) );
+
+ connect( mEditButton, SIGNAL( clicked() ), SLOT( editSensor() ) );
+ connect( mRemoveButton, SIGNAL( clicked() ), SLOT( removeSensor() ) );
+ connect( mMoveUpButton, SIGNAL( clicked() ), SLOT( moveUpSensor() ) );
+ connect( mMoveDownButton, SIGNAL( clicked() ), SLOT( moveDownSensor() ) );
+ connect ( mSensorView, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int )), SLOT(editSensor()));
+
+ KAcceleratorManager::manage( this );
+}
+
+FancyPlotterSettings::~FancyPlotterSettings()
+{
+}
+
+void FancyPlotterSettings::setTitle( const QString &title )
+{
+ mTitle->setText( title );
+}
+
+QString FancyPlotterSettings::title() const
+{
+ return mTitle->text();
+}
+
+void FancyPlotterSettings::setUseAutoRange( bool value )
+{
+ mUseAutoRange->setChecked( value );
+ mMinValue->setEnabled( !value );
+ mMaxValue->setEnabled( !value );
+}
+
+bool FancyPlotterSettings::useAutoRange() const
+{
+ return mUseAutoRange->isChecked();
+}
+
+void FancyPlotterSettings::setMinValue( double min )
+{
+ mMinValue->setText( QString::number( min ) );
+}
+
+double FancyPlotterSettings::minValue() const
+{
+ return mMinValue->text().toDouble();
+}
+
+void FancyPlotterSettings::setMaxValue( double max )
+{
+ mMaxValue->setText( QString::number( max ) );
+}
+
+double FancyPlotterSettings::maxValue() const
+{
+ return mMaxValue->text().toDouble();
+}
+
+void FancyPlotterSettings::setUsePolygonStyle( bool value )
+{
+ if ( value )
+ mUsePolygonStyle->setChecked( true );
+ else
+ mUseOriginalStyle->setChecked( true );
+}
+
+bool FancyPlotterSettings::usePolygonStyle() const
+{
+ return mUsePolygonStyle->isChecked();
+}
+
+void FancyPlotterSettings::setHorizontalScale( int scale )
+{
+ mHorizontalScale->setValue( scale );
+}
+
+int FancyPlotterSettings::horizontalScale() const
+{
+ return mHorizontalScale->value();
+}
+
+void FancyPlotterSettings::setShowVerticalLines( bool value )
+{
+ mShowVerticalLines->setChecked( value );
+ mVerticalLinesDistance->setEnabled( value );
+ mVerticalLinesScroll->setEnabled( value );
+ mVerticalLinesColor->setEnabled( value );
+}
+
+bool FancyPlotterSettings::showVerticalLines() const
+{
+ return mShowVerticalLines->isChecked();
+}
+
+void FancyPlotterSettings::setVerticalLinesColor( const QColor &color )
+{
+ mVerticalLinesColor->setColor( color );
+}
+
+QColor FancyPlotterSettings::verticalLinesColor() const
+{
+ return mVerticalLinesColor->color();
+}
+
+void FancyPlotterSettings::setVerticalLinesDistance( int distance )
+{
+ mVerticalLinesDistance->setValue( distance );
+}
+
+int FancyPlotterSettings::verticalLinesDistance() const
+{
+ return mVerticalLinesDistance->value();
+}
+
+void FancyPlotterSettings::setVerticalLinesScroll( bool value )
+{
+ mVerticalLinesScroll->setChecked( value );
+}
+
+bool FancyPlotterSettings::verticalLinesScroll() const
+{
+ return mVerticalLinesScroll->isChecked();
+}
+
+void FancyPlotterSettings::setShowHorizontalLines( bool value )
+{
+ mShowHorizontalLines->setChecked( value );
+ mHorizontalLinesCount->setEnabled( value );
+ mHorizontalLinesColor->setEnabled( value );
+ mShowLabels->setEnabled( value );
+
+}
+
+bool FancyPlotterSettings::showHorizontalLines() const
+{
+ return mShowHorizontalLines->isChecked();
+}
+
+void FancyPlotterSettings::setHorizontalLinesColor( const QColor &color )
+{
+ mHorizontalLinesColor->setColor( color );
+}
+
+QColor FancyPlotterSettings::horizontalLinesColor() const
+{
+ return mHorizontalLinesColor->color();
+}
+
+void FancyPlotterSettings::setHorizontalLinesCount( int count )
+{
+ mHorizontalLinesCount->setValue( count );
+}
+
+int FancyPlotterSettings::horizontalLinesCount() const
+{
+ return mHorizontalLinesCount->value();
+}
+
+void FancyPlotterSettings::setShowLabels( bool value )
+{
+ mShowLabels->setChecked( value );
+}
+
+bool FancyPlotterSettings::showLabels() const
+{
+ return mShowLabels->isChecked();
+}
+
+void FancyPlotterSettings::setShowTopBar( bool value )
+{
+ mShowTopBar->setChecked( value );
+}
+
+bool FancyPlotterSettings::showTopBar() const
+{
+ return mShowTopBar->isChecked();
+}
+
+void FancyPlotterSettings::setFontSize( int size )
+{
+ mFontSize->setValue( size );
+}
+
+int FancyPlotterSettings::fontSize() const
+{
+ return mFontSize->value();
+}
+
+void FancyPlotterSettings::setBackgroundColor( const QColor &color )
+{
+ mBackgroundColor->setColor( color );
+}
+
+QColor FancyPlotterSettings::backgroundColor() const
+{
+ return mBackgroundColor->color();
+}
+void FancyPlotterSettings::clearDeleted()
+{
+ mDeleted.clear();
+}
+QValueList<int> FancyPlotterSettings::deleted() const
+{
+ return mDeleted;
+}
+
+QValueList<int> FancyPlotterSettings::order() const
+{
+ QValueList<int> newOrder;
+
+ QListViewItemIterator it( mSensorView );
+ for ( ; it.current(); ++it ) {
+ newOrder.prepend(it.current()->text(0).toInt());
+ }
+ return newOrder;
+}
+
+void FancyPlotterSettings::resetOrder()
+{
+ int i = mSensorView->childCount()-1;
+ QListViewItemIterator it( mSensorView );
+ for ( ; it.current(); ++it, --i) {
+ it.current()->setText(0, QString::number(i));
+ }
+}
+
+void FancyPlotterSettings::setSensors( const QValueList< QStringList > &list )
+{
+ mSensorView->clear();
+
+ QValueList< QStringList >::ConstIterator it;
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ QListViewItem* lvi = new QListViewItem( mSensorView,
+ (*it)[ 0 ], // id
+ (*it)[ 1 ], // host name
+ (*it)[ 2 ], // sensor name
+ (*it)[ 3 ], // unit
+ (*it)[ 4 ] ); // status
+ QPixmap pm( 12, 12 );
+ pm.fill( QColor( (*it)[ 5 ] ) );
+ lvi->setPixmap( 2, pm );
+ mSensorView->insertItem( lvi );
+ }
+}
+
+QValueList< QStringList > FancyPlotterSettings::sensors() const
+{
+ QValueList< QStringList > list;
+
+ QListViewItemIterator it( mSensorView );
+
+ for ( ; it.current(); ++it ) {
+ QStringList entry;
+ entry << it.current()->text( 0 );
+ entry << it.current()->text( 1 );
+ entry << it.current()->text( 2 );
+ entry << it.current()->text( 3 );
+ entry << it.current()->text( 4 );
+ QRgb rgb = it.current()->pixmap( 2 )->convertToImage().pixel( 1, 1 );
+ QColor color( qRed( rgb ), qGreen( rgb ), qBlue( rgb ) );
+ entry << ( color.name() );
+
+ list.prepend( entry );
+ }
+
+ return list;
+}
+
+void FancyPlotterSettings::editSensor()
+{
+ QListViewItem* lvi = mSensorView->currentItem();
+
+ if ( !lvi )
+ return;
+
+ QColor color = lvi->pixmap( 2 )->convertToImage().pixel( 1, 1 );
+ int result = KColorDialog::getColor( color, parentWidget() );
+ if ( result == KColorDialog::Accepted ) {
+ QPixmap newPm( 12, 12 );
+ newPm.fill( color );
+ lvi->setPixmap( 2, newPm );
+ }
+}
+
+void FancyPlotterSettings::removeSensor()
+{
+ QListViewItem* lvi = mSensorView->currentItem();
+
+ if ( lvi ) {
+ //Note down the id of the one we are deleting
+ int id = lvi->text(0).toInt();
+ mDeleted.append(id);
+
+ /* Before we delete the currently selected item, we determine a
+ * new item to be selected. That way we can ensure that multiple
+ * items can be deleted without forcing the user to select a new
+ * item between the deletes. If all items are deleted, the buttons
+ * are disabled again. */
+ QListViewItem* newSelected = 0;
+ if ( lvi->itemBelow() ) {
+ lvi->itemBelow()->setSelected( true );
+ newSelected = lvi->itemBelow();
+ } else if ( lvi->itemAbove() ) {
+ lvi->itemAbove()->setSelected( true );
+ newSelected = lvi->itemAbove();
+ } else
+ selectionChanged( 0 );
+
+ delete lvi;
+
+ QListViewItemIterator it( mSensorView );
+ for ( ; it.current(); ++it ) {
+ if(it.current()->text(0).toInt() > id)
+ it.current()->setText(0, QString::number(it.current()->text(0).toInt() -1));
+ }
+
+
+ if ( newSelected )
+ mSensorView->ensureItemVisible( newSelected );
+ }
+}
+
+void FancyPlotterSettings::moveUpSensor()
+{
+ if ( mSensorView->currentItem() != 0 ) {
+ QListViewItem* item = mSensorView->currentItem()->itemAbove();
+ if ( item ) {
+ if ( item->itemAbove() )
+ {
+ mSensorView->currentItem()->moveItem( item->itemAbove() );
+ }
+ else
+ {
+ item->moveItem( mSensorView->currentItem() );
+ }
+ }
+
+ selectionChanged( mSensorView->currentItem() );
+ }
+}
+
+void FancyPlotterSettings::moveDownSensor()
+{
+ if ( mSensorView->currentItem() != 0 ) {
+ if ( mSensorView->currentItem()->itemBelow() )
+ mSensorView->currentItem()->moveItem( mSensorView->currentItem()->itemBelow() );
+
+ selectionChanged( mSensorView->currentItem() );
+ }
+}
+
+void FancyPlotterSettings::selectionChanged( QListViewItem *item )
+{
+ bool state = ( item != 0 );
+
+ mEditButton->setEnabled( state );
+ mRemoveButton->setEnabled( state );
+ mMoveUpButton->setEnabled( state && item->itemAbove() );
+ mMoveDownButton->setEnabled( state && item->itemBelow() );
+}
+
+#include "FancyPlotterSettings.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.h b/ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.h
new file mode 100644
index 000000000..b813bee34
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.h
@@ -0,0 +1,143 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef FANCYPLOTTERSETTINGS_H
+#define FANCYPLOTTERSETTINGS_H
+
+#include <kdialogbase.h>
+
+class KColorButton;
+class KIntNumInput;
+class KLineEdit;
+class KListView;
+
+class QCheckBox;
+class QListViewItem;
+class QPushButton;
+class QRadioButton;
+
+class FancyPlotterSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ FancyPlotterSettings( QWidget* parent = 0, const char* name = 0 );
+ ~FancyPlotterSettings();
+
+ void setTitle( const QString &title );
+ QString title() const;
+
+ void setUseAutoRange( bool value );
+ bool useAutoRange() const;
+
+ void setMinValue( double min );
+ double minValue() const;
+
+ void setMaxValue( double max );
+ double maxValue() const;
+
+ void setUsePolygonStyle( bool value );
+ bool usePolygonStyle() const;
+
+ void setHorizontalScale( int scale );
+ int horizontalScale() const;
+
+ void setShowVerticalLines( bool value );
+ bool showVerticalLines() const;
+
+ void setVerticalLinesColor( const QColor &color );
+ QColor verticalLinesColor() const;
+
+ void setVerticalLinesDistance( int distance );
+ int verticalLinesDistance() const;
+
+ void setVerticalLinesScroll( bool value );
+ bool verticalLinesScroll() const;
+
+ void setShowHorizontalLines( bool value );
+ bool showHorizontalLines() const;
+
+ void setHorizontalLinesColor( const QColor &color );
+ QColor horizontalLinesColor() const;
+
+ void setHorizontalLinesCount( int count );
+ int horizontalLinesCount() const;
+
+ void setShowLabels( bool value );
+ bool showLabels() const;
+
+ void setShowTopBar( bool value );
+ bool showTopBar() const;
+
+ void setFontSize( int size );
+ int fontSize() const;
+
+ void setBackgroundColor( const QColor &color );
+ QColor backgroundColor() const;
+
+ void setSensors( const QValueList< QStringList > &list );
+ QValueList< QStringList > sensors() const;
+ QValueList<int> order() const;
+ QValueList<int> deleted() const;
+ void clearDeleted();
+ void resetOrder();
+
+ private slots:
+ void editSensor();
+ void removeSensor();
+ void moveUpSensor();
+ void moveDownSensor();
+ void selectionChanged( QListViewItem* );
+
+ private:
+
+ KColorButton *mVerticalLinesColor;
+ KColorButton *mHorizontalLinesColor;
+ KColorButton *mBackgroundColor;
+ KLineEdit *mMinValue;
+ KLineEdit *mMaxValue;
+ KLineEdit *mTitle;
+ KIntNumInput *mHorizontalScale;
+ KIntNumInput *mVerticalLinesDistance;
+ KIntNumInput *mHorizontalLinesCount;
+ KIntNumInput *mFontSize;
+ KListView *mSensorView;
+
+ QCheckBox *mShowVerticalLines;
+ QCheckBox *mShowHorizontalLines;
+ QCheckBox *mVerticalLinesScroll;
+ QCheckBox *mUseAutoRange;
+ QCheckBox *mShowLabels;
+ QCheckBox *mShowTopBar;
+ QPushButton *mEditButton;
+ QPushButton *mRemoveButton;
+ QPushButton *mMoveUpButton;
+ QPushButton *mMoveDownButton;
+ QRadioButton *mUsePolygonStyle;
+ QRadioButton *mUseOriginalStyle;
+
+ /** The numbers of the sensors to be delete.*/
+ QValueList<int> mDeleted;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/ListView.cc b/ksysguard/gui/SensorDisplayLib/ListView.cc
new file mode 100644
index 000000000..885daded6
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ListView.cc
@@ -0,0 +1,371 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <config.h>
+#include <qdom.h>
+
+#include <kcolorbutton.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+
+#include "ListView.h"
+#include "ListView.moc"
+#include "ListViewSettings.h"
+
+PrivateListViewItem::PrivateListViewItem(PrivateListView *parent)
+ : QListViewItem(parent)
+{
+ _parent = parent;
+}
+
+int PrivateListViewItem::compare( QListViewItem *item, int col, bool ascending ) const
+{
+ int type = ((PrivateListView*)listView())->columnType( col );
+
+ if ( type == PrivateListView::Int ) {
+ int prev = (int)KGlobal::locale()->readNumber( key( col, ascending ) );
+ int next = (int)KGlobal::locale()->readNumber( item->key( col, ascending ) );
+ if ( prev < next )
+ return -1;
+ else if ( prev == next )
+ return 0;
+ else
+ return 1;
+ } else if ( type == PrivateListView::Float ) {
+ double prev = KGlobal::locale()->readNumber( key( col, ascending ) );
+ double next = KGlobal::locale()->readNumber( item->key( col, ascending ) );
+ if ( prev < next )
+ return -1;
+ else
+ return 1;
+ } else if ( type == PrivateListView::Time ) {
+ int hourPrev, hourNext, minutesPrev, minutesNext;
+ sscanf( key( col, ascending ).latin1(), "%d:%d", &hourPrev, &minutesPrev );
+ sscanf( item->key( col, ascending ).latin1(), "%d:%d", &hourNext, &minutesNext );
+ int prev = hourPrev * 60 + minutesPrev;
+ int next = hourNext * 60 + minutesNext;
+ if ( prev < next )
+ return -1;
+ else if ( prev == next )
+ return 0;
+ else
+ return 1;
+ } else if ( type == PrivateListView::DiskStat ) {
+ QString prev = key( col, ascending );
+ QString next = item->key( col, ascending );
+ QString prevKey, nextKey;
+
+ uint counter = prev.length();
+ for ( uint i = 0; i < counter; ++i )
+ if ( prev[ i ].isDigit() ) {
+ prevKey.sprintf( "%s%016d", prev.left( i ).latin1(), prev.mid( i ).toInt() );
+ break;
+ }
+
+ counter = next.length();
+ for ( uint i = 0; i < counter; ++i )
+ if ( next[ i ].isDigit() ) {
+ nextKey.sprintf( "%s%016d", next.left( i ).latin1(), next.mid( i ).toInt() );
+ break;
+ }
+
+ return prevKey.compare( nextKey );
+ } else
+ return key( col, ascending ).localeAwareCompare( item->key( col, ascending ) );
+}
+
+PrivateListView::PrivateListView(QWidget *parent, const char *name)
+ : QListView(parent, name)
+{
+ QColorGroup cg = colorGroup();
+
+ cg.setColor(QColorGroup::Link, KSGRD::Style->firstForegroundColor());
+ cg.setColor(QColorGroup::Text, KSGRD::Style->secondForegroundColor());
+ cg.setColor(QColorGroup::Base, KSGRD::Style->backgroundColor());
+
+ setPalette(QPalette(cg, cg, cg));
+}
+
+void PrivateListView::update(const QString& answer)
+{
+ setUpdatesEnabled(false);
+ viewport()->setUpdatesEnabled(false);
+
+ int vpos = verticalScrollBar()->value();
+ int hpos = horizontalScrollBar()->value();
+
+ clear();
+
+ KSGRD::SensorTokenizer lines(answer, '\n');
+ for (uint i = 0; i < lines.count(); i++) {
+ PrivateListViewItem *item = new PrivateListViewItem(this);
+ KSGRD::SensorTokenizer records(lines[i], '\t');
+ for (uint j = 0; j < records.count(); j++) {
+ if ( mColumnTypes[ j ] == "f" )
+ item->setText(j, KGlobal::locale()->formatNumber( records[j].toFloat() ) );
+ else if ( mColumnTypes[ j ] == "D" )
+ item->setText(j, KGlobal::locale()->formatNumber( records[j].toDouble(), 0 ) );
+ else
+ item->setText(j, records[j]);
+ }
+
+ insertItem(item);
+ }
+
+ verticalScrollBar()->setValue(vpos);
+ horizontalScrollBar()->setValue(hpos);
+
+ viewport()->setUpdatesEnabled(true);
+ setUpdatesEnabled(true);
+
+ triggerUpdate();
+}
+
+int PrivateListView::columnType( uint pos ) const
+{
+ if ( pos >= mColumnTypes.count() )
+ return 0;
+
+ if ( mColumnTypes[ pos ] == "d" || mColumnTypes[ pos ] == "D" )
+ return Int;
+ else if ( mColumnTypes[ pos ] == "f" || mColumnTypes[ pos ] == "F" )
+ return Float;
+ else if ( mColumnTypes[ pos ] == "t" )
+ return Time;
+ else if ( mColumnTypes[ pos ] == "M" )
+ return DiskStat;
+ else
+ return Text;
+}
+
+void PrivateListView::removeColumns(void)
+{
+ for (int i = columns() - 1; i >= 0; --i)
+ removeColumn(i);
+}
+
+void PrivateListView::addColumn(const QString& label, const QString& type)
+{
+ QListView::addColumn( label );
+ int col = columns() - 1;
+
+ if (type == "s" || type == "S")
+ setColumnAlignment(col, AlignLeft);
+ else if (type == "d" || type == "D")
+ setColumnAlignment(col, AlignRight);
+ else if (type == "t")
+ setColumnAlignment(col, AlignRight);
+ else if (type == "f")
+ setColumnAlignment(col, AlignRight);
+ else if (type == "M")
+ setColumnAlignment(col, AlignLeft);
+ else
+ {
+ kdDebug(1215) << "Unknown type " << type << " of column " << label
+ << " in ListView!" << endl;
+ return;
+ }
+
+ mColumnTypes.append( type );
+
+ /* Just use some sensible default values as initial setting. */
+ QFontMetrics fm = fontMetrics();
+ setColumnWidth(col, fm.width(label) + 10);
+}
+
+ListView::ListView(QWidget* parent, const char* name, const QString& title, int, int)
+ : KSGRD::SensorDisplay(parent, name, title)
+{
+ setBackgroundColor(KSGRD::Style->backgroundColor());
+
+ monitor = new PrivateListView( frame() );
+ Q_CHECK_PTR(monitor);
+ monitor->setSelectionMode(QListView::NoSelection);
+ monitor->setItemMargin(2);
+
+ setMinimumSize(50, 25);
+
+ setPlotterWidget(monitor);
+
+ setModified(false);
+}
+
+bool
+ListView::addSensor(const QString& hostName, const QString& sensorName, const QString& sensorType, const QString& title)
+{
+ if (sensorType != "listview")
+ return (false);
+
+ registerSensor(new KSGRD::SensorProperties(hostName, sensorName, sensorType, title));
+
+ setTitle(title);
+
+ /* To differentiate between answers from value requests and info
+ * requests we use 100 for info requests. */
+ sendRequest(hostName, sensorName + "?", 100);
+ sendRequest(hostName, sensorName, 19);
+ setModified(true);
+ return (true);
+}
+
+void
+ListView::updateList()
+{
+ sendRequest(sensors().at(0)->hostName(), sensors().at(0)->name(), 19);
+}
+
+void
+ListView::answerReceived(int id, const QString& answer)
+{
+ /* We received something, so the sensor is probably ok. */
+ sensorError(id, false);
+
+ switch (id)
+ {
+ case 100: {
+ /* We have received the answer to a '?' command that contains
+ * the information about the table headers. */
+ KSGRD::SensorTokenizer lines(answer, '\n');
+ if (lines.count() != 2)
+ {
+ kdDebug(1215) << "wrong number of lines" << endl;
+ return;
+ }
+ KSGRD::SensorTokenizer headers(lines[0], '\t');
+ KSGRD::SensorTokenizer colTypes(lines[1], '\t');
+
+ /* remove all columns from list */
+ monitor->removeColumns();
+
+ /* add the new columns */
+ for (unsigned int i = 0; i < headers.count(); i++)
+ /* TODO: Implement translation support for header texts */
+ monitor->addColumn(headers[i], colTypes[i]);
+ break;
+ }
+ case 19: {
+ monitor->update(answer);
+ break;
+ }
+ }
+}
+
+void
+ListView::resizeEvent(QResizeEvent*)
+{
+ frame()->setGeometry(0, 0, width(), height());
+ monitor->setGeometry(10, 20, width() - 20, height() - 30);
+}
+
+bool
+ListView::restoreSettings(QDomElement& element)
+{
+ addSensor(element.attribute("hostName"), element.attribute("sensorName"), (element.attribute("sensorType").isEmpty() ? "listview" : element.attribute("sensorType")), element.attribute("title"));
+
+ QColorGroup colorGroup = monitor->colorGroup();
+ colorGroup.setColor(QColorGroup::Link, restoreColor(element, "gridColor", KSGRD::Style->firstForegroundColor()));
+ colorGroup.setColor(QColorGroup::Text, restoreColor(element, "textColor", KSGRD::Style->secondForegroundColor()));
+ colorGroup.setColor(QColorGroup::Base, restoreColor(element, "backgroundColor", KSGRD::Style->backgroundColor()));
+
+ monitor->setPalette(QPalette(colorGroup, colorGroup, colorGroup));
+
+ SensorDisplay::restoreSettings(element);
+
+ setModified(false);
+
+ return (true);
+}
+
+bool
+ListView::saveSettings(QDomDocument& doc, QDomElement& element, bool save)
+{
+ element.setAttribute("hostName", sensors().at(0)->hostName());
+ element.setAttribute("sensorName", sensors().at(0)->name());
+ element.setAttribute("sensorType", sensors().at(0)->type());
+
+ QColorGroup colorGroup = monitor->colorGroup();
+ saveColor(element, "gridColor", colorGroup.color(QColorGroup::Link));
+ saveColor(element, "textColor", colorGroup.color(QColorGroup::Text));
+ saveColor(element, "backgroundColor", colorGroup.color(QColorGroup::Base));
+
+ SensorDisplay::saveSettings(doc, element);
+
+ if (save)
+ setModified(false);
+
+ return (true);
+}
+
+void
+ListView::configureSettings()
+{
+ lvs = new ListViewSettings(this, "ListViewSettings");
+ Q_CHECK_PTR(lvs);
+ connect(lvs, SIGNAL(applyClicked()), SLOT(applySettings()));
+
+ QColorGroup colorGroup = monitor->colorGroup();
+ lvs->setGridColor(colorGroup.color(QColorGroup::Link));
+ lvs->setTextColor(colorGroup.color(QColorGroup::Text));
+ lvs->setBackgroundColor(colorGroup.color(QColorGroup::Base));
+ lvs->setTitle(title());
+
+ if (lvs->exec())
+ applySettings();
+
+ delete lvs;
+ lvs = 0;
+}
+
+void
+ListView::applySettings()
+{
+ QColorGroup colorGroup = monitor->colorGroup();
+ colorGroup.setColor(QColorGroup::Link, lvs->gridColor());
+ colorGroup.setColor(QColorGroup::Text, lvs->textColor());
+ colorGroup.setColor(QColorGroup::Base, lvs->backgroundColor());
+ monitor->setPalette(QPalette(colorGroup, colorGroup, colorGroup));
+
+ setTitle(lvs->title());
+
+ setModified(true);
+}
+
+void
+ListView::applyStyle()
+{
+ QColorGroup colorGroup = monitor->colorGroup();
+ colorGroup.setColor(QColorGroup::Link, KSGRD::Style->firstForegroundColor());
+ colorGroup.setColor(QColorGroup::Text, KSGRD::Style->secondForegroundColor());
+ colorGroup.setColor(QColorGroup::Base, KSGRD::Style->backgroundColor());
+ monitor->setPalette(QPalette(colorGroup, colorGroup, colorGroup));
+
+ setModified(true);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/ListView.h b/ksysguard/gui/SensorDisplayLib/ListView.h
new file mode 100644
index 000000000..4b96329c0
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ListView.h
@@ -0,0 +1,112 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef _ListView_h_
+#define _ListView_h_
+
+#include <qlistview.h>
+#include <qpainter.h>
+
+#include <SensorDisplay.h>
+
+typedef const char* (*KeyFunc)(const char*);
+
+class QLabel;
+class QBoxGroup;
+class ListViewSettings;
+
+class PrivateListView : public QListView
+{
+ Q_OBJECT
+public:
+ enum ColumnType { Text, Int, Float, Time, DiskStat };
+
+ PrivateListView(QWidget *parent = 0, const char *name = 0);
+
+ void addColumn(const QString& label, const QString& type);
+ void removeColumns(void);
+ void update(const QString& answer);
+ int columnType( uint pos ) const;
+
+private:
+ QStringList mColumnTypes;
+};
+
+class PrivateListViewItem : public QListViewItem
+{
+public:
+ PrivateListViewItem(PrivateListView *parent = 0);
+
+ void paintCell(QPainter *p, const QColorGroup &, int column, int width, int alignment) {
+ QColorGroup cgroup = _parent->colorGroup();
+ QListViewItem::paintCell(p, cgroup, column, width, alignment);
+ p->setPen(cgroup.color(QColorGroup::Link));
+ p->drawLine(0, height() - 1, width - 1, height() - 1);
+ }
+
+ void paintFocus(QPainter *, const QColorGroup, const QRect) {}
+
+ virtual int compare( QListViewItem*, int column, bool ascending ) const;
+
+private:
+ QWidget *_parent;
+};
+
+class ListView : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+public:
+ ListView(QWidget* parent = 0, const char* name = 0,
+ const QString& = QString::null, int min = 0, int max = 0);
+ ~ListView() {}
+
+ bool addSensor(const QString& hostName, const QString& sensorName, const QString& sensorType, const QString& sensorDescr);
+ void answerReceived(int id, const QString& answer);
+ void resizeEvent(QResizeEvent*);
+ void updateList();
+
+ bool restoreSettings(QDomElement& element);
+ bool saveSettings(QDomDocument& doc, QDomElement& element, bool save = true);
+
+ virtual bool hasSettingsDialog() const
+ {
+ return (true);
+ }
+
+ virtual void timerEvent(QTimerEvent*)
+ {
+ updateList();
+ }
+
+ void configureSettings();
+
+public slots:
+ void applySettings();
+ void applyStyle();
+
+private:
+ PrivateListView* monitor;
+ ListViewSettings* lvs;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/ListViewSettings.cc b/ksysguard/gui/SensorDisplayLib/ListViewSettings.cc
new file mode 100644
index 000000000..15822206e
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ListViewSettings.cc
@@ -0,0 +1,77 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ListViewSettings.h"
+#include "ListViewSettingsWidget.h"
+
+#include <klocale.h>
+
+ListViewSettings::ListViewSettings( QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n( "List View Settings" ),
+ Ok|Apply|Cancel, Ok, true )
+{
+ m_settingsWidget = new ListViewSettingsWidget( this, "m_settingsWidget" );
+ setMainWidget( m_settingsWidget );
+}
+
+QString ListViewSettings::title() const
+{
+ return m_settingsWidget->title();
+}
+
+QColor ListViewSettings::textColor() const
+{
+ return m_settingsWidget->textColor();
+}
+
+QColor ListViewSettings::backgroundColor() const
+{
+ return m_settingsWidget->backgroundColor();
+}
+
+QColor ListViewSettings::gridColor() const
+{
+ return m_settingsWidget->gridColor();
+}
+
+void ListViewSettings::setTitle( const QString &title )
+{
+ m_settingsWidget->setTitle( title );
+}
+
+void ListViewSettings::setBackgroundColor( const QColor &c )
+{
+ m_settingsWidget->setBackgroundColor( c );
+}
+
+void ListViewSettings::setTextColor( const QColor &c )
+{
+ m_settingsWidget->setTextColor( c );
+}
+
+void ListViewSettings::setGridColor( const QColor &c )
+{
+ m_settingsWidget->setGridColor( c );
+}
+
+#include "ListViewSettings.moc"
+
+/* vim: et sw=2 ts=2
+*/
+
diff --git a/ksysguard/gui/SensorDisplayLib/ListViewSettings.h b/ksysguard/gui/SensorDisplayLib/ListViewSettings.h
new file mode 100644
index 000000000..9a9790791
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ListViewSettings.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef LISTVIEWSETTINGS_H
+#define LISTVIEWSETTINGS_H
+
+#include <kdialogbase.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+
+class ListViewSettingsWidget;
+
+class ListViewSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+
+ ListViewSettings( QWidget *parent=0, const char *name=0 );
+
+ QString title() const;
+ QColor textColor() const;
+ QColor backgroundColor() const;
+ QColor gridColor() const;
+
+ void setTitle( const QString & );
+ void setTextColor( const QColor & );
+ void setBackgroundColor( const QColor & );
+ void setGridColor( const QColor & );
+
+ private:
+
+ ListViewSettingsWidget *m_settingsWidget;
+};
+
+#endif // LISTVIEWSETTINGS_H
+
+/* vim: et sw=2 ts=2
+*/
diff --git a/ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui b/ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui
new file mode 100644
index 000000000..f61f30dd7
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui
@@ -0,0 +1,178 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ListViewSettingsWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ListViewSettingsWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>399</width>
+ <height>202</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>titleFrame</cstring>
+ </property>
+ <property name="title">
+ <string>Title</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>colorFrame</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>Box</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>Colors</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter|AlignLeft</set>
+ </property>
+ <property name="vAlign" stdset="0">
+ </property>
+ <property name="wordwrap" stdset="0">
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Text color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Grid color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_textColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_gridColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_backgroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<includes>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+ <include location="local" impldecl="in implementation">ListViewSettingsWidget.ui.h</include>
+</includes>
+<functions>
+ <function specifier="non virtual" returnType="QString">title()</function>
+ <function specifier="non virtual" returnType="QColor">gridColor()</function>
+ <function specifier="non virtual" returnType="QColor">backgroundColor()</function>
+ <function specifier="non virtual" returnType="QColor">textColor()</function>
+ <function specifier="non virtual">setTitle( const QString &amp; t )</function>
+ <function specifier="non virtual">setBackgroundColor( const QColor &amp; c )</function>
+ <function specifier="non virtual">setTextColor( const QColor &amp; c )</function>
+ <function specifier="non virtual">setGridColor( const QColor &amp; c )</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+</UI>
diff --git a/ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui.h b/ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui.h
new file mode 100644
index 000000000..14ff5990d
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+QString ListViewSettingsWidget::title()
+{
+ return m_title->text();
+}
+
+
+QColor ListViewSettingsWidget::gridColor()
+{
+ return m_gridColor->color();
+}
+
+
+QColor ListViewSettingsWidget::backgroundColor()
+{
+ return m_backgroundColor->color();
+}
+
+
+QColor ListViewSettingsWidget::textColor()
+{
+ return m_textColor->color();
+}
+
+
+void ListViewSettingsWidget::setTitle( const QString &t )
+{
+ m_title->setText(t);
+}
+
+
+void ListViewSettingsWidget::setBackgroundColor( const QColor &c )
+{
+ m_backgroundColor->setColor(c);
+}
+
+
+void ListViewSettingsWidget::setTextColor( const QColor &c )
+{
+ m_textColor->setColor(c);
+}
+
+
+void ListViewSettingsWidget::setGridColor( const QColor &c )
+{
+ m_gridColor->setColor(c);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/LogFile.cc b/ksysguard/gui/SensorDisplayLib/LogFile.cc
new file mode 100644
index 000000000..9db4c7116
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/LogFile.cc
@@ -0,0 +1,285 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <qpushbutton.h>
+#include <qregexp.h>
+
+#include <qfile.h>
+#include <qlistbox.h>
+
+#include <kfontdialog.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kcolorbutton.h>
+
+#include <ksgrd/StyleEngine.h>
+
+#include "LogFile.moc"
+
+LogFile::LogFile(QWidget *parent, const char *name, const QString& title)
+ : KSGRD::SensorDisplay(parent, name, title)
+{
+ monitor = new QListBox(this);
+ Q_CHECK_PTR(monitor);
+
+ setMinimumSize(50, 25);
+
+ setPlotterWidget(monitor);
+
+ setModified(false);
+}
+
+LogFile::~LogFile(void)
+{
+ sendRequest(sensors().at(0)->hostName(), QString("logfile_unregister %1" ).arg(logFileID), 43);
+}
+
+bool
+LogFile::addSensor(const QString& hostName, const QString& sensorName, const QString& sensorType, const QString& title)
+{
+ if (sensorType != "logfile")
+ return (false);
+
+ registerSensor(new KSGRD::SensorProperties(hostName, sensorName, sensorType, title));
+
+ QString sensorID = sensorName.right(sensorName.length() - (sensorName.findRev("/") + 1));
+
+ sendRequest(sensors().at(0)->hostName(), QString("logfile_register %1" ).arg(sensorID), 42);
+
+ if (title.isEmpty())
+ setTitle(sensors().at(0)->hostName() + ":" + sensorID);
+ else
+ setTitle(title);
+
+ setModified(true);
+
+ return (true);
+}
+
+
+void LogFile::configureSettings(void)
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ lfs = new LogFileSettings(this);
+ Q_CHECK_PTR(lfs);
+
+ lfs->fgColor->setColor(cgroup.text());
+ lfs->fgColor->setText(i18n("Foreground color:"));
+ lfs->bgColor->setColor(cgroup.base());
+ lfs->bgColor->setText(i18n("Background color:"));
+ lfs->fontButton->setFont(monitor->font());
+ lfs->ruleList->insertStringList(filterRules);
+ lfs->title->setText(title());
+
+ connect(lfs->okButton, SIGNAL(clicked()), lfs, SLOT(accept()));
+ connect(lfs->applyButton, SIGNAL(clicked()), this, SLOT(applySettings()));
+ connect(lfs->cancelButton, SIGNAL(clicked()), lfs, SLOT(reject()));
+
+ connect(lfs->fontButton, SIGNAL(clicked()), this, SLOT(settingsFontSelection()));
+ connect(lfs->addButton, SIGNAL(clicked()), this, SLOT(settingsAddRule()));
+ connect(lfs->deleteButton, SIGNAL(clicked()), this, SLOT(settingsDeleteRule()));
+ connect(lfs->changeButton, SIGNAL(clicked()), this, SLOT(settingsChangeRule()));
+ connect(lfs->ruleList, SIGNAL(selected(int)), this, SLOT(settingsRuleListSelected(int)));
+ connect(lfs->ruleText, SIGNAL(returnPressed()), this, SLOT(settingsAddRule()));
+
+ if (lfs->exec()) {
+ applySettings();
+ }
+
+ delete lfs;
+ lfs = 0;
+}
+
+void LogFile::settingsFontSelection()
+{
+ QFont tmpFont = lfs->fontButton->font();
+
+ if (KFontDialog::getFont(tmpFont) == KFontDialog::Accepted) {
+ lfs->fontButton->setFont(tmpFont);
+ }
+}
+
+void LogFile::settingsAddRule()
+{
+ if (!lfs->ruleText->text().isEmpty()) {
+ lfs->ruleList->insertItem(lfs->ruleText->text(), -1);
+ lfs->ruleText->setText("");
+ }
+}
+
+void LogFile::settingsDeleteRule()
+{
+ lfs->ruleList->removeItem(lfs->ruleList->currentItem());
+ lfs->ruleText->setText("");
+}
+
+void LogFile::settingsChangeRule()
+{
+ lfs->ruleList->changeItem(lfs->ruleText->text(), lfs->ruleList->currentItem());
+ lfs->ruleText->setText("");
+}
+
+void LogFile::settingsRuleListSelected(int index)
+{
+ lfs->ruleText->setText(lfs->ruleList->text(index));
+}
+
+void LogFile::applySettings(void)
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ cgroup.setColor(QColorGroup::Text, lfs->fgColor->color());
+ cgroup.setColor(QColorGroup::Base, lfs->bgColor->color());
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+ monitor->setFont(lfs->fontButton->font());
+
+ filterRules.clear();
+ for (uint i = 0; i < lfs->ruleList->count(); i++)
+ filterRules.append(lfs->ruleList->text(i));
+
+ setTitle(lfs->title->text());
+
+ setModified(true);
+}
+
+void
+LogFile::applyStyle()
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ cgroup.setColor(QColorGroup::Text, KSGRD::Style->firstForegroundColor());
+ cgroup.setColor(QColorGroup::Base, KSGRD::Style->backgroundColor());
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+
+ setModified(true);
+}
+
+bool
+LogFile::restoreSettings(QDomElement& element)
+{
+ QFont font;
+ QColorGroup cgroup = monitor->colorGroup();
+
+ cgroup.setColor(QColorGroup::Text, restoreColor(element, "textColor", Qt::green));
+ cgroup.setColor(QColorGroup::Base, restoreColor(element, "backgroundColor", Qt::black));
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+
+ addSensor(element.attribute("hostName"), element.attribute("sensorName"), (element.attribute("sensorType").isEmpty() ? "logfile" : element.attribute("sensorType")), element.attribute("title"));
+
+ font.fromString( element.attribute( "font" ) );
+ monitor->setFont(font);
+
+ QDomNodeList dnList = element.elementsByTagName("filter");
+ for (uint i = 0; i < dnList.count(); i++) {
+ QDomElement element = dnList.item(i).toElement();
+ filterRules.append(element.attribute("rule"));
+ }
+
+ SensorDisplay::restoreSettings(element);
+
+ setModified(false);
+
+ return true;
+}
+
+bool
+LogFile::saveSettings(QDomDocument& doc, QDomElement& element, bool save)
+{
+ element.setAttribute("hostName", sensors().at(0)->hostName());
+ element.setAttribute("sensorName", sensors().at(0)->name());
+ element.setAttribute("sensorType", sensors().at(0)->type());
+
+ element.setAttribute("font", monitor->font().toString());
+
+ saveColor(element, "textColor", monitor->colorGroup().text());
+ saveColor(element, "backgroundColor", monitor->colorGroup().base());
+
+ for (QStringList::Iterator it = filterRules.begin();
+ it != filterRules.end(); it++)
+ {
+ QDomElement filter = doc.createElement("filter");
+ filter.setAttribute("rule", (*it));
+ element.appendChild(filter);
+ }
+
+ SensorDisplay::saveSettings(doc, element);
+
+ if (save)
+ setModified(false);
+
+ return true;
+}
+
+void
+LogFile::updateMonitor()
+{
+ sendRequest(sensors().at(0)->hostName(),
+ QString("%1 %2" ).arg(sensors().at(0)->name()).arg(logFileID), 19);
+}
+
+void
+LogFile::answerReceived(int id, const QString& answer)
+{
+ /* We received something, so the sensor is probably ok. */
+ sensorError(id, false);
+
+ switch (id)
+ {
+ case 19: {
+ KSGRD::SensorTokenizer lines(answer, '\n');
+
+ for (uint i = 0; i < lines.count(); i++) {
+ if (monitor->count() == MAXLINES)
+ monitor->removeItem(0);
+
+ monitor->insertItem(lines[i], -1);
+
+ for (QStringList::Iterator it = filterRules.begin(); it != filterRules.end(); it++) {
+ QRegExp *expr = new QRegExp((*it).latin1());
+ if (expr->search(lines[i].latin1()) != -1) {
+ KNotifyClient::event(winId(), "pattern_match", QString("rule '%1' matched").arg((*it).latin1()));
+ }
+ delete expr;
+ }
+ }
+
+ monitor->setCurrentItem( monitor->count() - 1 );
+ monitor->ensureCurrentVisible();
+
+ break;
+ }
+
+ case 42: {
+ logFileID = answer.toULong();
+ break;
+ }
+ }
+}
+
+void
+LogFile::resizeEvent(QResizeEvent*)
+{
+ frame()->setGeometry(0, 0, this->width(), this->height());
+ monitor->setGeometry(10, 20, this->width() - 20, this->height() - 30);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/LogFile.h b/ksysguard/gui/SensorDisplayLib/LogFile.h
new file mode 100644
index 000000000..9428f934d
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/LogFile.h
@@ -0,0 +1,85 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _LogFile_h
+#define _LogFile_h
+
+#define MAXLINES 500
+
+class QFile;
+class QListBox;
+
+#include <qdom.h>
+#include <qpopupmenu.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include <SensorDisplay.h>
+
+#include "LogFileSettings.h"
+
+class LogFile : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+public:
+ LogFile(QWidget *parent = 0, const char *name = 0, const QString& title = 0);
+ ~LogFile(void);
+
+ bool addSensor(const QString& hostName, const QString& sensorName,
+ const QString& sensorType, const QString& sensorDescr);
+ void answerReceived(int id, const QString& answer);
+ void resizeEvent(QResizeEvent*);
+
+ bool restoreSettings(QDomElement& element);
+ bool saveSettings(QDomDocument& doc, QDomElement& element, bool save = true);
+
+ void updateMonitor(void);
+
+ void configureSettings(void);
+
+ virtual void timerEvent(QTimerEvent*)
+ {
+ updateMonitor();
+ }
+
+ virtual bool hasSettingsDialog() const
+ {
+ return (true);
+ }
+
+public slots:
+ void applySettings();
+ void applyStyle();
+
+ void settingsFontSelection();
+ void settingsAddRule();
+ void settingsDeleteRule();
+ void settingsChangeRule();
+ void settingsRuleListSelected(int index);
+
+private:
+ LogFileSettings* lfs;
+ QListBox* monitor;
+ QStringList filterRules;
+
+ unsigned long logFileID;
+};
+
+#endif // _LogFile_h
diff --git a/ksysguard/gui/SensorDisplayLib/LogFileSettings.ui b/ksysguard/gui/SensorDisplayLib/LogFileSettings.ui
new file mode 100644
index 000000000..b5dcff0ee
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/LogFileSettings.ui
@@ -0,0 +1,345 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>LogFileSettings</class>
+<author>Tobias Koenig &lt;tokoe@kde.org&gt;</author>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>LogFileSettings</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>438</width>
+ <height>320</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Log File Settings</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>TabWidget</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Text</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox8</cstring>
+ </property>
+ <property name="title">
+ <string>Title</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>title</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>styleGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Colors</string>
+ </property>
+ <property name="exclusive">
+ <bool>true</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Foreground color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>fgColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>bgColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox11</cstring>
+ </property>
+ <property name="title">
+ <string>Font</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer14</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>fontButton</cstring>
+ </property>
+ <property name="text">
+ <string>Select Font...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Filter</string>
+ </attribute>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout7</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>ruleText</cstring>
+ </property>
+ </widget>
+ <widget class="QListBox">
+ <property name="name">
+ <cstring>ruleList</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout9</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>addButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Add</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>deleteButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Delete</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>changeButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Change</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer7_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>okButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>applyButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Apply</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>cancelButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<tabstops>
+ <tabstop>okButton</tabstop>
+ <tabstop>applyButton</tabstop>
+ <tabstop>cancelButton</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+</UI>
diff --git a/ksysguard/gui/SensorDisplayLib/Makefile.am b/ksysguard/gui/SensorDisplayLib/Makefile.am
new file mode 100644
index 000000000..a1327a4ac
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/Makefile.am
@@ -0,0 +1,39 @@
+
+# set the include path for X, qt and KDE
+INCLUDES= -I$(srcdir)/.. -I$(srcdir)/../ksgrd -I../ksgrd $(all_includes)
+
+noinst_LTLIBRARIES = libsensordisplays.la
+
+libsensordisplays_la_LDFLAGS = $(all_libraries) -no-undefined
+libsensordisplays_la_LIBADD = ../ksgrd/libksgrd.la $(LIB_KIO)
+
+# Which sources should be compiled for the sensor display lib.
+libsensordisplays_la_SOURCES = \
+ SensorDisplay.cc \
+ BarGraph.cc \
+ DancingBars.cc \
+ DancingBarsSettings.cc \
+ DummyDisplay.cc \
+ FancyPlotter.cc \
+ FancyPlotterSettings.cc \
+ ListView.cc \
+ LogFile.cc \
+ MultiMeter.cc \
+ MultiMeterSettings.cc \
+ ProcessController.cc \
+ ProcessList.cc \
+ ReniceDlg.cc \
+ SensorLogger.cc \
+ SensorLoggerDlg.cc \
+ SensorLoggerSettings.cc \
+ ListViewSettings.cc \
+ SignalPlotter.cc \
+ ListViewSettingsWidget.ui \
+ LogFileSettings.ui \
+ MultiMeterSettingsWidget.ui \
+ SensorLoggerDlgWidget.ui \
+ SensorLoggerSettingsWidget.ui
+
+# just to make sure, automake makes them
+METASOURCES = AUTO
+
diff --git a/ksysguard/gui/SensorDisplayLib/MultiMeter.cc b/ksysguard/gui/SensorDisplayLib/MultiMeter.cc
new file mode 100644
index 000000000..14e805b9d
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/MultiMeter.cc
@@ -0,0 +1,258 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000, 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <math.h>
+#include <stdlib.h>
+
+#include <qdom.h>
+#include <qlcdnumber.h>
+#include <qtooltip.h>
+
+#include <kdebug.h>
+
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+
+#include "MultiMeter.moc"
+#include "MultiMeterSettings.h"
+
+MultiMeter::MultiMeter(QWidget* parent, const char* name,
+ const QString& title, double, double, bool nf, bool isApplet)
+ : KSGRD::SensorDisplay(parent, name, title, nf, isApplet)
+{
+ setShowUnit( true );
+ lowerLimit = upperLimit = 0;
+ lowerLimitActive = upperLimitActive = false;
+
+ normalDigitColor = KSGRD::Style->firstForegroundColor();
+ alarmDigitColor = KSGRD::Style->alarmColor();
+ if (noFrame())
+ lcd = new QLCDNumber(this, "meterLCD");
+ else
+ lcd = new QLCDNumber(frame(), "meterLCD");
+ Q_CHECK_PTR(lcd);
+ lcd->setSegmentStyle(QLCDNumber::Filled);
+ setDigitColor(KSGRD::Style->backgroundColor());
+ lcd->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,
+ QSizePolicy::Expanding, false));
+
+ setBackgroundColor(KSGRD::Style->backgroundColor());
+ /* All RMB clicks to the lcd widget will be handled by
+ * SensorDisplay::eventFilter. */
+ lcd->installEventFilter(this);
+
+ setPlotterWidget(lcd);
+
+ setMinimumSize(5, 5);
+ setModified(false);
+}
+
+bool
+MultiMeter::addSensor(const QString& hostName, const QString& sensorName,
+ const QString& sensorType, const QString& title)
+{
+ if (sensorType != "integer" && sensorType != "float")
+ return (false);
+
+ registerSensor(new KSGRD::SensorProperties(hostName, sensorName, sensorType, title));
+
+ /* To differentiate between answers from value requests and info
+ * requests we use 100 for info requests. */
+ sendRequest(hostName, sensorName + "?", 100);
+
+ QToolTip::remove(lcd);
+ QToolTip::add(lcd, QString("%1:%2").arg(hostName).arg(sensorName));
+
+ setModified(true);
+ return (true);
+}
+
+void
+MultiMeter::answerReceived(int id, const QString& answer)
+{
+ /* We received something, so the sensor is probably ok. */
+ sensorError(id, false);
+
+ if (id == 100)
+ {
+ KSGRD::SensorIntegerInfo info(answer);
+ setUnit(KSGRD::SensorMgr->translateUnit(info.unit()));
+ }
+ else
+ {
+ double val = answer.toDouble();
+ int digits = (int) log10(val) + 1;
+
+ if (noFrame())
+ if (digits > 4)
+ lcd->setNumDigits(4);
+ else
+ lcd->setNumDigits(digits);
+ else
+ {
+ if (digits > 5)
+ lcd->setNumDigits(digits);
+ else
+ lcd->setNumDigits(5);
+ }
+
+ lcd->display(val);
+ if (lowerLimitActive && val < lowerLimit)
+ {
+ setDigitColor(alarmDigitColor);
+ }
+ else if (upperLimitActive && val > upperLimit)
+ {
+ setDigitColor(alarmDigitColor);
+ }
+ else
+ setDigitColor(normalDigitColor);
+ }
+}
+
+void
+MultiMeter::resizeEvent(QResizeEvent*)
+{
+ if (noFrame())
+ lcd->setGeometry(0, 0, width(), height());
+ else
+ frame()->setGeometry(0, 0, width(), height());
+}
+
+bool
+MultiMeter::restoreSettings(QDomElement& element)
+{
+ lowerLimitActive = element.attribute("lowerLimitActive").toInt();
+ lowerLimit = element.attribute("lowerLimit").toLong();
+ upperLimitActive = element.attribute("upperLimitActive").toInt();
+ upperLimit = element.attribute("upperLimit").toLong();
+
+ normalDigitColor = restoreColor(element, "normalDigitColor",
+ KSGRD::Style->firstForegroundColor());
+ alarmDigitColor = restoreColor(element, "alarmDigitColor",
+ KSGRD::Style->alarmColor());
+ setBackgroundColor(restoreColor(element, "backgroundColor",
+ KSGRD::Style->backgroundColor()));
+
+ addSensor(element.attribute("hostName"), element.attribute("sensorName"), (element.attribute("sensorType").isEmpty() ? "integer" : element.attribute("sensorType")), "");
+
+ SensorDisplay::restoreSettings(element);
+
+ setModified(false);
+
+ return (true);
+}
+
+bool
+MultiMeter::saveSettings(QDomDocument& doc, QDomElement& element, bool save)
+{
+ element.setAttribute("hostName", sensors().at(0)->hostName());
+ element.setAttribute("sensorName", sensors().at(0)->name());
+ element.setAttribute("sensorType", sensors().at(0)->type());
+ element.setAttribute("showUnit", showUnit());
+ element.setAttribute("lowerLimitActive", (int) lowerLimitActive);
+ element.setAttribute("lowerLimit", (int) lowerLimit);
+ element.setAttribute("upperLimitActive", (int) upperLimitActive);
+ element.setAttribute("upperLimit", (int) upperLimit);
+
+ saveColor(element, "normalDigitColor", normalDigitColor);
+ saveColor(element, "alarmDigitColor", alarmDigitColor);
+ saveColor(element, "backgroundColor", lcd->backgroundColor());
+
+ SensorDisplay::saveSettings(doc, element);
+
+ if (save)
+ setModified(false);
+
+ return (true);
+}
+
+void
+MultiMeter::configureSettings()
+{
+ mms = new MultiMeterSettings(this, "MultiMeterSettings");
+ Q_CHECK_PTR(mms);
+ mms->setTitle(title());
+ mms->setShowUnit(showUnit());
+ mms->setLowerLimitActive(lowerLimitActive);
+ mms->setLowerLimit(lowerLimit);
+ mms->setUpperLimitActive(upperLimitActive);
+ mms->setUpperLimit(upperLimit);
+ mms->setNormalDigitColor(normalDigitColor);
+ mms->setAlarmDigitColor(alarmDigitColor);
+ mms->setMeterBackgroundColor(lcd->backgroundColor());
+
+ connect(mms, SIGNAL(applyClicked()), SLOT(applySettings()));
+
+ if (mms->exec())
+ applySettings();
+
+ delete mms;
+ mms = 0;
+}
+
+void
+MultiMeter::applySettings()
+{
+ setShowUnit( mms->showUnit() );
+ setTitle(mms->title());
+ lowerLimitActive = mms->lowerLimitActive();
+ lowerLimit = mms->lowerLimit();
+ upperLimitActive = mms->upperLimitActive();
+ upperLimit = mms->upperLimit();
+
+ normalDigitColor = mms->normalDigitColor();
+ alarmDigitColor = mms->alarmDigitColor();
+ setBackgroundColor(mms->meterBackgroundColor());
+
+ repaint();
+ setModified(true);
+}
+
+void
+MultiMeter::applyStyle()
+{
+ normalDigitColor = KSGRD::Style->firstForegroundColor();
+ setBackgroundColor(KSGRD::Style->backgroundColor());
+ repaint();
+ setModified(true);
+}
+
+void
+MultiMeter::setDigitColor(const QColor& col)
+{
+ QPalette p = lcd->palette();
+ p.setColor(QColorGroup::Foreground, col);
+ lcd->setPalette(p);
+}
+
+void
+MultiMeter::setBackgroundColor(const QColor& col)
+{
+ lcd->setBackgroundColor(col);
+
+ QPalette p = lcd->palette();
+ p.setColor(QColorGroup::Light, col);
+ p.setColor(QColorGroup::Dark, col);
+ lcd->setPalette(p);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/MultiMeter.h b/ksysguard/gui/SensorDisplayLib/MultiMeter.h
new file mode 100644
index 000000000..58d2477c1
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/MultiMeter.h
@@ -0,0 +1,79 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef _MultiMeter_h_
+#define _MultiMeter_h_
+
+#include <SensorDisplay.h>
+
+class QGroupBox;
+class QLCDNumber;
+class QLabel;
+class MultiMeterSettings;
+
+class MultiMeter : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+
+public:
+ MultiMeter(QWidget* parent = 0, const char* name = 0,
+ const QString& = QString::null, double min = 0, double max = 0, bool nf = false, bool isApplet = false);
+ virtual ~MultiMeter()
+ {
+ }
+
+ bool addSensor(const QString& hostName, const QString& sensorName,
+ const QString& sensorType, const QString& sensorDescr);
+ void answerReceived(int id, const QString& answer);
+ void resizeEvent(QResizeEvent*);
+
+ bool restoreSettings(QDomElement& element);
+ bool saveSettings(QDomDocument& doc, QDomElement& element, bool save = true);
+
+ virtual bool hasSettingsDialog() const
+ {
+ return (true);
+ }
+
+ void configureSettings();
+
+public slots:
+ void applySettings();
+ void applyStyle();
+
+private:
+ void setDigitColor(const QColor& col);
+ void setBackgroundColor(const QColor& col);
+
+ QLCDNumber* lcd;
+ QColor normalDigitColor;
+ QColor alarmDigitColor;
+
+ MultiMeterSettings* mms;
+ bool lowerLimitActive;
+ double lowerLimit;
+ bool upperLimitActive;
+ double upperLimit;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/MultiMeterSettings.cc b/ksysguard/gui/SensorDisplayLib/MultiMeterSettings.cc
new file mode 100644
index 000000000..9114c583b
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/MultiMeterSettings.cc
@@ -0,0 +1,127 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "MultiMeterSettings.h"
+#include "MultiMeterSettingsWidget.h"
+
+#include <klocale.h>
+
+MultiMeterSettings::MultiMeterSettings( QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n( "Multimeter Settings" ),
+ Ok|Apply|Cancel, Ok, true )
+{
+ m_settingsWidget = new MultiMeterSettingsWidget( this, "m_settingsWidget" );
+ setMainWidget( m_settingsWidget );
+}
+
+QString MultiMeterSettings::title()
+{
+ return m_settingsWidget->title();
+}
+
+bool MultiMeterSettings::showUnit()
+{
+ return m_settingsWidget->showUnit();
+}
+
+bool MultiMeterSettings::lowerLimitActive()
+{
+ return m_settingsWidget->lowerLimitActive();
+}
+
+bool MultiMeterSettings::upperLimitActive()
+{
+ return m_settingsWidget->upperLimitActive();
+}
+
+double MultiMeterSettings::lowerLimit()
+{
+ return m_settingsWidget->lowerLimit();
+}
+
+double MultiMeterSettings::upperLimit()
+{
+ return m_settingsWidget->upperLimit();
+}
+
+QColor MultiMeterSettings::normalDigitColor()
+{
+ return m_settingsWidget->normalDigitColor();
+}
+
+QColor MultiMeterSettings::alarmDigitColor()
+{
+ return m_settingsWidget->alarmDigitColor();
+}
+
+QColor MultiMeterSettings::meterBackgroundColor()
+{
+ return m_settingsWidget->meterBackgroundColor();
+}
+
+void MultiMeterSettings::setTitle( const QString &title )
+{
+ m_settingsWidget->setTitle( title );
+}
+
+void MultiMeterSettings::setShowUnit( bool b )
+{
+ m_settingsWidget->setShowUnit( b );
+}
+
+void MultiMeterSettings::setLowerLimitActive( bool b )
+{
+ m_settingsWidget->setLowerLimitActive( b );
+}
+
+void MultiMeterSettings::setUpperLimitActive( bool b )
+{
+ m_settingsWidget->setUpperLimitActive( b );
+}
+
+void MultiMeterSettings::setLowerLimit( double limit )
+{
+ m_settingsWidget->setLowerLimit( limit );
+}
+
+void MultiMeterSettings::setUpperLimit( double limit )
+{
+ m_settingsWidget->setUpperLimit( limit );
+}
+
+void MultiMeterSettings::setNormalDigitColor( const QColor &c )
+{
+ m_settingsWidget->setNormalDigitColor( c );
+}
+
+void MultiMeterSettings::setAlarmDigitColor( const QColor &c )
+{
+ m_settingsWidget->setAlarmDigitColor( c );
+}
+
+void MultiMeterSettings::setMeterBackgroundColor( const QColor &c )
+{
+ m_settingsWidget->setMeterBackgroundColor( c );
+}
+
+#include "MultiMeterSettings.moc"
+
+/* vim: et sw=2 ts=2
+*/
+
diff --git a/ksysguard/gui/SensorDisplayLib/MultiMeterSettings.h b/ksysguard/gui/SensorDisplayLib/MultiMeterSettings.h
new file mode 100644
index 000000000..516a02128
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/MultiMeterSettings.h
@@ -0,0 +1,68 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef MULTIMETERSETTINGS_H
+#define MULTIMETERSETTINGS_H
+
+#include <kdialogbase.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+
+class MultiMeterSettingsWidget;
+
+class MultiMeterSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+
+ MultiMeterSettings( QWidget *parent=0, const char *name=0 );
+
+ QString title();
+ bool showUnit();
+ bool lowerLimitActive();
+ bool upperLimitActive();
+ double lowerLimit();
+ double upperLimit();
+ QColor normalDigitColor();
+ QColor alarmDigitColor();
+ QColor meterBackgroundColor();
+
+ void setTitle( const QString & );
+ void setShowUnit( bool );
+ void setLowerLimitActive( bool );
+ void setUpperLimitActive( bool );
+ void setLowerLimit( double );
+ void setUpperLimit( double );
+ void setNormalDigitColor( const QColor & );
+ void setAlarmDigitColor( const QColor & );
+ void setMeterBackgroundColor( const QColor & );
+
+ private:
+
+ MultiMeterSettingsWidget *m_settingsWidget;
+};
+
+#endif // MULTIMETERSETTINGS_H
+
+/* vim: et sw=2 ts=2
+*/
+
diff --git a/ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui b/ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui
new file mode 100644
index 000000000..7ecdef88f
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui
@@ -0,0 +1,475 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>MultiMeterSettingsWidget</class>
+<comment>MultiMeterSettingsWidget</comment>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>MultiMeterSettingsWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>378</width>
+ <height>229</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox7</cstring>
+ </property>
+ <property name="title">
+ <string>Title</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit" row="0" column="0">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the title of the display here.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>m_showUnit</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Show unit</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enable this to append the unit to the title of the display.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>TabWidget2</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Alarms</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>GroupBox1_2</cstring>
+ </property>
+ <property name="title">
+ <string>Alarm for Maximum Value</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>m_upperLimitActive</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;nable alarm</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enable the maximum value alarm.</string>
+ </property>
+ </widget>
+ <spacer row="0" column="1">
+ <property name="name">
+ <cstring>Spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>m_lblUpperLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Upper limit:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="3">
+ <property name="name">
+ <cstring>m_upperLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Alarm for Minimum Value</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>m_lowerLimitActive</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Enable alarm</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enable the minimum value alarm.</string>
+ </property>
+ </widget>
+ <spacer row="0" column="1">
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>m_lblLowerLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Lower limit:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="3">
+ <property name="name">
+ <cstring>m_lowerLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Colors</string>
+ </attribute>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Normal digit color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Alarm digit color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_normalDigitColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_alarmDigitColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_backgroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KColorButton</class>
+ <header location="local">kcolorbutton.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ <signal>destroyed()</signal>
+ <signal>destroyed(QObject*)</signal>
+ <signal>pressed()</signal>
+ <signal>released()</signal>
+ <signal>clicked()</signal>
+ <signal>toggled(bool)</signal>
+ <signal>stateChanged(int)</signal>
+ <signal>changed(const QColor&amp;)</signal>
+ <slot access="public" specifier="">deleteLater()</slot>
+ <slot access="private" specifier="">cleanupEventFilter(QObject*)</slot>
+ <slot access="public" specifier="">setEnabled(bool)</slot>
+ <slot access="public" specifier="">setDisabled(bool)</slot>
+ <slot access="public" specifier="">setCaption(const QString&amp;)</slot>
+ <slot access="public" specifier="">setIcon(const QPixmap&amp;)</slot>
+ <slot access="public" specifier="">setIconText(const QString&amp;)</slot>
+ <slot access="public" specifier="">setMouseTracking(bool)</slot>
+ <slot access="public" specifier="">setFocus()</slot>
+ <slot access="public" specifier="">clearFocus()</slot>
+ <slot access="public" specifier="">setUpdatesEnabled(bool)</slot>
+ <slot access="public" specifier="">update()</slot>
+ <slot access="public" specifier="">update(int,int,int,int)</slot>
+ <slot access="public" specifier="">update(const QRect&amp;)</slot>
+ <slot access="public" specifier="">repaint()</slot>
+ <slot access="public" specifier="">repaint(bool)</slot>
+ <slot access="public" specifier="">repaint(int,int,int,int)</slot>
+ <slot access="public" specifier="">repaint(int,int,int,int,bool)</slot>
+ <slot access="public" specifier="">repaint(const QRect&amp;)</slot>
+ <slot access="public" specifier="">repaint(const QRect&amp;,bool)</slot>
+ <slot access="public" specifier="">repaint(const QRegion&amp;)</slot>
+ <slot access="public" specifier="">repaint(const QRegion&amp;,bool)</slot>
+ <slot access="public" specifier="">show()</slot>
+ <slot access="public" specifier="">hide()</slot>
+ <slot access="public" specifier="">setShown(bool)</slot>
+ <slot access="public" specifier="">setHidden(bool)</slot>
+ <slot access="public" specifier="">iconify()</slot>
+ <slot access="public" specifier="">showMinimized()</slot>
+ <slot access="public" specifier="">showMaximized()</slot>
+ <slot access="public" specifier="">showFullScreen()</slot>
+ <slot access="public" specifier="">showNormal()</slot>
+ <slot access="public" specifier="">polish()</slot>
+ <slot access="public" specifier="">constPolish()</slot>
+ <slot access="public" specifier="">close()</slot>
+ <slot access="public" specifier="">raise()</slot>
+ <slot access="public" specifier="">lower()</slot>
+ <slot access="public" specifier="">stackUnder(QWidget*)</slot>
+ <slot access="public" specifier="">move(int,int)</slot>
+ <slot access="public" specifier="">move(const QPoint&amp;)</slot>
+ <slot access="public" specifier="">resize(int,int)</slot>
+ <slot access="public" specifier="">resize(const QSize&amp;)</slot>
+ <slot access="public" specifier="">setGeometry(int,int,int,int)</slot>
+ <slot access="public" specifier="">setGeometry(const QRect&amp;)</slot>
+ <slot access="public" specifier="">adjustSize()</slot>
+ <slot access="private" specifier="">focusProxyDestroyed()</slot>
+ <slot access="public" specifier="">animateClick()</slot>
+ <slot access="public" specifier="">toggle()</slot>
+ <slot access="private" specifier="">animateTimeout()</slot>
+ <slot access="private" specifier="">autoRepeatTimeout()</slot>
+ <slot access="private" specifier="">emulateClick()</slot>
+ <slot access="public" specifier="">setOn(bool)</slot>
+ <slot access="private" specifier="">popupPressed()</slot>
+ <slot access="protected" specifier="">chooseColor()</slot>
+ <property type="CString">name</property>
+ <property type="Bool">enabled</property>
+ <property type="Rect">geometry</property>
+ <property type="SizePolicy">sizePolicy</property>
+ <property type="Size">minimumSize</property>
+ <property type="Size">maximumSize</property>
+ <property type="Size">sizeIncrement</property>
+ <property type="Size">baseSize</property>
+ <property type="Color">paletteForegroundColor</property>
+ <property type="Color">paletteBackgroundColor</property>
+ <property type="Pixmap">paletteBackgroundPixmap</property>
+ <property type="Palette">palette</property>
+ <property type="BackgroundOrigin">backgroundOrigin</property>
+ <property type="Font">font</property>
+ <property type="Cursor">cursor</property>
+ <property type="String">caption</property>
+ <property type="Pixmap">icon</property>
+ <property type="String">iconText</property>
+ <property type="Bool">mouseTracking</property>
+ <property type="FocusPolicy">focusPolicy</property>
+ <property type="Bool">acceptDrops</property>
+ <property type="String">text</property>
+ <property type="Pixmap">pixmap</property>
+ <property type="KeySequence">accel</property>
+ <property type="Bool">autoRepeat</property>
+ <property type="Bool">autoDefault</property>
+ <property type="Bool">default</property>
+ <property type="IconSet">iconSet</property>
+ <property type="Bool">toggleButton</property>
+ <property type="Bool">on</property>
+ <property type="Bool">flat</property>
+ <property type="Bool">autoMask</property>
+ <property type="Color">color</property>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="827">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000030249444154789cad953188db6614c77f0e1a9ee0029fc10509ae20c30de7d1852e4733f846d30c2e74483aa5812ea54bba35590a693a640e1d0e0e0ae16e282443e1321cd499eca5d4072951e10af26090e00ef40d013d88411d3ed967f91228e4de22f4e97dbff7d7ff7b7a6a9465c9221a8d0657116559d258801ffcf080ce76076b6d996629f99bfc7f41acb524a709e33fc73067a9cc5b287dfaeb53c28f294dbb2042d1b9228b0ccf25fbd5b598afec9ec33401dd13262fb50407f7562a97a65d90d923f23c0114df578ab7423613f2730584660bda6d453640ab02721dc210262b6fb204a7594a8456508bef0baf5f1986bf5be2130b68952944dbc2eec0b0d303e66e5da46ed1129cbfc9d1b92ea1a3211cfc92b94d1b427bdb201ea43365fa8fb2ff73463635dcbe232b45df01765ac0f7e1f52ba9a04aeff380fe40687e0488a21a327a5170b097717498110411fd2f9b80ad81afad9729de0ac3e77609fdea1ba1195a104b7e26fcf13ca73ff0f9fabb00109e1d5aecf9bac4f55b0fb29910ff6d31c6d01f0878163c506bd87facc42796fc0ceede6b323e76b971ec6c7abf62a84e5f09a3eaf52be89347ee104d4bf8e48620a6a0d37527964eb532f23d60d7a72e41c4799aa786278f94f8c4151481f6a6ef9e7b0b985cb2e292e266cb25263345b5c9f8254ea91182c090cd2c0fefa7c49326e9a9eb8630f2d731f53ac5dc357fb4254cff55462f0afab77cf233c3ce0d21dcf479781fb2a9e5a76f135415d312badd8274566fb94b8a6503fa0303c0c15ec6e8b8e0eebd26dd1e44dd9cef7f6c630283b5169d2bbb838070eb92e07567dc67bad3836c66787698b1ff38637c2c743a0202e9698a9eeb72e75f434b723344bcfa87b23a2b2ee0285fdc114c1071f49beb86f8e4a2b86909fd41c46868b1aaa882b5752b96e0e434619a00d72fe0fd81b0d30b8963433a75ebe1a64ff7d382700b766f864ea497134feae04659966ec07b94ddcf8430ac5a6dce7264caa20d6bc629e209d6423c51d24cb16eb434ea6017251f16f541ffae071f1ad7c0fda3ae3a967d7c95f0b22cf90f71e859c3d57176e60000000049454e44ae426082</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>m_lowerLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_lowerLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_upperLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_upperLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_lowerLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_lblLowerLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_upperLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_lblUpperLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+ <include location="global" impldecl="in implementation">knumvalidator.h</include>
+ <include location="local" impldecl="in implementation">MultiMeterSettingsWidget.ui.h</include>
+</includes>
+<slots>
+ <slot>setMeterBackgroundColor( const QColor &amp; c )</slot>
+</slots>
+<functions>
+ <function access="private" specifier="non virtual">init()</function>
+ <function specifier="non virtual" returnType="QString">title()</function>
+ <function specifier="non virtual" returnType="bool">showUnit()</function>
+ <function returnType="bool">lowerLimitActive()</function>
+ <function specifier="non virtual" returnType="double">lowerLimit()</function>
+ <function returnType="bool">upperLimitActive()</function>
+ <function returnType="double">upperLimit()</function>
+ <function specifier="non virtual" returnType="QColor">normalDigitColor()</function>
+ <function specifier="non virtual" returnType="QColor">alarmDigitColor()</function>
+ <function returnType="QColor">meterBackgroundColor()</function>
+ <function specifier="non virtual">setTitle( const QString &amp; s )</function>
+ <function specifier="non virtual">setShowUnit( bool b )</function>
+ <function specifier="non virtual">setLowerLimitActive( bool b )</function>
+ <function specifier="non virtual">setLowerLimit( double d )</function>
+ <function specifier="non virtual">setUpperLimitActive( bool b )</function>
+ <function specifier="non virtual">setUpperLimit( double d )</function>
+ <function specifier="non virtual">setNormalDigitColor( const QColor &amp; c )</function>
+ <function specifier="non virtual">setAlarmDigitColor( const QColor &amp; c )</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui.h b/ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui.h
new file mode 100644
index 000000000..81d6e73f6
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+void MultiMeterSettingsWidget::init()
+{
+ m_lowerLimit->setValidator(new KDoubleValidator(m_lowerLimit));
+ m_upperLimit->setValidator(new KDoubleValidator(m_upperLimit));
+
+ m_title->setFocus();
+}
+
+QString MultiMeterSettingsWidget::title()
+{
+ return m_title->text();
+}
+
+
+bool MultiMeterSettingsWidget::showUnit()
+{
+ return m_showUnit->isChecked();
+}
+
+
+bool MultiMeterSettingsWidget::lowerLimitActive()
+{
+ return m_lowerLimitActive->isChecked();
+}
+
+
+double MultiMeterSettingsWidget::lowerLimit()
+{
+ return m_lowerLimit->text().toDouble();
+}
+
+
+bool MultiMeterSettingsWidget::upperLimitActive()
+{
+ return m_upperLimitActive->isChecked();
+}
+
+
+double MultiMeterSettingsWidget::upperLimit()
+{
+ return m_upperLimit->text().toDouble();
+}
+
+
+QColor MultiMeterSettingsWidget::normalDigitColor()
+{
+ return m_normalDigitColor->color();
+}
+
+
+QColor MultiMeterSettingsWidget::alarmDigitColor()
+{
+ return m_alarmDigitColor->color();
+}
+
+
+QColor MultiMeterSettingsWidget::meterBackgroundColor()
+{
+ return m_backgroundColor->color();
+}
+
+
+void MultiMeterSettingsWidget::setTitle( const QString &s )
+{
+ m_title->setText(s);
+}
+
+
+void MultiMeterSettingsWidget::setShowUnit( bool b )
+{
+ m_showUnit->setChecked(b);
+}
+
+
+void MultiMeterSettingsWidget::setLowerLimitActive( bool b )
+{
+ m_lowerLimitActive->setChecked(b);
+}
+
+
+void MultiMeterSettingsWidget::setLowerLimit( double d )
+{
+ m_lowerLimit->setText(QString("%1").arg(d));
+}
+
+
+void MultiMeterSettingsWidget::setUpperLimitActive( bool b )
+{
+ m_upperLimitActive->setChecked(b);
+}
+
+
+void MultiMeterSettingsWidget::setUpperLimit( double d )
+{
+ m_upperLimit->setText(QString("%1").arg(d));
+}
+
+
+void MultiMeterSettingsWidget::setNormalDigitColor( const QColor &c )
+{
+ m_normalDigitColor->setColor(c);
+}
+
+
+void MultiMeterSettingsWidget::setAlarmDigitColor( const QColor &c )
+{
+ m_alarmDigitColor->setColor(c);
+}
+
+
+void MultiMeterSettingsWidget::setMeterBackgroundColor( const QColor &c )
+{
+ m_backgroundColor->setColor(c);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/ProcessController.cc b/ksysguard/gui/SensorDisplayLib/ProcessController.cc
new file mode 100644
index 000000000..b9fcd4f06
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ProcessController.cc
@@ -0,0 +1,472 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms version 2 of of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <assert.h>
+
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdialogbase.h>
+#include <klistviewsearchline.h>
+
+#include <ksgrd/SensorManager.h>
+
+#include "ProcessController.moc"
+#include "SignalIDs.h"
+
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qgroupbox.h>
+#include <qlayout.h>
+
+#include <kapplication.h>
+#include <kpushbutton.h>
+
+
+
+ProcessController::ProcessController(QWidget* parent, const char* name, const QString &title, bool nf)
+ : KSGRD::SensorDisplay(parent, name, title, nf)
+{
+ dict.setAutoDelete(true);
+ dict.insert("Name", new QString(i18n("Name")));
+ dict.insert("PID", new QString(i18n("PID")));
+ dict.insert("PPID", new QString(i18n("PPID")));
+ dict.insert("UID", new QString(i18n("UID")));
+ dict.insert("GID", new QString(i18n("GID")));
+ dict.insert("Status", new QString(i18n("Status")));
+ dict.insert("User%", new QString(i18n("User%")));
+ dict.insert("System%", new QString(i18n("System%")));
+ dict.insert("Nice", new QString(i18n("Nice")));
+ dict.insert("VmSize", new QString(i18n("VmSize")));
+ dict.insert("VmRss", new QString(i18n("VmRss")));
+ dict.insert("Login", new QString(i18n("Login")));
+ dict.insert("Command", new QString(i18n("Command")));
+
+ // Setup the geometry management.
+ gm = new QVBoxLayout(this, 10);
+ Q_CHECK_PTR(gm);
+ gm->addSpacing(15);
+
+ gmSearch = new QHBoxLayout();
+ Q_CHECK_PTR(gmSearch);
+ gm->addLayout(gmSearch, 0);
+
+ // Create the table that lists the processes.
+ pList = new ProcessList(this, "pList");
+ Q_CHECK_PTR(pList);
+ pList->setShowSortIndicator(true);
+ pListSearchLine = new KListViewSearchLineWidget(pList, this, "process_list_search_line");
+ gmSearch->addWidget(pListSearchLine, 1);
+
+ connect(pList, SIGNAL(killProcess(int, int)),
+ this, SLOT(killProcess(int, int)));
+ connect(pList, SIGNAL(reniceProcess(const QValueList<int> &, int)),
+ this, SLOT(reniceProcess(const QValueList<int> &, int)));
+ connect(pList, SIGNAL(listModified(bool)),
+ this, SLOT(setModified(bool)));
+
+ /* Create the combo box to configure the process filter. The
+ * cbFilter must be created prior to constructing pList as the
+ * pList constructor sets cbFilter to its start value. */
+ cbFilter = new QComboBox(this, "pList_cbFilter");
+ Q_CHECK_PTR(cbFilter);
+ gmSearch->addWidget(cbFilter,0);
+ cbFilter->insertItem(i18n("All Processes"), 0);
+ cbFilter->insertItem(i18n("System Processes"), 1);
+ cbFilter->insertItem(i18n("User Processes"), 2);
+ cbFilter->insertItem(i18n("Own Processes"), 3);
+ cbFilter->setMinimumSize(cbFilter->sizeHint());
+ // Create the check box to switch between tree view and list view.
+ xbTreeView = new QCheckBox(i18n("&Tree"), this, "xbTreeView");
+ Q_CHECK_PTR(xbTreeView);
+ xbTreeView->setMinimumSize(xbTreeView->sizeHint());
+ connect(xbTreeView, SIGNAL(toggled(bool)),
+ this, SLOT(setTreeView(bool)));
+
+
+ /* When the both cbFilter and pList are constructed we can connect the
+ * missing link. */
+ connect(cbFilter, SIGNAL(activated(int)),
+ this, SLOT(filterModeChanged(int)));
+
+ // Create the 'Refresh' button.
+ bRefresh = new KPushButton( KGuiItem( i18n( "&Refresh" ), "reload" ),
+ this, "bRefresh" );
+ Q_CHECK_PTR(bRefresh);
+ bRefresh->setMinimumSize(bRefresh->sizeHint());
+ connect(bRefresh, SIGNAL(clicked()), this, SLOT(updateList()));
+
+ // Create the 'Kill' button.
+ bKill = new KPushButton(i18n("&Kill"), this, "bKill");
+ Q_CHECK_PTR(bKill);
+ bKill->setMinimumSize(bKill->sizeHint());
+ connect(bKill, SIGNAL(clicked()), this, SLOT(killProcess()));
+ /* Disable the kill button until we know that the daemon supports the
+ * kill command. */
+ bKill->setEnabled(false);
+ killSupported = false;
+
+ gm->addWidget(pList, 1);
+
+ gm1 = new QHBoxLayout();
+ Q_CHECK_PTR(gm1);
+ gm->addLayout(gm1, 0);
+ gm1->addStretch();
+ gm1->addWidget(xbTreeView);
+ gm1->addStretch();
+ gm1->addWidget(bRefresh);
+ gm1->addStretch();
+ gm1->addWidget(bKill);
+ gm1->addStretch();
+ gm->addSpacing(5);
+
+ gm->activate();
+
+ setPlotterWidget(pList);
+
+ setMinimumSize(sizeHint());
+ fixTabOrder();
+}
+
+void ProcessController::setSearchFocus() {
+ //stupid search line widget. See rant in fixTabOrder
+ if(!pListSearchLine->searchLine())
+ QTimer::singleShot(100, this, SLOT(setSearchFocus()));
+ else {
+ pListSearchLine->searchLine()->setFocus();
+ }
+}
+void ProcessController::fixTabOrder() {
+
+ //Wow, I hate this search line widget so much.
+ //It creates the searchline in a singleshot timer. This makes it totally unpredictable when searchLine is actually valid.
+ //So we set up singleshot timer and call ourselves over and over until it's ready.
+ //
+ //Did i mention I hate this?
+ if(!pListSearchLine->searchLine())
+ QTimer::singleShot(100, this, SLOT(fixTabOrder()));
+ else {
+ setTabOrder(pListSearchLine->searchLine(), cbFilter);
+ setTabOrder(cbFilter, pList);
+ setTabOrder(pList, xbTreeView);
+ setTabOrder(xbTreeView, bRefresh);
+ setTabOrder(bRefresh, bKill);
+ }
+}
+
+void
+ProcessController::resizeEvent(QResizeEvent* ev)
+{
+ if(frame())
+ frame()->setGeometry(0, 0, width(), height());
+
+ QWidget::resizeEvent(ev);
+}
+
+bool
+ProcessController::addSensor(const QString& hostName,
+ const QString& sensorName,
+ const QString& sensorType,
+ const QString& title)
+{
+ if (sensorType != "table")
+ return (false);
+
+ registerSensor(new KSGRD::SensorProperties(hostName, sensorName, sensorType, title));
+ /* This just triggers the first communication. The full set of
+ * requests are send whenever the sensor reconnects (detected in
+ * sensorError(). */
+
+ sendRequest(hostName, "test kill", 4);
+
+ if (title.isEmpty())
+ setTitle(i18n("%1: Running Processes").arg(hostName));
+ else
+ setTitle(title);
+
+ return (true);
+}
+
+void
+ProcessController::updateList()
+{
+ sendRequest(sensors().at(0)->hostName(), "ps", 2);
+}
+
+void
+ProcessController::killProcess(int pid, int sig)
+{
+ sendRequest(sensors().at(0)->hostName(),
+ QString("kill %1 %2" ).arg(pid).arg(sig), 3);
+
+ if ( !timerOn() )
+ // give ksysguardd time to update its proccess list
+ QTimer::singleShot(3000, this, SLOT(updateList()));
+ else
+ updateList();
+}
+
+void
+ProcessController::killProcess()
+{
+ const QStringList& selectedAsStrings = pList->getSelectedAsStrings();
+ if (selectedAsStrings.isEmpty())
+ {
+ KMessageBox::sorry(this,
+ i18n("You need to select a process first."));
+ return;
+ }
+ else
+ {
+ QString msg = i18n("Do you want to kill the selected process?",
+ "Do you want to kill the %n selected processes?",
+ selectedAsStrings.count());
+
+ KDialogBase *dlg = new KDialogBase ( i18n ("Kill Process"),
+ KDialogBase::Yes | KDialogBase::Cancel,
+ KDialogBase::Yes, KDialogBase::Cancel, this->parentWidget(),
+ "killconfirmation",
+ true, true, KGuiItem(i18n("Kill")));
+
+ bool dontAgain = false;
+
+ int res = KMessageBox::createKMessageBox(dlg, QMessageBox::Question,
+ msg, selectedAsStrings,
+ i18n("Do not ask again"), &dontAgain,
+ KMessageBox::Notify);
+
+ if (res != KDialogBase::Yes)
+ {
+ return;
+ }
+ }
+
+ const QValueList<int>& selectedPIds = pList->getSelectedPIds();
+
+ // send kill signal to all seleted processes
+ QValueListConstIterator<int> it;
+ for (it = selectedPIds.begin(); it != selectedPIds.end(); ++it)
+ sendRequest(sensors().at(0)->hostName(), QString("kill %1 %2" ).arg(*it)
+ .arg(MENU_ID_SIGKILL), 3);
+
+ if ( !timerOn())
+ // give ksysguardd time to update its proccess list
+ QTimer::singleShot(3000, this, SLOT(updateList()));
+ else
+ updateList();
+}
+
+void
+ProcessController::reniceProcess(const QValueList<int> &pids, int niceValue)
+{
+ for( QValueList<int>::ConstIterator it = pids.constBegin(), end = pids.constEnd(); it != end; ++it )
+ sendRequest(sensors().at(0)->hostName(),
+ QString("setpriority %1 %2" ).arg(*it).arg(niceValue), 5);
+ sendRequest(sensors().at(0)->hostName(), "ps", 2); //update the display afterwards
+}
+
+void
+ProcessController::answerReceived(int id, const QString& answer)
+{
+ /* We received something, so the sensor is probably ok. */
+ sensorError(id, false);
+
+ switch (id)
+ {
+ case 1:
+ {
+ /* We have received the answer to a ps? command that contains
+ * the information about the table headers. */
+ KSGRD::SensorTokenizer lines(answer, '\n');
+ if (lines.count() != 2)
+ {
+ kdDebug (1215) << "ProcessController::answerReceived(1)"
+ "wrong number of lines [" << answer << "]" << endl;
+ sensorError(id, true);
+ return;
+ }
+ KSGRD::SensorTokenizer headers(lines[0], '\t');
+ KSGRD::SensorTokenizer colTypes(lines[1], '\t');
+
+ pList->removeColumns();
+ for (unsigned int i = 0; i < headers.count(); i++)
+ {
+ QString header;
+ if (dict[headers[i]])
+ header = *dict[headers[i]];
+ else
+ header = headers[i];
+ pList->addColumn(header, colTypes[i]);
+ }
+
+ break;
+ }
+ case 2:
+ /* We have received the answer to a ps command that contains a
+ * list of processes with various additional information. */
+ pList->update(answer);
+ pListSearchLine->searchLine()->updateSearch(); //re-apply the filter
+ break;
+ case 3:
+ {
+ // result of kill operation
+ kdDebug(1215) << answer << endl;
+ KSGRD::SensorTokenizer vals(answer, '\t');
+ switch (vals[0].toInt())
+ {
+ case 0: // successful kill operation
+ break;
+ case 1: // unknown error
+ KSGRD::SensorMgr->notify(
+ i18n("Error while attempting to kill process %1.")
+ .arg(vals[1]));
+ break;
+ case 2:
+ KSGRD::SensorMgr->notify(
+ i18n("Insufficient permissions to kill "
+ "process %1.").arg(vals[1]));
+ break;
+ case 3:
+ KSGRD::SensorMgr->notify(
+ i18n("Process %1 has already disappeared.")
+ .arg(vals[1]));
+ break;
+ case 4:
+ KSGRD::SensorMgr->notify(i18n("Invalid Signal."));
+ break;
+ }
+ break;
+ }
+ case 4:
+ killSupported = (answer.toInt() == 1);
+ pList->setKillSupported(killSupported);
+ bKill->setEnabled(killSupported);
+ break;
+ case 5:
+ {
+ // result of renice operation
+ kdDebug(1215) << answer << endl;
+ KSGRD::SensorTokenizer vals(answer, '\t');
+ switch (vals[0].toInt())
+ {
+ case 0: // successful renice operation
+ break;
+ case 1: // unknown error
+ KSGRD::SensorMgr->notify(
+ i18n("Error while attempting to renice process %1.")
+ .arg(vals[1]));
+ break;
+ case 2:
+ KSGRD::SensorMgr->notify(
+ i18n("Insufficient permissions to renice "
+ "process %1.").arg(vals[1]));
+ break;
+ case 3:
+ KSGRD::SensorMgr->notify(
+ i18n("Process %1 has already disappeared.")
+ .arg(vals[1]));
+ break;
+ case 4:
+ KSGRD::SensorMgr->notify(i18n("Invalid argument."));
+ break;
+ }
+ break;
+ }
+ }
+}
+
+void
+ProcessController::sensorError(int, bool err)
+{
+ if (err == sensors().at(0)->isOk())
+ {
+ if (!err)
+ {
+ /* Whenever the communication with the sensor has been
+ * (re-)established we need to requests the full set of
+ * properties again, since the back-end might be a new
+ * one. */
+ sendRequest(sensors().at(0)->hostName(), "test kill", 4);
+ sendRequest(sensors().at(0)->hostName(), "ps?", 1);
+ sendRequest(sensors().at(0)->hostName(), "ps", 2);
+ }
+
+ /* This happens only when the sensorOk status needs to be changed. */
+ sensors().at(0)->setIsOk( !err );
+ }
+ setSensorOk(sensors().at(0)->isOk());
+}
+
+bool
+ProcessController::restoreSettings(QDomElement& element)
+{
+ bool result = addSensor(element.attribute("hostName"),
+ element.attribute("sensorName"), (element.attribute("sensorType").isEmpty() ? "table" : element.attribute("sensorType")),
+ QString::null);
+
+ xbTreeView->setChecked(element.attribute("tree").toInt());
+ setTreeView(element.attribute("tree").toInt());
+
+ uint filter = element.attribute("filter").toUInt();
+ cbFilter->setCurrentItem(filter);
+ filterModeChanged(filter);
+
+ uint col = element.attribute("sortColumn").toUInt();
+ bool inc = element.attribute("incrOrder").toUInt();
+
+ if (!pList->load(element))
+ return (false);
+
+ pList->setSortColumn(col, inc);
+
+ SensorDisplay::restoreSettings(element);
+
+ setModified(false);
+
+ return (result);
+}
+
+bool
+ProcessController::saveSettings(QDomDocument& doc, QDomElement& element, bool save)
+{
+ element.setAttribute("hostName", sensors().at(0)->hostName());
+ element.setAttribute("sensorName", sensors().at(0)->name());
+ element.setAttribute("sensorType", sensors().at(0)->type());
+ element.setAttribute("tree", (uint) xbTreeView->isChecked());
+ element.setAttribute("filter", cbFilter->currentItem());
+ element.setAttribute("sortColumn", pList->getSortColumn());
+ element.setAttribute("incrOrder", pList->getIncreasing());
+
+ if (!pList->save(doc, element))
+ return (false);
+
+ SensorDisplay::saveSettings(doc, element);
+
+ if (save)
+ setModified(false);
+
+ return (true);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/ProcessController.h b/ksysguard/gui/SensorDisplayLib/ProcessController.h
new file mode 100644
index 000000000..f834efbb6
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ProcessController.h
@@ -0,0 +1,154 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef _ProcessController_h_
+#define _ProcessController_h_
+
+#include <qdict.h>
+#include <qwidget.h>
+
+#include <kapplication.h>
+
+#include <SensorDisplay.h>
+
+#include "ProcessList.h"
+
+class QVBoxLayout;
+class QHBoxLayout;
+class QCheckBox;
+class QComboBox;
+class KPushButton;
+class KListViewSearchLineWidget;
+
+extern KApplication* Kapp;
+
+/**
+ * This widget implements a process list page. Besides the process
+ * list which is implemented as a ProcessList, it contains two
+ * comboxes and two buttons. The combo boxes are used to set the
+ * update rate and the process filter. The buttons are used to force
+ * an immediate update and to kill a process.
+ */
+class ProcessController : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+
+public:
+ ProcessController(QWidget* parent = 0, const char* name = 0, const QString &title = QString::null, bool nf = false);
+ virtual ~ProcessController() { }
+
+ void resizeEvent(QResizeEvent*);
+
+ bool restoreSettings(QDomElement& element);
+
+ bool saveSettings(QDomDocument& doc, QDomElement& element, bool save = true);
+
+ void refreshList(void)
+ {
+ updateList();
+ }
+
+ virtual void timerEvent(QTimerEvent*)
+ {
+ updateList();
+ }
+
+ virtual bool addSensor(const QString&, const QString&, const QString&, const QString&);
+
+ virtual void answerReceived(int id, const QString& answer);
+
+ virtual void sensorError(int, bool err);
+
+ void configureSettings() { }
+
+ virtual bool hasSettingsDialog() const
+ {
+ return (false);
+ }
+
+public slots:
+ void setSearchFocus();
+ void fixTabOrder();
+ void filterModeChanged(int filter)
+ {
+ pList->setFilterMode(filter);
+ updateList();
+ setModified(true);
+ }
+
+ void setTreeView(bool tv)
+ {
+ pList->setTreeView(tv);
+ updateList();
+ setModified(true);
+ }
+
+ virtual void setModified(bool mfd)
+ {
+ if (mfd != modified())
+ {
+ SensorDisplay::setModified( mfd );
+ if (!mfd)
+ pList->setModified(0);
+ emit modified(modified());
+ }
+ }
+
+ void killProcess();
+ void killProcess(int pid, int sig);
+
+ void reniceProcess(const QValueList<int> &pids, int niceValue);
+
+ void updateList();
+
+signals:
+ void setFilterMode(int);
+
+private:
+ QVBoxLayout* gm;
+
+ bool killSupported;
+
+ /// The process list.
+ ProcessList* pList;
+ ///Layout for the search line and process filter combo box
+ QHBoxLayout* gmSearch;
+ KListViewSearchLineWidget *pListSearchLine;
+
+ QHBoxLayout* gm1;
+
+ /// Checkbox to switch between tree and list view
+ QCheckBox* xbTreeView;
+
+ /// This combo boxes control the process filter.
+ QComboBox* cbFilter;
+
+ /// These buttons force an immedeate refresh or kill a process.
+ KPushButton* bRefresh;
+ KPushButton* bKill;
+
+ /// Dictionary for header translations.
+ QDict<QString> dict;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/ProcessList.cc b/ksysguard/gui/SensorDisplayLib/ProcessList.cc
new file mode 100644
index 000000000..6d158c872
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ProcessList.cc
@@ -0,0 +1,941 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (C) 1997 Bernd Johannes Wuebben
+ <wuebben@math.cornell.edu>
+
+ Copyright (C) 1998 Nicolas Leclercq <nicknet@planete.net>
+
+ Copyright (c) 1999, 2000, 2001, 2002 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <assert.h>
+#include <config.h>
+#include <ctype.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <qbitmap.h>
+#include <qheader.h>
+#include <qimage.h>
+#include <qpopupmenu.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include "ProcessController.h"
+#include "ProcessList.h"
+#include "ReniceDlg.h"
+#include "SignalIDs.h"
+
+#define NONE -1
+#define INIT_PID 1
+
+//extern const char* intKey(const char* text);
+//extern const char* timeKey(const char* text);
+//extern const char* floatKey(const char* text);
+
+QDict<QString> ProcessList::aliases;
+
+int ProcessLVI::compare( QListViewItem *item, int col, bool ascending ) const
+{
+ int type = ((ProcessList*)listView())->columnType( col );
+
+ if ( type == ProcessList::Int ) {
+ int prev = (int)KGlobal::locale()->readNumber( key( col, ascending ) );
+ int next = (int)KGlobal::locale()->readNumber( item->key( col, ascending ) );
+ if ( prev < next )
+ return -1;
+ else if ( prev == next )
+ return 0;
+ else
+ return 1;
+ }
+
+ if ( type == ProcessList::Float ) {
+ double prev = KGlobal::locale()->readNumber( key( col, ascending ) );
+ double next = KGlobal::locale()->readNumber( item->key( col, ascending ) );
+ if ( prev < next )
+ return -1;
+ else
+ return 1;
+ }
+
+ if ( type == ProcessList::Time ) {
+ int hourPrev, hourNext, minutesPrev, minutesNext;
+ sscanf( key( col, ascending ).latin1(), "%d:%d", &hourPrev, &minutesPrev );
+ sscanf( item->key( col, ascending ).latin1(), "%d:%d", &hourNext, &minutesNext );
+ int prev = hourPrev * 60 + minutesPrev;
+ int next = hourNext * 60 + minutesNext;
+ if ( prev < next )
+ return -1;
+ else if ( prev == next )
+ return 0;
+ else
+ return 1;
+ }
+
+ return key( col, ascending ).localeAwareCompare( item->key( col, ascending ) );
+}
+
+ProcessList::ProcessList(QWidget *parent, const char* name)
+ : KListView(parent, name)
+{
+ iconCache.setAutoDelete(true);
+
+ columnDict.setAutoDelete(true);
+ columnDict.insert("running",
+ new QString(i18n("process status", "running")));
+ columnDict.insert("sleeping",
+ new QString(i18n("process status", "sleeping")));
+ columnDict.insert("disk sleep",
+ new QString(i18n("process status", "disk sleep")));
+ columnDict.insert("zombie", new QString(i18n("process status", "zombie")));
+ columnDict.insert("stopped",
+ new QString(i18n("process status", "stopped")));
+ columnDict.insert("paging", new QString(i18n("process status", "paging")));
+ columnDict.insert("idle", new QString(i18n("process status", "idle")));
+
+ if (aliases.isEmpty())
+ {
+#ifdef Q_OS_LINUX
+ aliases.insert("init", new QString("penguin"));
+#else
+ aliases.insert("init", new QString("system"));
+#endif
+ /* kernel stuff */
+ aliases.insert("bdflush", new QString("kernel"));
+ aliases.insert("dhcpcd", new QString("kernel"));
+ aliases.insert("kapm-idled", new QString("kernel"));
+ aliases.insert("keventd", new QString("kernel"));
+ aliases.insert("khubd", new QString("kernel"));
+ aliases.insert("klogd", new QString("kernel"));
+ aliases.insert("kreclaimd", new QString("kernel"));
+ aliases.insert("kreiserfsd", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU0", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU1", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU2", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU3", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU4", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU5", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU6", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU7", new QString("kernel"));
+ aliases.insert("kswapd", new QString("kernel"));
+ aliases.insert("kupdated", new QString("kernel"));
+ aliases.insert("mdrecoveryd", new QString("kernel"));
+ aliases.insert("scsi_eh_0", new QString("kernel"));
+ aliases.insert("scsi_eh_1", new QString("kernel"));
+ aliases.insert("scsi_eh_2", new QString("kernel"));
+ aliases.insert("scsi_eh_3", new QString("kernel"));
+ aliases.insert("scsi_eh_4", new QString("kernel"));
+ aliases.insert("scsi_eh_5", new QString("kernel"));
+ aliases.insert("scsi_eh_6", new QString("kernel"));
+ aliases.insert("scsi_eh_7", new QString("kernel"));
+ /* daemon and other service providers */
+ aliases.insert("artsd", new QString("daemon"));
+ aliases.insert("atd", new QString("daemon"));
+ aliases.insert("automount", new QString("daemon"));
+ aliases.insert("cardmgr", new QString("daemon"));
+ aliases.insert("cron", new QString("daemon"));
+ aliases.insert("cupsd", new QString("daemon"));
+ aliases.insert("in.identd", new QString("daemon"));
+ aliases.insert("lpd", new QString("daemon"));
+ aliases.insert("mingetty", new QString("daemon"));
+ aliases.insert("nscd", new QString("daemon"));
+ aliases.insert("portmap", new QString("daemon"));
+ aliases.insert("rpc.statd", new QString("daemon"));
+ aliases.insert("rpciod", new QString("daemon"));
+ aliases.insert("sendmail", new QString("daemon"));
+ aliases.insert("sshd", new QString("daemon"));
+ aliases.insert("syslogd", new QString("daemon"));
+ aliases.insert("usbmgr", new QString("daemon"));
+ aliases.insert("wwwoffled", new QString("daemon"));
+ aliases.insert("xntpd", new QString("daemon"));
+ aliases.insert("ypbind", new QString("daemon"));
+ /* kde applications */
+ aliases.insert("appletproxy", new QString("kdeapp"));
+ aliases.insert("dcopserver", new QString("kdeapp"));
+ aliases.insert("kcookiejar", new QString("kdeapp"));
+ aliases.insert("kde", new QString("kdeapp"));
+ aliases.insert("kded", new QString("kdeapp"));
+ aliases.insert("kdeinit", new QString("kdeapp"));
+ aliases.insert("kdesktop", new QString("kdeapp"));
+ aliases.insert("kdesud", new QString("kdeapp"));
+ aliases.insert("kdm", new QString("kdeapp"));
+ aliases.insert("khotkeys", new QString("kdeapp"));
+ aliases.insert("kio_file", new QString("kdeapp"));
+ aliases.insert("kio_uiserver", new QString("kdeapp"));
+ aliases.insert("klauncher", new QString("kdeapp"));
+ aliases.insert("ksmserver", new QString("kdeapp"));
+ aliases.insert("kwrapper", new QString("kdeapp"));
+ aliases.insert("kwrited", new QString("kdeapp"));
+ aliases.insert("kxmlrpcd", new QString("kdeapp"));
+ aliases.insert("startkde", new QString("kdeapp"));
+ /* other processes */
+ aliases.insert("bash", new QString("shell"));
+ aliases.insert("cat", new QString("tools"));
+ aliases.insert("egrep", new QString("tools"));
+ aliases.insert("emacs", new QString("wordprocessing"));
+ aliases.insert("fgrep", new QString("tools"));
+ aliases.insert("find", new QString("tools"));
+ aliases.insert("grep", new QString("tools"));
+ aliases.insert("ksh", new QString("shell"));
+ aliases.insert("screen", new QString("openterm"));
+ aliases.insert("sh", new QString("shell"));
+ aliases.insert("sort", new QString("tools"));
+ aliases.insert("ssh", new QString("shell"));
+ aliases.insert("su", new QString("tools"));
+ aliases.insert("tcsh", new QString("shell"));
+ aliases.insert("tee", new QString("tools"));
+ aliases.insert("vi", new QString("wordprocessing"));
+ }
+
+ /* The filter mode is controlled by a combo box of the parent. If
+ * the mode is changed we get a signal. */
+ connect(parent, SIGNAL(setFilterMode(int)),
+ this, SLOT(setFilterMode(int)));
+
+ /* We need to catch this signal to show various popup menues. */
+ connect(this,
+ SIGNAL(rightButtonPressed(QListViewItem*, const QPoint&, int)),
+ this,
+ SLOT(handleRMBPressed(QListViewItem*, const QPoint&, int)));
+
+ /* Since Qt does not tell us the sorting details we have to do our
+ * own bookkeping, so we can save and restore the sorting
+ * settings. */
+ connect(header(), SIGNAL(clicked(int)), this, SLOT(sortingChanged(int)));
+
+ treeViewEnabled = false;
+ openAll = true;
+
+ filterMode = FILTER_ALL;
+
+ sortColumn = 1;
+ increasing = false;
+
+ // Elements in the process list may only live in this list.
+ pl.setAutoDelete(true);
+
+ setItemMargin(2);
+ setAllColumnsShowFocus(true);
+ setTreeStepSize(17);
+ setSorting(sortColumn, increasing);
+ setSelectionMode(QListView::Extended);
+
+ // Create popup menu for RMB clicks on table header
+ headerPM = new QPopupMenu();
+ headerPM->insertItem(i18n("Remove Column"), HEADER_REMOVE);
+ headerPM->insertItem(i18n("Add Column"), HEADER_ADD);
+ headerPM->insertItem(i18n("Help on Column"), HEADER_HELP);
+
+ connect(header(), SIGNAL(sizeChange(int, int, int)),
+ this, SLOT(sizeChanged(int, int, int)));
+ connect(header(), SIGNAL(indexChange(int, int, int)),
+ this, SLOT(indexChanged(int, int, int)));
+
+ killSupported = false;
+ setModified(false);
+}
+
+ProcessList::~ProcessList()
+{
+ delete(headerPM);
+}
+
+const QValueList<int>&
+ProcessList::getSelectedPIds()
+{
+ selectedPIds.clear();
+ // iterate through all selected visible items of the listview
+ QListViewItemIterator it(this, QListViewItemIterator::Visible | QListViewItemIterator::Selected );
+ for ( ; it.current(); ++it )
+ selectedPIds.append(it.current()->text(1).toInt());
+
+ return (selectedPIds);
+}
+
+const QStringList&
+ProcessList::getSelectedAsStrings()
+{
+ selectedAsStrings.clear();
+ // iterate through all selected visible items of the listview
+ QListViewItemIterator it(this, QListViewItemIterator::Visible | QListViewItemIterator::Selected );
+ QString spaces;
+ for ( ; it.current(); ++it ) {
+ spaces.fill(QChar(' '), 7 - it.current()->text(1).length());
+ selectedAsStrings.append("(PID: " + it.current()->text(1) + ")" + spaces + " " + it.current()->text(0));
+ }
+
+ return (selectedAsStrings);
+}
+bool
+ProcessList::update(const QString& list)
+{
+ /* Disable painting to avoid flickering effects,
+ * especially when in tree view mode.
+ * Ditto for the scrollbar. */
+ setUpdatesEnabled(false);
+ viewport()->setUpdatesEnabled(false);
+
+ pl.clear();
+
+ // Convert ps answer in a list of tokenized lines
+ KSGRD::SensorTokenizer procs(list, '\n');
+ for (unsigned int i = 0; i < procs.count(); i++)
+ {
+ KSGRD::SensorPSLine* line = new KSGRD::SensorPSLine(procs[i]);
+ if (line->count() != (uint) columns())
+ {
+#if 0
+ // This is needed for debugging only.
+ kdDebug(1215) << list << endl;
+ QString l;
+ for (uint j = 0; j < line->count(); j++)
+ l += (*line)[j] + "|";
+ kdDebug(1215) << "Incomplete ps line:" << l << endl;
+#endif
+ return (false);
+ }
+ else
+ pl.append(line);
+ }
+
+ int currItemPos = itemPos(currentItem());
+ int vpos = verticalScrollBar()->value();
+ int hpos = horizontalScrollBar()->value();
+
+ updateMetaInfo();
+
+ clear();
+
+ if (treeViewEnabled)
+ buildTree();
+ else
+ buildList();
+
+ QListViewItemIterator it( this );
+ while ( it.current() ) {
+ if ( itemPos( it.current() ) == currItemPos ) {
+ setCurrentItem( it.current() );
+ break;
+ }
+ ++it;
+ }
+
+ verticalScrollBar()->setValue(vpos);
+ horizontalScrollBar()->setValue(hpos);
+
+ // Re-enable painting, and force an update.
+ setUpdatesEnabled(true);
+ viewport()->setUpdatesEnabled(true);
+
+ triggerUpdate();
+
+ return (true);
+}
+
+void
+ProcessList::setTreeView(bool tv)
+{
+ if (treeViewEnabled = tv)
+ {
+ savedWidth[0] = columnWidth(0);
+ openAll = true;
+ }
+ else
+ {
+ /* In tree view the first column is wider than in list view mode.
+ * So we shrink it to 1 pixel. The next update will resize it again
+ * appropriately. */
+ setColumnWidth(0, savedWidth[0]);
+ }
+ /* In tree view mode borders are added to the icons. So we have to clear
+ * the cache when we change the tree view mode. */
+ iconCache.clear();
+}
+
+bool
+ProcessList::load(QDomElement& el)
+{
+ QDomNodeList dnList = el.elementsByTagName("column");
+ for (uint i = 0; i < dnList.count(); ++i)
+ {
+ QDomElement lel = dnList.item(i).toElement();
+ if (savedWidth.count() <= i)
+ savedWidth.append(lel.attribute("savedWidth").toInt());
+ else
+ savedWidth[i] = lel.attribute("savedWidth").toInt();
+ if (currentWidth.count() <= i)
+ currentWidth.append(lel.attribute("currentWidth").toInt());
+ else
+ currentWidth[i] = lel.attribute("currentWidth").toInt();
+ if (index.count() <= i)
+ index.append(lel.attribute("index").toInt());
+ else
+ index[i] = lel.attribute("index").toInt();
+ }
+
+ setModified(false);
+
+ return (true);
+}
+
+bool
+ProcessList::save(QDomDocument& doc, QDomElement& display)
+{
+ for (int i = 0; i < columns(); ++i)
+ {
+ QDomElement col = doc.createElement("column");
+ display.appendChild(col);
+ col.setAttribute("currentWidth", columnWidth(i));
+ col.setAttribute("savedWidth", savedWidth[i]);
+ col.setAttribute("index", header()->mapToIndex(i));
+ }
+
+ setModified(false);
+
+ return (true);
+}
+
+void
+ProcessList::sortingChanged(int col)
+{
+ if (col == sortColumn)
+ increasing = !increasing;
+ else
+ {
+ sortColumn = col;
+ increasing = true;
+ }
+ setSorting(sortColumn, increasing);
+ setModified(true);
+}
+
+int ProcessList::columnType( uint pos ) const
+{
+ if ( pos >= mColumnTypes.count() )
+ return 0;
+
+ if ( mColumnTypes[ pos ] == "d" || mColumnTypes[ pos ] == "D" )
+ return Int;
+ else if ( mColumnTypes[ pos ] == "f" || mColumnTypes[ pos ] == "F" )
+ return Float;
+ else if ( mColumnTypes[ pos ] == "t" )
+ return Time;
+ else
+ return Text;
+}
+
+bool
+ProcessList::matchesFilter(KSGRD::SensorPSLine* p) const
+{
+ // This mechanism is likely to change in the future!
+
+ switch (filterMode)
+ {
+ case FILTER_ALL:
+ return (true);
+
+ case FILTER_SYSTEM:
+ return (p->uid() < 100 ? true : false);
+
+ case FILTER_USER:
+ return (p->uid() >= 100 ? true : false);
+
+ case FILTER_OWN:
+ default:
+ return (p->uid() == (long) getuid() ? true : false);
+ }
+}
+
+void
+ProcessList::buildList()
+{
+ /* Get the first process in the list, check whether it matches the
+ * filter and append it to QListView widget if so. */
+ while (!pl.isEmpty())
+ {
+ KSGRD::SensorPSLine* p = pl.first();
+
+ if (matchesFilter(p))
+ {
+ ProcessLVI* pli = new ProcessLVI(this);
+
+ addProcess(p, pli);
+
+ if (selectedPIds.findIndex(p->pid()) != -1)
+ pli->setSelected(true);
+ }
+ pl.removeFirst();
+ }
+}
+
+void
+ProcessList::buildTree()
+{
+ // remove all leaves that do not match the filter
+ deleteLeaves();
+
+ KSGRD::SensorPSLine* ps = pl.first();
+
+ while (ps)
+ {
+ if (ps->pid() == INIT_PID)
+ {
+ // insert root item into the tree widget
+ ProcessLVI* pli = new ProcessLVI(this);
+ addProcess(ps, pli);
+
+ // remove the process from the process list, ps is now invalid
+ int pid = ps->pid();
+ pl.remove();
+
+ if (selectedPIds.findIndex(pid) != -1)
+ pli->setSelected(true);
+
+ // insert all child processes of current process
+ extendTree(&pl, pli, pid);
+ break;
+ }
+ else
+ ps = pl.next();
+ }
+}
+
+void
+ProcessList::deleteLeaves(void)
+{
+ for ( ; ; )
+ {
+ unsigned int i;
+ for (i = 0; i < pl.count() &&
+ (!isLeafProcess(pl.at(i)->pid()) ||
+ matchesFilter(pl.at(i))); i++)
+ ;
+ if (i == pl.count())
+ return;
+
+ pl.remove(i);
+ }
+}
+
+bool
+ProcessList::isLeafProcess(int pid)
+{
+ for (unsigned int i = 0; i < pl.count(); i++)
+ if (pl.at(i)->ppid() == pid)
+ return (false);
+
+ return (true);
+}
+
+void
+ProcessList::extendTree(QPtrList<KSGRD::SensorPSLine>* pl, ProcessLVI* parent, int ppid)
+{
+ KSGRD::SensorPSLine* ps;
+
+ // start at top list
+ ps = pl->first();
+
+ while (ps)
+ {
+ // look for a child process of the current parent
+ if (ps->ppid() == ppid)
+ {
+ ProcessLVI* pli = new ProcessLVI(parent);
+
+ addProcess(ps, pli);
+
+ if (selectedPIds.findIndex(ps->pid()) != -1)
+ pli->setSelected(true);
+
+ if (ps->ppid() != INIT_PID && closedSubTrees.findIndex(ps->ppid()) != -1)
+ parent->setOpen(false);
+ else
+ parent->setOpen(true);
+
+ // remove the process from the process list, ps is now invalid
+ int pid = ps->pid();
+ pl->remove();
+
+ // now look for the childs of the inserted process
+ extendTree(pl, pli, pid);
+
+ /* Since buildTree can remove processes from the list we
+ * can't find a "current" process. So we start searching
+ * at the top again. It's no endless loops since this
+ * branch is only entered when there are children of the
+ * current parent in the list. When we have removed them
+ * all the while loop will exit. */
+ ps = pl->first();
+ }
+ else
+ ps = pl->next();
+ }
+}
+void
+ProcessList::addProcess(KSGRD::SensorPSLine* p, ProcessLVI* pli)
+{
+ QString name = p->name();
+ if (aliases[name])
+ name = *aliases[name];
+
+ /* Get icon from icon list that might be appropriate for a process
+ * with this name. */
+ QPixmap pix;
+ if (!iconCache[name])
+ {
+ pix = KGlobal::iconLoader()->loadIcon(name, KIcon::Small,
+ KIcon::SizeSmall, KIcon::DefaultState,
+ 0L, true);
+ if (pix.isNull() || !pix.mask())
+ pix = KGlobal::iconLoader()->loadIcon("unknownapp", KIcon::User,
+ KIcon::SizeSmall);
+
+ if (pix.width() != 16 || pix.height() != 16)
+ {
+ /* I guess this isn't needed too often. The KIconLoader should
+ * scale the pixmaps already appropriately. Since I got a bug
+ * report claiming that it doesn't work with GNOME apps I've
+ * added this safeguard. */
+ QImage img;
+ img = pix;
+ img.smoothScale(16, 16);
+ pix = img;
+ }
+ /* We copy the icon into a 24x16 pixmap to add a 4 pixel margin on
+ * the left and right side. In tree view mode we use the original
+ * icon. */
+ QPixmap icon(24, 16, pix.depth());
+ if (!treeViewEnabled)
+ {
+ icon.fill();
+ bitBlt(&icon, 4, 0, &pix, 0, 0, pix.width(), pix.height());
+ QBitmap mask(24, 16, true);
+ bitBlt(&mask, 4, 0, pix.mask(), 0, 0, pix.width(), pix.height());
+ icon.setMask(mask);
+ pix = icon;
+ }
+ iconCache.insert(name, new QPixmap(pix));
+ }
+ else
+ pix = *(iconCache[name]);
+
+ // icon + process name
+ pli->setPixmap(0, pix);
+ pli->setText(0, p->name());
+
+ // insert remaining field into table
+ for (unsigned int col = 1; col < p->count(); col++)
+ {
+ if (mColumnTypes[col] == "S" && columnDict[(*p)[col]])
+ pli->setText(col, *columnDict[(*p)[col]]);
+ else if ( mColumnTypes[col] == "f" )
+ pli->setText( col, KGlobal::locale()->formatNumber( (*p)[col].toFloat() ) );
+ else if ( mColumnTypes[col] == "D" )
+ pli->setText( col, KGlobal::locale()->formatNumber( (*p)[col].toInt(), 0 ) );
+ else
+ pli->setText(col, (*p)[col]);
+ }
+}
+
+void
+ProcessList::updateMetaInfo(void)
+{
+ selectedPIds.clear();
+ closedSubTrees.clear();
+
+ QListViewItemIterator it(this);
+
+ // iterate through all items of the listview
+ for ( ; it.current(); ++it )
+ {
+ if (it.current()->isSelected() && it.current()->isVisible())
+ selectedPIds.append(it.current()->text(1).toInt());
+ if (treeViewEnabled && !it.current()->isOpen())
+ closedSubTrees.append(it.current()->text(1).toInt());
+ }
+
+ /* In list view mode all list items are set to closed by QListView.
+ * If the tree view is now selected, all item will be closed. This is
+ * annoying. So we use the openAll flag to force all trees to open when
+ * the treeViewEnbled flag was set to true. */
+ if (openAll)
+ {
+ if (treeViewEnabled)
+ closedSubTrees.clear();
+ openAll = false;
+ }
+}
+
+void
+ProcessList::removeColumns(void)
+{
+ for (int i = columns() - 1; i >= 0; --i)
+ removeColumn(i);
+}
+
+void
+ProcessList::addColumn(const QString& label, const QString& type)
+{
+ QListView::addColumn(label);
+ uint col = columns() - 1;
+ if (type == "s" || type == "S")
+ setColumnAlignment(col, AlignLeft);
+ else if (type == "d" || type == "D")
+ setColumnAlignment(col, AlignRight);
+ else if (type == "t")
+ setColumnAlignment(col, AlignRight);
+ else if (type == "f")
+ setColumnAlignment(col, AlignRight);
+ else
+ {
+ kdDebug(1215) << "Unknown type " << type << " of column " << label
+ << " in ProcessList!" << endl;
+ return;
+ }
+
+ mColumnTypes.append(type);
+
+ /* Just use some sensible default values as initial setting. */
+ QFontMetrics fm = fontMetrics();
+ setColumnWidth(col, fm.width(label) + 10);
+
+ if (currentWidth.count() - 1 == col)
+ {
+ /* Table has been loaded from file. We can restore the settings
+ * when the last column has been added. */
+ for (uint i = 0; i < col; ++i)
+ {
+ /* In case the language has been changed the column width
+ * might need to be increased. */
+ if (currentWidth[i] == 0)
+ {
+ if (fm.width(header()->label(i)) + 10 > savedWidth[i])
+ savedWidth[i] = fm.width(header()->label(i)) + 10;
+ setColumnWidth(i, 0);
+ }
+ else
+ {
+ if (fm.width(header()->label(i)) + 10 > currentWidth[i])
+ setColumnWidth(i, fm.width(header()->label(i)) + 10);
+ else
+ setColumnWidth(i, currentWidth[i]);
+ }
+ setColumnWidthMode(i, currentWidth[i] == 0 ?
+ QListView::Manual : QListView::Maximum);
+ header()->moveSection(i, index[i]);
+ }
+ setSorting(sortColumn, increasing);
+ }
+}
+
+void
+ProcessList::handleRMBPressed(QListViewItem* lvi, const QPoint& p, int col)
+{
+ if (!lvi)
+ return;
+
+ lvi->setSelected( true );
+
+ /* lvi is only valid until the next time we hit the main event
+ * loop. So we need to save the information we need after calling
+ * processPM->exec(). */
+ int currentPId = lvi->text(1).toInt();
+
+ int currentNiceValue = 0;
+ for (int i = 0; i < columns(); ++i)
+ if (QString::compare(header()->label(i), i18n("Nice")) == 0)
+ currentNiceValue = lvi->text(i).toInt();
+
+ QPopupMenu processPM;
+ if (columnWidth(col) != 0)
+ processPM.insertItem(i18n("Hide Column"), 5);
+ QPopupMenu* hiddenPM = new QPopupMenu(&processPM);
+ for (int i = 0; i < columns(); ++i)
+ if (columnWidth(i) == 0)
+ hiddenPM->insertItem(header()->label(i), i + 100);
+ if(columns())
+ processPM.insertItem(i18n("Show Column"), hiddenPM);
+
+ processPM.insertSeparator();
+
+ processPM.insertItem(i18n("Select All Processes"), 1);
+ processPM.insertItem(i18n("Unselect All Processes"), 2);
+
+ QPopupMenu* signalPM = new QPopupMenu(&processPM);
+ if (killSupported && lvi->isSelected())
+ {
+ processPM.insertSeparator();
+ processPM.insertItem(i18n("Select All Child Processes"), 3);
+ processPM.insertItem(i18n("Unselect All Child Processes"), 4);
+
+ signalPM->insertItem(i18n("SIGABRT"), MENU_ID_SIGABRT);
+ signalPM->insertItem(i18n("SIGALRM"), MENU_ID_SIGALRM);
+ signalPM->insertItem(i18n("SIGCHLD"), MENU_ID_SIGCHLD);
+ signalPM->insertItem(i18n("SIGCONT"), MENU_ID_SIGCONT);
+ signalPM->insertItem(i18n("SIGFPE"), MENU_ID_SIGFPE);
+ signalPM->insertItem(i18n("SIGHUP"), MENU_ID_SIGHUP);
+ signalPM->insertItem(i18n("SIGILL"), MENU_ID_SIGILL);
+ signalPM->insertItem(i18n("SIGINT"), MENU_ID_SIGINT);
+ signalPM->insertItem(i18n("SIGKILL"), MENU_ID_SIGKILL);
+ signalPM->insertItem(i18n("SIGPIPE"), MENU_ID_SIGPIPE);
+ signalPM->insertItem(i18n("SIGQUIT"), MENU_ID_SIGQUIT);
+ signalPM->insertItem(i18n("SIGSEGV"), MENU_ID_SIGSEGV);
+ signalPM->insertItem(i18n("SIGSTOP"), MENU_ID_SIGSTOP);
+ signalPM->insertItem(i18n("SIGTERM"), MENU_ID_SIGTERM);
+ signalPM->insertItem(i18n("SIGTSTP"), MENU_ID_SIGTSTP);
+ signalPM->insertItem(i18n("SIGTTIN"), MENU_ID_SIGTTIN);
+ signalPM->insertItem(i18n("SIGTTOU"), MENU_ID_SIGTTOU);
+ signalPM->insertItem(i18n("SIGUSR1"), MENU_ID_SIGUSR1);
+ signalPM->insertItem(i18n("SIGUSR2"), MENU_ID_SIGUSR2);
+
+ processPM.insertSeparator();
+ processPM.insertItem(i18n("Send Signal"), signalPM);
+ }
+
+ /* differ between killSupported and reniceSupported in a future
+ * version. */
+ if (killSupported && lvi->isSelected())
+ {
+ processPM.insertSeparator();
+ processPM.insertItem(i18n("Renice Process..."), 300);
+ }
+
+ int id;
+ switch (id = processPM.exec(p))
+ {
+ case -1:
+ break;
+ case 1:
+ case 2:
+ selectAllItems(id & 1);
+ break;
+ case 3:
+ case 4:
+ selectAllChilds(currentPId, id & 1);
+ break;
+ case 5:
+ setColumnWidthMode(col, QListView::Manual);
+ savedWidth[col] = columnWidth(col);
+ setColumnWidth(col, 0);
+ setModified(true);
+ break;
+ case 300:
+ {
+ ReniceDlg reniceDlg(this, "reniceDlg", currentNiceValue, currentPId);
+
+ int reniceVal;
+ if ((reniceVal = reniceDlg.exec()) != 40) {
+ emit reniceProcess(selectedPIds, reniceVal);
+ }
+ }
+ break;
+ default:
+ /* IDs < 100 are used for signals. */
+ if (id < 100)
+ {
+ /* we go through list to get all task also
+ when update interval is paused */
+ selectedPIds.clear();
+ QListViewItemIterator it(this, QListViewItemIterator::Visible | QListViewItemIterator::Selected);
+
+ // iterate through all selected visible items of the listview
+ for ( ; it.current(); ++it )
+ {
+ selectedPIds.append(it.current()->text(1).toInt());
+ }
+
+ QString msg = i18n("Do you really want to send signal %1 to the selected process?",
+ "Do you really want to send signal %1 to the %n selected processes?",
+ selectedPIds.count())
+ .arg(signalPM->text(id));
+ int answ;
+ switch(answ = KMessageBox::questionYesNo(this, msg, QString::null, i18n("Send"), KStdGuiItem::cancel()))
+ {
+ case KMessageBox::Yes:
+ {
+ QValueList<int>::Iterator it;
+ for (it = selectedPIds.begin(); it != selectedPIds.end(); ++it)
+ emit (killProcess(*it, id));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /* IDs >= 100 are used for hidden columns. */
+ int col = id - 100;
+ setColumnWidthMode(col, QListView::Maximum);
+ setColumnWidth(col, savedWidth[col]);
+ setModified(true);
+ }
+ }
+}
+
+void
+ProcessList::selectAllItems(bool select)
+{
+ selectedPIds.clear();
+
+ QListViewItemIterator it(this, QListViewItemIterator::Visible);
+
+ // iterate through all items of the listview
+ for ( ; it.current(); ++it )
+ {
+ it.current()->setSelected(select);
+ repaintItem(it.current());
+ if (select)
+ selectedPIds.append(it.current()->text(1).toInt());
+ }
+}
+
+void
+ProcessList::selectAllChilds(int pid, bool select)
+{
+ QListViewItemIterator it(this, QListViewItemIterator::Visible );
+
+ // iterate through all items of the listview
+ for ( ; it.current(); ++it )
+ {
+ // Check if PPID matches the pid (current is a child of pid)
+ if (it.current()->text(2).toInt() == pid)
+ {
+ int currPId = it.current()->text(1).toInt();
+ it.current()->setSelected(select);
+ repaintItem(it.current());
+ if (select)
+ selectedPIds.append(currPId);
+ else
+ selectedPIds.remove(currPId);
+ selectAllChilds(currPId, select);
+ }
+ }
+}
+
+#include "ProcessList.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/ProcessList.h b/ksysguard/gui/SensorDisplayLib/ProcessList.h
new file mode 100644
index 000000000..b3f484484
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ProcessList.h
@@ -0,0 +1,270 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me
+ first. Thanks!
+
+ */
+
+#ifndef _ProcessList_h_
+#define _ProcessList_h_
+
+#include <qdict.h>
+#include <qdom.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qwidget.h>
+
+#include <kiconloader.h>
+#include <klistview.h>
+
+#include "SensorClient.h"
+
+typedef const char* (*KeyFunc)(const char*);
+
+/**
+ * To support bi-directional sorting, and sorting of text, integers etc. we
+ * need a specialized version of QListViewItem.
+ */
+class ProcessLVI : public KListViewItem
+{
+public:
+ ProcessLVI(QListView* lv) : KListViewItem(lv) { }
+ ProcessLVI(QListViewItem* lvi) : KListViewItem(lvi) { }
+
+ virtual int compare( QListViewItem *item, int column, bool ) const;
+};
+
+class QPopupMenu;
+
+/**
+ * This class implementes a table filled with information about the running
+ * processes. The table is derived from QListView.
+ */
+class ProcessList : public KListView
+{
+ Q_OBJECT
+
+public:
+ // possible values for the filter mode
+ enum
+ {
+ FILTER_ALL = 0,
+ FILTER_SYSTEM,
+ FILTER_USER,
+ FILTER_OWN
+ };
+
+ enum ColumnType { Text, Int, Float, Time };
+
+ /// The constructor.
+ ProcessList(QWidget* parent = 0, const char* name = 0);
+
+ /// The destructor.
+ ~ProcessList();
+
+ void removeColumns();
+
+ void addColumn(const QString& header, const QString& type);
+
+ void setSortColumn(uint col, bool inc)
+ {
+ sortColumn = col;
+ increasing = inc;
+ setSorting(col, inc);
+ }
+
+ uint getSortColumn() const
+ {
+ return sortColumn;
+ }
+
+ bool getIncreasing() const
+ {
+ return increasing;
+ }
+
+ const QValueList<int>& getSelectedPIds();
+ const QStringList& getSelectedAsStrings();
+
+ /**
+ * The udpate function can be used to update the displayed process
+ * list. A current list of processes is requested from the OS. In
+ * case the list contains invalid or corrupted info, FALSE is
+ * returned.
+ */
+ bool update(const QString& list);
+
+ int columnType( uint col ) const;
+
+ void setSensorOk(bool ok);
+
+ void setKillSupported(bool supported)
+ {
+ killSupported = supported;
+ }
+
+ bool load(QDomElement& el);
+ bool save(QDomDocument& doc, QDomElement& display);
+
+public slots:
+ void setTreeView(bool tv);
+
+ /**
+ * This slot allows the filter mode to be set by other
+ * widgets. Possible values are FILTER_ALL, FILTER_SYSTEM,
+ * FILTER_USER and FILTER_OWN. This filter mechanism will be much
+ * more sophisticated in the future.
+ */
+ void setFilterMode(int fm)
+ {
+ filterMode = fm;
+ setModified(true);
+ }
+
+ void sortingChanged(int col);
+
+ void handleRMBPressed(QListViewItem* lvi, const QPoint& p, int col);
+
+ void sizeChanged(int, int, int)
+ {
+ setModified(true);
+ }
+
+ void indexChanged(int, int, int)
+ {
+ setModified(true);
+ }
+
+ virtual void setModified(bool mfd)
+ {
+ if (mfd != modified)
+ {
+ modified = mfd;
+ emit listModified(modified);
+ }
+ }
+
+signals:
+ // This signal is emitted when process pid should receive signal sig.
+ void killProcess(int pid, int sig);
+
+ // This signal is emitted when process pid should be reniced.
+ void reniceProcess(const QValueList<int> &pids, int niceValue);
+
+ void listModified(bool);
+
+private:
+ // items of table header RMB popup menu
+ enum
+ {
+ HEADER_REMOVE = 0,
+ HEADER_ADD,
+ HEADER_HELP
+ };
+
+ /**
+ * This function updates the lists of selected PID und the closed
+ * sub trees.
+ */
+ void updateMetaInfo(void);
+
+ /**
+ * This function determines whether a process matches the current
+ * filter mode or not. If it machtes the criteria it returns true,
+ * false otherwise.
+ */
+ bool matchesFilter(KSGRD::SensorPSLine* p) const;
+
+ /**
+ * This function constructs the list of processes for list
+ * mode. It's a straightforward appending operation to the
+ * QListView widget.
+ */
+ void buildList();
+
+ /**
+ * This function constructs the tree of processes for tree mode. It
+ * filters out leaf-sub-trees that contain no processes that match
+ * the filter criteria.
+ */
+ void buildTree();
+
+ /**
+ * This function deletes the leaf-sub-trees that do not match the
+ * filter criteria.
+ */
+ void deleteLeaves(void);
+
+ /**
+ * This function returns true if the process is a leaf process with
+ * respect to the other processes in the process list. It does not
+ * have to be a leaf process in the overall list of processes.
+ */
+ bool isLeafProcess(int pid);
+
+ /**
+ * This function is used to recursively construct the tree by
+ * removing processes from the process list an inserting them into
+ * the tree.
+ */
+ void extendTree(QPtrList<KSGRD::SensorPSLine>* pl, ProcessLVI* parent, int ppid);
+
+ /**
+ * This function adds a process to the list/tree.
+ */
+ void addProcess(KSGRD::SensorPSLine* p, ProcessLVI* pli);
+
+private:
+ void selectAllItems(bool select);
+ void selectAllChilds(int pid, bool select);
+
+ bool modified;
+ int filterMode;
+ int sortColumn;
+ bool increasing;
+ int refreshRate;
+ int currColumn;
+ bool killSupported;
+ bool treeViewEnabled;
+ bool openAll;
+
+ /* The following lists are primarily used to store table specs between
+ * load() and the actual table creation in addColumn(). */
+ QValueList<int> savedWidth;
+ QValueList<int> currentWidth;
+ QValueList<int> index;
+
+ QPtrList<KSGRD::SensorPSLine> pl;
+
+ QStringList mColumnTypes;
+ QDict<QString> columnDict;
+
+ QValueList<int> selectedPIds;
+ QValueList<int> closedSubTrees;
+ QStringList selectedAsStrings;
+
+ static QDict<QString> aliases;
+
+ QDict<QPixmap> iconCache;
+
+ QPopupMenu* headerPM;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/ReniceDlg.cc b/ksysguard/gui/SensorDisplayLib/ReniceDlg.cc
new file mode 100644
index 000000000..39c05eecf
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ReniceDlg.cc
@@ -0,0 +1,66 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>. Please do
+ not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <klocale.h>
+#include <knuminput.h>
+
+#include "ReniceDlg.moc"
+
+ReniceDlg::ReniceDlg(QWidget* parent, const char* name, int currentPPrio,
+ int pid)
+ : KDialogBase( parent, name, true, i18n("Renice Process"),
+ KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true )
+{
+ QWidget *page = new QWidget( this );
+ setMainWidget(page);
+ vLay = new QVBoxLayout(page, 20, -1, "ReniceLayout");
+
+ QString msg;
+ msg = i18n("You are about to change the scheduling priority of\n"
+ "process %1. Be aware that only the Superuser (root)\n"
+ "can decrease the nice level of a process. The lower\n"
+ "the number is the higher the priority.\n\n"
+ "Please enter the desired nice level:").arg(pid);
+ message = new QLabel(msg, page);
+ message->setMinimumSize(message->sizeHint());
+ vLay->addWidget(message);
+
+ /*
+ * Create a slider with an LCD display to the right using a horizontal
+ * layout. The slider and the LCD are kept in sync through signals
+ */
+ input = new KIntNumInput(currentPPrio, page, 10);
+ input->setRange(-20, 19);
+ vLay->addWidget(input);
+}
+
+void ReniceDlg::slotOk()
+{
+ done(input->value());
+}
+
+void ReniceDlg::slotCancel()
+{
+ done(40);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/ReniceDlg.h b/ksysguard/gui/SensorDisplayLib/ReniceDlg.h
new file mode 100644
index 000000000..d8f0d2685
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ReniceDlg.h
@@ -0,0 +1,61 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>. Please do
+ not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef _ReniceDlg_h_
+#define _ReniceDlg_h_
+
+#include <kdialogbase.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlcdnumber.h>
+#include <qpushbutton.h>
+#include <qslider.h>
+
+class KIntNumInput;
+
+/**
+ * This class creates and handles a simple dialog to change the scheduling
+ * priority of a process.
+ */
+class ReniceDlg : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ ReniceDlg(QWidget* parent, const char* name, int currentPPrio, int pid);
+
+public slots:
+ void slotOk();
+ void slotCancel();
+
+private:
+ QBoxLayout* vLay;
+ QBoxLayout* butLay;
+ QBoxLayout* sldLay;
+
+ QLabel* message;
+ KIntNumInput* input;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/SensorDisplay.cc b/ksysguard/gui/SensorDisplayLib/SensorDisplay.cc
new file mode 100644
index 000000000..805c9a492
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorDisplay.cc
@@ -0,0 +1,611 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2002 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <qcheckbox.h>
+#include <qdom.h>
+#include <qpopupmenu.h>
+#include <qspinbox.h>
+#include <qwhatsthis.h>
+#include <qbitmap.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <krun.h>
+#include <kservice.h>
+
+#include "SensorManager.h"
+#include "TimerSettings.h"
+
+#include "SensorDisplay.h"
+
+using namespace KSGRD;
+
+SensorDisplay::SensorDisplay( QWidget *parent, const char *name,
+ const QString &title, bool nf, bool isApplet)
+ : QWidget( parent, name )
+{
+ mIsApplet = isApplet;
+ mSensors.setAutoDelete( true );
+
+ // default interval is 2 seconds.
+ mUpdateInterval = 2;
+ mUseGlobalUpdateInterval = true;
+ mModified = false;
+ mShowUnit = false;
+ mTimerId = NONE;
+ mFrame = 0;
+ mErrorIndicator = 0;
+ mPlotterWdg = 0;
+
+ setTimerOn( true );
+ QWhatsThis::add( this, "dummy" );
+
+ if(!nf) {
+ mFrame = new QGroupBox( 2, Qt::Vertical, "", this, "displayFrame");
+ mFrame->setFlat(true);
+ mFrame->setAlignment(Qt::AlignHCenter);
+ mFrame->setInsideMargin(2);
+
+ setTitle( title );
+ /* All RMB clicks to the box frame will be handled by
+ * SensorDisplay::eventFilter. */
+ mFrame->installEventFilter( this );
+ }
+
+
+ setMinimumSize( 16, 16 );
+ setModified( false );
+ setSensorOk( false );
+
+ /* Let's call updateWhatsThis() in case the derived class does not do
+ * this. */
+ updateWhatsThis();
+}
+
+SensorDisplay::~SensorDisplay()
+{
+ if ( SensorMgr != 0 )
+ SensorMgr->disconnectClient( this );
+
+ killTimer( mTimerId );
+}
+
+void SensorDisplay::registerSensor( SensorProperties *sp )
+{
+ /* Make sure that we have a connection established to the specified
+ * host. When a work sheet has been saved while it had dangling
+ * sensors, the connect info is not saved in the work sheet. In such
+ * a case the user can re-enter the connect information and the
+ * connection will be established. */
+ if ( !SensorMgr->engageHost( sp->hostName() ) ) {
+ QString msg = i18n( "It is impossible to connect to \'%1\'." ).arg( sp->hostName() );
+ KMessageBox::error( this, msg );
+ }
+
+ mSensors.append( sp );
+}
+
+void SensorDisplay::unregisterSensor( uint pos )
+{
+ mSensors.remove( pos );
+}
+
+void SensorDisplay::configureUpdateInterval()
+{
+ TimerSettings dlg( this );
+
+ dlg.setUseGlobalUpdate( mUseGlobalUpdateInterval );
+ dlg.setInterval( mUpdateInterval );
+
+ if ( dlg.exec() ) {
+ if ( dlg.useGlobalUpdate() ) {
+ mUseGlobalUpdateInterval = true;
+
+ SensorBoard* sb = dynamic_cast<SensorBoard*>( parentWidget() );
+ if ( !sb ) {
+ kdDebug(1215) << "dynamic cast lacks" << endl;
+ setUpdateInterval( 2 );
+ } else {
+ setUpdateInterval( sb->updateInterval() );
+ }
+ } else {
+ mUseGlobalUpdateInterval = false;
+ setUpdateInterval( dlg.interval() );
+ }
+
+ setModified( true );
+ }
+}
+
+void SensorDisplay::timerEvent( QTimerEvent* )
+{
+ int i = 0;
+ for ( SensorProperties *s = mSensors.first(); s; s = mSensors.next(), ++i )
+ sendRequest( s->hostName(), s->name(), i );
+}
+
+void SensorDisplay::resizeEvent( QResizeEvent* )
+{
+ if(mFrame)
+ mFrame->setGeometry( rect() );
+}
+
+bool SensorDisplay::eventFilter( QObject *object, QEvent *event )
+{
+ if ( event->type() == QEvent::MouseButtonPress &&
+ ( (QMouseEvent*)event)->button() == RightButton ) {
+ QPopupMenu pm;
+ if ( mIsApplet ) {
+ pm.insertItem( i18n( "Launch &System Guard"), 1 );
+ pm.insertSeparator();
+ }
+ if ( hasSettingsDialog() )
+ pm.insertItem( i18n( "&Properties" ), 2 );
+ pm.insertItem( i18n( "&Remove Display" ), 3 );
+ pm.insertSeparator();
+ pm.insertItem( i18n( "&Setup Update Interval..." ), 4 );
+ if ( !timerOn() )
+ pm.insertItem( i18n( "&Continue Update" ), 5 );
+ else
+ pm.insertItem( i18n( "P&ause Update" ), 6 );
+
+ switch ( pm.exec( QCursor::pos() ) ) {
+ case 1:
+ KRun::run(*KService::serviceByDesktopName("ksysguard"), KURL::List());
+ break;
+ case 2:
+ configureSettings();
+ break;
+ case 3: {
+ QCustomEvent *e = new QCustomEvent( QEvent::User );
+ e->setData( this );
+ kapp->postEvent( parent(), e );
+ }
+ break;
+ case 4:
+ configureUpdateInterval();
+ break;
+ case 5:
+ setTimerOn( true );
+ setModified( true );
+ break;
+ case 6:
+ setTimerOn( false );
+ setModified( true );
+ break;
+ }
+
+ return true;
+ } else if ( event->type() == QEvent::MouseButtonRelease &&
+ ( ( QMouseEvent*)event)->button() == LeftButton ) {
+ setFocus();
+ }
+
+ return QWidget::eventFilter( object, event );
+}
+
+void SensorDisplay::sendRequest( const QString &hostName,
+ const QString &command, int id )
+{
+ if ( !SensorMgr->sendRequest( hostName, command, (SensorClient*)this, id ) )
+ sensorError( id, true );
+}
+
+void SensorDisplay::sensorError( int sensorId, bool err )
+{
+ if ( sensorId >= (int)mSensors.count() || sensorId < 0 )
+ return;
+
+ if ( err == mSensors.at( sensorId )->isOk() ) {
+ // this happens only when the sensorOk status needs to be changed.
+ mSensors.at( sensorId )->setIsOk( !err );
+ }
+
+ bool ok = true;
+ for ( uint i = 0; i < mSensors.count(); ++i )
+ if ( !mSensors.at( i )->isOk() ) {
+ ok = false;
+ break;
+ }
+
+ setSensorOk( ok );
+}
+
+void SensorDisplay::updateWhatsThis()
+{
+ QWhatsThis::add( this, i18n(
+ "<qt><p>This is a sensor display. To customize a sensor display click "
+ "and hold the right mouse button on either the frame or the "
+ "display box and select the <i>Properties</i> entry from the popup "
+ "menu. Select <i>Remove</i> to delete the display from the worksheet."
+ "</p>%1</qt>" ).arg( additionalWhatsThis() ) );
+}
+
+void SensorDisplay::hosts( QStringList& list )
+{
+ for ( SensorProperties *s = mSensors.first(); s; s = mSensors.next() )
+ if ( !list.contains( s->hostName() ) )
+ list.append( s->hostName() );
+}
+
+QColor SensorDisplay::restoreColor( QDomElement &element, const QString &attr,
+ const QColor& fallback )
+{
+ bool ok;
+ uint c = element.attribute( attr ).toUInt( &ok );
+ if ( !ok )
+ return fallback;
+ else
+ return QColor( (c >> 16) & 0xFF, (c >> 8) & 0xFF, c & 0xFF );
+}
+
+void SensorDisplay::saveColor( QDomElement &element, const QString &attr,
+ const QColor &color )
+{
+ int r, g, b;
+ color.rgb( &r, &g, &b );
+ element.setAttribute( attr, (r << 16) | (g << 8) | b );
+}
+
+bool SensorDisplay::addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &description )
+{
+ registerSensor( new SensorProperties( hostName, name, type, description ) );
+ return true;
+}
+
+bool SensorDisplay::removeSensor( uint pos )
+{
+ unregisterSensor( pos );
+ return true;
+}
+
+void SensorDisplay::setUpdateInterval( uint interval )
+{
+ bool timerActive = timerOn();
+
+ if ( timerActive )
+ setTimerOn( false );
+
+ mUpdateInterval = interval;
+
+ if ( timerActive )
+ setTimerOn( true );
+}
+
+bool SensorDisplay::hasSettingsDialog() const
+{
+ return false;
+}
+
+void SensorDisplay::configureSettings()
+{
+}
+
+void SensorDisplay::setUseGlobalUpdateInterval( bool value )
+{
+ mUseGlobalUpdateInterval = value;
+}
+
+bool SensorDisplay::useGlobalUpdateInterval() const
+{
+ return mUseGlobalUpdateInterval;
+}
+
+QString SensorDisplay::additionalWhatsThis()
+{
+ return QString::null;
+}
+
+void SensorDisplay::sensorLost( int reqId )
+{
+ sensorError( reqId, true );
+}
+
+bool SensorDisplay::restoreSettings( QDomElement &element )
+{
+ QString str = element.attribute( "showUnit", "X" );
+ if(!str.isEmpty() && str != "X") {
+ mShowUnit = str.toInt();
+ }
+ str = element.attribute( "unit", QString::null );
+ if(!str.isEmpty())
+ setUnit(str);
+ str = element.attribute( "title", QString::null );
+ if(!str.isEmpty())
+ setTitle(str);
+
+ if ( element.attribute( "updateInterval" ) != QString::null ) {
+ mUseGlobalUpdateInterval = false;
+ setUpdateInterval( element.attribute( "updateInterval", "2" ).toInt() );
+ } else {
+ mUseGlobalUpdateInterval = true;
+
+ SensorBoard* sb = dynamic_cast<SensorBoard*>( parentWidget() );
+ if ( !sb ) {
+ kdDebug(1215) << "dynamic cast lacks" << endl;
+ setUpdateInterval( 2 );
+ } else
+ setUpdateInterval( sb->updateInterval() );
+ }
+
+ if ( element.attribute( "pause", "0" ).toInt() == 0 )
+ setTimerOn( true );
+ else
+ setTimerOn( false );
+
+ return true;
+}
+
+bool SensorDisplay::saveSettings( QDomDocument&, QDomElement &element, bool )
+{
+ element.setAttribute( "title", title() );
+ element.setAttribute( "unit", unit() );
+ element.setAttribute( "showUnit", mShowUnit );
+
+ if ( mUseGlobalUpdateInterval )
+ element.setAttribute( "globalUpdate", "1" );
+ else {
+ element.setAttribute( "globalUpdate", "0" );
+ element.setAttribute( "updateInterval", mUpdateInterval );
+ }
+
+ if ( !timerOn() )
+ element.setAttribute( "pause", 1 );
+ else
+ element.setAttribute( "pause", 0 );
+
+ return true;
+}
+
+void SensorDisplay::setTimerOn( bool on )
+{
+ if ( on ) {
+ if ( mTimerId == NONE )
+ mTimerId = startTimer( mUpdateInterval * 1000 );
+ } else {
+ if ( mTimerId != NONE ) {
+ killTimer( mTimerId );
+ mTimerId = NONE;
+ }
+ }
+}
+
+bool SensorDisplay::timerOn() const
+{
+ return ( mTimerId != NONE );
+}
+
+bool SensorDisplay::modified() const
+{
+ return mModified;
+}
+
+QPtrList<SensorProperties> &SensorDisplay::sensors()
+{
+ return mSensors;
+}
+
+void SensorDisplay::rmbPressed()
+{
+ emit showPopupMenu( this );
+}
+
+void SensorDisplay::applySettings()
+{
+}
+
+void SensorDisplay::applyStyle()
+{
+}
+
+void SensorDisplay::setModified( bool value )
+{
+ if ( value != mModified ) {
+ mModified = value;
+ emit modified( mModified );
+ }
+}
+
+void SensorDisplay::setSensorOk( bool ok )
+{
+ if ( ok ) {
+ delete mErrorIndicator;
+ mErrorIndicator = 0;
+ } else {
+ if ( mErrorIndicator )
+ return;
+
+ QPixmap errorIcon = KGlobal::iconLoader()->loadIcon( "connect_creating", KIcon::Desktop,
+ KIcon::SizeSmall );
+ if ( !mPlotterWdg )
+ return;
+
+ mErrorIndicator = new QWidget( mPlotterWdg );
+ mErrorIndicator->setErasePixmap( errorIcon );
+ mErrorIndicator->resize( errorIcon.size() );
+ if ( errorIcon.mask() )
+ mErrorIndicator->setMask( *errorIcon.mask() );
+ mErrorIndicator->move( 0, 0 );
+ mErrorIndicator->show();
+ }
+}
+
+void SensorDisplay::setTitle( const QString &title )
+{
+ mTitle = title;
+
+ if(!mFrame) {
+ return; //fixme. create a frame and move widget inside it.
+ }
+
+ /* Changing the frame title may increase the width of the frame and
+ * hence breaks the layout. To avoid this, we save the original size
+ * and restore it after we have set the frame title. */
+ QSize s = mFrame->size();
+
+ if ( mShowUnit && !mUnit.isEmpty() )
+ mFrame->setTitle( mTitle + " [" + mUnit + "]" );
+ else
+ mFrame->setTitle( mTitle );
+ mFrame->setGeometry( 0, 0, s.width(), s.height() );
+}
+
+QString SensorDisplay::title() const
+{
+ return mTitle;
+}
+
+void SensorDisplay::setUnit( const QString &unit )
+{
+ mUnit = unit;
+}
+
+QString SensorDisplay::unit() const
+{
+ return mUnit;
+}
+
+void SensorDisplay::setShowUnit( bool value )
+{
+ mShowUnit = value;
+}
+
+bool SensorDisplay::showUnit() const
+{
+ return mShowUnit;
+}
+
+void SensorDisplay::setPlotterWidget( QWidget *wdg )
+{
+ mPlotterWdg = wdg;
+
+}
+
+QWidget *SensorDisplay::frame()
+{
+ return mFrame;
+}
+
+//void SensorDisplay::setNoFrame( bool /*value*/ )
+//{
+ //FIXME - delete or create the frame as needed
+//}
+
+bool SensorDisplay::noFrame() const
+{
+ return !mFrame;
+}
+
+void SensorDisplay::reorderSensors(const QValueList<int> &orderOfSensors)
+{
+ QPtrList<SensorProperties> newSensors;
+ for ( uint i = 0; i < orderOfSensors.count(); ++i ) {
+ newSensors.append( mSensors.at(orderOfSensors[i] ));
+ }
+
+ mSensors.setAutoDelete( false );
+ mSensors = newSensors;
+ mSensors.setAutoDelete( true );
+}
+
+
+SensorProperties::SensorProperties()
+{
+}
+
+SensorProperties::SensorProperties( const QString &hostName, const QString &name,
+ const QString &type, const QString &description )
+ : mHostName( hostName ), mName( name ), mType( type ), mDescription( description )
+{
+ mOk = false;
+}
+
+SensorProperties::~SensorProperties()
+{
+}
+
+void SensorProperties::setHostName( const QString &hostName )
+{
+ mHostName = hostName;
+}
+
+QString SensorProperties::hostName() const
+{
+ return mHostName;
+}
+
+void SensorProperties::setName( const QString &name )
+{
+ mName = name;
+}
+
+QString SensorProperties::name() const
+{
+ return mName;
+}
+
+void SensorProperties::setType( const QString &type )
+{
+ mType = type;
+}
+
+QString SensorProperties::type() const
+{
+ return mType;
+}
+
+void SensorProperties::setDescription( const QString &description )
+{
+ mDescription = description;
+}
+
+QString SensorProperties::description() const
+{
+ return mDescription;
+}
+
+void SensorProperties::setUnit( const QString &unit )
+{
+ mUnit = unit;
+}
+
+QString SensorProperties::unit() const
+{
+ return mUnit;
+}
+
+void SensorProperties::setIsOk( bool value )
+{
+ mOk = value;
+}
+
+bool SensorProperties::isOk() const
+{
+ return mOk;
+}
+
+#include "SensorDisplay.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/SensorDisplay.h b/ksysguard/gui/SensorDisplayLib/SensorDisplay.h
new file mode 100644
index 000000000..e5e867a01
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorDisplay.h
@@ -0,0 +1,331 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_SENSORDISPLAY_H
+#define KSG_SENSORDISPLAY_H
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qvaluelist.h>
+#include <qwidget.h>
+
+#include <knotifyclient.h>
+
+#include <ksgrd/SensorClient.h>
+
+#define NONE -1
+
+class QDomDocument;
+class QDomElement;
+
+namespace KSGRD {
+
+class SensorProperties;
+
+/**
+ This class is the base class for all displays for sensors. A
+ display is any kind of widget that can display the value of one or
+ more sensors in any form. It must be inherited by all displays that
+ should be inserted into the work sheet.
+ */
+class SensorDisplay : public QWidget, public SensorClient
+{
+ Q_OBJECT
+
+ public:
+ /**
+ Constructor.
+ */
+ SensorDisplay( QWidget *parent = 0, const char *name = 0,
+ const QString& title = 0, bool nf = false, bool isApplet = false );
+
+ /**
+ Destructor.
+ */
+ virtual ~SensorDisplay();
+
+ /**
+ Sets the title of the display.
+ */
+ void setTitle( const QString &title );
+
+ /**
+ Returns the title of the display.
+ */
+ QString title() const;
+
+ /**
+ Sets the unit of the display.
+ */
+ void setUnit( const QString &unit );
+
+ /**
+ Returns the unit of the display.
+ */
+ QString unit() const;
+
+ /**
+ Sets whether the unit string should be displayed at the top
+ of the display frame.
+ */
+ void setShowUnit( bool value );
+
+ /**
+ Returns whether the unit string should be displayed at the top
+ of the display frame. @see setShowUnit()
+ */
+ bool showUnit() const;
+
+ /**
+ Sets whether the update interval of the work sheet should be
+ used instead of the one, set by @ref setUpdateInterval().
+ */
+ void setUseGlobalUpdateInterval( bool value );
+
+ /**
+ Returns whether the update interval of the work sheet should be
+ used instead of the one, set by @ref setUpdateInterval().
+ see @ref setUseGlobalUpdateInterval()
+ */
+ bool useGlobalUpdateInterval() const;
+
+ /**
+ Sets the update interval of the timer, which triggers the timer
+ events. The state of the timer can be set with @ref setTimerOn().
+ */
+ void setUpdateInterval( uint interval );
+
+ /**
+ Returns the update interval.
+ */
+ uint updateInterval() const;
+
+ /**
+ This method appends all hosts of the display to @ref list.
+ */
+ void hosts( QStringList& list );
+
+ /**
+ Sets the widget on which the error icon can be drawn.
+ */
+ void setPlotterWidget( QWidget *plotter );
+
+ /**
+ Returns the widget on which the error icon can be drawn.
+ */
+ QWidget *plotterWidget() const;
+
+ /**
+ Add a sensor to the display.
+
+ @param hostName The name of the host, the sensor belongs to.
+ @param name The sensor name.
+ @param type The type of the sensor.
+ @param description A short description of the sensor.
+ */
+ virtual bool addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &description );
+
+ /**
+ Removes the sensor from the display, that is at the position
+ @ref pos of the intern sensor list.
+ */
+ virtual bool removeSensor( uint pos );
+
+ /**
+ This function is a wrapper function to SensorManager::sendRequest.
+ It should be used by all SensorDisplay functions that need to send
+ a request to a sensor since it performs an appropriate error
+ handling by removing the display of necessary.
+ */
+ void sendRequest( const QString &hostName, const QString &cmd, int id );
+
+ /**
+ Raises the configure dialog to setup the update interval.
+ */
+ void configureUpdateInterval();
+
+ /**
+ Returns whether the display provides a settings dialog.
+ This method should be reimplemented in the derived class.
+ */
+ virtual bool hasSettingsDialog() const;
+
+ /**
+ This method is called to raise the settings dialog of the
+ display. It should be reimplemented in the derived class.
+ */
+ virtual void configureSettings();
+
+ /**
+ Reimplement this method to setup the display from config data.
+ */
+ virtual bool restoreSettings( QDomElement& );
+
+ /**
+ Reimplement this method to save the displays config data.
+ */
+ virtual bool saveSettings( QDomDocument&, QDomElement&, bool = true );
+
+ /**
+ Reimplement this method to catch error messages from the SensorManager.
+
+ @param sensorId The unique id of the sensor.
+ @param mode The mode: true = error, false = everthing ok
+ */
+ virtual void sensorError( int sensorId, bool mode );
+
+ /**
+ Normaly you shouldn't reimplement this methode
+ */
+ virtual void sensorLost( int reqId );
+
+ public slots:
+ /**
+ If @ref value is true, this method starts the timer that triggers
+ timer events. If @ref value is false, the timer is stopped.
+ */
+ void setTimerOn( bool value );
+
+ /**
+ Calling this method emits the @ref showPopupMenu() with this
+ display as argument.
+ */
+ void rmbPressed();
+
+ /**
+ Sets whether the display is modified of not.
+ */
+ void setModified( bool modified );
+
+ /**
+ This method can be used to apply the new settings. Just connect
+ the applyClicked() signal of your configuration dialog with this
+ slot and reimplement it.
+ */
+ virtual void applySettings();
+
+ /**
+ This methid is called whenever the global style is changed.
+ Reimplement it to apply the new style settings to the display.
+ */
+ virtual void applyStyle();
+
+
+ signals:
+ void showPopupMenu( KSGRD::SensorDisplay *display );
+ void modified( bool modified );
+
+ protected:
+ virtual bool eventFilter( QObject*, QEvent* );
+ virtual void resizeEvent( QResizeEvent* );
+ virtual void timerEvent( QTimerEvent* );
+
+ void registerSensor( SensorProperties *sp );
+ void unregisterSensor( uint pos );
+
+ QColor restoreColor( QDomElement &element, const QString &attr,
+ const QColor& fallback );
+ void saveColor( QDomElement &element, const QString &attr,
+ const QColor &color );
+
+ virtual QString additionalWhatsThis();
+
+ void setSensorOk( bool ok );
+
+ bool modified() const;
+ bool timerOn() const;
+
+ QWidget *frame();
+
+// void setNoFrame( bool value );
+ bool noFrame() const;
+
+ void reorderSensors(const QValueList<int> &orderOfSensors);
+ QPtrList<SensorProperties> &sensors();
+
+ private:
+ void updateWhatsThis();
+
+ bool mShowUnit;
+ bool mUseGlobalUpdateInterval;
+ bool mModified;
+ bool mNoFrame;
+ bool mIsApplet;
+
+ int mTimerId;
+ int mUpdateInterval;
+
+ // The frame around the other widgets.
+ QGroupBox* mFrame;
+
+ QPtrList<SensorProperties> mSensors;
+
+ QString mTitle;
+ QString mUnit;
+
+ QWidget* mErrorIndicator;
+ QWidget* mPlotterWdg;
+};
+
+class SensorProperties
+{
+ public:
+ SensorProperties();
+ SensorProperties( const QString &hostName, const QString &name,
+ const QString &type, const QString &description );
+ ~SensorProperties();
+
+ void setHostName( const QString &hostName );
+ QString hostName() const;
+
+ void setName( const QString &name );
+ QString name() const;
+
+ void setType( const QString &type );
+ QString type() const;
+
+ void setDescription( const QString &description );
+ QString description() const;
+
+ void setUnit( const QString &unit );
+ QString unit() const;
+
+ void setIsOk( bool value );
+ bool isOk() const;
+
+ private:
+ QString mHostName;
+ QString mName;
+ QString mType;
+ QString mDescription;
+ QString mUnit;
+
+ /* This flag indicates whether the communication to the sensor is
+ * ok or not. */
+ bool mOk;
+};
+
+}
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLogger.cc b/ksysguard/gui/SensorDisplayLib/SensorLogger.cc
new file mode 100644
index 000000000..b51ba67e0
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLogger.cc
@@ -0,0 +1,437 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <klocale.h>
+
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+
+#include <qfile.h>
+
+#include "SensorLogger.moc"
+#include "SensorLoggerSettings.h"
+
+SLListViewItem::SLListViewItem(QListView *parent)
+ : QListViewItem(parent)
+{
+}
+
+LogSensor::LogSensor(QListView *parent)
+ : timerID( NONE ), lowerLimitActive( 0 ), upperLimitActive( 0 ),
+ lowerLimit( 0 ), upperLimit( 0 )
+{
+ Q_CHECK_PTR(parent);
+
+ monitor = parent;
+
+ lvi = new SLListViewItem(monitor);
+ Q_CHECK_PTR(lvi);
+
+ pixmap_running = UserIcon( "running" );
+ pixmap_waiting = UserIcon( "waiting" );
+
+ lvi->setPixmap(0, pixmap_waiting);
+ lvi->setTextColor(monitor->colorGroup().text());
+
+ monitor->insertItem(lvi);
+}
+
+LogSensor::~LogSensor(void)
+{
+ if ((lvi) && (monitor))
+ delete lvi;
+}
+
+void
+LogSensor::startLogging(void)
+{
+ lvi->setPixmap(0, pixmap_running);
+ timerOn();
+}
+
+void
+LogSensor::stopLogging(void)
+{
+ lvi->setPixmap(0, pixmap_waiting);
+ lvi->setTextColor(monitor->colorGroup().text());
+ lvi->repaint();
+ timerOff();
+}
+
+void
+LogSensor::timerEvent(QTimerEvent*)
+{
+ KSGRD::SensorMgr->sendRequest(hostName, sensorName, (KSGRD::SensorClient*) this, 42);
+}
+
+void
+LogSensor::answerReceived(int id, const QString& answer)
+{
+ QFile logFile(fileName);
+
+ if (!logFile.open(IO_ReadWrite | IO_Append))
+ {
+ stopLogging();
+ return;
+ }
+
+ switch (id)
+ {
+ case 42: {
+ QTextStream stream(&logFile);
+ double value = answer.toDouble();
+
+ if (lowerLimitActive && value < lowerLimit)
+ {
+ timerOff();
+ lowerLimitActive = false;
+ lvi->setTextColor(monitor->colorGroup().foreground());
+ lvi->repaint();
+ KNotifyClient::event(monitor->winId(), "sensor_alarm", QString("sensor '%1' at '%2' reached lower limit").arg(sensorName).arg(hostName));
+ timerOn();
+ } else if (upperLimitActive && value > upperLimit)
+ {
+ timerOff();
+ upperLimitActive = false;
+ lvi->setTextColor(monitor->colorGroup().foreground());
+ lvi->repaint();
+ KNotifyClient::event(monitor->winId(), "sensor_alarm", QString("sensor '%1' at '%2' reached upper limit").arg(sensorName).arg(hostName));
+ timerOn();
+ }
+ QDate date = QDateTime::currentDateTime().date();
+ QTime time = QDateTime::currentDateTime().time();
+
+ stream << QString("%1 %2 %3 %4 %5: %6\n").arg(date.shortMonthName(date.month())).arg(date.day()).arg(time.toString()).arg(hostName).arg(sensorName).arg(value);
+ }
+ }
+
+ logFile.close();
+}
+
+SensorLogger::SensorLogger(QWidget *parent, const char *name, const QString& title)
+ : KSGRD::SensorDisplay(parent, name, title)
+{
+ monitor = new QListView(this, "monitor");
+ Q_CHECK_PTR(monitor);
+
+ monitor->addColumn(i18n("Logging"));
+ monitor->addColumn(i18n("Timer Interval"));
+ monitor->addColumn(i18n("Sensor Name"));
+ monitor->addColumn(i18n("Host Name"));
+ monitor->addColumn(i18n("Log File"));
+
+ QColorGroup cgroup = monitor->colorGroup();
+ cgroup.setColor(QColorGroup::Text, KSGRD::Style->firstForegroundColor());
+ cgroup.setColor(QColorGroup::Base, KSGRD::Style->backgroundColor());
+ cgroup.setColor(QColorGroup::Foreground, KSGRD::Style->alarmColor());
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+ monitor->setSelectionMode(QListView::NoSelection);
+
+ connect(monitor, SIGNAL(rightButtonClicked(QListViewItem*, const QPoint&, int)), this, SLOT(RMBClicked(QListViewItem*, const QPoint&, int)));
+
+ setTitle(i18n("Sensor Logger"));
+
+ logSensors.setAutoDelete(true);
+
+ setPlotterWidget(monitor);
+
+ setMinimumSize(50, 25);
+ setModified(false);
+}
+
+SensorLogger::~SensorLogger(void)
+{
+}
+
+bool
+SensorLogger::addSensor(const QString& hostName, const QString& sensorName, const QString& sensorType, const QString&)
+{
+ if (sensorType != "integer" && sensorType != "float")
+ return (false);
+
+ sld = new SensorLoggerDlg(this, "SensorLoggerDlg");
+ Q_CHECK_PTR(sld);
+
+ if (sld->exec()) {
+ if (!sld->fileName().isEmpty()) {
+ LogSensor *sensor = new LogSensor(monitor);
+ Q_CHECK_PTR(sensor);
+
+ sensor->setHostName(hostName);
+ sensor->setSensorName(sensorName);
+ sensor->setFileName(sld->fileName());
+ sensor->setTimerInterval(sld->timerInterval());
+ sensor->setLowerLimitActive(sld->lowerLimitActive());
+ sensor->setUpperLimitActive(sld->upperLimitActive());
+ sensor->setLowerLimit(sld->lowerLimit());
+ sensor->setUpperLimit(sld->upperLimit());
+
+ logSensors.append(sensor);
+
+ setModified(true);
+ }
+ }
+
+ delete sld;
+ sld = 0;
+
+ return (true);
+}
+
+bool
+SensorLogger::editSensor(LogSensor* sensor)
+{
+ sld = new SensorLoggerDlg(this, "SensorLoggerDlg");
+ Q_CHECK_PTR(sld);
+
+ sld->setFileName(sensor->getFileName());
+ sld->setTimerInterval(sensor->getTimerInterval());
+ sld->setLowerLimitActive(sensor->getLowerLimitActive());
+ sld->setLowerLimit(sensor->getLowerLimit());
+ sld->setUpperLimitActive(sensor->getUpperLimitActive());
+ sld->setUpperLimit(sensor->getUpperLimit());
+
+ if (sld->exec()) {
+ if (!sld->fileName().isEmpty()) {
+ sensor->setFileName(sld->fileName());
+ sensor->setTimerInterval(sld->timerInterval());
+ sensor->setLowerLimitActive(sld->lowerLimitActive());
+ sensor->setUpperLimitActive(sld->upperLimitActive());
+ sensor->setLowerLimit(sld->lowerLimit());
+ sensor->setUpperLimit(sld->upperLimit());
+
+ setModified(true);
+ }
+ }
+
+ delete sld;
+ sld = 0;
+
+ return (true);
+}
+
+void
+SensorLogger::configureSettings()
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ sls = new SensorLoggerSettings(this, "SensorLoggerSettings");
+ Q_CHECK_PTR(sls);
+
+ connect( sls, SIGNAL( applyClicked() ), SLOT( applySettings() ) );
+
+ sls->setTitle(title());
+ sls->setForegroundColor(cgroup.text());
+ sls->setBackgroundColor(cgroup.base());
+ sls->setAlarmColor(cgroup.foreground());
+
+ if (sls->exec())
+ applySettings();
+
+ delete sls;
+ sls = 0;
+}
+
+void
+SensorLogger::applySettings()
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ setTitle(sls->title());
+
+ cgroup.setColor(QColorGroup::Text, sls->foregroundColor());
+ cgroup.setColor(QColorGroup::Base, sls->backgroundColor());
+ cgroup.setColor(QColorGroup::Foreground, sls->alarmColor());
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+
+ setModified(true);
+}
+
+void
+SensorLogger::applyStyle(void)
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ cgroup.setColor(QColorGroup::Text, KSGRD::Style->firstForegroundColor());
+ cgroup.setColor(QColorGroup::Base, KSGRD::Style->backgroundColor());
+ cgroup.setColor(QColorGroup::Foreground, KSGRD::Style->alarmColor());
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+
+ setModified(true);
+}
+
+bool
+SensorLogger::restoreSettings(QDomElement& element)
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ cgroup.setColor(QColorGroup::Text, restoreColor(element, "textColor", Qt::green));
+ cgroup.setColor(QColorGroup::Base, restoreColor(element, "backgroundColor", Qt::black));
+ cgroup.setColor(QColorGroup::Foreground, restoreColor(element, "alarmColor", Qt::red));
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+
+ logSensors.clear();
+
+ QDomNodeList dnList = element.elementsByTagName("logsensors");
+ for (uint i = 0; i < dnList.count(); i++) {
+ QDomElement element = dnList.item(i).toElement();
+ LogSensor* sensor = new LogSensor(monitor);
+ Q_CHECK_PTR(sensor);
+
+ sensor->setHostName(element.attribute("hostName"));
+ sensor->setSensorName(element.attribute("sensorName"));
+ sensor->setFileName(element.attribute("fileName"));
+ sensor->setTimerInterval(element.attribute("timerInterval").toInt());
+ sensor->setLowerLimitActive(element.attribute("lowerLimitActive").toInt());
+ sensor->setLowerLimit(element.attribute("lowerLimit").toDouble());
+ sensor->setUpperLimitActive(element.attribute("upperLimitActive").toInt());
+ sensor->setUpperLimit(element.attribute("upperLimit").toDouble());
+
+ logSensors.append(sensor);
+ }
+
+ SensorDisplay::restoreSettings(element);
+
+ setModified(false);
+
+ return (true);
+}
+
+bool
+SensorLogger::saveSettings(QDomDocument& doc, QDomElement& element, bool save)
+{
+ saveColor(element, "textColor", monitor->colorGroup().text());
+ saveColor(element, "backgroundColor", monitor->colorGroup().base());
+ saveColor(element, "alarmColor", monitor->colorGroup().foreground());
+
+ for (LogSensor* sensor = logSensors.first(); sensor != 0; sensor = logSensors.next())
+ {
+ QDomElement log = doc.createElement("logsensors");
+ log.setAttribute("sensorName", sensor->getSensorName());
+ log.setAttribute("hostName", sensor->getHostName());
+ log.setAttribute("fileName", sensor->getFileName());
+ log.setAttribute("timerInterval", sensor->getTimerInterval());
+ log.setAttribute("lowerLimitActive", QString("%1").arg(sensor->getLowerLimitActive()));
+ log.setAttribute("lowerLimit", QString("%1").arg(sensor->getLowerLimit()));
+ log.setAttribute("upperLimitActive", QString("%1").arg(sensor->getUpperLimitActive()));
+ log.setAttribute("upperLimit", QString("%1").arg(sensor->getUpperLimit()));
+
+ element.appendChild(log);
+ }
+
+ SensorDisplay::saveSettings(doc, element);
+
+ if (save)
+ setModified(false);
+
+ return (true);
+}
+
+void
+SensorLogger::answerReceived(int, const QString&)
+{
+ // we do not use this, since all answers are received by the LogSensors
+}
+
+void
+SensorLogger::resizeEvent(QResizeEvent*)
+{
+ frame()->setGeometry(0, 0, this->width(), this->height());
+ monitor->setGeometry(10, 20, this->width() - 20, this->height() - 30);
+}
+
+LogSensor*
+SensorLogger::getLogSensor(QListViewItem* item)
+{
+ for (LogSensor* sensor = logSensors.first(); sensor != 0; sensor = logSensors.next())
+ {
+ if (item == sensor->getListViewItem()) {
+ return sensor;
+ }
+ }
+
+ return NULL;
+}
+
+void
+SensorLogger::RMBClicked(QListViewItem* item, const QPoint& point, int)
+{
+ QPopupMenu pm;
+ if (hasSettingsDialog())
+ pm.insertItem(i18n("&Properties"), 1);
+ pm.insertItem(i18n("&Remove Display"), 2);
+ pm.insertSeparator(-1);
+ pm.insertItem(i18n("&Remove Sensor"), 3);
+ pm.insertItem(i18n("&Edit Sensor..."), 4);
+
+ if ( !item )
+ {
+ pm.setItemEnabled( 3, false );
+ pm.setItemEnabled( 4, false );
+ }
+ else
+ {
+ LogSensor* sensor = getLogSensor(item);
+
+ if ( sensor->isLogging() )
+ pm.insertItem(i18n("St&op Logging"), 6);
+ else
+ pm.insertItem(i18n("S&tart Logging"), 5);
+ }
+
+ switch (pm.exec(point))
+ {
+ case 1:
+ configureSettings();
+ break;
+ case 2: {
+ QCustomEvent* ev = new QCustomEvent(QEvent::User);
+ ev->setData(this);
+ kapp->postEvent(parent(), ev);
+ break;
+ }
+ case 3: {
+ LogSensor* sensor = getLogSensor(item);
+ if (sensor)
+ logSensors.remove(sensor);
+ break;
+ }
+ case 4: {
+ LogSensor* sensor = getLogSensor(item);
+ if (sensor)
+ editSensor(sensor);
+ break;
+ }
+ case 5: {
+ LogSensor* sensor = getLogSensor(item);
+ if (sensor)
+ sensor->startLogging();
+ break;
+ }
+ case 6: {
+ LogSensor* sensor = getLogSensor(item);
+ if (sensor)
+ sensor->stopLogging();
+ break;
+ }
+ }
+}
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLogger.h b/ksysguard/gui/SensorDisplayLib/SensorLogger.h
new file mode 100644
index 000000000..835e62401
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLogger.h
@@ -0,0 +1,184 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _SensorLogger_h
+#define _SensorLogger_h
+
+#include <qdom.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qlistview.h>
+#include <qpopupmenu.h>
+#include <qspinbox.h>
+#include <qstring.h>
+
+#include <SensorDisplay.h>
+
+#include "SensorLoggerDlg.h"
+
+#define NONE -1
+
+class SensorLoggerSettings;
+
+class SLListViewItem : public QListViewItem
+{
+public:
+ SLListViewItem(QListView *parent = 0);
+
+ void setTextColor(const QColor& color) { textColor = color; }
+
+ void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) {
+ QColorGroup cgroup(cg);
+ cgroup.setColor(QColorGroup::Text, textColor);
+ QListViewItem::paintCell(p, cgroup, column, width, alignment);
+
+ }
+
+ void paintFocus(QPainter *, const QColorGroup, const QRect) {}
+
+private:
+ QColor textColor;
+};
+
+class LogSensor : public QObject, public KSGRD::SensorClient
+{
+ Q_OBJECT
+public:
+ LogSensor(QListView *parent);
+ ~LogSensor(void);
+
+ void answerReceived(int id, const QString& answer);
+
+ void setHostName(const QString& name) { hostName = name; lvi->setText(3, name); }
+ void setSensorName(const QString& name) { sensorName = name; lvi->setText(2, name); }
+ void setFileName(const QString& name)
+ {
+ fileName = name;
+ lvi->setText(4, name);
+ }
+ void setUpperLimitActive(bool value) { upperLimitActive = value; }
+ void setLowerLimitActive(bool value) { lowerLimitActive = value; }
+ void setUpperLimit(double value) { upperLimit = value; }
+ void setLowerLimit(double value) { lowerLimit = value; }
+
+ void setTimerInterval(int interval) {
+ timerInterval = interval;
+
+ if (timerID != NONE)
+ {
+ timerOff();
+ timerOn();
+ }
+
+ lvi->setText(1, QString("%1").arg(interval));
+ }
+
+ QString getSensorName(void) { return sensorName; }
+ QString getHostName(void) { return hostName; }
+ QString getFileName(void) { return fileName; }
+ int getTimerInterval(void) { return timerInterval; }
+ bool getUpperLimitActive(void) { return upperLimitActive; }
+ bool getLowerLimitActive(void) { return lowerLimitActive; }
+ double getUpperLimit(void) { return upperLimit; }
+ double getLowerLimit(void) { return lowerLimit; }
+ QListViewItem* getListViewItem(void) { return lvi; }
+
+public slots:
+ void timerOff()
+ {
+ killTimer(timerID);
+ timerID = NONE;
+ }
+
+ void timerOn()
+ {
+ timerID = startTimer(timerInterval * 1000);
+ }
+
+ bool isLogging() { return timerID != NONE; }
+
+ void startLogging(void);
+ void stopLogging(void);
+
+protected:
+ virtual void timerEvent(QTimerEvent*);
+
+private:
+ QListView* monitor;
+ SLListViewItem* lvi;
+ QPixmap pixmap_running;
+ QPixmap pixmap_waiting;
+ QString sensorName;
+ QString hostName;
+ QString fileName;
+
+ int timerInterval;
+ int timerID;
+
+ bool lowerLimitActive;
+ bool upperLimitActive;
+
+ double lowerLimit;
+ double upperLimit;
+};
+
+class SensorLogger : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+public:
+ SensorLogger(QWidget *parent = 0, const char *name = 0, const QString& title = 0);
+ ~SensorLogger(void);
+
+ bool addSensor(const QString& hostName, const QString& sensorName, const QString& sensorType,
+ const QString& sensorDescr);
+
+ bool editSensor(LogSensor*);
+
+ void answerReceived(int id, const QString& answer);
+ void resizeEvent(QResizeEvent*);
+
+ bool restoreSettings(QDomElement& element);
+ bool saveSettings(QDomDocument& doc, QDomElement& element, bool save = true);
+
+ void configureSettings(void);
+
+ virtual bool hasSettingsDialog() const
+ {
+ return (true);
+ }
+
+public slots:
+ void applySettings();
+ void applyStyle();
+ void RMBClicked(QListViewItem*, const QPoint&, int);
+
+protected:
+ LogSensor* getLogSensor(QListViewItem*);
+
+private:
+ QListView* monitor;
+
+ QPtrList<LogSensor> logSensors;
+
+ SensorLoggerDlg *sld;
+ SensorLoggerSettings *sls;
+};
+
+#endif // _SensorLogger_h
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.cc b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.cc
new file mode 100644
index 000000000..f07b55ae4
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.cc
@@ -0,0 +1,106 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "SensorLoggerDlg.h"
+#include "SensorLoggerDlgWidget.h"
+
+#include <qlayout.h>
+
+#include <klocale.h>
+
+SensorLoggerDlg::SensorLoggerDlg( QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n( "Sensor Logger" ),
+ Ok|Cancel, Ok, true )
+{
+ QWidget *main = new QWidget( this );
+
+ QVBoxLayout *topLayout = new QVBoxLayout( main, 0, KDialog::spacingHint() );
+
+ m_loggerWidget = new SensorLoggerDlgWidget( main, "m_loggerWidget" );
+ topLayout->addWidget( m_loggerWidget );
+ topLayout->addStretch();
+
+ setMainWidget( main );
+}
+
+QString SensorLoggerDlg::fileName() const
+{
+ return m_loggerWidget->fileName();
+}
+
+int SensorLoggerDlg::timerInterval() const
+{
+ return m_loggerWidget->timerInterval();
+}
+
+bool SensorLoggerDlg::lowerLimitActive() const
+{
+ return m_loggerWidget->lowerLimitActive();
+}
+
+bool SensorLoggerDlg::upperLimitActive() const
+{
+ return m_loggerWidget->upperLimitActive();
+}
+
+double SensorLoggerDlg::lowerLimit() const
+{
+ return m_loggerWidget->lowerLimit();
+}
+
+double SensorLoggerDlg::upperLimit() const
+{
+ return m_loggerWidget->upperLimit();
+}
+
+void SensorLoggerDlg::setFileName( const QString &url )
+{
+ m_loggerWidget->setFileName( url );
+}
+
+void SensorLoggerDlg::setTimerInterval( int i )
+{
+ m_loggerWidget->setTimerInterval( i );
+}
+
+void SensorLoggerDlg::setLowerLimitActive( bool b )
+{
+ m_loggerWidget->setLowerLimitActive( b );
+}
+
+void SensorLoggerDlg::setUpperLimitActive( bool b )
+{
+ m_loggerWidget->setUpperLimitActive( b );
+}
+
+void SensorLoggerDlg::setLowerLimit( double limit )
+{
+ m_loggerWidget->setLowerLimit( limit );
+}
+
+void SensorLoggerDlg::setUpperLimit( double limit )
+{
+ m_loggerWidget->setUpperLimit( limit );
+}
+
+#include "SensorLoggerDlg.moc"
+
+/* vim: et sw=2 ts=2
+*/
+
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.h b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.h
new file mode 100644
index 000000000..3af8290c8
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef SENSORLOGGERDLG_H
+#define SENSORLOGGERDLG_H
+
+#include <kdialogbase.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+
+class SensorLoggerDlgWidget;
+
+class SensorLoggerDlg : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+
+ SensorLoggerDlg( QWidget *parent=0, const char *name=0 );
+
+ QString fileName() const;
+ int timerInterval() const;
+ bool lowerLimitActive() const;
+ bool upperLimitActive() const;
+ double lowerLimit() const;
+ double upperLimit() const;
+
+ void setFileName( const QString & );
+ void setTimerInterval( int );
+ void setLowerLimitActive( bool );
+ void setUpperLimitActive( bool );
+ void setLowerLimit( double );
+ void setUpperLimit( double );
+
+ private:
+
+ SensorLoggerDlgWidget *m_loggerWidget;
+};
+
+#endif // SENSORLOGGERDLG_H
+
+/* vim: et sw=2 ts=2
+*/
+
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui
new file mode 100644
index 000000000..26d3b2d49
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui
@@ -0,0 +1,263 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>SensorLoggerDlgWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>SensorLoggerDlgWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>363</width>
+ <height>254</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>fileFrame</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>GroupBoxPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>File</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>m_fileName</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>timerFrame</cstring>
+ </property>
+ <property name="title">
+ <string>Timer Interval</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KIntNumInput">
+ <property name="name">
+ <cstring>m_timerInterval</cstring>
+ </property>
+ <property name="value">
+ <number>2</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="maxValue">
+ <number>99</number>
+ </property>
+ <property name="suffix">
+ <string> sec</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Alarm for Minimum Value</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_lowerLimitActive</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Enable alarm</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enable the minimum value alarm.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_lblLowerLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Lower limit:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_lowerLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox1_2</cstring>
+ </property>
+ <property name="title">
+ <string>Alarm for Maximum Value</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_upperLimitActive</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;nable alarm</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enable the maximum value alarm.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_lblUpperLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Upper limit:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_upperLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>m_lowerLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_lowerLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_upperLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_upperLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_lowerLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_lblLowerLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_upperLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_lblUpperLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+ <include location="global" impldecl="in implementation">knumvalidator.h</include>
+ <include location="local" impldecl="in implementation">SensorLoggerDlgWidget.ui.h</include>
+</includes>
+<functions>
+ <function access="private" specifier="non virtual">init()</function>
+ <function specifier="non virtual" returnType="QString">fileName()</function>
+ <function specifier="non virtual" returnType="int">timerInterval()</function>
+ <function specifier="non virtual" returnType="bool">lowerLimitActive()</function>
+ <function specifier="non virtual" returnType="double">lowerLimit()</function>
+ <function returnType="bool">upperLimitActive()</function>
+ <function specifier="non virtual" returnType="double">upperLimit()</function>
+ <function specifier="non virtual">setFileName( const QString &amp; url )</function>
+ <function specifier="non virtual">setTimerInterval( int i )</function>
+ <function specifier="non virtual">setLowerLimitActive( bool b )</function>
+ <function specifier="non virtual">setLowerLimit( double d )</function>
+ <function specifier="non virtual">setUpperLimitActive( bool b )</function>
+ <function specifier="non virtual">setUpperLimit( double d )</function>
+</functions>
+
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui.h b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui.h
new file mode 100644
index 000000000..afe0767e9
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+void SensorLoggerDlgWidget::init()
+{
+ m_lowerLimit->setValidator(new KDoubleValidator(m_lowerLimit));
+ m_upperLimit->setValidator(new KDoubleValidator(m_upperLimit));
+ m_timerInterval->setRange(1, 99, 1, true);
+
+ m_fileName->setFocus();
+}
+
+
+QString SensorLoggerDlgWidget::fileName()
+{
+ return m_fileName->url();
+}
+
+
+int SensorLoggerDlgWidget::timerInterval()
+{
+ return m_timerInterval->value();
+}
+
+
+bool SensorLoggerDlgWidget::lowerLimitActive()
+{
+ return m_lowerLimitActive->isChecked();
+}
+
+
+double SensorLoggerDlgWidget::lowerLimit()
+{
+ return m_lowerLimit->text().toDouble();
+}
+
+
+bool SensorLoggerDlgWidget::upperLimitActive()
+{
+ return m_upperLimitActive->isChecked();
+}
+
+
+double SensorLoggerDlgWidget::upperLimit()
+{
+ return m_upperLimit->text().toDouble();
+}
+
+
+void SensorLoggerDlgWidget::setFileName( const QString &url )
+{
+ m_fileName->setURL(url);
+}
+
+
+void SensorLoggerDlgWidget::setTimerInterval( int i )
+{
+ m_timerInterval->setValue(i);
+}
+
+
+void SensorLoggerDlgWidget::setLowerLimitActive( bool b )
+{
+ m_lowerLimitActive->setChecked(b);
+}
+
+
+void SensorLoggerDlgWidget::setLowerLimit( double d )
+{
+ m_lowerLimit->setText(QString("%1").arg(d));
+}
+
+
+void SensorLoggerDlgWidget::setUpperLimitActive( bool b )
+{
+ m_upperLimitActive->setChecked(b);
+}
+
+
+void SensorLoggerDlgWidget::setUpperLimit( double d )
+{
+ m_upperLimit->setText(QString("%1").arg(d));
+}
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.cc b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.cc
new file mode 100644
index 000000000..568108547
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.cc
@@ -0,0 +1,77 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "SensorLoggerSettings.h"
+#include "SensorLoggerSettingsWidget.h"
+
+#include <klocale.h>
+
+SensorLoggerSettings::SensorLoggerSettings( QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n( "Sensor Logger Settings" ),
+ Ok|Apply|Cancel, Ok, true )
+{
+ m_settingsWidget = new SensorLoggerSettingsWidget( this, "m_settingsWidget" );
+ setMainWidget( m_settingsWidget );
+}
+
+QString SensorLoggerSettings::title()
+{
+ return m_settingsWidget->title();
+}
+
+QColor SensorLoggerSettings::foregroundColor()
+{
+ return m_settingsWidget->foregroundColor();
+}
+
+QColor SensorLoggerSettings::backgroundColor()
+{
+ return m_settingsWidget->backgroundColor();
+}
+
+QColor SensorLoggerSettings::alarmColor()
+{
+ return m_settingsWidget->alarmColor();
+}
+
+void SensorLoggerSettings::setTitle( const QString &title )
+{
+ m_settingsWidget->setTitle( title );
+}
+
+void SensorLoggerSettings::setBackgroundColor( const QColor &c )
+{
+ m_settingsWidget->setBackgroundColor( c );
+}
+
+void SensorLoggerSettings::setForegroundColor( const QColor &c )
+{
+ m_settingsWidget->setForegroundColor( c );
+}
+
+void SensorLoggerSettings::setAlarmColor( const QColor &c )
+{
+ m_settingsWidget->setAlarmColor( c );
+}
+
+#include "SensorLoggerSettings.moc"
+
+/* vim: et sw=2 ts=2
+*/
+
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.h b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.h
new file mode 100644
index 000000000..639f55944
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef SENSORLOGGERSETTINGS_H
+#define SENSORLOGGERSETTINGS_H
+
+#include <kdialogbase.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+
+class SensorLoggerSettingsWidget;
+
+class SensorLoggerSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+
+ SensorLoggerSettings( QWidget *parent=0, const char *name=0 );
+
+ QString title();
+ QColor foregroundColor();
+ QColor backgroundColor();
+ QColor alarmColor();
+
+ void setTitle( const QString & );
+ void setForegroundColor( const QColor & );
+ void setBackgroundColor( const QColor & );
+ void setAlarmColor( const QColor & );
+
+ private:
+
+ SensorLoggerSettingsWidget *m_settingsWidget;
+};
+
+#endif // SENSORLOGGERSETTINGS_H
+
+/* vim: et sw=2 ts=2
+*/
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui
new file mode 100644
index 000000000..c86e671b2
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui
@@ -0,0 +1,180 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>SensorLoggerSettingsWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>SensorLoggerSettingsWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>415</width>
+ <height>202</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>titleFrame</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="title">
+ <string>Title</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>colorFrame</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>Box</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>Colors</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter|AlignLeft</set>
+ </property>
+ <property name="vAlign" stdset="0">
+ </property>
+ <property name="wordwrap" stdset="0">
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Text color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Alarm color:</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_foregroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_backgroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_alarmColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<includes>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+ <include location="local" impldecl="in implementation">SensorLoggerSettingsWidget.ui.h</include>
+</includes>
+<functions>
+ <function specifier="non virtual" returnType="QString">title()</function>
+ <function specifier="non virtual" returnType="QColor">foregroundColor()</function>
+ <function specifier="non virtual" returnType="QColor">backgroundColor()</function>
+ <function specifier="non virtual" returnType="QColor">alarmColor()</function>
+ <function specifier="non virtual">setTitle( const QString &amp; t )</function>
+ <function specifier="non virtual">setForegroundColor( const QColor &amp; c )</function>
+ <function specifier="non virtual">setBackgroundColor( const QColor &amp; c )</function>
+ <function specifier="non virtual">setAlarmColor( const QColor &amp; c )</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+</UI>
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui.h b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui.h
new file mode 100644
index 000000000..751366466
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+QString SensorLoggerSettingsWidget::title()
+{
+ return m_title->text();
+}
+
+
+QColor SensorLoggerSettingsWidget::foregroundColor()
+{
+ return m_foregroundColor->color();
+}
+
+
+QColor SensorLoggerSettingsWidget::backgroundColor()
+{
+ return m_backgroundColor->color();
+}
+
+
+QColor SensorLoggerSettingsWidget::alarmColor()
+{
+ return m_alarmColor->color();
+}
+
+
+void SensorLoggerSettingsWidget::setTitle( const QString &t )
+{
+ m_title->setText(t);
+}
+
+
+void SensorLoggerSettingsWidget::setForegroundColor( const QColor &c )
+{
+ m_foregroundColor->setColor(c);
+}
+
+
+void SensorLoggerSettingsWidget::setBackgroundColor( const QColor &c )
+{
+ m_backgroundColor->setColor(c);
+}
+
+
+void SensorLoggerSettingsWidget::setAlarmColor( const QColor &c )
+{
+ m_alarmColor->setColor(c);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/SignalPlotter.cc b/ksysguard/gui/SensorDisplayLib/SignalPlotter.cc
new file mode 100644
index 000000000..f8ad121f1
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SignalPlotter.cc
@@ -0,0 +1,648 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2002 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <math.h>
+#include <string.h>
+
+#include <qpainter.h>
+#include <qpixmap.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+
+#include <ksgrd/StyleEngine.h>
+
+#include "SignalPlotter.h"
+
+SignalPlotter::SignalPlotter( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ // Auto deletion does not work for pointer to arrays.
+ mBeamData.setAutoDelete( false );
+
+ setBackgroundMode( NoBackground );
+ mShowThinFrame = true;
+ mSamples = 0;
+ mMinValue = mMaxValue = 0.0;
+ mUseAutoRange = true;
+
+ mGraphStyle = GRAPH_POLYGON;
+
+ // Anything smaller than this does not make sense.
+ setMinimumSize( 16, 16 );
+ setSizePolicy( QSizePolicy( QSizePolicy::Expanding,
+ QSizePolicy::Expanding, false ) );
+
+ mShowVerticalLines = true;
+ mVerticalLinesColor = KSGRD::Style->firstForegroundColor();
+ mVerticalLinesDistance = 30;
+ mVerticalLinesScroll = true;
+ mVerticalLinesOffset = 0;
+ mHorizontalScale = 1;
+
+ mShowHorizontalLines = true;
+ mHorizontalLinesColor = KSGRD::Style->secondForegroundColor();
+ mHorizontalLinesCount = 5;
+
+ mShowLabels = true;
+ mShowTopBar = false;
+ mFontSize = KSGRD::Style->fontSize();
+
+ mBackgroundColor = KSGRD::Style->backgroundColor();
+}
+
+SignalPlotter::~SignalPlotter()
+{
+ for ( double* p = mBeamData.first(); p; p = mBeamData.next() )
+ delete [] p;
+}
+
+bool SignalPlotter::addBeam( const QColor &color )
+{
+ double* d = new double[ mSamples ];
+ memset( d, 0, sizeof(double) * mSamples );
+ mBeamData.append( d );
+ mBeamColor.append( color );
+
+ return true;
+}
+
+void SignalPlotter::addSample( const QValueList<double>& sampleBuf )
+{
+ if ( mBeamData.count() != sampleBuf.count() )
+ return;
+
+ double* d;
+ if ( mUseAutoRange ) {
+ double sum = 0;
+ for ( d = mBeamData.first(); d; d = mBeamData.next() ) {
+ sum += d[ 0 ];
+ if ( sum < mMinValue )
+ mMinValue = sum;
+ if ( sum > mMaxValue )
+ mMaxValue = sum;
+ }
+ }
+
+ /* If the vertical lines are scrolling, increment the offset
+ * so they move with the data. The vOffset / hScale confusion
+ * is because v refers to Vertical Lines, and h to the horizontal
+ * distance between the vertical lines. */
+ if ( mVerticalLinesScroll ) {
+ mVerticalLinesOffset = ( mVerticalLinesOffset + mHorizontalScale)
+ % mVerticalLinesDistance;
+ }
+
+ // Shift data buffers one sample down and insert new samples.
+ QValueList<double>::ConstIterator s;
+ for ( d = mBeamData.first(), s = sampleBuf.begin(); d; d = mBeamData.next(), ++s ) {
+ memmove( d, d + 1, ( mSamples - 1 ) * sizeof( double ) );
+ d[ mSamples - 1 ] = *s;
+ }
+
+ update();
+}
+
+void SignalPlotter::reorderBeams( const QValueList<int>& newOrder )
+{
+ if(newOrder.count() != mBeamData.count()) {
+ kdDebug() << "Serious problem in move sample" << endl;
+ return;
+ }
+ QPtrList<double> newBeamData;
+ QValueList<QColor> newBeamColor;
+
+ for(uint i = 0; i < newOrder.count(); i++) {
+ int newIndex = newOrder[i];
+ newBeamData.append(mBeamData.at(newIndex));
+ newBeamColor.append(*mBeamColor.at(newIndex));
+ }
+ mBeamData = newBeamData;
+ mBeamColor = newBeamColor;
+
+}
+
+void SignalPlotter::changeRange( int beam, double min, double max )
+{
+ // Only the first beam affects range calculation.
+ if ( beam > 1 )
+ return;
+
+ mMinValue = min;
+ mMaxValue = max;
+}
+
+QValueList<QColor> &SignalPlotter::beamColors()
+{
+ return mBeamColor;
+}
+
+void SignalPlotter::removeBeam( uint pos )
+{
+ mBeamColor.remove( mBeamColor.at( pos ) );
+ double *p = mBeamData.take( pos );
+ delete [] p;
+}
+
+void SignalPlotter::setTitle( const QString &title )
+{
+ mTitle = title;
+}
+
+QString SignalPlotter::title() const
+{
+ return mTitle;
+}
+
+void SignalPlotter::setUseAutoRange( bool value )
+{
+ mUseAutoRange = value;
+}
+
+bool SignalPlotter::useAutoRange() const
+{
+ return mUseAutoRange;
+}
+
+void SignalPlotter::setMinValue( double min )
+{
+ mMinValue = min;
+}
+
+double SignalPlotter::minValue() const
+{
+ return ( mUseAutoRange ? 0 : mMinValue );
+}
+
+void SignalPlotter::setMaxValue( double max )
+{
+ mMaxValue = max;
+}
+
+double SignalPlotter::maxValue() const
+{
+ return ( mUseAutoRange ? 0 : mMaxValue );
+}
+
+void SignalPlotter::setGraphStyle( uint style )
+{
+ mGraphStyle = style;
+}
+
+uint SignalPlotter::graphStyle() const
+{
+ return mGraphStyle;
+}
+
+void SignalPlotter::setHorizontalScale( uint scale )
+{
+ if (scale == mHorizontalScale)
+ return;
+
+ mHorizontalScale = scale;
+ if (isVisible())
+ updateDataBuffers();
+}
+
+int SignalPlotter::horizontalScale() const
+{
+ return mHorizontalScale;
+}
+
+void SignalPlotter::setShowVerticalLines( bool value )
+{
+ mShowVerticalLines = value;
+}
+
+bool SignalPlotter::showVerticalLines() const
+{
+ return mShowVerticalLines;
+}
+
+void SignalPlotter::setVerticalLinesColor( const QColor &color )
+{
+ mVerticalLinesColor = color;
+}
+
+QColor SignalPlotter::verticalLinesColor() const
+{
+ return mVerticalLinesColor;
+}
+
+void SignalPlotter::setVerticalLinesDistance( int distance )
+{
+ mVerticalLinesDistance = distance;
+}
+
+int SignalPlotter::verticalLinesDistance() const
+{
+ return mVerticalLinesDistance;
+}
+
+void SignalPlotter::setVerticalLinesScroll( bool value )
+{
+ mVerticalLinesScroll = value;
+}
+
+bool SignalPlotter::verticalLinesScroll() const
+{
+ return mVerticalLinesScroll;
+}
+
+void SignalPlotter::setShowHorizontalLines( bool value )
+{
+ mShowHorizontalLines = value;
+}
+
+bool SignalPlotter::showHorizontalLines() const
+{
+ return mShowHorizontalLines;
+}
+
+void SignalPlotter::setHorizontalLinesColor( const QColor &color )
+{
+ mHorizontalLinesColor = color;
+}
+
+QColor SignalPlotter::horizontalLinesColor() const
+{
+ return mHorizontalLinesColor;
+}
+
+void SignalPlotter::setHorizontalLinesCount( int count )
+{
+ mHorizontalLinesCount = count;
+}
+
+int SignalPlotter::horizontalLinesCount() const
+{
+ return mHorizontalLinesCount;
+}
+
+void SignalPlotter::setShowLabels( bool value )
+{
+ mShowLabels = value;
+}
+
+bool SignalPlotter::showLabels() const
+{
+ return mShowLabels;
+}
+
+void SignalPlotter::setShowTopBar( bool value )
+{
+ mShowTopBar = value;
+}
+
+bool SignalPlotter::showTopBar() const
+{
+ return mShowTopBar;
+}
+
+void SignalPlotter::setFontSize( int size )
+{
+ mFontSize = size;
+}
+
+int SignalPlotter::fontSize() const
+{
+ return mFontSize;
+}
+
+void SignalPlotter::setBackgroundColor( const QColor &color )
+{
+ mBackgroundColor = color;
+}
+
+QColor SignalPlotter::backgroundColor() const
+{
+ return mBackgroundColor;
+}
+
+void SignalPlotter::resizeEvent( QResizeEvent* )
+{
+ Q_ASSERT( width() > 2 );
+
+ updateDataBuffers();
+}
+
+void SignalPlotter::updateDataBuffers()
+{
+ /* Since the data buffers for the beams are equal in size to the
+ * width of the widget minus 2 we have to enlarge or shrink the
+ * buffers accordingly when a resize occures. To have a nicer
+ * display we try to keep as much data as possible. Data that is
+ * lost due to shrinking the buffers cannot be recovered on
+ * enlarging though. */
+
+ /* Determine new number of samples first.
+ * +0.5 to ensure rounding up
+ * +2 for extra data points so there is
+ * 1) no wasted space and
+ * 2) no loss of precision when drawing the first data point. */
+ uint newSampleNum = static_cast<uint>( ( ( width() - 2 ) /
+ mHorizontalScale ) + 2.5 );
+
+ // overlap between the old and the new buffers.
+ int overlap = kMin( mSamples, newSampleNum );
+
+ for ( uint i = 0; i < mBeamData.count(); ++i ) {
+ double* nd = new double[ newSampleNum ];
+
+ // initialize new part of the new buffer
+ if ( newSampleNum > (uint)overlap )
+ memset( nd, 0, sizeof( double ) * ( newSampleNum - overlap ) );
+
+ // copy overlap from old buffer to new buffer
+ memcpy( nd + ( newSampleNum - overlap ), mBeamData.at( i ) +
+ ( mSamples - overlap ), overlap * sizeof( double ) );
+
+ double *p = mBeamData.take( i );
+ delete [] p;
+ mBeamData.insert( i, nd );
+ }
+
+ mSamples = newSampleNum;
+}
+
+void SignalPlotter::paintEvent( QPaintEvent* )
+{
+ uint w = width();
+ uint h = height();
+
+ /* Do not do repaints when the widget is not yet setup properly. */
+ if ( w <= 2 )
+ return;
+
+ QPixmap pm( w, h );
+ QPainter p;
+ p.begin( &pm, this );
+
+ pm.fill( mBackgroundColor );
+ /* Draw white line along the bottom and the right side of the
+ * widget to create a 3D like look. */
+ p.setPen( QColor( colorGroup().light() ) );
+ if(mShowThinFrame) {
+ p.drawLine( 0, h - 1, w - 1, h - 1 );
+ p.drawLine( w - 1, 0, w - 1, h - 1 );
+
+ h--;
+ w--;
+ p.setClipRect( 0, 0, w, h );
+ }
+ double range = mMaxValue - mMinValue;
+
+ /* If the range is too small we will force it to 1.0 since it
+ * looks a lot nicer. */
+ if ( range < 0.000001 )
+ range = 1.0;
+
+ double minValue = mMinValue;
+ if ( mUseAutoRange ) {
+ if ( mMinValue != 0.0 ) {
+ double dim = pow( 10, floor( log10( fabs( mMinValue ) ) ) ) / 2;
+ if ( mMinValue < 0.0 )
+ minValue = dim * floor( mMinValue / dim );
+ else
+ minValue = dim * ceil( mMinValue / dim );
+ range = mMaxValue - minValue;
+ if ( range < 0.000001 )
+ range = 1.0;
+ }
+ // Massage the range so that the grid shows some nice values.
+ double step = range / (mHorizontalLinesCount+1);
+ double dim = pow( 10, floor( log10( step ) ) ) / 2;
+ range = dim * ceil( step / dim ) * (mHorizontalLinesCount+1);
+ }
+ double maxValue = minValue + range;
+
+ int top = 0;
+ if ( mShowTopBar && h > ( mFontSize/*top bar size*/ + 2/*padding*/ +5/*smallest reasonable size for a graph*/ ) ) {
+ /* Draw horizontal bar with current sensor values at top of display. */
+ p.setPen( mHorizontalLinesColor );
+ int x0 = w / 2;
+ p.setFont( QFont( p.font().family(), mFontSize ) );
+ top = p.fontMetrics().height();
+ h -= top;
+ int h0 = top - 2; // h0 is our new top. It's at least 5 pixels high
+ p.drawText(0, 0, x0, top - 2, Qt::AlignCenter, mTitle );
+
+ p.drawLine( x0 - 1, 1, x0 - 1, h0 );
+ p.drawLine( 0, top - 1, w - 2, top - 1 );
+
+ double bias = -minValue;
+ double scaleFac = ( w - x0 - 2 ) / range;
+ QValueList<QColor>::Iterator col;
+ col = mBeamColor.begin();
+ for ( double* d = mBeamData.first(); d; d = mBeamData.next(), ++col ) {
+ int start = x0 + (int)( bias * scaleFac );
+ int end = x0 + (int)( ( bias += d[ mSamples - 1 ] ) * scaleFac );
+ /* If the rect is wider than 2 pixels we draw only the last
+ * pixels with the bright color. The rest is painted with
+ * a 50% darker color. */
+ if ( end - start > 1 ) {
+ p.setPen( (*col).dark( 150 ) );
+ p.setBrush( (*col).dark( 150 ) );
+ p.drawRect( start, 1, end - start, h0 );
+ p.setPen( *col );
+ p.drawLine( end, 1, end, h0 );
+ } else if ( start - end > 1 ) {
+ p.setPen( (*col).dark( 150 ) );
+ p.setBrush( (*col).dark( 150 ) );
+ p.drawRect( end, 1, start - end, h0 );
+ p.setPen( *col );
+ p.drawLine( end, 1, end, h0 );
+ } else {
+ p.setPen( *col );
+ p.drawLine( start, 1, start, h0 );
+ }
+ }
+ }
+
+ /* Draw scope-like grid vertical lines */
+ if ( mShowVerticalLines && w > 60 ) {
+ p.setPen( mVerticalLinesColor );
+ for ( uint x = mVerticalLinesOffset; x < ( w - 2 ); x += mVerticalLinesDistance )
+ p.drawLine( w - x, top, w - x, h + top - 2 );
+ }
+
+ /* In autoRange mode we determine the range and plot the values in
+ * one go. This is more efficiently than running through the
+ * buffers twice but we do react on recently discarded samples as
+ * well as new samples one plot too late. So the range is not
+ * correct if the recently discarded samples are larger or smaller
+ * than the current extreme values. But we can probably live with
+ * this. */
+ if ( mUseAutoRange )
+ mMinValue = mMaxValue = 0.0;
+
+ /* Plot stacked values */
+ double scaleFac = ( h - 2 ) / range;
+ if ( mGraphStyle == GRAPH_ORIGINAL ) {
+ int xPos = 0;
+ for ( int i = 0; i < mSamples; i++, xPos += mHorizontalScale ) {
+ double bias = -minValue;
+ QValueList<QColor>::Iterator col;
+ col = mBeamColor.begin();
+ double sum = 0.0;
+ for ( double* d = mBeamData.first(); d; d = mBeamData.next(), ++col ) {
+ if ( mUseAutoRange ) {
+ sum += d[ i ];
+ if ( sum < mMinValue )
+ mMinValue = sum;
+ if ( sum > mMaxValue )
+ mMaxValue = sum;
+ }
+ int start = top + h - 2 - (int)( bias * scaleFac );
+ int end = top + h - 2 - (int)( ( bias + d[ i ] ) * scaleFac );
+ bias += d[ i ];
+ /* If the line is longer than 2 pixels we draw only the last
+ * 2 pixels with the bright color. The rest is painted with
+ * a 50% darker color. */
+ if ( end - start > 2 ) {
+ p.fillRect( xPos, start, mHorizontalScale, end - start - 1, (*col).dark( 150 ) );
+ p.fillRect( xPos, end - 1, mHorizontalScale, 2, *col );
+ } else if ( start - end > 2 ) {
+ p.fillRect( xPos, start, mHorizontalScale, end - start + 1, (*col).dark( 150 ) );
+ p.fillRect( xPos, end + 1, mHorizontalScale, 2, *col );
+ } else
+ p.fillRect( xPos, start, mHorizontalScale, end - start, *col );
+
+ }
+ }
+ } else if ( mGraphStyle == GRAPH_POLYGON ) {
+ int *prevVals = new int[ mBeamData.count() ];
+ int hack[ 4 ];
+ hack[ 0 ] = hack[ 1 ] = hack[ 2 ] = hack[ 3 ] = 0;
+ int x1 = w - ( ( mSamples + 1 ) * mHorizontalScale );
+
+ for ( int i = 0; i < mSamples; i++ ) {
+ QValueList<QColor>::Iterator col;
+ col = mBeamColor.begin();
+ double sum = 0.0;
+ int y = top + h - 2;
+ int oldY = top + h;
+ int oldPrevY = oldY;
+ int height = 0;
+ int j = 0;
+ int jMax = mBeamData.count() - 1;
+ x1 += mHorizontalScale;
+ int x2 = x1 + mHorizontalScale;
+
+ for ( double* d = mBeamData.first(); d; d = mBeamData.next(), ++col, j++ ) {
+ if ( mUseAutoRange ) {
+ sum += d[ i ];
+ if ( sum < mMinValue )
+ mMinValue = sum;
+ if ( sum > mMaxValue )
+ mMaxValue = sum;
+ }
+ height = (int)( ( d[ i ] - minValue ) * scaleFac );
+ y -= height;
+
+ /* If the line is longer than 2 pixels we draw only the last
+ * 2 pixels with the bright color. The rest is painted with
+ * a 50% darker color. */
+ QPen lastPen = QPen( p.pen() );
+ p.setPen( (*col).dark( 150 ) );
+ p.setBrush( (*col).dark( 150 ) );
+ QPointArray pa( 4 );
+ int prevY = ( i == 0 ) ? y : prevVals[ j ];
+ pa.putPoints( 0, 1, x1, prevY );
+ pa.putPoints( 1, 1, x2, y );
+ pa.putPoints( 2, 1, x2, oldY );
+ pa.putPoints( 3, 1, x1, oldPrevY );
+ p.drawPolygon( pa );
+ p.setPen( lastPen );
+ if ( jMax == 0 ) {
+ // draw as normal, no deferred drawing req'd.
+ p.setPen( *col );
+ p.drawLine( x1, prevY, x2, y );
+ } else if ( j == jMax ) {
+ // draw previous values and current values
+ p.drawLine( hack[ 0 ], hack[ 1 ], hack[ 2 ], hack[ 3 ] );
+ p.setPen( *col );
+ p.drawLine( x1, prevY, x2, y );
+ } else if ( j == 0 ) {
+ // save values only
+ hack[ 0 ] = x1;
+ hack[ 1 ] = prevY;
+ hack[ 2 ] = x2;
+ hack[ 3 ] = y;
+ p.setPen( *col );
+ } else {
+ p.drawLine( hack[ 0 ], hack[ 1 ], hack[ 2 ], hack[ 3 ] );
+ hack[ 0 ] = x1;
+ hack[ 1 ] = prevY;
+ hack[ 2 ] = x2;
+ hack[ 3 ] = y;
+ p.setPen( *col );
+ }
+
+ prevVals[ j ] = y;
+ oldY = y;
+ oldPrevY = prevY;
+ }
+ }
+
+ delete[] prevVals;
+ }
+
+ /* Draw horizontal lines and values. Lines are always drawn.
+ * Values are only draw when width is greater than 60 */
+ if ( mShowHorizontalLines ) {
+ p.setPen( mHorizontalLinesColor );
+ p.setFont( QFont( p.font().family(), mFontSize ) );
+ QString val;
+
+ /* top = 0 or font.height depending on whether there's a topbar or not
+ * h = graphing area.height - i.e. the actual space we have to draw inside
+ *
+ * Note we are drawing from 0,0 as the top left corner. So we have to add on top to get to the top of where we are drawing
+ * so top+h is the height of the widget
+ */
+ for ( uint y = 1; y <= mHorizontalLinesCount; y++ ) {
+
+ int y_coord = top + (y * h) / (mHorizontalLinesCount+1); //Make sure it's y*h first to avoid rounding bugs
+ p.drawLine( 0, y_coord, w - 2, y_coord );
+
+ if ( mShowLabels && h > ( mFontSize + 1 ) * ( mHorizontalLinesCount + 1 )
+ && w > 60 ) {
+ val = QString::number(maxValue - (y * range) / (mHorizontalLinesCount+1 ) );
+ p.drawText( 6, y_coord - 1, val ); //draw the text one pixel raised above the line
+ }
+ }
+
+ //Draw the bottom most (minimum) number as well
+ if ( mShowLabels && h > ( mFontSize + 1 ) * ( mHorizontalLinesCount + 1 )
+ && w > 60 ) {
+ val = QString::number( minValue );
+ p.drawText( 6, top + h - 2, val );
+ }
+ }
+
+ p.end();
+ bitBlt( this, 0, 0, &pm );
+}
+
+#include "SignalPlotter.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/SignalPlotter.h b/ksysguard/gui/SensorDisplayLib/SignalPlotter.h
new file mode 100644
index 000000000..9a9544b3c
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SignalPlotter.h
@@ -0,0 +1,147 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_SIGNALPLOTTER_H
+#define KSG_SIGNALPLOTTER_H
+
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <qwidget.h>
+
+#define GRAPH_POLYGON 0
+#define GRAPH_ORIGINAL 1
+
+class QColor;
+
+class SignalPlotter : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ SignalPlotter( QWidget *parent = 0, const char *name = 0 );
+ ~SignalPlotter();
+
+ bool addBeam( const QColor &color );
+ void addSample( const QValueList<double> &samples );
+
+ void removeBeam( uint pos );
+
+ void changeRange( int beam, double min, double max );
+
+ QValueList<QColor> &beamColors();
+
+ void setTitle( const QString &title );
+ QString title() const;
+
+ void setUseAutoRange( bool value );
+ bool useAutoRange() const;
+
+ void setMinValue( double min );
+ double minValue() const;
+
+ void setMaxValue( double max );
+ double maxValue() const;
+
+ void setGraphStyle( uint style );
+ uint graphStyle() const;
+
+ void setHorizontalScale( uint scale );
+ int horizontalScale() const;
+
+ void setShowVerticalLines( bool value );
+ bool showVerticalLines() const;
+
+ void setVerticalLinesColor( const QColor &color );
+ QColor verticalLinesColor() const;
+
+ void setVerticalLinesDistance( int distance );
+ int verticalLinesDistance() const;
+
+ void setVerticalLinesScroll( bool value );
+ bool verticalLinesScroll() const;
+
+ void setShowHorizontalLines( bool value );
+ bool showHorizontalLines() const;
+
+ void setHorizontalLinesColor( const QColor &color );
+ QColor horizontalLinesColor() const;
+
+ void setHorizontalLinesCount( int count );
+ int horizontalLinesCount() const;
+
+ void setShowLabels( bool value );
+ bool showLabels() const;
+
+ void setShowTopBar( bool value );
+ bool showTopBar() const;
+
+ void setFontSize( int size );
+ int fontSize() const;
+
+ void setBackgroundColor( const QColor &color );
+ QColor backgroundColor() const;
+ void reorderBeams( const QValueList<int>& newOrder );
+
+ void setThinFrame(bool set) { mShowThinFrame = set; }
+
+ protected:
+ void updateDataBuffers();
+
+ virtual void resizeEvent( QResizeEvent* );
+ virtual void paintEvent( QPaintEvent* );
+
+ private:
+ double mMinValue;
+ double mMaxValue;
+ bool mUseAutoRange;
+ bool mShowThinFrame;
+
+ uint mGraphStyle;
+
+ bool mShowVerticalLines;
+ QColor mVerticalLinesColor;
+ uint mVerticalLinesDistance;
+ bool mVerticalLinesScroll;
+ uint mVerticalLinesOffset;
+ uint mHorizontalScale;
+
+ bool mShowHorizontalLines;
+ QColor mHorizontalLinesColor;
+ uint mHorizontalLinesCount;
+
+ bool mShowLabels;
+ bool mShowTopBar;
+ uint mFontSize;
+
+ QColor mBackgroundColor;
+
+ QPtrList<double> mBeamData;
+ QValueList<QColor> mBeamColor;
+
+ unsigned int mSamples;
+
+ QString mTitle;
+};
+
+#endif