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 the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License or (at your option) version 3 or any later version
10 accepted by the membership of KDE e.V. (or its successor approved
11 by the membership of KDE e.V.), which shall act as a proxy
12 defined in Section 14 of version 3 of the license.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include <QDebug>
24 #include <QIcon>
25 #include <QLineEdit>
26 #include <QMimeData>
27 #include <QVBoxLayout>
28
29 #include <KLocalizedString>
30 #include <KMessageBox>
31 #include <ksgrd/SensorManager.h>
32
33 #include "SensorBrowser.h"
34 //#define SENSOR_MODEL_DO_TEST
35 //uncomment the above to test the model
36 #ifdef SENSOR_MODEL_DO_TEST
37 #include "modeltest.h"
38 #endif
39
SensorBrowserModel()40 SensorBrowserModel::SensorBrowserModel()
41 {
42 #ifdef SENSOR_MODEL_DO_TEST
43 new ModelTest(this);
44 #endif
45 mIdCount=1;
46 }
~SensorBrowserModel()47 SensorBrowserModel::~SensorBrowserModel()
48 {
49 qDeleteAll( mHostInfoMap );
50 mHostInfoMap.clear();
51 qDeleteAll( mSensorInfoMap );
52 mSensorInfoMap.clear();
53 }
54
columnCount(const QModelIndex &) const55 int SensorBrowserModel::columnCount( const QModelIndex &) const { //virtual
56 return 1;
57 }
58
data(const QModelIndex & index,int role) const59 QVariant SensorBrowserModel::data( const QModelIndex & index, int role) const { //virtual
60 if(!index.isValid()) return QVariant();
61 switch(role) {
62 case Qt::DisplayRole: {
63 if(index.column()==0) {
64 uint id = index.internalId();
65 if(mSensorInfoMap.contains(id)) {
66 Q_ASSERT(mSensorInfoMap.value(id));
67 SensorInfo *sensorInfo = mSensorInfoMap.value(id);
68 return QString(sensorInfo->description() + " (" + KSGRD::SensorMgr->translateSensorType(sensorInfo->type()) + ')' );
69 }
70 if(mTreeNodeNames.contains(id)) return mTreeNodeNames.value(id);
71 if(mHostInfoMap.contains(id)) {
72 Q_ASSERT(mHostInfoMap.value(id));
73 return mHostInfoMap.value(id)->hostName();
74 }
75 }
76 return QString();
77 }
78 case Qt::DecorationRole: {
79 if(index.column() == 0) {
80 HostInfo *host = getHostInfo(index.internalId());
81 KSGRD::SensorAgent *agent;
82 if(host != nullptr && (agent = host->sensorAgent())) {
83 if(agent->daemonOnLine())
84 return QIcon::fromTheme(QStringLiteral("computer"));
85 else
86 return QIcon::fromTheme(QStringLiteral("dialog-warning"));
87 } else
88 return QIcon();
89 } else
90 return QIcon();
91 break;
92 }
93 case Qt::ToolTipRole: {
94 if(index.column() == 0) {
95 HostInfo *host = getHostInfo(index.internalId());
96 KSGRD::SensorAgent *agent;
97 if(host != nullptr && (agent = host->sensorAgent())) {
98 if(agent->daemonOnLine())
99 return agent->hostName();
100 else
101 return agent->reasonForOffline();
102 }
103 }
104 break;
105 }
106
107 } //switch
108 return QVariant();
109 }
110
headerData(int section,Qt::Orientation,int role) const111 QVariant SensorBrowserModel::headerData ( int section, Qt::Orientation , int role) const { //virtual
112 if(role != Qt::DisplayRole) return QVariant();
113 if(section==0) return i18n("Sensor Browser");
114 return QVariant();
115 }
116
retranslate()117 void SensorBrowserModel::retranslate() {
118 emit headerDataChanged(Qt::Horizontal, 0,0);
119 }
120
index(int row,int column,const QModelIndex & parent) const121 QModelIndex SensorBrowserModel::index ( int row, int column, const QModelIndex & parent) const { //virtual
122 if(column != 0) return QModelIndex();
123 QList<int> ids;
124 if(!parent.isValid()) {
125 ids = mHostInfoMap.keys();
126 }
127 else {
128 ids = mTreeMap.value(parent.internalId());
129 }
130 if( row >= ids.size() || row< 0) {
131 return QModelIndex();
132 }
133 QModelIndex index = createIndex(row, column, ids[row]);
134 Q_ASSERT(index.isValid());
135 return index;
136 }
137
listHosts() const138 QStringList SensorBrowserModel::listHosts() const
139 {
140 QStringList hostList;
141
142 QMapIterator<int, HostInfo*> it( mHostInfoMap );
143 while ( it.hasNext() ) {
144 it.next();
145 Q_ASSERT(it.value());
146 hostList.append( it.value()->hostName() );
147 }
148
149 return hostList;
150 }
151
listSensors(const QString & hostName) const152 QStringList SensorBrowserModel::listSensors( const QString &hostName ) const
153 {
154 QMapIterator<int, HostInfo*> it( mHostInfoMap );
155 while ( it.hasNext() ) {
156 it.next();
157 Q_ASSERT(it.value());
158 if ( it.value()->hostName() == hostName ) {
159 Q_ASSERT(mSensorInfoMap.contains(it.key()));
160 return listSensors( it.key() );
161 }
162 }
163 return QStringList();
164 }
165
listSensors(int parentId) const166 QStringList SensorBrowserModel::listSensors( int parentId) const
167 {
168 SensorInfo *sensor=mSensorInfoMap.value(parentId);
169 if(sensor) return QStringList(sensor->name());
170
171 QStringList childSensors;
172 QList<int> children = mTreeMap.value(parentId);
173 for(int i=0; i < children.size(); i++) {
174 childSensors+= listSensors(children[i]);
175 }
176 return childSensors;
177 }
getSensorInfo(QModelIndex index) const178 SensorInfo *SensorBrowserModel::getSensorInfo(QModelIndex index) const
179 {
180 if(!index.isValid()) return nullptr;
181 return mSensorInfoMap.value(index.internalId());
182 }
makeSensor(HostInfo * hostInfo,int parentId,const QString & sensorName,const QString & name,const QString & sensorType)183 int SensorBrowserModel::makeSensor(HostInfo *hostInfo, int parentId, const QString &sensorName, const QString &name, const QString &sensorType) {
184 //sensorName is the full version. e.g. mem/free
185 //name is the short version. e.g. free
186 //sensortype is e.g. Integer
187 QList<int> children = mTreeMap.value(parentId);
188 for(int i=0; i<children.size(); i++)
189 if(mSensorInfoMap.contains(children[i])) {
190 Q_ASSERT(mSensorInfoMap.value(children[i]));
191 if(mSensorInfoMap.value(children[i])->name() == sensorName)
192 return children[i];
193 }
194
195 QModelIndex parentModelIndex;
196 if(hostInfo->id() == parentId) {
197 parentModelIndex = createIndex(mHostInfoMap.keys().indexOf(parentId), 0 , parentId);
198 } else {
199 int parentsParentId = mParentsTreeMap.value(parentId);
200 parentModelIndex = createIndex(mTreeMap.value(parentsParentId).indexOf(parentId), 0, parentId);
201 }
202 Q_ASSERT(parentModelIndex.isValid());
203 QList<int> &parentTreemap = mTreeMap[parentId];
204 SensorInfo *sensorInfo = new SensorInfo(hostInfo, sensorName, name, sensorType);
205 beginInsertRows( parentModelIndex , parentTreemap.size(), parentTreemap.size() );
206 parentTreemap << mIdCount;
207 mParentsTreeMap.insert( mIdCount, parentId );
208 mSensorInfoMap.insert(mIdCount, sensorInfo);
209 mHostSensorsMap[hostInfo->id()].insert(sensorName, true);
210 mIdCount++;
211 endInsertRows();
212 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
213 }
214
removeSensor(HostInfo * hostInfo,int parentId,const QString & sensorName)215 void SensorBrowserModel::removeSensor(HostInfo *hostInfo, int parentId, const QString &sensorName) {
216 //sensorName is the full version. e.g. mem/free
217 QList<int> children = mTreeMap.value(parentId);
218 int idCount = -1;
219 int index;
220 for(index=0; index<children.size(); index++)
221 if(mSensorInfoMap.contains(children[index])) {
222 Q_ASSERT(mSensorInfoMap.value(children[index]));
223 if(mSensorInfoMap.value(children[index])->name() == sensorName) {
224 idCount = children[index];
225 break;
226 }
227 }
228 if(idCount == -1) {
229 qDebug() << "removeSensor called for sensor that doesn't exist in the tree: " << sensorName ;
230 return;
231 }
232 QModelIndex parentModelIndex;
233 int parentsParentId = -1;
234 if(hostInfo->id() == parentId) {
235 parentModelIndex = createIndex(mHostInfoMap.keys().indexOf(parentId), 0 , parentId);
236 } else {
237 parentsParentId = mParentsTreeMap.value(parentId);
238 parentModelIndex = createIndex(mTreeMap.value(parentsParentId).indexOf(parentId), 0, parentId);
239 }
240 Q_ASSERT(parentModelIndex.isValid());
241 QList<int> &parentTreemap = mTreeMap[parentId];
242 beginRemoveRows( parentModelIndex, index, index );
243 parentTreemap.removeAll(idCount);
244 mParentsTreeMap.remove(idCount);
245 SensorInfo *sensorInfo = mSensorInfoMap.take(idCount);
246 delete sensorInfo;
247 mHostSensorsMap[hostInfo->id()].remove(sensorName);
248 endRemoveRows();
249
250 if(parentsParentId != -1)
251 removeEmptyParentTreeBranches(hostInfo->id(), parentId, parentsParentId);
252 }
removeEmptyParentTreeBranches(int hostId,int id,int parentId)253 void SensorBrowserModel::removeEmptyParentTreeBranches(int hostId, int id, int parentId) {
254 if(hostId == id)
255 return; //We don't want to remove hosts
256
257 if(!mTreeMap.value(id).isEmpty()) return; // We should have no children
258
259 QModelIndex parentModelIndex;
260 int parentsParentId = -1;
261 if(hostId == parentId) {
262 parentModelIndex = createIndex(mHostInfoMap.keys().indexOf(parentId), 0 , parentId);
263 } else {
264 parentsParentId = mParentsTreeMap.value(parentId);
265 parentModelIndex = createIndex(mTreeMap.value(parentsParentId).indexOf(parentId), 0, parentId);
266 }
267
268 int index = mTreeMap.value(parentId).indexOf(id);
269 int idCount = mTreeMap.value(parentId).at(index);
270
271 QList<int> &parentTreemap = mTreeMap[parentId];
272 beginRemoveRows( parentModelIndex, index, index );
273 parentTreemap.removeAll(idCount);
274 mParentsTreeMap.remove(idCount);
275 mTreeMap.remove(idCount);
276 mTreeNodeNames.remove(idCount);
277 endRemoveRows();
278
279 if(parentsParentId != -1)
280 removeEmptyParentTreeBranches(hostId, parentId, parentsParentId);
281 }
makeTreeBranch(int parentId,const QString & name)282 int SensorBrowserModel::makeTreeBranch(int parentId, const QString &name) {
283 QList<int> children = mTreeMap.value(parentId);
284 for(int i=0; i<children.size(); i++)
285 if(mTreeNodeNames.value(children[i]) == name) return children[i];
286
287 QModelIndex parentModelIndex;
288 if(mHostInfoMap.contains(parentId)) {
289 parentModelIndex = createIndex(mHostInfoMap.keys().indexOf(parentId), 0 , parentId);
290 } else {
291 int parentsParentId = mParentsTreeMap.value(parentId);
292 parentModelIndex = createIndex(mTreeMap.value(parentsParentId).indexOf(parentId), 0, parentId);
293 }
294 Q_ASSERT(parentModelIndex.isValid());
295 QList<int> &parentTreemap = mTreeMap[parentId];
296 beginInsertRows( parentModelIndex , parentTreemap.size(), parentTreemap.size() );
297 parentTreemap << mIdCount;
298 mParentsTreeMap.insert( mIdCount, parentId );
299 mTreeMap[mIdCount]; //create with empty qlist
300 mTreeNodeNames.insert(mIdCount, name);
301 mIdCount++;
302 endInsertRows();
303
304 return mIdCount-1;
305 }
306
answerReceived(int hostId,const QList<QByteArray> & answer)307 void SensorBrowserModel::answerReceived( int hostId, const QList<QByteArray>&answer )
308 {
309 /* An answer has the following example format:
310
311 cpu/system/idle integer
312 cpu/system/sys integer
313 cpu/system/nice integer
314 cpu/system/user integer
315 ps table
316 */
317 HostInfo *hostInfo = getHostInfo(hostId);
318 if(!hostInfo) {
319 qDebug() << "Invalid hostId " << hostId ;
320 return;
321 }
322 /* We keep a copy of the previous sensor names so that we can detect what sensors have been removed */
323 QHash<QString,bool> oldSensorNames = mHostSensorsMap.value(hostId);
324 for ( int i = 0; i < answer.count(); ++i ) {
325 if ( answer[ i ].isEmpty() )
326 continue;
327
328 QList<QByteArray> words = answer[ i ].split('\t');
329 if(words.size() != 2) {
330 qDebug() << "Invalid data " << answer[i];
331 continue; /* Something wrong with this line of data */
332 }
333 QString sensorName = QString::fromUtf8(words[ 0 ]);
334 QString sensorType = QString::fromUtf8(words[ 1 ]);
335 oldSensorNames.remove(sensorName); /* This sensor has not been removed */
336 if ( hasSensor(hostId, sensorName)) {
337 continue;
338 }
339 if(sensorName.isEmpty()) continue;
340
341 if(sensorType == QLatin1String("string")) continue;
342
343 /* The sensor browser can display sensors in a hierarchical order.
344 * Sensors can be grouped into nodes by separating the hierarchical
345 * nodes through slashes in the sensor name. E. g. cpu/system/user is
346 * the sensor user in the cpu node. There is no limit for the
347 * depth of nodes. */
348 int currentNodeId = hostId; //Start from the host branch and work our way down the tree
349 QStringList absolutePath = sensorName.split( '/' );
350 for ( int j = 0; j < absolutePath.count()-1; ++j ) {
351 // Localize the sensor name part by part.
352 QString name = KSGRD::SensorMgr->translateSensorPath( absolutePath[ j ] );
353 currentNodeId = makeTreeBranch(currentNodeId, name);
354 }
355 QString name = KSGRD::SensorMgr->translateSensorPath( absolutePath[ absolutePath.size()-1] );
356 makeSensor(hostInfo, currentNodeId, sensorName, name, sensorType);
357 }
358 /* Now we have to remove sensors that were not found */
359 QHashIterator<QString, bool> it( oldSensorNames );
360 while ( it.hasNext() ) {
361 it.next();
362
363 int currentNodeId = hostId; //Start from the host branch and work our way down the tree
364 QStringList absolutePath = it.key().split( '/' );
365 for ( int j = 0; j < absolutePath.count()-1; ++j ) {
366 // Localize the sensor name part by part.
367 QString name = KSGRD::SensorMgr->translateSensorPath( absolutePath[ j ] );
368 currentNodeId = makeTreeBranch(currentNodeId, name);
369 }
370 removeSensor(hostInfo, currentNodeId, it.key());
371 }
372 emit sensorsAddedToHost( createIndex( mHostInfoMap.keys().indexOf(hostId), 0, hostId ) );
373 }
374
375 //virtual
parent(const QModelIndex & index) const376 QModelIndex SensorBrowserModel::parent ( const QModelIndex & index ) const {
377 if(!index.isValid() || index.column() != 0)
378 return QModelIndex();
379 if(mHostInfoMap.contains(index.internalId())) return QModelIndex();
380 if(!mParentsTreeMap.contains(index.internalId())) {
381 qDebug() << "Something is wrong with the model. Doesn't contain " << index.internalId();
382 return QModelIndex();
383 }
384 int parentId = mParentsTreeMap.value(index.internalId());
385
386 QModelIndex parentModelIndex;
387 if(mHostInfoMap.contains(parentId)) {
388 parentModelIndex = createIndex(mHostInfoMap.keys().indexOf(parentId), 0 , parentId);
389 } else {
390 int parentsParentId = mParentsTreeMap.value(parentId);
391 parentModelIndex = createIndex(mTreeMap.value(parentsParentId).indexOf(parentId), 0, parentId);
392 }
393 Q_ASSERT(parentModelIndex.isValid());
394 return parentModelIndex;
395 }
396 //virtual
rowCount(const QModelIndex & parent) const397 int SensorBrowserModel::rowCount ( const QModelIndex & parent ) const {
398 if(!parent.isValid()) return mHostInfoMap.size();
399 if(parent.column() != 0) return 0;
400 return mTreeMap.value(parent.internalId()).size();
401 }
402 //virtual
flags(const QModelIndex & index) const403 Qt::ItemFlags SensorBrowserModel::flags ( const QModelIndex & index ) const {
404 if(!index.isValid()) return Qt::NoItemFlags;
405 if(mSensorInfoMap.contains(index.internalId())) return Qt::ItemIsDragEnabled | Qt::ItemIsSelectable | Qt::ItemIsEnabled;
406 else return Qt::ItemIsEnabled;
407 }
408
SensorBrowserWidget(QWidget * parent,KSGRD::SensorManager * sm)409 SensorBrowserWidget::SensorBrowserWidget( QWidget* parent, KSGRD::SensorManager* sm ) : QWidget( parent )
410 {
411 QVBoxLayout *layout = new QVBoxLayout;
412 m_treeWidget = new SensorBrowserTreeWidget(this, sm);
413 QLineEdit * search_line = new QLineEdit(this);
414 connect(search_line, &QLineEdit::textChanged, this, [this](const QString &text) {
415 m_treeWidget->model().setFilterFixedString(text);
416 });
417 layout->addWidget(search_line);
418 layout->addWidget(m_treeWidget);
419 setLayout(layout);
420 }
~SensorBrowserWidget()421 SensorBrowserWidget::~SensorBrowserWidget()
422 {
423 }
SensorBrowserTreeWidget(QWidget * parent,KSGRD::SensorManager * sm)424 SensorBrowserTreeWidget::SensorBrowserTreeWidget( QWidget* parent, KSGRD::SensorManager* sm ) : QTreeView( parent ), mSensorManager( sm )
425 {
426 mSortFilterProxyModel.setSourceModel(&mSensorBrowserModel);
427 mSortFilterProxyModel.setRecursiveFilteringEnabled(true);
428 mSortFilterProxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive);
429 setModel(&mSortFilterProxyModel);
430 connect(mSensorManager, &KSGRD::SensorManager::update, &mSensorBrowserModel, &SensorBrowserModel::update);
431 connect(mSensorManager, &KSGRD::SensorManager::hostAdded, &mSensorBrowserModel, &SensorBrowserModel::hostAdded);
432 connect(mSensorManager, &KSGRD::SensorManager::hostConnectionLost, &mSensorBrowserModel, &SensorBrowserModel::hostRemoved);
433 // connect( mSensorManager, SIGNAL(hostAdded(KSGRD::SensorAgent*,QString)), SLOT(updateView()) );
434 // connect( mSensorManager, SIGNAL(hostConnectionLost(QString)), SLOT(updateView()) );
435 connect(&mSortFilterProxyModel, &QSortFilterProxyModel::rowsInserted, this, &SensorBrowserTreeWidget::updateView);
436
437 setDragDropMode(QAbstractItemView::DragOnly);
438 setUniformRowHeights(true);
439
440 //setMinimumWidth( 1 );
441 retranslateUi();
442 connect(&mSensorBrowserModel, &SensorBrowserModel::sensorsAddedToHost, this, &SensorBrowserTreeWidget::expandItem);
443
444 KSGRD::SensorManagerIterator it( mSensorManager );
445 while ( it.hasNext() ) {
446 KSGRD::SensorAgent* sensorAgent = it.next().value();
447 QString hostName = mSensorManager->hostName( sensorAgent );
448 mSensorBrowserModel.addHost(sensorAgent, hostName);
449 }
450 updateView();
451 }
452
~SensorBrowserTreeWidget()453 SensorBrowserTreeWidget::~SensorBrowserTreeWidget()
454 {
455 }
456
updateView()457 void SensorBrowserTreeWidget::updateView()
458 {
459 if(mSensorManager->count() == 1) {
460 setRootIsDecorated( false );
461 //expand the top level
462 for(int i = 0; i < mSortFilterProxyModel.rowCount(); i++)
463 expand(mSortFilterProxyModel.index(i,0));
464 } else
465 setRootIsDecorated( true );
466 }
expandItem(const QModelIndex & model_index)467 void SensorBrowserTreeWidget::expandItem(const QModelIndex &model_index)
468 {
469 expand(mSortFilterProxyModel.mapFromSource(model_index));
470 }
retranslateUi()471 void SensorBrowserTreeWidget::retranslateUi() {
472
473 this->setToolTip( i18n( "Drag sensors to empty cells of a worksheet "));
474 this->setWhatsThis( i18n( "The sensor browser lists the connected hosts and the sensors "
475 "that they provide. Click and drag sensors into drop zones "
476 "of a worksheet. A display will appear "
477 "that visualizes the "
478 "values provided by the sensor. Some sensor displays can "
479 "display values of multiple sensors. Simply drag other "
480 "sensors on to the display to add more sensors." ) );
481 }
482
changeEvent(QEvent * event)483 void SensorBrowserTreeWidget::changeEvent( QEvent * event )
484 {
485 if (event->type() == QEvent::LanguageChange) {
486 retranslateUi();
487 mSensorBrowserModel.retranslate();
488 mSensorBrowserModel.update();
489 }
490 QWidget::changeEvent(event);
491 }
492
disconnect()493 void SensorBrowserTreeWidget::disconnect()
494 {
495 QModelIndexList indexlist = selectionModel()->selectedRows();
496 for(int i=0; i < indexlist.size(); i++)
497 {
498 mSensorBrowserModel.disconnectHost(indexlist.value(i).internalId());
499 }
500 }
501
hostReconfigured(const QString &)502 void SensorBrowserTreeWidget::hostReconfigured( const QString& )
503 {
504 // TODO: not yet implemented.
505 }
506
clear()507 void SensorBrowserModel::clear() {
508 qDeleteAll(mHostInfoMap);
509 mHostInfoMap.clear();
510
511 }
512
disconnectHost(uint id)513 void SensorBrowserModel::disconnectHost(uint id)
514 {
515 disconnectHost(mHostInfoMap.value(id));
516 }
disconnectHost(const HostInfo * hostInfo)517 void SensorBrowserModel::disconnectHost(const HostInfo *hostInfo)
518 {
519 KSGRD::SensorMgr->disengage( hostInfo->sensorAgent() );
520 }
disconnectHost(const QString & hostname)521 void SensorBrowserModel::disconnectHost(const QString &hostname)
522 {
523 HostInfo* toDelete = findHostInfoByHostName(hostname);
524 if (toDelete != nullptr)
525 disconnectHost(toDelete);
526 }
findHostInfoByHostName(const QString & hostName) const527 HostInfo* SensorBrowserModel::findHostInfoByHostName(const QString &hostName) const {
528 HostInfo* toReturn = nullptr;
529 QMapIterator<int, HostInfo*> it( mHostInfoMap );
530 while (it.hasNext() && toReturn == nullptr) {
531 it.next();
532 if (it.value()->hostName() == hostName) {
533 toReturn = it.value();
534 }
535 }
536 return toReturn;
537 }
hostAdded(KSGRD::SensorAgent * sensorAgent,const QString & hostName)538 void SensorBrowserModel::hostAdded(KSGRD::SensorAgent *sensorAgent, const QString &hostName) {
539 addHost(sensorAgent,hostName);
540 update();
541 }
542
hostRemoved(const QString & hostName)543 void SensorBrowserModel::hostRemoved(const QString &hostName) {
544 HostInfo* toRemove = findHostInfoByHostName(hostName);
545 if (toRemove != nullptr) {
546 beginResetModel();
547 int hostId = toRemove->id();
548 removeAllSensorUnderBranch(toRemove,hostId);
549 removeEmptyParentTreeBranches(hostId,hostId,hostId);
550
551 delete mHostInfoMap.take(hostId);
552 mTreeMap.take(hostId);
553 mHostSensorsMap.take(hostId);
554 endResetModel();
555 }
556 update();
557 }
558
removeAllSensorUnderBranch(HostInfo * hostInfo,int parentId)559 void SensorBrowserModel::removeAllSensorUnderBranch(HostInfo* hostInfo, int parentId) {
560
561 QList<int> children = mTreeMap.value(parentId);
562
563 for (int i = 0; i < children.size(); i++) {
564
565 if (mTreeMap.contains(children[i])) {
566 //well our children is not a sensor so remove what is under him
567 removeAllSensorUnderBranch(hostInfo,children[i]);
568
569 } else {
570 //well this should be a sensor so remove it
571 if (mSensorInfoMap.contains(children[i])) {
572 SensorInfo* sensorToRemove = mSensorInfoMap.value(children[i]);
573 Q_ASSERT(sensorToRemove);
574 removeSensor(hostInfo, parentId, sensorToRemove->name());
575 }
576 }
577 }
578
579
580 }
addHost(KSGRD::SensorAgent * sensorAgent,const QString & hostName)581 void SensorBrowserModel::addHost(KSGRD::SensorAgent *sensorAgent, const QString &hostName)
582 {
583 beginInsertRows( QModelIndex() , mHostInfoMap.size(), mHostInfoMap.size() );
584 HostInfo* hostInfo = new HostInfo( mIdCount, sensorAgent, hostName);
585 mHostInfoMap.insert(mIdCount, hostInfo);
586 mTreeMap.insert(mIdCount, QList<int>());
587 mHostSensorsMap.insert(mIdCount, QHash<QString, bool>());
588 mIdCount++;
589 endInsertRows();
590 hostInfo->sensorAgent()->sendRequest( QStringLiteral("monitors"), this, mIdCount-1 );
591 }
592
update()593 void SensorBrowserModel::update()
594 {
595 QMapIterator<int, HostInfo*> it( mHostInfoMap );
596 while ( it.hasNext() ) {
597 it.next();
598 KSGRD::SensorAgent* sensorAgent = it.value()->sensorAgent();
599 int id = it.key();
600 sensorAgent->sendRequest( QStringLiteral("monitors"), this, id );
601 }
602 }
mimeData(const QModelIndexList & indexes) const603 QMimeData * SensorBrowserModel::mimeData ( const QModelIndexList & indexes ) const { //virtual
604 QMimeData *mimeData = new QMimeData();
605 if(indexes.size() != 1) return mimeData;
606 SensorInfo *sensor = getSensorInfo(indexes[0]);
607 if(!sensor) return mimeData;
608 // Create text drag object as
609 // "<hostname> <sensorname> <sensortype> <sensordescription>".
610 // Only the description may contain blanks.
611 Q_ASSERT(sensor);
612 Q_ASSERT(sensor->hostInfo());
613 QString mDragText = sensor->hostInfo()->hostName() + ' ' +
614 sensor->name() + ' ' +
615 sensor->type()+ ' ' +
616 sensor->description();
617
618
619 mimeData->setData( QStringLiteral("application/x-ksysguard"), mDragText.toUtf8() );
620 return mimeData;
621 }
622
SensorInfo(HostInfo * hostInfo,const QString & name,const QString & desc,const QString & type)623 SensorInfo::SensorInfo( HostInfo *hostInfo, const QString &name,
624 const QString &desc, const QString &type )
625 : mName( name ), mDesc( desc ), mType( type ), mHostInfo( hostInfo )
626 {
627 Q_ASSERT(mHostInfo);
628 }
629
name() const630 QString SensorInfo::name() const
631 {
632 return mName;
633 }
634
type() const635 QString SensorInfo::type() const
636 {
637 return mType;
638 }
639
description() const640 QString SensorInfo::description() const
641 {
642 return mDesc;
643 }
644
hostInfo() const645 HostInfo *SensorInfo::hostInfo() const
646 {
647 return mHostInfo;
648 }
649
650
651
652
653