~ubuntu-branches/ubuntu/gutsy/kdebase-workspace/gutsy-backports

« back to all changes in this revision

Viewing changes to ksysguard/gui/SensorBrowser.cc

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2007-09-05 20:45:14 UTC
  • Revision ID: james.westby@ubuntu.com-20070905204514-632hhspl0nvrc84i
Tags: upstream-3.93.0
ImportĀ upstreamĀ versionĀ 3.93.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    KSysGuard, the KDE System Guard
 
3
 
 
4
    Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
 
5
 
 
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.
 
9
 
 
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.
 
14
 
 
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.
 
18
 
 
19
*/
 
20
 
 
21
#include <QtGui/QDrag>
 
22
#include <QtGui/QLabel>
 
23
#include <QtGui/QMouseEvent>
 
24
#include <QtGui/QPainter>
 
25
#include <QtGui/QPixmap>
 
26
#include <QMimeData>
 
27
 
 
28
#include <kdebug.h>
 
29
#include <kicon.h>
 
30
#include <klocale.h>
 
31
#include <kmessagebox.h>
 
32
#include <ksgrd/SensorManager.h>
 
33
 
 
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"
 
39
#endif
 
40
 
 
41
SensorBrowserModel::SensorBrowserModel()
 
42
{
 
43
#ifdef SENSOR_MODEL_DO_TEST
 
44
  new ModelTest(this);
 
45
#endif
 
46
  mIdCount=1;
 
47
}
 
48
SensorBrowserModel::~SensorBrowserModel()
 
49
{
 
50
 
 
51
  qDeleteAll( mHostInfoMap );
 
52
  mHostInfoMap.clear();
 
53
  qDeleteAll( mSensorInfoMap );
 
54
  mSensorInfoMap.clear();
 
55
}
 
56
 
 
57
int SensorBrowserModel::columnCount( const QModelIndex &) const { //virtual 
 
58
  return 1;
 
59
}
 
60
 
 
61
QVariant SensorBrowserModel::data( const QModelIndex & index, int role) const { //virtual
 
62
  if(!index.isValid()) return QVariant();
 
63
  switch(role) {
 
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() +')' ;
 
71
        }
 
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();
 
76
        }
 
77
      }
 
78
      return QString();
 
79
    }
 
80
    case Qt::DecorationRole: {
 
81
      if(index.column() == 0 && mHostInfoMap.contains(index.internalId())) {
 
82
        return KIcon("system");
 
83
      } else 
 
84
        return QIcon(); //work around for drawing bug
 
85
      break;
 
86
    }
 
87
  } //switch
 
88
  return QVariant();
 
89
}
 
90
 
 
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");
 
94
        return QVariant();
 
95
}
 
96
 
 
97
QModelIndex SensorBrowserModel::index ( int row, int column, const QModelIndex & parent) const { //virtual
 
98
  if(column != 0) return QModelIndex();
 
99
  QList<int> ids;
 
100
  if(!parent.isValid()) {
 
101
    ids = mHostInfoMap.keys();
 
102
  }
 
103
  else {
 
104
    ids = mTreeMap.value(parent.internalId());
 
105
  }
 
106
  if( row >= ids.size() || row< 0) {
 
107
    return QModelIndex();
 
108
  }
 
109
  QModelIndex index = createIndex(row, column, ids[row]);
 
110
  Q_ASSERT(index.isValid());
 
111
  return index;
 
112
}
 
113
 
 
114
QStringList SensorBrowserModel::listHosts() const
 
115
{
 
116
  QStringList hostList;
 
117
 
 
118
  QMapIterator<int, HostInfo*> it( mHostInfoMap );
 
119
  while ( it.hasNext() ) {
 
120
    it.next();
 
121
    Q_ASSERT(it.value());
 
122
    hostList.append( it.value()->hostName() );
 
123
  }
 
124
 
 
125
  return hostList;
 
126
}
 
127
 
 
128
QStringList SensorBrowserModel::listSensors( const QString &hostName ) const
 
129
{
 
130
  QMapIterator<int, HostInfo*> it( mHostInfoMap );
 
131
  while ( it.hasNext() ) {
 
132
    it.next();
 
133
    Q_ASSERT(it.value());
 
134
    if ( it.value()->hostName() == hostName ) {
 
135
      Q_ASSERT(mSensorInfoMap.contains(it.key()));
 
136
      return listSensors( it.key() );
 
137
    }
 
138
  }
 
139
  return QStringList();
 
140
}
 
141
 
 
142
QStringList SensorBrowserModel::listSensors( int parentId) const
 
143
{
 
144
  SensorInfo *sensor=mSensorInfoMap.value(parentId);
 
145
  if(sensor) return QStringList(sensor->name());
 
146
 
 
147
  QStringList childSensors;
 
148
  QList<int> children = mTreeMap.value(parentId);
 
149
  for(int i=0; i < children.size(); i++) {
 
150
    childSensors+= listSensors(children[i]); 
 
151
  }
 
152
  return childSensors; 
 
153
}
 
154
SensorInfo *SensorBrowserModel::getSensorInfo(QModelIndex index) const
 
155
{
 
156
  if(!index.isValid()) return NULL;
 
157
  return mSensorInfoMap.value(index.internalId());
 
158
}
 
159
 
 
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) 
 
169
        return children[i];
 
170
    }
 
171
 
 
172
  QModelIndex parentModelIndex;
 
173
  if(hostInfo->id() == parentId) {
 
174
    parentModelIndex = createIndex(mHostInfoMap.keys().indexOf(parentId), 0 , parentId);
 
175
  } else {
 
176
    int parentsParentId = mParentsTreeMap.value(parentId);
 
177
    parentModelIndex = createIndex(mTreeMap.value(parentsParentId).indexOf(parentId), 0, parentId);
 
178
  }
 
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);
 
187
    mIdCount++;
 
188
  endInsertRows();
 
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  
 
190
}
 
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];
 
195
 
 
196
  QModelIndex parentModelIndex;
 
197
  if(mHostInfoMap.contains(parentId)) {
 
198
    parentModelIndex = createIndex(mHostInfoMap.keys().indexOf(parentId), 0 , parentId);
 
199
  } else {
 
200
    int parentsParentId = mParentsTreeMap.value(parentId);
 
201
    parentModelIndex = createIndex(mTreeMap.value(parentsParentId).indexOf(parentId), 0, parentId);
 
202
  }
 
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);
 
210
    mIdCount++;
 
211
  endInsertRows();
 
212
  
 
213
  return mIdCount-1;
 
214
}
 
215
 
 
216
void SensorBrowserModel::answerReceived( int hostId,  const QList<QByteArray>&answer )
 
217
{
 
218
  /* An answer has the following example format:
 
219
 
 
220
     cpu/system/idle integer
 
221
     cpu/system/sys  integer
 
222
     cpu/system/nice integer
 
223
     cpu/system/user integer
 
224
     ps       table
 
225
  */
 
226
 
 
227
  HostInfo *hostInfo = getHostInfo(hostId);
 
228
  if(!hostInfo) {
 
229
    kDebug(1215) << "SensorBrowserModel::answerReceived with invalid hostId " << hostId ;
 
230
    return;
 
231
  }  
 
232
  for ( int i = 0; i < answer.count(); ++i ) {
 
233
    if ( answer[ i ].isEmpty() )
 
234
      break;
 
235
 
 
236
    QList<QByteArray> words = answer[ i ].split('\t');
 
237
    QString sensorName = QString::fromUtf8(words[ 0 ]);
 
238
    QString sensorType = QString::fromUtf8(words[ 1 ]);
 
239
 
 
240
    if ( hasSensor(hostId, sensorName))
 
241
      break;
 
242
    if(sensorName.isEmpty()) break;
 
243
 
 
244
    if(sensorType == "string") continue;
 
245
 
 
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
 
250
     * depth of nodes. */
 
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);
 
257
    }
 
258
    QString name = KSGRD::SensorMgr->translateSensorPath( absolutePath[ absolutePath.size()-1] );
 
259
    makeSensor(hostInfo, currentNodeId, sensorName, name, sensorType);
 
260
  }
 
261
  emit sensorsAddedToHost( createIndex( mHostInfoMap.keys().indexOf(hostId), 0, hostId ) )  ;
 
262
}
 
263
 
 
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();
 
271
  }
 
272
  int parentId = mParentsTreeMap.value(index.internalId());
 
273
 
 
274
  QModelIndex parentModelIndex;
 
275
  if(mHostInfoMap.contains(parentId)) {
 
276
    parentModelIndex = createIndex(mHostInfoMap.keys().indexOf(parentId), 0 , parentId);
 
277
  } else {
 
278
    int parentsParentId = mParentsTreeMap.value(parentId);
 
279
    parentModelIndex = createIndex(mTreeMap.value(parentsParentId).indexOf(parentId), 0, parentId);
 
280
  }
 
281
  Q_ASSERT(parentModelIndex.isValid());
 
282
  return parentModelIndex;
 
283
}
 
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();
 
288
}
 
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;
 
293
}
 
294
 
 
295
SensorBrowserWidget::SensorBrowserWidget( QWidget* parent, KSGRD::SensorManager* sm )
 
296
  : QTreeView( parent ), mSensorManager( sm )
 
297
{
 
298
  connect( mSensorManager, SIGNAL( update() ), SLOT( update() ) );
 
299
  setModel(&mSensorBrowserModel);
 
300
 
 
301
  this->setToolTip( i18n( "Drag sensors to empty cells of a worksheet "
 
302
                             "or the panel applet." ) );
 
303
//  setRootIsDecorated( false );
 
304
  setDragDropMode(QAbstractItemView::DragOnly);
 
305
 
 
306
  //setMinimumWidth( 1 );
 
307
 
 
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&)));
 
316
  update();
 
317
}
 
318
 
 
319
SensorBrowserWidget::~SensorBrowserWidget()
 
320
{
 
321
}
 
322
 
 
323
void SensorBrowserWidget::disconnect()
 
324
{
 
325
  QModelIndexList indexlist = selectionModel()->selectedRows();
 
326
  for(int i=0; i < indexlist.size(); i++)
 
327
  {
 
328
    mSensorBrowserModel.disconnectHost(indexlist.value(i).internalId());
 
329
  }
 
330
}
 
331
 
 
332
void SensorBrowserWidget::hostReconfigured( const QString& )
 
333
{
 
334
  // TODO: not yet implemented.
 
335
}
 
336
 
 
337
void SensorBrowserModel::clear() {
 
338
  qDeleteAll(mHostInfoMap);
 
339
  mHostInfoMap.clear();
 
340
 
 
341
}
 
342
 
 
343
void SensorBrowserModel::disconnectHost(uint id)
 
344
{
 
345
  disconnectHost(mHostInfoMap.value(id));
 
346
}
 
347
void SensorBrowserModel::disconnectHost(const HostInfo *hostInfo)
 
348
{
 
349
  KSGRD::SensorMgr->requestDisengage( hostInfo->sensorAgent() );
 
350
}
 
351
void SensorBrowserModel::disconnectHost(const QString &hostname)
 
352
{
 
353
  QMapIterator<int, HostInfo*> it( mHostInfoMap );
 
354
  while ( it.hasNext() ) {
 
355
    it.next();
 
356
    if(it.value()->hostName() == hostname) {
 
357
      disconnectHost(it.value());
 
358
      return;
 
359
    }
 
360
  }
 
361
}
 
362
 
 
363
void SensorBrowserModel::addHost(KSGRD::SensorAgent *sensorAgent, const QString &hostName)
 
364
{
 
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>());
 
370
    mIdCount++;
 
371
  endInsertRows();
 
372
  hostInfo->sensorAgent()->sendRequest( "monitors", this, mIdCount-1 );
 
373
}
 
374
 
 
375
void SensorBrowserWidget::update()
 
376
{
 
377
  mSensorBrowserModel.clear();
 
378
 
 
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);
 
384
  }
 
385
}
 
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.
 
394
  Q_ASSERT(sensor);
 
395
  Q_ASSERT(sensor->hostInfo());
 
396
  QString mDragText = sensor->hostInfo()->hostName() + ' ' +
 
397
                      sensor->name() + ' ' +
 
398
                      sensor->type()+ ' ' +
 
399
                      sensor->description();
 
400
 
 
401
 
 
402
  mimeData->setText( mDragText );
 
403
  return mimeData;
 
404
}
 
405
 
 
406
SensorInfo::SensorInfo( HostInfo *hostInfo, const QString &name,
 
407
                        const QString &desc, const QString &type )
 
408
  : mName( name ), mDesc( desc ), mType( type ), mHostInfo( hostInfo )
 
409
{
 
410
  Q_ASSERT(mHostInfo);
 
411
}
 
412
 
 
413
QString SensorInfo::name() const
 
414
{
 
415
  return mName;
 
416
}
 
417
 
 
418
QString SensorInfo::type() const
 
419
{
 
420
  return mType;
 
421
}
 
422
 
 
423
QString SensorInfo::description() const
 
424
{
 
425
  return mDesc;
 
426
}
 
427
 
 
428
HostInfo *SensorInfo::hostInfo() const
 
429
{
 
430
  return mHostInfo;
 
431
}
 
432
 
 
433
 
 
434
 
 
435
#include "SensorBrowser.moc"