You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/ksysguard/gui/KSysGuardApplet.cc

496 lines
14 KiB

/*
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!
*/
#include <qcursor.h>
#include <qdom.h>
#include <qdragobject.h>
#include <qfile.h>
#include <qpushbutton.h>
#include <qspinbox.h>
#include <qtooltip.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <ksavefile.h>
#include <kstandarddirs.h>
#include <kpopupmenu.h>
#include <ksgrd/SensorClient.h>
#include <ksgrd/SensorManager.h>
#include <ksgrd/StyleEngine.h>
#include "DancingBars.h"
#include "FancyPlotter.h"
#include "KSGAppletSettings.h"
#include "MultiMeter.h"
#include "KSysGuardApplet.h"
extern "C"
{
KDE_EXPORT KPanelApplet* init( QWidget *parent, const QString& configFile )
{
KGlobal::locale()->insertCatalogue( "ksysguard" );
return new KSysGuardApplet( configFile, KPanelApplet::Normal,
KPanelApplet::Preferences, parent,
"ksysguardapplet" );
}
}
KSysGuardApplet::KSysGuardApplet( const QString& configFile, Type type,
int actions, QWidget *parent,
const char *name )
: KPanelApplet( configFile, type, actions, parent, name)
{
mSettingsDlg = 0;
KSGRD::SensorMgr = new KSGRD::SensorManager();
KSGRD::Style = new KSGRD::StyleEngine();
mDockCount = 1;
mDockList = new QWidget*[ mDockCount ];
mSizeRatio = 1.0;
addEmptyDisplay( mDockList, 0 );
updateInterval( 2 );
load();
setAcceptDrops( true );
}
KSysGuardApplet::~KSysGuardApplet()
{
save();
delete [] mDockList;
mDockList = 0;
delete mSettingsDlg;
mSettingsDlg = 0;
delete KSGRD::Style;
delete KSGRD::SensorMgr;
KSGRD::SensorMgr = 0;
}
int KSysGuardApplet::widthForHeight( int height ) const
{
return ( (int) ( height * mSizeRatio + 0.5 ) * mDockCount );
}
int KSysGuardApplet::heightForWidth( int width ) const
{
return ( (int) ( width * mSizeRatio + 0.5 ) * mDockCount );
}
void KSysGuardApplet::resizeEvent( QResizeEvent* )
{
layout();
}
void KSysGuardApplet::preferences()
{
if(mSettingsDlg) {
return;
}
mSettingsDlg = new KSGAppletSettings( this );
connect( mSettingsDlg, SIGNAL( applyClicked() ), SLOT( applySettings() ) );
connect( mSettingsDlg, SIGNAL( okClicked() ), SLOT( applySettings() ) );
connect( mSettingsDlg, SIGNAL( finished() ), SLOT( preferencesFinished() ) );
mSettingsDlg->setNumDisplay( mDockCount );
mSettingsDlg->setSizeRatio( (int) ( mSizeRatio * 100.0 + 0.5 ) );
mSettingsDlg->setUpdateInterval( updateInterval() );
mSettingsDlg->show();
}
void KSysGuardApplet::preferencesFinished()
{
mSettingsDlg->delayedDestruct();
mSettingsDlg = 0;
}
void KSysGuardApplet::applySettings()
{
updateInterval( mSettingsDlg->updateInterval() );
mSizeRatio = mSettingsDlg->sizeRatio() / 100.0;
resizeDocks( mSettingsDlg->numDisplay() );
for ( uint i = 0; i < mDockCount; ++i )
if ( !mDockList[ i ]->isA( "QFrame" ) )
((KSGRD::SensorDisplay*)mDockList[ i ])->setUpdateInterval( updateInterval() );
save();
}
void KSysGuardApplet::sensorDisplayModified( bool modified )
{
if ( modified )
save();
}
void KSysGuardApplet::layout()
{
if ( orientation() == Horizontal ) {
int h = height();
int w = (int) ( h * mSizeRatio + 0.5 );
for ( uint i = 0; i < mDockCount; ++i )
if ( mDockList[ i ] )
mDockList[ i ]->setGeometry( i * w, 0, w, h );
} else {
int w = width();
int h = (int) ( w * mSizeRatio + 0.5 );
for ( uint i = 0; i < mDockCount; ++i )
if ( mDockList[ i ] )
mDockList[ i ]->setGeometry( 0, i * h, w, h );
}
}
int KSysGuardApplet::findDock( const QPoint& point )
{
if ( orientation() == Horizontal )
return ( point.x() / (int) ( height() * mSizeRatio + 0.5 ) );
else
return ( point.y() / (int) ( width() * mSizeRatio + 0.5 ) );
}
void KSysGuardApplet::dragEnterEvent( QDragEnterEvent *e )
{
e->accept( QTextDrag::canDecode( e ) );
}
void KSysGuardApplet::dropEvent( QDropEvent *e )
{
QString dragObject;
if ( QTextDrag::decode( e, dragObject ) ) {
// The host name, sensor name and type are seperated by a ' '.
QStringList parts = QStringList::split( ' ', dragObject );
QString hostName = parts[ 0 ];
QString sensorName = parts[ 1 ];
QString sensorType = parts[ 2 ];
QString sensorDescr = parts[ 3 ];
if ( hostName.isEmpty() || sensorName.isEmpty() || sensorType.isEmpty() )
return;
int dock = findDock( e->pos() );
if ( mDockList[ dock ]->isA( "QFrame" ) ) {
if ( sensorType == "integer" || sensorType == "float" ) {
KPopupMenu popup;
QWidget *wdg = 0;
popup.insertTitle( i18n( "Select Display Type" ) );
popup.insertItem( i18n( "&Signal Plotter" ), 1 );
popup.insertItem( i18n( "&Multimeter" ), 2 );
popup.insertItem( i18n( "&Dancing Bars" ), 3 );
switch ( popup.exec( QCursor::pos() ) ) {
case 1:
wdg = new FancyPlotter( this, "FancyPlotter", sensorDescr,
100.0, 100.0, true );
break;
case 2:
wdg = new MultiMeter( this, "MultiMeter", sensorDescr,
100.0, 100.0, true );
break;
case 3:
wdg = new DancingBars( this, "DancingBars", sensorDescr,
100, 100, true );
break;
}
if ( wdg ) {
delete mDockList[ dock ];
mDockList[ dock ] = wdg;
layout();
connect( wdg, SIGNAL( modified( bool ) ),
SLOT( sensorDisplayModified( bool ) ) );
mDockList[ dock ]->show();
}
} else {
KMessageBox::sorry( this,
i18n( "The KSysGuard applet does not support displaying of "
"this type of sensor. Please choose another sensor." ) );
layout();
}
}
if ( !mDockList[ dock ]->isA( "QFrame" ) )
((KSGRD::SensorDisplay*)mDockList[ dock ])->
addSensor( hostName, sensorName, sensorType, sensorDescr );
}
save();
}
void KSysGuardApplet::customEvent( QCustomEvent *e )
{
if ( e->type() == QEvent::User ) {
// SensorDisplays send out this event if they want to be removed.
removeDisplay( (KSGRD::SensorDisplay*)e->data() );
save();
}
}
void KSysGuardApplet::removeDisplay( KSGRD::SensorDisplay *display )
{
for ( uint i = 0; i < mDockCount; ++i )
if ( display == mDockList[i] ) {
delete mDockList[ i ];
addEmptyDisplay( mDockList, i );
return;
}
}
void KSysGuardApplet::resizeDocks( uint newDockCount )
{
/* This function alters the number of available docks. The number of
* docks can be increased or decreased. We try to preserve existing
* docks if possible. */
if ( newDockCount == mDockCount ) {
emit updateLayout();
return;
}
// Create and initialize new dock array.
QWidget** tmp = new QWidget*[ newDockCount ];
uint i;
for ( i = 0; ( i < newDockCount ) && ( i < mDockCount ); ++i )
tmp[ i ] = mDockList[ i ];
for ( i = newDockCount; i < mDockCount; ++i )
if ( mDockList[ i ] )
delete mDockList[ i ];
for ( i = mDockCount; i < newDockCount; ++i )
addEmptyDisplay( tmp, i );
delete [] mDockList;
mDockList = tmp;
mDockCount = newDockCount;
emit updateLayout();
}
bool KSysGuardApplet::load()
{
KStandardDirs* kstd = KGlobal::dirs();
kstd->addResourceType( "data", "share/apps/ksysguard" );
QString fileName = kstd->findResource( "data", "KSysGuardApplet.xml" );
QFile file( fileName );
if ( !file.open( IO_ReadOnly ) ) {
KMessageBox::sorry( this, i18n( "Cannot open the file %1." ).arg( fileName ) );
return false;
}
// Parse the XML file.
QDomDocument doc;
// Read in file and check for a valid XML header.
if ( !doc.setContent( &file ) ) {
KMessageBox::sorry( this, i18n( "The file %1 does not contain valid XML." )
.arg( fileName ) );
return false;
}
// Check for proper document type.
if ( doc.doctype().name() != "KSysGuardApplet" ) {
KMessageBox::sorry( this, i18n( "The file %1 does not contain a valid applet "
"definition, which must have a document type 'KSysGuardApplet'." )
.arg( fileName ) );
return false;
}
QDomElement element = doc.documentElement();
bool ok;
uint count = element.attribute( "dockCnt" ).toUInt( &ok );
if ( !ok )
count = 1;
mSizeRatio = element.attribute( "sizeRatio" ).toDouble( &ok );
if ( !ok )
mSizeRatio = 1.0;
updateInterval( element.attribute( "interval" ).toUInt( &ok ) );
if ( !ok )
updateInterval( 2 );
resizeDocks( count );
/* Load lists of hosts that are needed for the work sheet and try
* to establish a connection. */
QDomNodeList dnList = element.elementsByTagName( "host" );
uint i;
for ( i = 0; i < dnList.count(); ++i ) {
QDomElement element = dnList.item( i ).toElement();
int port = element.attribute( "port" ).toInt( &ok );
if ( !ok )
port = -1;
KSGRD::SensorMgr->engage( element.attribute( "name" ),
element.attribute( "shell" ),
element.attribute( "command" ), port );
}
//if no hosts are specified, at least connect to localhost
if(dnList.count() == 0)
KSGRD::SensorMgr->engage( "localhost", "", "ksysguardd", -1);
// Load the displays and place them into the work sheet.
dnList = element.elementsByTagName( "display" );
for ( i = 0; i < dnList.count(); ++i ) {
QDomElement element = dnList.item( i ).toElement();
uint dock = element.attribute( "dock" ).toUInt();
if ( i >= mDockCount ) {
kdDebug (1215) << "Dock number " << i << " out of range "
<< mDockCount << endl;
return false;
}
QString classType = element.attribute( "class" );
KSGRD::SensorDisplay* newDisplay;
if ( classType == "FancyPlotter" )
newDisplay = new FancyPlotter( this, "FancyPlotter", "Dummy", 100.0, 100.0, true /*no frame*/, true /*run ksysguard menu*/);
else if ( classType == "MultiMeter" )
newDisplay = new MultiMeter( this, "MultiMeter", "Dummy", 100.0, 100.0, true /*no frame*/, true /*run ksysguard menu*/ );
else if ( classType == "DancingBars" )
newDisplay = new DancingBars( this, "DancingBars", "Dummy", 100, 100, true /*no frame*/, true /*run ksysguard menu*/);
else {
KMessageBox::sorry( this, i18n( "The KSysGuard applet does not support displaying of "
"this type of sensor. Please choose another sensor." ) );
return false;
}
newDisplay->setUpdateInterval( updateInterval() );
// load display specific settings
if ( !newDisplay->restoreSettings( element ) )
return false;
delete mDockList[ dock ];
mDockList[ dock ] = newDisplay;
connect( newDisplay, SIGNAL( modified( bool ) ),
SLOT( sensorDisplayModified( bool ) ) );
}
return true;
}
bool KSysGuardApplet::save()
{
// Parse the XML file.
QDomDocument doc( "KSysGuardApplet" );
doc.appendChild( doc.createProcessingInstruction(
"xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
// save work sheet information
QDomElement ws = doc.createElement( "WorkSheet" );
doc.appendChild( ws );
ws.setAttribute( "dockCnt", mDockCount );
ws.setAttribute( "sizeRatio", mSizeRatio );
ws.setAttribute( "interval", updateInterval() );
QStringList hosts;
uint i;
for ( i = 0; i < mDockCount; ++i )
if ( !mDockList[ i ]->isA( "QFrame" ) )
((KSGRD::SensorDisplay*)mDockList[ i ])->hosts( hosts );
// save host information (name, shell, etc.)
QStringList::Iterator it;
for ( it = hosts.begin(); it != hosts.end(); ++it ) {
QString shell, command;
int port;
if ( KSGRD::SensorMgr->hostInfo( *it, shell, command, port ) ) {
QDomElement host = doc.createElement( "host" );
ws.appendChild( host );
host.setAttribute( "name", *it );
host.setAttribute( "shell", shell );
host.setAttribute( "command", command );
host.setAttribute( "port", port );
}
}
for ( i = 0; i < mDockCount; ++i )
if ( !mDockList[ i ]->isA( "QFrame" ) ) {
QDomElement element = doc.createElement( "display" );
ws.appendChild( element );
element.setAttribute( "dock", i );
element.setAttribute( "class", mDockList[ i ]->className() );
((KSGRD::SensorDisplay*)mDockList[ i ])->saveSettings( doc, element );
}
KStandardDirs* kstd = KGlobal::dirs();
kstd->addResourceType( "data", "share/apps/ksysguard" );
QString fileName = kstd->saveLocation( "data", "ksysguard" );
fileName += "/KSysGuardApplet.xml";
KSaveFile file( fileName, 0644 );
if ( file.status() == 0 )
{
file.textStream()->setEncoding( QTextStream::UnicodeUTF8 );
*(file.textStream()) << doc;
file.close();
}
else
{
KMessageBox::sorry( this, i18n( "Cannot save file %1" ).arg( fileName ) );
return false;
}
return true;
}
void KSysGuardApplet::addEmptyDisplay( QWidget **dock, uint pos )
{
dock[ pos ] = new QFrame( this );
((QFrame*)dock[ pos ])->setFrameStyle( QFrame::WinPanel | QFrame::Sunken );
QToolTip::add( dock[ pos ],
i18n( "Drag sensors from the KDE System Guard into this cell." ) );
layout();
if ( isVisible() )
dock[ pos ]->show();
}
#include "KSysGuardApplet.moc"