Prepare for multi-cpu support.
[system_status.git] / applet / system_monitor.cpp
blobc3054a22402b1697db4d0acd5de484eb6d0107f6
1 /***********************************************************************************
2 * System Monitor: Plasmoid and data engines to monitor CPU/Memory/Swap Usage.
3 * Copyright (C) 2008 Matthew Dawson
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
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.
19 ***********************************************************************************/
21 #include "system_monitor.h"
23 #include <Plasma/ToolTipManager>
24 //#include <Plasma/ToolTipContent>
25 #include "plasma/tooltipcontent.h"
27 #include <KConfigDialog>
29 #include <QPainter>
31 #include <cmath>
33 systemMonitor::systemMonitor(QObject *parent, const QVariantList &args)
34 : Plasma::Applet(parent, args),
35 m_ramfree(0),
36 m_ramused(0),
37 m_rambuffers(0),
38 m_ramcached(0),
39 m_ramtotal(1),
40 m_swapfree(0),
41 m_swapused(0),
42 m_swaptotal(1){
44 m_cpuInfo.resize(1);
45 setHasConfigurationInterface(true);
46 resize(100, 100);
49 systemMonitor::~systemMonitor(){
51 if(hasFailedToLaunch()){
53 }else {
59 void systemMonitor::init(){
61 readConfig();
63 sys_mon = dataEngine("systemmonitor");
64 connect(sys_mon, SIGNAL(sourceAdded(const QString &)), this, SLOT(sourcesAdded(const QString &)));
65 reconnectSources();
67 Plasma::ToolTipManager::self()->registerWidget(this);
71 void systemMonitor::reconnectSources(){
73 reconnectCPUSources();
75 sys_mon->connectSource("mem/physical/used", this, 500);
76 sys_mon->connectSource("mem/physical/free", this, 500);
77 sys_mon->connectSource("mem/physical/buf", this, 500);
78 sys_mon->connectSource("mem/physical/cached", this, 500);
80 sys_mon->connectSource("mem/swap/used", this, 500);
81 sys_mon->connectSource("mem/swap/free", this, 500);
85 void systemMonitor::reconnectCPUSources(){
87 sys_mon->connectSource("cpu/system/user", this, 500);
88 sys_mon->connectSource("cpu/system/sys", this, 500);
89 sys_mon->connectSource("cpu/system/nice", this, 500);
90 sys_mon->connectSource("cpu/system/wait", this, 500);
91 sys_mon->connectSource("cpu/system/idle", this, 500);
95 void systemMonitor::disconnectSources(){
97 sys_mon->disconnectSource("mem/physical/used", this);
98 sys_mon->disconnectSource("mem/physical/free", this);
99 sys_mon->disconnectSource("mem/physical/buf", this);
100 sys_mon->disconnectSource("mem/physical/cached", this);
102 sys_mon->disconnectSource("mem/swap/used", this);
103 sys_mon->disconnectSource("mem/swap/free", this);
107 void systemMonitor::sourcesAdded(const QString &source){
109 if(source.startsWith("cpu/system/") && !m_showMultiCPU){
111 if(source.endsWith("/user") || source.endsWith("/sys") || source.endsWith("/nice") || source.endsWith("/wait") || source.endsWith("/idle")){
113 sys_mon->connectSource(source, this, 500);
117 }else if(source.startsWith("mem/swap")){
119 sys_mon->connectSource(source, this, 500);
121 }else if(source.startsWith("mem/physical/")){
123 if(!source.endsWith("application")){
125 sys_mon->connectSource(source, this, 500);
133 void systemMonitor::constraintsEvent(Plasma::Constraints constraints){
135 if(constraints.testFlag(Plasma::FormFactorConstraint)){
137 if(formFactor() == Plasma::Planar || formFactor() == Plasma::MediaCenter){
138 setAspectRatioMode(Plasma::IgnoreAspectRatio);
139 }else {
140 setAspectRatioMode(Plasma::ConstrainedSquare);
143 //If only StandardBackground is set, it should be completely transparent. (it gets
144 //set in Plasma::Applet on certain conditions.
145 if(backgroundHints() == StandardBackground){
146 setBackgroundHints(NoBackground);
153 void systemMonitor::createConfigurationInterface(KConfigDialog *parent){
155 QWidget *widGeneral = new QWidget();
156 uiGeneral.setupUi(widGeneral);
158 uiGeneral.chkIsVertical->setChecked(m_isVertical);
159 uiGeneral.chkUseOxygen->setChecked(m_useOxygen);
160 uiGeneral.kcmbBackground->setItemData(0, DefaultBackground);
161 uiGeneral.kcmbBackground->setItemData(1, TranslucentBackground);
162 uiGeneral.kcmbBackground->setItemData(2, NoBackground);
164 switch( (int)backgroundHints() ){
166 case (int)DefaultBackground:
167 uiGeneral.kcmbBackground->setCurrentIndex(0);
168 break;
169 //StandardBackground may get set. Doesn't effect drawing, so this just makes sure we catch it.
170 case (int)TranslucentBackground:
171 case (int)TranslucentBackground | StandardBackground:
172 uiGeneral.kcmbBackground->setCurrentIndex(1);
173 break;
174 case (int)NoBackground:
175 uiGeneral.kcmbBackground->setCurrentIndex(2);
176 break;
177 default:
178 Q_ASSERT("Unknown background hints!");
179 break;
183 QWidget *widColours = new QWidget();
184 uiColours.setupUi(widColours);
186 uiColours.kcbCpuUser->setColor(this->m_cpuUserColour);
187 uiColours.kcbCpuNice->setColor(this->m_cpuNiceColour);
188 uiColours.kcbCpuDisk->setColor(this->m_cpuDiskColour);
189 uiColours.kcbCpuSystem->setColor(this->m_cpuSysColour);
190 uiColours.kcbRamBuffers->setColor(this->m_ramBuffersColour);
191 uiColours.kcbRamCached->setColor(this->m_ramCachedColour);
192 uiColours.kcbRamUser->setColor(this->m_ramUsedColour);
193 uiColours.kcbSwap->setColor(this->m_swapUsedColour);
195 parent->setButtons (KDialog::Ok | KDialog::Cancel | KDialog::Apply );
196 connect(parent, SIGNAL(applyClicked()), this, SLOT(configUpdated()));
197 connect(parent, SIGNAL(okClicked()), this, SLOT(configUpdated()));
199 parent->addPage(widGeneral, "General", icon(), QString(), false);
200 parent->addPage(widColours, "Colours", icon(), QString(), false);
202 parent->setFaceType(KConfigDialog::Tabbed);
206 void systemMonitor::configUpdated(){
208 KConfigGroup cg = config();
210 if(uiGeneral.kcmbBackground->itemData(uiGeneral.kcmbBackground->currentIndex()).toInt() != (int)this->backgroundHints()){
211 this->setBackgroundHints(QFlag(uiGeneral.kcmbBackground->itemData(uiGeneral.kcmbBackground->currentIndex()).toInt()));
212 cg.writeEntry("background", (int)this->backgroundHints());
215 if(uiGeneral.chkIsVertical->isChecked() != this->m_isVertical){
216 this->m_isVertical = uiGeneral.chkIsVertical->isChecked();
217 cg.writeEntry("vertical", this->m_isVertical);
219 if(uiGeneral.chkUseOxygen->isChecked() != this->m_useOxygen){
220 this->m_useOxygen = uiGeneral.chkUseOxygen->isChecked();
221 cg.writeEntry("use_oxygen", this->m_useOxygen);
223 if(uiColours.kcbCpuUser->color() != this->m_cpuUserColour){
224 this->m_cpuUserColour = uiColours.kcbCpuUser->color();
225 cg.writeEntry("colour_cpu_user", this->m_cpuUserColour.name());
227 if(uiColours.kcbCpuNice->color() != this->m_cpuNiceColour){
228 this->m_cpuNiceColour = uiColours.kcbCpuNice->color();
229 cg.writeEntry("colour_cpu_nice", this->m_cpuNiceColour.name());
231 if(uiColours.kcbCpuDisk->color() != this->m_cpuDiskColour){
232 this->m_cpuDiskColour = uiColours.kcbCpuDisk->color();
233 cg.writeEntry("colour_cpu_disk", this->m_cpuDiskColour.name());
235 if(uiColours.kcbCpuSystem->color() != this->m_cpuSysColour){
236 this->m_cpuSysColour = uiColours.kcbCpuSystem->color();
237 cg.writeEntry("colour_cpu_sys", this->m_cpuSysColour.name());
239 if(uiColours.kcbRamCached->color() != this->m_ramCachedColour){
240 this->m_ramCachedColour = uiColours.kcbRamCached->color();
241 cg.writeEntry("colour_ram_cached", this->m_ramCachedColour.name());
243 if(uiColours.kcbRamBuffers->color() != this->m_ramBuffersColour){
244 this->m_ramBuffersColour = uiColours.kcbRamBuffers->color();
245 cg.writeEntry("colour_ram_buffers", this->m_ramBuffersColour.name());
247 if(uiColours.kcbRamUser->color() != this->m_ramUsedColour){
248 this->m_ramUsedColour = uiColours.kcbRamUser->color();
249 cg.writeEntry("colour_ram_used", this->m_ramUsedColour.name());
251 if(uiColours.kcbSwap->color() != this->m_swapUsedColour){
252 this->m_swapUsedColour = uiColours.kcbSwap->color();
253 cg.writeEntry("colour_swap_used", this->m_swapUsedColour.name());
256 emit configNeedsSaving();
257 update();
261 void systemMonitor::dataUpdated(const QString& source, const Plasma::DataEngine::Data &data){
263 if(source.startsWith("cpu/system/") && !m_showMultiCPU){
265 if(source.endsWith("/user")){
267 m_cpuInfo[0].user = (data["value"].toString().toDouble()) / 100;
269 }else if(source.endsWith("/sys")){
271 m_cpuInfo[0].sys = (data["value"].toString().toDouble()) / 100;
273 }else if(source.endsWith("/nice")){
275 m_cpuInfo[0].nice = (data["value"].toString().toDouble()) / 100;
277 }else if(source.endsWith("/wait")){
279 m_cpuInfo[0].disk = (data["value"].toString().toDouble()) / 100;
281 }else if(source.endsWith("/idle")){
283 m_cpuInfo[0].idle = (data["value"].toString().toDouble()) / 100;
287 }else if(source.startsWith("mem/swap")){
289 if(source.endsWith("/used")){
291 m_swapused = data["value"].toDouble() / 100;
293 }else if(source.endsWith("/free")){
295 m_swapfree = data["value"].toDouble() / 100;
299 m_swaptotal = m_swapfree + m_swapused;
301 if(m_swaptotal == 0){
303 m_swaptotal = 1;
307 update();
309 }else if(source.startsWith("mem/physical/")){
311 if(source.endsWith("/used")){
313 m_ramused = data["value"].toDouble();
315 }else if(source.endsWith("/cached")){
317 m_ramcached = data["value"].toDouble();
319 }else if(source.endsWith("/buf")){
321 m_rambuffers = data["value"].toDouble();
323 }else if(source.endsWith("/free")){
325 m_ramfree = data["value"].toDouble();
329 m_ramtotal = m_ramused + m_ramcached + m_rambuffers + m_ramfree;
331 if(m_ramtotal == 0){
333 m_ramtotal = 1;
341 void systemMonitor::paintCPUUsage(QPainter *p, const QStyleOptionGraphicsItem *option, const QRect& contentsRect, const cpuInfo &cpu){
343 Q_UNUSED(option)
345 p->save();
347 p->translate(0, contentsRect.height() * cpu.idle);
350 p->setBrush(this->m_cpuUserColour);
351 p->setPen(this->m_cpuUserColour);
353 p->drawRect(QRectF(contentsRect.left(), contentsRect.top(), contentsRect.width(), contentsRect.height() * cpu.user));
354 p->translate(0, contentsRect.height() * cpu.user);
357 p->setBrush(this->m_cpuNiceColour);
358 p->setPen(this->m_cpuNiceColour);
360 p->drawRect(QRectF(contentsRect.left(), contentsRect.top(), contentsRect.width(), contentsRect.height() * cpu.nice));
361 p->translate(0, contentsRect.height() * cpu.nice);
364 p->setBrush(this->m_cpuDiskColour);
365 p->setPen(this->m_cpuDiskColour);
367 p->drawRect(QRectF(contentsRect.left(), contentsRect.top(), contentsRect.width(), contentsRect.height() * cpu.disk));
368 p->translate(0, contentsRect.height() * cpu.disk);
371 p->setBrush(this->m_cpuSysColour);
372 p->setPen(this->m_cpuSysColour);
374 p->drawRect(QRectF(contentsRect.left(), contentsRect.top(), contentsRect.width(), contentsRect.height() * cpu.sys));
376 p->restore();
380 void systemMonitor::paintSwapUsage(QPainter *p, const QStyleOptionGraphicsItem *option, const QRect& contentsRect){
382 Q_UNUSED(option)
384 p->save();
386 p->translate(0, contentsRect.height() * m_swapfree / m_swaptotal);
389 p->setBrush(this->m_swapUsedColour);
390 p->setPen(this->m_swapUsedColour);
392 p->drawRect(QRectF(contentsRect.left(), contentsRect.top(), contentsRect.width(), contentsRect.height() * m_swapused / m_swaptotal));
394 p->restore();
398 void systemMonitor::paintRAMUsage(QPainter *p, const QStyleOptionGraphicsItem *option, const QRect& contentsRect){
400 Q_UNUSED(option)
402 p->save();
404 p->translate(0, contentsRect.height() * m_ramfree / m_ramtotal);
407 p->setBrush(this->m_ramCachedColour);
408 p->setPen(this->m_ramCachedColour);
410 p->drawRect(QRectF(contentsRect.left(), contentsRect.top(), contentsRect.width(), contentsRect.height() * m_ramcached / m_ramtotal));
411 p->translate(0, contentsRect.height() * m_ramcached / m_ramtotal);
414 p->setBrush(this->m_ramBuffersColour);
415 p->setPen(this->m_ramBuffersColour);
417 p->drawRect(QRectF(contentsRect.left(), contentsRect.top(), contentsRect.width(), contentsRect.height() * m_rambuffers / m_ramtotal));
418 p->translate(0, contentsRect.height() * m_rambuffers / m_ramtotal);
421 p->setBrush(this->m_ramUsedColour);
422 p->setPen(this->m_ramUsedColour);
424 p->drawRect(QRectF(contentsRect.left(), contentsRect.top(), contentsRect.width(), contentsRect.height() * m_ramused / m_ramtotal));
426 p->restore();
430 void systemMonitor::paintFrontGlass(QPainter* p, const QStyleOptionGraphicsItem *option, const QRect& contentsRect) {
432 Q_UNUSED(option);
434 QLinearGradient grad(0,contentsRect.top(),0,contentsRect.bottom());
435 grad.setColorAt(0,QColor(255,255,255, 30));
436 grad.setColorAt(1,QColor( 0, 0, 0,150));
437 p->setBrush(grad);
438 p->setPen(QColor(0,0,0,100));
439 p->drawRect(contentsRect);
443 void systemMonitor::paintInterface(QPainter *p, const QStyleOptionGraphicsItem *option, const QRect& contentsRect){
445 p->setRenderHint(QPainter::SmoothPixmapTransform);
446 p->setRenderHint(QPainter::Antialiasing);
448 QRect rotatedContentsRect(contentsRect);
451 if(!this->m_isVertical && (this->formFactor() == Plasma::Horizontal || this->formFactor() == Plasma::Vertical) ){
452 p->setWorldTransform(QTransform().rotate(90).translate(0, -(contentsRect.width() + contentsRect.x() * 2)));
453 rotatedContentsRect.setWidth(contentsRect.height());
454 rotatedContentsRect.setHeight(contentsRect.width());
457 int origWidth = rotatedContentsRect.width();
459 if(m_useOxygen){
460 rotatedContentsRect.setWidth(rotatedContentsRect.width() * 0.325);
461 rotatedContentsRect.moveLeft(rotatedContentsRect.left() + origWidth * 0.009);
462 }else{
463 rotatedContentsRect.setWidth(rotatedContentsRect.width() * 0.33);
466 paintCPUUsage(p, option, rotatedContentsRect, m_cpuInfo[0]);
467 if(m_useOxygen){
468 paintFrontGlass(p, option, rotatedContentsRect);
470 rotatedContentsRect.moveLeft(rotatedContentsRect.left() + 0.33*origWidth);
472 paintRAMUsage(p, option, rotatedContentsRect);
473 if(m_useOxygen){
474 paintFrontGlass(p, option, rotatedContentsRect);
476 rotatedContentsRect.moveLeft(rotatedContentsRect.left() + 0.33*origWidth);
478 paintSwapUsage(p, option, rotatedContentsRect);
479 if(m_useOxygen){
480 paintFrontGlass(p, option, rotatedContentsRect);
486 void systemMonitor::readConfig(){
488 KConfigGroup cg = config();
490 this->m_isVertical = cg.readEntry("vertical", true);
491 this->m_useOxygen = cg.readEntry("use_oxygen", false);
492 this->m_showMultiCPU = false;
494 this->m_cpuUserColour = QColor( cg.readEntry("colour_cpu_user", QString("#0000FF")) );
495 this->m_cpuNiceColour = QColor( cg.readEntry("colour_cpu_nice", QString("#FFFF00")) );
496 this->m_cpuDiskColour = QColor( cg.readEntry("colour_cpu_disk", QString("#006400")) );
497 this->m_cpuSysColour = QColor( cg.readEntry("colour_cpu_sys", QString("#FF0000")) );
498 this->m_ramCachedColour = QColor( cg.readEntry("colour_ram_cached", QString("#007800")) );
499 this->m_ramBuffersColour = QColor( cg.readEntry("colour_ram_buffers", QString("#FFFF00")) );
500 this->m_ramUsedColour = QColor( cg.readEntry("colour_ram_used", QString("#0000B1")) );
501 this->m_swapUsedColour = QColor( cg.readEntry("colour_swap_used", QString("#00CDCD")) );
503 this->setBackgroundHints(QFlag(cg.readEntry("background", (int)(TranslucentBackground))));
507 void systemMonitor::toolTipAboutToShow(){
509 Plasma::ToolTipManager::self()->setContent(this, Plasma::ToolTipContent("System Status:", QString("CPU usage: %1%<br>Ram Usage: %2%<br>Swap Usage: %3%").arg( round((1 - m_cpuInfo[0].idle) * 100)).arg( round((1 - m_ramfree / m_ramtotal) * 100)).arg( round((1 - m_swapfree / m_swaptotal) * 100 ))));
513 #include "system_monitor.moc"