/* This file is part of the KDE project Copyright (C) 2024 Ivailo Monev This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2, as published by the Free Software Foundation. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "system-monitor.h" #include "ksysguard/ksgrd/SensorClient.h" #include "ksysguard/ksgrd/SensorManager.h" #include #include #include #include #include #include #include #include #include #include #include #include static const QString s_hostname = QString::fromLatin1("localhost"); static const int s_port = -1; // NOTE: values of thermal zones are in celsius, see: // https://www.kernel.org/doc/Documentation/thermal/sysfs-api.txt static const int s_temperatureunit = static_cast(KTemperature::Celsius); static const int s_monitorsid = -1; static const int s_update = 1; // 1 sec static const QSizeF s_minimumvisualizersize = QSizeF(120, 70); static const QSizeF s_minimummetersize = QSizeF(70, 70); enum KSensorType { UnknownSensor = 0, CPUSensor = 1, NetReceiverSensor = 2, NetTransmitterSensor = 3, PartitionFreeSensor = 4, PartitionUsedSensor = 5, ThermalSensor = 6 }; static KSensorType kSensorType(const QByteArray &sensor) { // qDebug() << Q_FUNC_INFO << sensor; // the only CPU sensor required if (sensor == "cpu/system/TotalLoad") { return KSensorType::CPUSensor; // any network receiver or transmitter except loopback } else if (sensor.startsWith("network/interfaces/") && sensor.endsWith("/receiver/data")) { if (sensor.contains("/interfaces/lo/")) { return KSensorType::UnknownSensor; } return KSensorType::NetReceiverSensor; } else if (sensor.startsWith("network/interfaces/") && sensor.endsWith("/transmitter/data")) { if (sensor.contains("/interfaces/lo/")) { return KSensorType::UnknownSensor; } return KSensorType::NetTransmitterSensor; // any partition } else if (sensor.startsWith("partitions/") && sensor.endsWith("/freespace")) { return KSensorType::PartitionFreeSensor; } else if (sensor.startsWith("partitions/") && sensor.endsWith("/usedspace")) { return KSensorType::PartitionUsedSensor; // any thermal zone } else if (sensor.startsWith("acpi/Thermal_Zone/")) { return KSensorType::ThermalSensor; } return KSensorType::UnknownSensor; } static QByteArray kNetID(const QByteArray &sensor) { if (sensor.endsWith("/receiver/data")) { return sensor.mid(0, sensor.size() - 14); } else if (sensor.endsWith("/transmitter/data")) { return sensor.mid(0, sensor.size() - 17); } kWarning() << "invalid network sensor" << sensor; return sensor; } static QByteArray kPartitionID(const QByteArray &sensor) { if (sensor.endsWith("/freespace") || sensor.endsWith("/usedspace")) { return sensor.mid(0, sensor.size() - 10); } kWarning() << "invalid partition sensor" << sensor; return sensor; } static QByteArray kThermalID(const QByteArray &sensor) { if (sensor.endsWith("/Temperature")) { return sensor.mid(0, sensor.size() - 12); } kWarning() << "invalid thermal sensor" << sensor; return sensor; } static QString kSensorDisplayString(const QByteArray &sensor) { const int indexofslash = sensor.lastIndexOf('/'); if (indexofslash >= 0) { return sensor.mid(indexofslash + 1, sensor.size() - indexofslash - 1); } return sensor; } static void kSetupFrame(Plasma::Frame* plasmaframe) { plasmaframe->setFrameShadow(Plasma::Frame::Sunken); plasmaframe->setMinimumSize(s_minimumvisualizersize); plasmaframe->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); QGraphicsLinearLayout* plasmaframelayout = new QGraphicsLinearLayout(plasmaframe); plasmaframelayout->setContentsMargins(0, 0, 0, 0); plasmaframe->setLayout(plasmaframelayout); } static void kAddItem(QGraphicsWidget *parent, QGraphicsWidget *widget) { QGraphicsLinearLayout* parentlayout = static_cast(parent->layout()); Q_ASSERT(parentlayout); parentlayout->addItem(widget); } static QColor kCPUVisualizerColor() { return Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor); } static QColor kNetReceiverVisualizerColor() { return Plasma::Theme::defaultTheme()->color(Plasma::Theme::VisitedLinkColor); } static QColor kNetTransmitterVisualizerColor() { return Plasma::Theme::defaultTheme()->color(Plasma::Theme::LinkColor); } class SystemMonitorNet : public Plasma::Frame { Q_OBJECT public: SystemMonitorNet(QGraphicsWidget *parent, const QByteArray &netid, const QColor &receivercolor, const QColor &transmittercolor); QByteArray netID() const; void resetSample(); void addReceiveSample(const double value); void addTransmitSample(const double value); private: Plasma::SignalPlotter* m_netplotter; const QByteArray m_netid; QList m_netsample; }; SystemMonitorNet::SystemMonitorNet(QGraphicsWidget *parent, const QByteArray &netid, const QColor &receivercolor, const QColor &transmittercolor) : Plasma::Frame(parent), m_netplotter(nullptr), m_netid(netid) { kSetupFrame(this); m_netplotter = new Plasma::SignalPlotter(this); m_netplotter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_netplotter->setTitle(kSensorDisplayString(m_netid)); m_netplotter->setUnit("KiB/s"); m_netplotter->setShowTopBar(true); m_netplotter->setShowLabels(true); m_netplotter->setShowVerticalLines(false); m_netplotter->setShowHorizontalLines(false); m_netplotter->setThinFrame(false); m_netplotter->setUseAutoRange(true); m_netplotter->setStackPlots(true); m_netplotter->addPlot(receivercolor); m_netplotter->addPlot(transmittercolor); kAddItem(this, m_netplotter); } QByteArray SystemMonitorNet::netID() const { return m_netid; } void SystemMonitorNet::resetSample() { m_netsample.clear(); m_netsample.reserve(2); m_netsample.append(0.0); m_netsample.append(0.0); } void SystemMonitorNet::addReceiveSample(const double value) { m_netsample[0] = value; m_netplotter->addSample(m_netsample); } void SystemMonitorNet::addTransmitSample(const double value) { m_netsample[1] = value; m_netplotter->addSample(m_netsample); } class SystemMonitorPartition : public Plasma::Meter { Q_OBJECT public: SystemMonitorPartition(QGraphicsWidget *parent, const QByteArray &partitionid); QByteArray partitionID() const; void resetSpace(); void setFreeSpace(const double value); void setUsedSpace(const double value); protected: void paint(QPainter *p, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) final; private: void calculateValues(); const QByteArray m_partitionid; QString m_partitiondisplaystring; int m_partitionvalues[2]; }; SystemMonitorPartition::SystemMonitorPartition(QGraphicsWidget *parent, const QByteArray &partitionid) : Plasma::Meter(parent), m_partitionid(partitionid), m_partitiondisplaystring(kSensorDisplayString(m_partitionid)) { resetSpace(); setMeterType(Plasma::Meter::BarMeterHorizontal); setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); setMinimum(0); setMaximum(0); if (m_partitiondisplaystring.isEmpty()) { m_partitiondisplaystring = QLatin1String("root"); } } QByteArray SystemMonitorPartition::partitionID() const { return m_partitionid; } void SystemMonitorPartition::resetSpace() { m_partitionvalues[0] = -1; m_partitionvalues[1] = -1; } void SystemMonitorPartition::setFreeSpace(const double value) { m_partitionvalues[0] = qRound(value / 1024.0); calculateValues(); } void SystemMonitorPartition::setUsedSpace(const double value) { m_partitionvalues[1] = qRound(value / 1024.0); calculateValues(); } void SystemMonitorPartition::paint(QPainter *p, const QStyleOptionGraphicsItem *option, QWidget *widget) { Plasma::Meter::paint(p, option, widget); p->setPen(Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor)); QFontMetricsF pfmetrics(p->font()); const QRectF rect(QPointF(0, 0), size()); // the partition display string may be very long (it is the final directory of the mount point) // and Plasma::Meter does not do eliding so it is done here const QString pstring = pfmetrics.elidedText(m_partitiondisplaystring, Qt::ElideRight, rect.width()); p->drawText(rect, Qt::AlignCenter, pstring); } void SystemMonitorPartition::calculateValues() { if (m_partitionvalues[0] != -1 && m_partitionvalues[1] != -1) { setMaximum(m_partitionvalues[0] + m_partitionvalues[1]); setValue(m_partitionvalues[1]); } } class SystemMonitorThermal : public Plasma::Meter { Q_OBJECT public: SystemMonitorThermal(QGraphicsWidget *parent, const QByteArray &thermalid, const int temperatureunit); QByteArray thermalID() const; void setSensorValue(const double value); private: const QByteArray m_thermalid; const KTemperature::KTempUnit m_temperatureunit; const QString m_thermaldisplaystring; }; SystemMonitorThermal::SystemMonitorThermal(QGraphicsWidget *parent, const QByteArray &thermalid, const int temperatureunit) : Plasma::Meter(parent), m_thermalid(thermalid), m_temperatureunit(static_cast(temperatureunit)), m_thermaldisplaystring(kSensorDisplayString(m_thermalid)) { setMeterType(Plasma::Meter::AnalogMeter); setMinimumSize(s_minimummetersize); setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); setLabel(0, m_thermaldisplaystring); switch (m_temperatureunit) { case KTemperature::Celsius: { setMinimum(0); setMaximum(110); break; } case KTemperature::Kelvin: { setMinimum(64); setMaximum(384); break; } case KTemperature::Fahrenheit: { setMinimum(32); setMaximum(230); break; } default: { kWarning() << "unhandled temperature unit" << temperatureunit; setMinimum(0); setMaximum(100); break; } } } QByteArray SystemMonitorThermal::thermalID() const { return m_thermalid; } void SystemMonitorThermal::setSensorValue(const double value) { const double valueinunit = KTemperature(value, KTemperature::Celsius).convertTo(m_temperatureunit); const QString valuestring = KTemperature(valueinunit, m_temperatureunit).toString(); setLabel(0, QString::fromLatin1("%1 - %2").arg(m_thermaldisplaystring).arg(valuestring)); setValue(qRound(valueinunit)); } class SystemMonitorClient : public QObject, public KSGRD::SensorClient { Q_OBJECT public: SystemMonitorClient(QObject *parent); bool setup(const QString &hostname, const int port); QList sensors() const; void requestValue(const QByteArray &sensor); Q_SIGNALS: void sensorsChanged(); void sensorValue(const QByteArray &sensor, const double value); private Q_SLOTS: void slotUpdate(); protected: void answerReceived(int id, const QList &answer) final; void sensorLost(int id) final; private: QString m_hostname; QList m_sensors; }; SystemMonitorClient::SystemMonitorClient(QObject *parent) : QObject(parent), m_hostname(s_hostname) { KSGRD::SensorMgr = new KSGRD::SensorManager(this); connect(KSGRD::SensorMgr, SIGNAL(update()), this, SLOT(slotUpdate())); } bool SystemMonitorClient::setup(const QString &hostname, const int port) { if (KSGRD::SensorMgr->isConnected(m_hostname)) { KSGRD::SensorMgr->disengage(m_hostname); } m_hostname = hostname; kDebug() << "connecting to sensor manager on" << m_hostname << port; const bool result = KSGRD::SensorMgr->engage(m_hostname, "", "ksysguardd", port); if (!result) { kWarning() << "could not connect to sensor manager on" << m_hostname << port; m_sensors.clear(); } else { slotUpdate(); } return result; } QList SystemMonitorClient::sensors() const { return m_sensors; } void SystemMonitorClient::requestValue(const QByteArray &sensor) { const int sensorid = m_sensors.indexOf(sensor); if (sensorid < 0) { // this can actually happen if there was no answer yet for "monitors" kWarning() << "unmapped sensor" << sensor; return; } const QString sensorstring = QString::fromLatin1(sensor.constData(), sensor.size()); KSGRD::SensorMgr->sendRequest(m_hostname, sensorstring, this, sensorid); } void SystemMonitorClient::slotUpdate() { KSGRD::SensorMgr->sendRequest(m_hostname, "monitors", this, s_monitorsid); } void SystemMonitorClient::answerReceived(int id, const QList &answer) { if (id == s_monitorsid) { m_sensors.clear(); // pre-sort, order of occurance matters and thermal sensors are not even received in sorted // order QList thermalsensors; foreach (const QByteArray &sensoranswer, answer) { const QList splitsensoranswer = sensoranswer.split('\t'); if (splitsensoranswer.size() != 2) { kWarning() << "invalid sensor answer" << sensoranswer; continue; } const QByteArray sensortype = splitsensoranswer.at(1); if (sensortype != "integer" && sensortype != "float") { continue; } const QByteArray sensorname = splitsensoranswer.at(0); const KSensorType ksensortype = kSensorType(sensorname); switch (ksensortype) { case KSensorType::ThermalSensor: { kDebug() << "mapping thermal sensor" << sensorname << sensortype; thermalsensors.append(sensorname); break; } case KSensorType::PartitionFreeSensor: case KSensorType::PartitionUsedSensor: { kDebug() << "mapping sensor to back" << sensorname << sensortype; m_sensors.append(sensorname); break; } case KSensorType::CPUSensor: case KSensorType::NetReceiverSensor: case KSensorType::NetTransmitterSensor: { kDebug() << "mapping sensor to front" << sensorname << sensortype; m_sensors.prepend(sensorname); break; } case KSensorType::UnknownSensor: { break; } } } if (!thermalsensors.isEmpty()) { qSort(thermalsensors); m_sensors.append(thermalsensors); } // qDebug() << Q_FUNC_INFO << m_sensors; emit sensorsChanged(); } else if (id < m_sensors.size()) { foreach (const QByteArray &sensoranswer, answer) { const QByteArray sensorname = m_sensors.at(id); bool ok = false; const double sensorvalue = sensoranswer.toDouble(&ok); if (Q_UNLIKELY(!ok)) { kWarning() << "sensor value conversion failed" << sensoranswer; } else { kDebug() << "got sensor value" << id << sensorname << sensorvalue; emit sensorValue(sensorname, sensorvalue); } } } else { kWarning() << "invalid sensor ID" << id; } } void SystemMonitorClient::sensorLost(int id) { kDebug() << "sensor lost" << id; slotUpdate(); } class SystemMonitorWidget : public QGraphicsWidget { Q_OBJECT public: SystemMonitorWidget(SystemMonitor* systemmonitor); void setupMonitors(const QString &hostname, const int port, const int update, const QColor &cpucolor, const QColor &receivercolor, const QColor &transmittercolor, const int temperatureunit); public Q_SLOTS: void slotUpdateLayout(); private Q_SLOTS: void slotRequestValues(); void slotSensorValue(const QByteArray &sensor, const double value); private: QMutex m_mutex; SystemMonitor* m_systemmonitor; QGraphicsGridLayout* m_layout; SystemMonitorClient* m_systemmonitorclient; Plasma::Frame* m_cpuframe; Plasma::SignalPlotter* m_cpuplotter; QList m_netmonitors; QList m_partitionmonitors; QList m_thermalmonitors; QTimer* m_updatetimer; QList m_requestsensors; QColor m_receivercolor; QColor m_transmittercolor; int m_temperatureunit; }; SystemMonitorWidget::SystemMonitorWidget(SystemMonitor* systemmonitor) : QGraphicsWidget(systemmonitor), m_systemmonitor(systemmonitor), m_layout(nullptr), m_systemmonitorclient(nullptr), m_cpuframe(nullptr), m_cpuplotter(nullptr) { m_systemmonitorclient = new SystemMonitorClient(this); m_layout = new QGraphicsGridLayout(this); m_cpuframe = new Plasma::Frame(this); kSetupFrame(m_cpuframe); m_cpuplotter = new Plasma::SignalPlotter(m_cpuframe); m_cpuplotter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_cpuplotter->setTitle(i18n("CPU")); m_cpuplotter->setUnit("%"); m_cpuplotter->setShowTopBar(true); m_cpuplotter->setShowLabels(true); m_cpuplotter->setShowVerticalLines(false); m_cpuplotter->setShowHorizontalLines(false); m_cpuplotter->setThinFrame(false); m_cpuplotter->setUseAutoRange(false); m_cpuplotter->setVerticalRange(0.0, 100.0); m_cpuplotter->addPlot(kCPUVisualizerColor()); kAddItem(m_cpuframe, m_cpuplotter); m_layout->addItem(m_cpuframe, 0, 0); m_layout->setColumnStretchFactor(0, 2); setLayout(m_layout); m_updatetimer = new QTimer(this); // the time is in seconds, has to be in ms for the timer m_updatetimer->setInterval(s_update * 1000); connect(m_updatetimer, SIGNAL(timeout()), this, SLOT(slotRequestValues())); } void SystemMonitorWidget::setupMonitors(const QString &hostname, const int port, const int update, const QColor &cpucolor, const QColor &receivercolor, const QColor &transmittercolor, const int temperatureunit) { m_updatetimer->stop(); m_updatetimer->setInterval(qMax(update, s_update) * 1000); disconnect(m_systemmonitorclient, 0, this, 0); m_systemmonitor->setBusy(true); if (!m_systemmonitorclient->setup(hostname, port)) { slotUpdateLayout(); const QString errorstring = i18n("Could not connect to: %1 on port %2", hostname, QString::number(port)); m_systemmonitor->showMessage(KIcon("dialog-error"), errorstring, Plasma::MessageButton::ButtonOk); return; } m_cpuplotter->removePlot(0); m_cpuplotter->addPlot(cpucolor); m_receivercolor = receivercolor; m_transmittercolor = transmittercolor; m_temperatureunit = temperatureunit; slotUpdateLayout(); connect( m_systemmonitorclient, SIGNAL(sensorValue(QByteArray,double)), this, SLOT(slotSensorValue(QByteArray,double)) ); connect( m_systemmonitorclient, SIGNAL(sensorsChanged()), this, SLOT(slotUpdateLayout()) ); } void SystemMonitorWidget::slotUpdateLayout() { QMutexLocker locker(&m_mutex); foreach (SystemMonitorNet* netmonitor, m_netmonitors) { m_layout->removeItem(netmonitor); } qDeleteAll(m_netmonitors); m_netmonitors.clear(); foreach (SystemMonitorPartition* partitionmonitor, m_partitionmonitors) { m_layout->removeItem(partitionmonitor); } qDeleteAll(m_partitionmonitors); m_partitionmonitors.clear(); foreach (SystemMonitorThermal* thermalmonitor, m_thermalmonitors) { m_layout->removeItem(thermalmonitor); } qDeleteAll(m_thermalmonitors); m_thermalmonitors.clear(); m_requestsensors.clear(); foreach (const QByteArray &sensor, m_systemmonitorclient->sensors()) { const KSensorType ksensortype = kSensorType(sensor); Q_ASSERT(ksensortype != KSensorType::UnknownSensor); m_requestsensors.append(sensor); if (ksensortype == KSensorType::NetReceiverSensor) { const QByteArray knetid = kNetID(sensor); kDebug() << "creating net monitor for" << knetid; SystemMonitorNet* netmonitor = new SystemMonitorNet( this, knetid, m_receivercolor, m_transmittercolor ); m_layout->addItem(netmonitor, 1, 0); m_netmonitors.append(netmonitor); } if (ksensortype == KSensorType::PartitionFreeSensor) { const QByteArray kpartitionid = kPartitionID(sensor); kDebug() << "creating partition monitor for" << kpartitionid; SystemMonitorPartition* partitionmonitor = new SystemMonitorPartition( this, kpartitionid ); m_layout->addItem(partitionmonitor, m_layout->rowCount(), 0, 1, 2); m_partitionmonitors.append(partitionmonitor); } } foreach (const QByteArray &sensor, m_systemmonitorclient->sensors()) { const KSensorType ksensortype = kSensorType(sensor); if (ksensortype == KSensorType::ThermalSensor) { // bottom is reserved, thermal monitors are aligned to the CPU monitor + the network // monitors count if (m_thermalmonitors.size() >= (m_netmonitors.size() + 1)) { kWarning() << "not enough space for thermal sensor" << sensor; continue; } const QByteArray thermalid = kThermalID(sensor); kDebug() << "creating thermal monitor for" << thermalid; SystemMonitorThermal* thermalmonitor = new SystemMonitorThermal( this, thermalid, m_temperatureunit ); m_layout->addItem(thermalmonitor, m_thermalmonitors.size(), 1); m_thermalmonitors.append(thermalmonitor); } } // immediate update in case the update time is long locker.unlock(); slotRequestValues(); // and start polling for updates m_updatetimer->start(); m_systemmonitor->setBusy(false); } void SystemMonitorWidget::slotRequestValues() { QMutexLocker locker(&m_mutex); foreach (SystemMonitorNet* netmonitor, m_netmonitors) { netmonitor->resetSample(); } foreach (SystemMonitorPartition* partitionmonitor, m_partitionmonitors) { partitionmonitor->resetSpace(); } locker.unlock(); foreach (const QByteArray &request, m_requestsensors) { m_systemmonitorclient->requestValue(request); } } void SystemMonitorWidget::slotSensorValue(const QByteArray &sensor, const double value) { const KSensorType ksensortype = kSensorType(sensor); switch (ksensortype) { case KSensorType::CPUSensor: { m_cpuplotter->addSample(QList() << value); break; } case KSensorType::NetReceiverSensor: { QMutexLocker locker(&m_mutex); const QByteArray netid = kNetID(sensor); foreach (SystemMonitorNet* netmonitor, m_netmonitors) { if (netmonitor->netID() == netid) { netmonitor->addReceiveSample(value); break; } } break; } case KSensorType::NetTransmitterSensor: { QMutexLocker locker(&m_mutex); const QByteArray netid = kNetID(sensor); foreach (SystemMonitorNet* netmonitor, m_netmonitors) { if (netmonitor->netID() == netid) { netmonitor->addTransmitSample(value); break; } } break; } case KSensorType::PartitionFreeSensor: { QMutexLocker locker(&m_mutex); const QByteArray partitionid = kPartitionID(sensor); foreach (SystemMonitorPartition* partitionmonitor, m_partitionmonitors) { if (partitionmonitor->partitionID() == partitionid) { partitionmonitor->setFreeSpace(value); break; } } break; } case KSensorType::PartitionUsedSensor: { QMutexLocker locker(&m_mutex); const QByteArray partitionid = kPartitionID(sensor); foreach (SystemMonitorPartition* partitionmonitor, m_partitionmonitors) { if (partitionmonitor->partitionID() == partitionid) { partitionmonitor->setUsedSpace(value); break; } } break; } case KSensorType::ThermalSensor: { QMutexLocker locker(&m_mutex); const QByteArray thermalid = kThermalID(sensor); foreach (SystemMonitorThermal* thermalmonitor, m_thermalmonitors) { if (thermalmonitor->thermalID() == thermalid) { thermalmonitor->setSensorValue(value); break; } } break; } case KSensorType::UnknownSensor: { kWarning() << "got value for unknown sensor" << sensor; break; } } } SystemMonitor::SystemMonitor(QObject *parent, const QVariantList &args) : Plasma::PopupApplet(parent, args), m_systemmonitorwidget(nullptr), m_hostname(s_hostname), m_port(s_port), m_update(s_update), m_temperatureunit(s_temperatureunit), m_hostnameedit(nullptr), m_portbox(nullptr), m_updateedit(nullptr), m_cpubutton(nullptr), m_receiverbutton(nullptr), m_transmitterbutton(nullptr), m_temperaturebox(nullptr), m_spacer(nullptr) { KGlobal::locale()->insertCatalog("plasma_applet_system-monitor"); setAspectRatioMode(Plasma::IgnoreAspectRatio); setHasConfigurationInterface(true); m_systemmonitorwidget = new SystemMonitorWidget(this); setPopupIcon("utilities-system-monitor"); } SystemMonitor::~SystemMonitor() { delete m_systemmonitorwidget; } void SystemMonitor::init() { slotThemeChanged(); connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(slotThemeChanged())); } void SystemMonitor::createConfigurationInterface(KConfigDialog *parent) { QWidget* widget = new QWidget(); QGridLayout* widgetlayout = new QGridLayout(widget); QLabel* hostnamelabel = new QLabel(widget); hostnamelabel->setText(i18n("Hostname:")); widgetlayout->addWidget(hostnamelabel, 0, 0, Qt::AlignRight); m_hostnameedit = new KLineEdit(widget); m_hostnameedit->setText(m_hostname); widgetlayout->addWidget(m_hostnameedit, 0, 1); QLabel* portlabel = new QLabel(widget); portlabel->setText(i18n("Port:")); widgetlayout->addWidget(portlabel, 1, 0, Qt::AlignRight); m_portbox = new KIntNumInput(widget); m_portbox->setMinimum(s_port); m_portbox->setMaximum(USHRT_MAX); m_portbox->setSpecialValueText(i18n("Default")); m_portbox->setValue(m_port); widgetlayout->addWidget(m_portbox, 1, 1); QLabel* updatelabel = new QLabel(widget); updatelabel->setText(i18n("Update interval:")); widgetlayout->addWidget(updatelabel, 2, 0, Qt::AlignRight); m_updateedit = new KTimeEdit(widget); m_updateedit->setMinimumTime(QTime(0, 0, 1)); m_updateedit->setTime(QTime(0, 0, 0).addSecs(m_update)); widgetlayout->addWidget(m_updateedit, 2, 1); QLabel* cpulabel = new QLabel(widget); cpulabel->setText(i18n("CPU color:")); widgetlayout->addWidget(cpulabel, 3, 0, Qt::AlignRight); const QColor defaultcpucolor = kCPUVisualizerColor(); QColor cpucolor = m_cpucolor; if (!cpucolor.isValid()) { cpucolor = defaultcpucolor; } m_cpubutton = new KColorButton(widget); m_cpubutton->setDefaultColor(defaultcpucolor); m_cpubutton->setColor(cpucolor); widgetlayout->addWidget(m_cpubutton, 3, 1); QLabel* receiverlabel = new QLabel(widget); receiverlabel->setText(i18n("Receiver color:")); widgetlayout->addWidget(receiverlabel, 4, 0, Qt::AlignRight); const QColor defaultreceivercolor = kNetReceiverVisualizerColor(); QColor receivercolor = m_receivercolor; if (!receivercolor.isValid()) { receivercolor = defaultreceivercolor; } m_receiverbutton = new KColorButton(widget); m_receiverbutton->setDefaultColor(defaultreceivercolor); m_receiverbutton->setColor(receivercolor); widgetlayout->addWidget(m_receiverbutton, 4, 1); QLabel* transmitterlabel = new QLabel(widget); transmitterlabel->setText(i18n("Transmitter color:")); widgetlayout->addWidget(transmitterlabel, 5, 0, Qt::AlignRight); const QColor defaulttransmittercolor = kNetTransmitterVisualizerColor(); QColor transmittercolor = m_transmittercolor; if (!transmittercolor.isValid()) { transmittercolor = defaulttransmittercolor; } m_transmitterbutton = new KColorButton(widget); m_transmitterbutton->setDefaultColor(defaulttransmittercolor); m_transmitterbutton->setColor(transmittercolor); widgetlayout->addWidget(m_transmitterbutton, 5, 1); QLabel* temperaturelabel = new QLabel(widget); temperaturelabel->setText(i18n("Temeprature unit:")); widgetlayout->addWidget(temperaturelabel, 6, 0, Qt::AlignRight); m_temperaturebox = new QComboBox(widget); for (int i = 0; i < KTemperature::UnitCount; i++) { m_temperaturebox->addItem(KTemperature::unitDescription(static_cast(i))); } m_temperaturebox->setCurrentIndex(m_temperatureunit); widgetlayout->addWidget(m_temperaturebox, 6, 1); m_spacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding); widgetlayout->addItem(m_spacer, 7, 0, 1, 2); widget->setLayout(widgetlayout); parent->addPage(widget, i18n("System Monitor"), "utilities-system-monitor"); connect(parent, SIGNAL(applyClicked()), this, SLOT(slotConfigAccepted())); connect(parent, SIGNAL(okClicked()), this, SLOT(slotConfigAccepted())); connect(m_hostnameedit, SIGNAL(textChanged(QString)), parent, SLOT(settingsModified())); connect(m_portbox, SIGNAL(valueChanged(int)), parent, SLOT(settingsModified())); connect(m_updateedit, SIGNAL(timeChanged(QTime)), parent, SLOT(settingsModified())); connect(m_cpubutton, SIGNAL(changed(QColor)), parent, SLOT(settingsModified())); connect(m_receiverbutton, SIGNAL(changed(QColor)), parent, SLOT(settingsModified())); connect(m_transmitterbutton, SIGNAL(changed(QColor)), parent, SLOT(settingsModified())); connect(m_temperaturebox, SIGNAL(currentIndexChanged(int)), parent, SLOT(settingsModified())); } QGraphicsWidget *SystemMonitor::graphicsWidget() { return m_systemmonitorwidget; } void SystemMonitor::slotConfigAccepted() { Q_ASSERT(m_hostnameedit != nullptr); Q_ASSERT(m_portbox != nullptr); Q_ASSERT(m_updateedit != nullptr); Q_ASSERT(m_cpubutton != nullptr); Q_ASSERT(m_receiverbutton != nullptr); Q_ASSERT(m_transmitterbutton != nullptr); Q_ASSERT(m_temperaturebox != nullptr); m_hostname = m_hostnameedit->text(); m_port = m_portbox->value(); m_update = QTime(0, 0, 0).secsTo(m_updateedit->time()); m_cpucolor = m_cpubutton->color(); m_receivercolor = m_receiverbutton->color(); m_transmittercolor = m_transmitterbutton->color(); m_temperatureunit = m_temperaturebox->currentIndex(); KConfigGroup configgroup = config(); configgroup.writeEntry("hostname", m_hostname); configgroup.writeEntry("port", m_port); configgroup.writeEntry("update", m_update); if (m_cpucolor == kCPUVisualizerColor()) { configgroup.writeEntry("cpucolor", QColor()); } else { configgroup.writeEntry("cpucolor", m_cpucolor); } if (m_receivercolor == kNetReceiverVisualizerColor()) { configgroup.writeEntry("netreceivercolor", QColor()); } else { configgroup.writeEntry("netreceivercolor", m_receivercolor); } if (m_transmittercolor == kNetTransmitterVisualizerColor()) { configgroup.writeEntry("nettransmittercolor", QColor()); } else { configgroup.writeEntry("nettransmittercolor", m_transmittercolor); } configgroup.writeEntry("temperatureunit", m_temperatureunit); emit configNeedsSaving(); m_systemmonitorwidget->setupMonitors( m_hostname, m_port, m_update, m_cpucolor, m_receivercolor, m_transmittercolor, m_temperatureunit ); } void SystemMonitor::slotThemeChanged() { KConfigGroup configgroup = config(); m_hostname = configgroup.readEntry("hostname", s_hostname); m_port = configgroup.readEntry("port", s_port); m_update = configgroup.readEntry("update", s_update); m_cpucolor = configgroup.readEntry("cpucolor", QColor()); if (!m_cpucolor.isValid()) { m_cpucolor = kCPUVisualizerColor(); } m_receivercolor = configgroup.readEntry("netreceivercolor", QColor()); if (!m_receivercolor.isValid()) { m_receivercolor = kNetReceiverVisualizerColor(); } m_transmittercolor = configgroup.readEntry("nettransmittercolor", QColor()); if (!m_transmittercolor.isValid()) { m_transmittercolor = kNetTransmitterVisualizerColor(); } m_temperatureunit = configgroup.readEntry("temperatureunit", s_temperatureunit); m_systemmonitorwidget->setupMonitors( m_hostname, m_port, m_update, m_cpucolor, m_receivercolor, m_transmittercolor, m_temperatureunit ); } K_EXPORT_PLASMA_APPLET(system-monitor_applet, SystemMonitor) #include "moc_system-monitor.cpp" #include "system-monitor.moc"