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/SensorBrowser.cpp

413 lines
11 KiB

/*
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 <tqdragobject.h>
#include <tqtooltip.h>
#include <tqwhatsthis.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <ksgrd/SensorManager.h>
#include "SensorBrowser.h"
class HostItem : public TQListViewItem
{
public:
HostItem( SensorBrowser *parent, const TQString &text, int id,
KSGRD::SensorAgent *host)
: TQListViewItem( parent, text ), mInited( false ), mId( id ),
mHost( host ), mParent( parent )
{
setExpandable( true );
}
void setOpen( bool open )
{
if ( open && !mInited ) {
mInited = true;
// request sensor list from host
mHost->sendRequest( "monitors", mParent, mId );
}
TQListViewItem::setOpen( open );
}
private:
bool mInited;
int mId;
KSGRD::SensorAgent* mHost;
SensorBrowser* mParent;
};
SensorBrowser::SensorBrowser( TQWidget* parent, KSGRD::SensorManager* sm,
const char* name)
: TDEListView( parent, name ), mSensorManager( sm )
{
mHostInfoList.setAutoDelete(true);
connect( mSensorManager, TQT_SIGNAL( update() ), TQT_SLOT( update() ) );
connect( this, TQT_SIGNAL( clicked( TQListViewItem* ) ),
TQT_SLOT( newItemSelected( TQListViewItem* ) ) );
connect( this, TQT_SIGNAL( returnPressed( TQListViewItem* ) ),
TQT_SLOT( newItemSelected( TQListViewItem* ) ) );
addColumn( i18n( "Sensor Browser" ) );
addColumn( i18n( "Sensor Type" ) );
setFullWidth( true );
TQToolTip::add( this, i18n( "Drag sensors to empty cells of a worksheet "
"or the panel applet." ) );
setRootIsDecorated( true );
// The sensor browser can be completely hidden.
setMinimumWidth( 1 );
TQWhatsThis::add( this, i18n( "The sensor browser lists the connected hosts and the sensors "
"that they provide. Click and drag sensors into drop zones "
"of a worksheet or the panel applet. A display will appear "
"that visualizes the "
"values provided by the sensor. Some sensor displays can "
"display values of multiple sensors. Simply drag other "
"sensors on to the display to add more sensors." ) );
}
SensorBrowser::~SensorBrowser()
{
}
void SensorBrowser::disconnect()
{
TQPtrListIterator<HostInfo> it( mHostInfoList );
for ( ; it.current(); ++it )
if ( (*it)->listViewItem()->isSelected() ) {
kdDebug(1215) << "Disconnecting " << (*it)->hostName() << endl;
KSGRD::SensorMgr->requestDisengage( (*it)->sensorAgent() );
}
}
void SensorBrowser::hostReconfigured( const TQString& )
{
// TODO: not yet implemented.
}
void SensorBrowser::update()
{
static int id = 0;
KSGRD::SensorManagerIterator it( mSensorManager );
mHostInfoList.clear();
clear();
KSGRD::SensorAgent* host;
for ( int i = 0 ; ( host = it.current() ); ++it, ++i ) {
TQString hostName = mSensorManager->hostName( host );
HostItem* lvi = new HostItem( this, hostName, id, host );
TQPixmap pix = TDEGlobal::iconLoader()->loadIcon( "computer", TDEIcon::Desktop, TDEIcon::SizeSmall );
lvi->setPixmap( 0, pix );
HostInfo* hostInfo = new HostInfo( id, host, hostName, lvi );
mHostInfoList.append( hostInfo );
++id;
}
setMouseTracking( false );
}
void SensorBrowser::newItemSelected( TQListViewItem *item )
{
static bool showAnnoyingPopup = true;
if ( item && item->pixmap( 0 ) && showAnnoyingPopup)
{
showAnnoyingPopup = false;
KMessageBox::information( this, i18n( "Drag sensors to empty fields in a worksheet." ),
TQString::null, "ShowSBUseInfo" );
}
}
void SensorBrowser::answerReceived( int id, const TQString &answer )
{
/* An answer has the following format:
cpu/idle integer
cpu/sys integer
cpu/nice integer
cpu/user integer
ps table
*/
TQPtrListIterator<HostInfo> it( mHostInfoList );
/* Check if id is still valid. It can get obsolete by rapid calls
* of update() or when the sensor died. */
for ( ; it.current(); ++it )
if ( (*it)->id() == id )
break;
if ( !it.current() )
return;
KSGRD::SensorTokenizer lines( answer, '\n' );
for ( uint i = 0; i < lines.count(); ++i ) {
if ( lines[ i ].isEmpty() )
break;
KSGRD::SensorTokenizer words( lines[ i ], '\t' );
TQString sensorName = words[ 0 ];
TQString sensorType = words[ 1 ];
/* Calling update() a rapid sequence will create pending
* requests that do not get erased by calling
* clear(). Subsequent updates will receive the old pending
* answers so we need to make sure that we register each
* sensor only once. */
if ( (*it)->isRegistered( sensorName ) )
return;
/* The sensor browser can display sensors in a hierachical order.
* Sensors can be grouped into nodes by seperating the hierachical
* nodes through slashes in the sensor name. E. g. cpu/user is
* the sensor user in the cpu node. There is no limit for the
* depth of nodes. */
KSGRD::SensorTokenizer absolutePath( sensorName, '/' );
TQListViewItem* parent = (*it)->listViewItem();
for ( uint j = 0; j < absolutePath.count(); ++j ) {
// Localize the sensor name part by part.
TQString name = KSGRD::SensorMgr->translateSensorPath( absolutePath[ j ] );
bool found = false;
TQListViewItem* sibling = parent->firstChild();
while ( sibling && !found ) {
if (sibling->text( 0 ) == name ) {
// The node or sensor is already known.
found = true;
} else
sibling = sibling->nextSibling();
}
if ( !found ) {
TQListViewItem* lvi = new TQListViewItem( parent, name );
if ( j == absolutePath.count() - 1 ) {
TQPixmap pix = TDEGlobal::iconLoader()->loadIcon( "ksysguardd", TDEIcon::Desktop,
TDEIcon::SizeSmall );
lvi->setPixmap( 0, pix );
lvi->setText( 1, KSGRD::SensorMgr->translateSensorType( sensorType ) );
// add sensor info to internal data structure
(*it)->addSensor( lvi, sensorName, name, sensorType );
} else
parent = lvi;
// The child indicator might need to be updated.
repaintItem( parent );
} else
parent = sibling;
}
}
repaintItem( (*it)->listViewItem() );
}
void SensorBrowser::viewportMouseMoveEvent( TQMouseEvent *e )
{
/* setMouseTracking(false) seems to be broken. With current Qt
* mouse tracking cannot be turned off. So we have to check each event
* whether the LMB is really pressed. */
if ( !( e->state() & Qt::LeftButton ) )
return;
TQListViewItem* item = itemAt( e->pos() );
if ( !item ) // no item under cursor
return;
// Make sure that a sensor and not a node or hostname has been picked.
TQPtrListIterator<HostInfo> it( mHostInfoList );
for ( ; it.current() && !(*it)->isRegistered( item ); ++it );
if ( !it.current() )
return;
// Create text drag object as
// "<hostname> <sensorname> <sensortype> <sensordescription>".
// Only the description may contain blanks.
mDragText = (*it)->hostName() + " " +
(*it)->sensorName( item ) + " " +
(*it)->sensorType( item ) + " " +
(*it)->sensorDescription( item );
TQDragObject* dragObject = new TQTextDrag( mDragText, this );
dragObject->dragCopy();
}
TQStringList SensorBrowser::listHosts()
{
TQStringList hostList;
TQPtrListIterator<HostInfo> it( mHostInfoList );
for ( ; it.current(); ++it )
hostList.append( (*it)->hostName() );
return hostList;
}
TQStringList SensorBrowser::listSensors( const TQString &hostName )
{
TQPtrListIterator<HostInfo> it( mHostInfoList );
for ( ; it.current(); ++it ) {
if ( (*it)->hostName() == hostName ) {
return (*it)->allSensorNames();
}
}
return TQStringList();
}
/**
Helper classes
*/
SensorInfo::SensorInfo( TQListViewItem *lvi, const TQString &name,
const TQString &desc, const TQString &type )
: mLvi( lvi ), mName( name ), mDesc( desc ), mType( type )
{
}
TQListViewItem* SensorInfo::listViewItem() const
{
return mLvi;
}
const TQString& SensorInfo::name() const
{
return mName;
}
const TQString& SensorInfo::type() const
{
return mType;
}
const TQString& SensorInfo::description() const
{
return mDesc;
}
HostInfo::HostInfo( int id, const KSGRD::SensorAgent *agent,
const TQString &name, TQListViewItem *lvi )
: mId( id ), mSensorAgent( agent ), mHostName( name ), mLvi( lvi )
{
mSensorList.setAutoDelete( true );
}
int HostInfo::id() const
{
return ( mId );
}
const KSGRD::SensorAgent* HostInfo::sensorAgent() const
{
return mSensorAgent;
}
const TQString& HostInfo::hostName() const
{
return mHostName;
}
TQListViewItem* HostInfo::listViewItem() const
{
return mLvi;
}
const TQString& HostInfo::sensorName( const TQListViewItem *lvi ) const
{
TQPtrListIterator<SensorInfo> it( mSensorList );
for ( ; it.current() && (*it)->listViewItem() != lvi; ++it );
Q_ASSERT( it.current() );
return ( (*it)->name() );
}
TQStringList HostInfo::allSensorNames() const
{
TQStringList list;
TQPtrListIterator<SensorInfo> it( mSensorList );
for ( ; it.current(); ++it )
list.append( it.current()->name() );
return list;
}
const TQString& HostInfo::sensorType( const TQListViewItem *lvi ) const
{
TQPtrListIterator<SensorInfo> it( mSensorList );
for ( ; it.current() && (*it)->listViewItem() != lvi; ++it );
Q_ASSERT( it.current() );
return ( (*it)->type() );
}
const TQString& HostInfo::sensorDescription( const TQListViewItem *lvi ) const
{
TQPtrListIterator<SensorInfo> it( mSensorList );
for ( ; it.current() && (*it)->listViewItem() != lvi; ++it );
Q_ASSERT( it.current() );
return ( (*it)->description() );
}
void HostInfo::addSensor( TQListViewItem *lvi, const TQString& name,
const TQString& desc, const TQString& type )
{
SensorInfo* info = new SensorInfo( lvi, name, desc, type );
mSensorList.append( info );
}
bool HostInfo::isRegistered( const TQString& name ) const
{
TQPtrListIterator<SensorInfo> it( mSensorList );
for ( ; it.current(); ++it )
if ( (*it)->name() == name )
return true;
return false;
}
bool HostInfo::isRegistered( TQListViewItem *lvi ) const
{
TQPtrListIterator<SensorInfo> it( mSensorList );
for ( ; it.current(); ++it )
if ( (*it)->listViewItem() == lvi )
return true;
return false;
}
#include "SensorBrowser.moc"