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>
33 systemMonitor::systemMonitor(QObject
*parent
, const QVariantList
&args
)
34 : Plasma::Applet(parent
, args
),
45 setHasConfigurationInterface(true);
49 systemMonitor::~systemMonitor(){
51 if(hasFailedToLaunch()){
59 void systemMonitor::init(){
63 sys_mon
= dataEngine("systemmonitor");
64 connect(sys_mon
, SIGNAL(sourceAdded(const QString
&)), this, SLOT(sourcesAdded(const QString
&)));
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
);
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);
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);
174 case (int)NoBackground
:
175 uiGeneral
.kcmbBackground
->setCurrentIndex(2);
178 Q_ASSERT("Unknown background hints!");
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();
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){
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
;
341 void systemMonitor::paintCPUUsage(QPainter
*p
, const QStyleOptionGraphicsItem
*option
, const QRect
& contentsRect
, const cpuInfo
&cpu
){
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
));
380 void systemMonitor::paintSwapUsage(QPainter
*p
, const QStyleOptionGraphicsItem
*option
, const QRect
& contentsRect
){
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
));
398 void systemMonitor::paintRAMUsage(QPainter
*p
, const QStyleOptionGraphicsItem
*option
, const QRect
& contentsRect
){
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
));
430 void systemMonitor::paintFrontGlass(QPainter
* p
, const QStyleOptionGraphicsItem
*option
, const QRect
& contentsRect
) {
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));
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();
460 rotatedContentsRect
.setWidth(rotatedContentsRect
.width() * 0.325);
461 rotatedContentsRect
.moveLeft(rotatedContentsRect
.left() + origWidth
* 0.009);
463 rotatedContentsRect
.setWidth(rotatedContentsRect
.width() * 0.33);
466 paintCPUUsage(p
, option
, rotatedContentsRect
, m_cpuInfo
[0]);
468 paintFrontGlass(p
, option
, rotatedContentsRect
);
470 rotatedContentsRect
.moveLeft(rotatedContentsRect
.left() + 0.33*origWidth
);
472 paintRAMUsage(p
, option
, rotatedContentsRect
);
474 paintFrontGlass(p
, option
, rotatedContentsRect
);
476 rotatedContentsRect
.moveLeft(rotatedContentsRect
.left() + 0.33*origWidth
);
478 paintSwapUsage(p
, option
, rotatedContentsRect
);
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"