2
KSysGuard, the KDE System Guard
4
Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
6
This program is free software; you can redistribute it and/or
7
modify it under the terms of version 2 of the GNU General Public
8
License as published by the Free Software Foundation.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
#include <QtGui/QDrag>
22
#include <QtGui/QLabel>
23
#include <QtGui/QMouseEvent>
24
#include <QtGui/QPainter>
25
#include <QtGui/QPixmap>
31
#include <kmessagebox.h>
32
#include <ksgrd/SensorManager.h>
34
#include "SensorBrowser.h"
35
//#define SENSOR_MODEL_DO_TEST
36
//uncomment the above to test the model
37
#ifdef SENSOR_MODEL_DO_TEST
38
#include "modeltest.h"
41
SensorBrowserModel::SensorBrowserModel()
43
#ifdef SENSOR_MODEL_DO_TEST
48
SensorBrowserModel::~SensorBrowserModel()
51
qDeleteAll( mHostInfoMap );
53
qDeleteAll( mSensorInfoMap );
54
mSensorInfoMap.clear();
57
int SensorBrowserModel::columnCount( const QModelIndex &) const { //virtual
61
QVariant SensorBrowserModel::data( const QModelIndex & index, int role) const { //virtual
62
if(!index.isValid()) return QVariant();
64
case Qt::DisplayRole: {
65
if(index.column()==0) {
66
uint id = index.internalId();
67
if(mSensorInfoMap.contains(id)) {
68
Q_ASSERT(mSensorInfoMap.value(id));
69
SensorInfo *sensorInfo = mSensorInfoMap.value(id);
70
return sensorInfo->description() + " (" +sensorInfo->type() +')' ;
72
if(mTreeNodeNames.contains(id)) return mTreeNodeNames.value(id);
73
if(mHostInfoMap.contains(id)) {
74
Q_ASSERT(mHostInfoMap.value(id));
75
return mHostInfoMap.value(id)->hostName();
80
case Qt::DecorationRole: {
81
if(index.column() == 0 && mHostInfoMap.contains(index.internalId())) {
82
return KIcon("system");
84
return QIcon(); //work around for drawing bug
91
QVariant SensorBrowserModel::headerData ( int section, Qt::Orientation , int role) const { //virtual
92
if(role != Qt::DisplayRole) return QVariant();
93
if(section==0) return i18n("Sensor Browser");
97
QModelIndex SensorBrowserModel::index ( int row, int column, const QModelIndex & parent) const { //virtual
98
if(column != 0) return QModelIndex();
100
if(!parent.isValid()) {
101
ids = mHostInfoMap.keys();
104
ids = mTreeMap.value(parent.internalId());
106
if( row >= ids.size() || row< 0) {
107
return QModelIndex();
109
QModelIndex index = createIndex(row, column, ids[row]);
110
Q_ASSERT(index.isValid());
114
QStringList SensorBrowserModel::listHosts() const
116
QStringList hostList;
118
QMapIterator<int, HostInfo*> it( mHostInfoMap );
119
while ( it.hasNext() ) {
121
Q_ASSERT(it.value());
122
hostList.append( it.value()->hostName() );
128
QStringList SensorBrowserModel::listSensors( const QString &hostName ) const
130
QMapIterator<int, HostInfo*> it( mHostInfoMap );
131
while ( it.hasNext() ) {
133
Q_ASSERT(it.value());
134
if ( it.value()->hostName() == hostName ) {
135
Q_ASSERT(mSensorInfoMap.contains(it.key()));
136
return listSensors( it.key() );
139
return QStringList();
142
QStringList SensorBrowserModel::listSensors( int parentId) const
144
SensorInfo *sensor=mSensorInfoMap.value(parentId);
145
if(sensor) return QStringList(sensor->name());
147
QStringList childSensors;
148
QList<int> children = mTreeMap.value(parentId);
149
for(int i=0; i < children.size(); i++) {
150
childSensors+= listSensors(children[i]);
154
SensorInfo *SensorBrowserModel::getSensorInfo(QModelIndex index) const
156
if(!index.isValid()) return NULL;
157
return mSensorInfoMap.value(index.internalId());
160
int SensorBrowserModel::makeSensor(HostInfo *hostInfo, int parentId, const QString &sensorName, const QString &name, const QString &sensorType) {
161
//sensorName is the full version. e.g. mem/free
162
//name is the short version. e.g. free
163
//sensortype is e.g. Integer
164
QList<int> children = mTreeMap.value(parentId);
165
for(int i=0; i<children.size(); i++)
166
if(mSensorInfoMap.contains(children[i])) {
167
Q_ASSERT(mSensorInfoMap.value(children[i]));
168
if(mSensorInfoMap.value(children[i])->name() == sensorName)
172
QModelIndex parentModelIndex;
173
if(hostInfo->id() == parentId) {
174
parentModelIndex = createIndex(mHostInfoMap.keys().indexOf(parentId), 0 , parentId);
176
int parentsParentId = mParentsTreeMap.value(parentId);
177
parentModelIndex = createIndex(mTreeMap.value(parentsParentId).indexOf(parentId), 0, parentId);
179
Q_ASSERT(parentModelIndex.isValid());
180
QList<int> &parentTreemap = mTreeMap[parentId];
181
SensorInfo *sensorInfo = new SensorInfo(hostInfo, sensorName, name, sensorType);
182
beginInsertRows( parentModelIndex , parentTreemap.size(), parentTreemap.size() );
183
parentTreemap << mIdCount;
184
mParentsTreeMap.insert( mIdCount, parentId );
185
mSensorInfoMap.insert(mIdCount, sensorInfo);
186
mHostSensorsMap[hostInfo->id()].insert(sensorName, true);
189
return mIdCount-1; //NOTE mIdCount is next available number. Se we use it, then increment it, but return the number of the one that we use
191
int SensorBrowserModel::makeTreeBranch(int parentId, const QString &name) {
192
QList<int> children = mTreeMap.value(parentId);
193
for(int i=0; i<children.size(); i++)
194
if(mTreeNodeNames.value(children[i]) == name) return children[i];
196
QModelIndex parentModelIndex;
197
if(mHostInfoMap.contains(parentId)) {
198
parentModelIndex = createIndex(mHostInfoMap.keys().indexOf(parentId), 0 , parentId);
200
int parentsParentId = mParentsTreeMap.value(parentId);
201
parentModelIndex = createIndex(mTreeMap.value(parentsParentId).indexOf(parentId), 0, parentId);
203
Q_ASSERT(parentModelIndex.isValid());
204
QList<int> &parentTreemap = mTreeMap[parentId];
205
beginInsertRows( parentModelIndex , parentTreemap.size(), parentTreemap.size() );
206
parentTreemap << mIdCount;
207
mParentsTreeMap.insert( mIdCount, parentId );
208
mTreeMap[mIdCount]; //create with empty qlist
209
mTreeNodeNames.insert(mIdCount, name);
216
void SensorBrowserModel::answerReceived( int hostId, const QList<QByteArray>&answer )
218
/* An answer has the following example format:
220
cpu/system/idle integer
221
cpu/system/sys integer
222
cpu/system/nice integer
223
cpu/system/user integer
227
HostInfo *hostInfo = getHostInfo(hostId);
229
kDebug(1215) << "SensorBrowserModel::answerReceived with invalid hostId " << hostId ;
232
for ( int i = 0; i < answer.count(); ++i ) {
233
if ( answer[ i ].isEmpty() )
236
QList<QByteArray> words = answer[ i ].split('\t');
237
QString sensorName = QString::fromUtf8(words[ 0 ]);
238
QString sensorType = QString::fromUtf8(words[ 1 ]);
240
if ( hasSensor(hostId, sensorName))
242
if(sensorName.isEmpty()) break;
244
if(sensorType == "string") continue;
246
/* The sensor browser can display sensors in a hierachical order.
247
* Sensors can be grouped into nodes by seperating the hierachical
248
* nodes through slashes in the sensor name. E. g. cpu/system/user is
249
* the sensor user in the cpu node. There is no limit for the
251
int currentNodeId = hostId; //Start from the host branch and work our way down the tree
252
QStringList absolutePath = sensorName.split( '/' );
253
for ( int j = 0; j < absolutePath.count()-1; ++j ) {
254
// Localize the sensor name part by part.
255
QString name = KSGRD::SensorMgr->translateSensorPath( absolutePath[ j ] );
256
currentNodeId = makeTreeBranch(currentNodeId, name);
258
QString name = KSGRD::SensorMgr->translateSensorPath( absolutePath[ absolutePath.size()-1] );
259
makeSensor(hostInfo, currentNodeId, sensorName, name, sensorType);
261
emit sensorsAddedToHost( createIndex( mHostInfoMap.keys().indexOf(hostId), 0, hostId ) ) ;
264
QModelIndex SensorBrowserModel::parent ( const QModelIndex & index ) const { //virtual
265
if(!index.isValid() || index.column() != 0)
266
return QModelIndex();
267
if(mHostInfoMap.contains(index.internalId())) return QModelIndex();
268
if(!mParentsTreeMap.contains(index.internalId())) {
269
kDebug(1215) << "Something is wrong with the model. Doesn't contain " << index.internalId();
270
return QModelIndex();
272
int parentId = mParentsTreeMap.value(index.internalId());
274
QModelIndex parentModelIndex;
275
if(mHostInfoMap.contains(parentId)) {
276
parentModelIndex = createIndex(mHostInfoMap.keys().indexOf(parentId), 0 , parentId);
278
int parentsParentId = mParentsTreeMap.value(parentId);
279
parentModelIndex = createIndex(mTreeMap.value(parentsParentId).indexOf(parentId), 0, parentId);
281
Q_ASSERT(parentModelIndex.isValid());
282
return parentModelIndex;
284
int SensorBrowserModel::rowCount ( const QModelIndex & parent ) const { //virtual
285
if(!parent.isValid()) return mHostInfoMap.size();
286
if(parent.column() != 0) return 0;
287
return mTreeMap.value(parent.internalId()).size();
289
Qt::ItemFlags SensorBrowserModel::flags ( const QModelIndex & index ) const { //virtual
290
if(!index.isValid()) return 0;
291
if(mSensorInfoMap.contains(index.internalId())) return Qt::ItemIsDragEnabled | Qt::ItemIsSelectable | Qt::ItemIsEnabled;
292
else return Qt::ItemIsEnabled;
295
SensorBrowserWidget::SensorBrowserWidget( QWidget* parent, KSGRD::SensorManager* sm )
296
: QTreeView( parent ), mSensorManager( sm )
298
connect( mSensorManager, SIGNAL( update() ), SLOT( update() ) );
299
setModel(&mSensorBrowserModel);
301
this->setToolTip( i18n( "Drag sensors to empty cells of a worksheet "
302
"or the panel applet." ) );
303
// setRootIsDecorated( false );
304
setDragDropMode(QAbstractItemView::DragOnly);
306
//setMinimumWidth( 1 );
308
this->setWhatsThis( i18n( "The sensor browser lists the connected hosts and the sensors "
309
"that they provide. Click and drag sensors into drop zones "
310
"of a worksheet or the panel applet. A display will appear "
311
"that visualizes the "
312
"values provided by the sensor. Some sensor displays can "
313
"display values of multiple sensors. Simply drag other "
314
"sensors on to the display to add more sensors." ) );
315
connect( &mSensorBrowserModel, SIGNAL(sensorsAddedToHost(const QModelIndex&)), this, SLOT(expand(const QModelIndex&)));
319
SensorBrowserWidget::~SensorBrowserWidget()
323
void SensorBrowserWidget::disconnect()
325
QModelIndexList indexlist = selectionModel()->selectedRows();
326
for(int i=0; i < indexlist.size(); i++)
328
mSensorBrowserModel.disconnectHost(indexlist.value(i).internalId());
332
void SensorBrowserWidget::hostReconfigured( const QString& )
334
// TODO: not yet implemented.
337
void SensorBrowserModel::clear() {
338
qDeleteAll(mHostInfoMap);
339
mHostInfoMap.clear();
343
void SensorBrowserModel::disconnectHost(uint id)
345
disconnectHost(mHostInfoMap.value(id));
347
void SensorBrowserModel::disconnectHost(const HostInfo *hostInfo)
349
KSGRD::SensorMgr->requestDisengage( hostInfo->sensorAgent() );
351
void SensorBrowserModel::disconnectHost(const QString &hostname)
353
QMapIterator<int, HostInfo*> it( mHostInfoMap );
354
while ( it.hasNext() ) {
356
if(it.value()->hostName() == hostname) {
357
disconnectHost(it.value());
363
void SensorBrowserModel::addHost(KSGRD::SensorAgent *sensorAgent, const QString &hostName)
365
beginInsertRows( QModelIndex() , mHostInfoMap.size(), mHostInfoMap.size() );
366
HostInfo* hostInfo = new HostInfo( mIdCount, sensorAgent, hostName);
367
mHostInfoMap.insert(mIdCount, hostInfo);
368
mTreeMap.insert(mIdCount, QList<int>());
369
mHostSensorsMap.insert(mIdCount, QHash<QString, bool>());
372
hostInfo->sensorAgent()->sendRequest( "monitors", this, mIdCount-1 );
375
void SensorBrowserWidget::update()
377
mSensorBrowserModel.clear();
379
KSGRD::SensorManagerIterator it( mSensorManager );
380
while ( it.hasNext() ) {
381
KSGRD::SensorAgent* sensorAgent = it.next().value();
382
QString hostName = mSensorManager->hostName( sensorAgent );
383
mSensorBrowserModel.addHost(sensorAgent, hostName);
386
QMimeData * SensorBrowserModel::mimeData ( const QModelIndexList & indexes ) const { //virtual
387
QMimeData *mimeData = new QMimeData();
388
if(indexes.size() != 1) return mimeData;
389
SensorInfo *sensor = getSensorInfo(indexes[0]);
390
if(!sensor) return mimeData;
391
// Create text drag object as
392
// "<hostname> <sensorname> <sensortype> <sensordescription>".
393
// Only the description may contain blanks.
395
Q_ASSERT(sensor->hostInfo());
396
QString mDragText = sensor->hostInfo()->hostName() + ' ' +
397
sensor->name() + ' ' +
398
sensor->type()+ ' ' +
399
sensor->description();
402
mimeData->setText( mDragText );
406
SensorInfo::SensorInfo( HostInfo *hostInfo, const QString &name,
407
const QString &desc, const QString &type )
408
: mName( name ), mDesc( desc ), mType( type ), mHostInfo( hostInfo )
413
QString SensorInfo::name() const
418
QString SensorInfo::type() const
423
QString SensorInfo::description() const
428
HostInfo *SensorInfo::hostInfo() const
435
#include "SensorBrowser.moc"