current rate is now shown in watt and ampere and some bugfixes
[qbat.git] / powermanager.cpp
blobb8bc449eac208afbff90a8c9589a336758fc91de
1 //
2 // C++ Implementation: cpowermanager
3 //
4 // Author: Oliver Groß <z.o.gross@gmx.de>, (C) 2008
5 //
6 // Copyright: See COPYING file that comes with this distribution
7 //
8 #include <QtGui>
9 #include "powermanager.h"
10 #include "common.h"
11 #include "settings.h"
12 #include "batteryicon.h"
13 #include "qtimermessagebox.h"
15 namespace qbat {
16 using namespace std;
18 CPowerManager::CPowerManager(QObject * parent) :
19 QObject(parent),
20 m_CriticalHandled(false),
21 m_SysfsDir(UI_PATH_SYSFS_DIR),
22 m_SettingsFile(UI_FILE_CONFIG, QSettings::IniFormat, this),
23 m_DefaultTrayIcon(QIcon(UI_ICON_QBAT), this)
25 readSettings();
26 m_ContextMenu.addAction(tr("&Settings"), this, SLOT(showSettings()))->setEnabled(m_SysfsDir.exists());
27 m_ContextMenu.addAction(tr("&About"), this, SLOT(showAbout()));
28 m_ContextMenu.addSeparator();
29 m_ContextMenu.addAction(tr("&Quit"), qApp, SLOT(quit()));
31 m_DefaultTrayIcon.setContextMenu(&m_ContextMenu);
33 timerEvent(NULL);
34 if (m_SysfsDir.exists()) {
35 m_Timer = startTimer(m_Settings.pollingRate);
39 CPowerManager::~CPowerManager() {
40 killTimer(m_Timer);
41 writeSettings();
44 inline void CPowerManager::readSettings() {
45 m_SettingsFile.beginGroup("Main");
46 m_Settings.pollingRate = m_SettingsFile.value("pollingRate", 3000).toUInt();
47 m_Settings.showBalloon = m_SettingsFile.value("showBalloon", false).toBool();
48 m_SettingsFile.endGroup();
50 m_SettingsFile.beginGroup("TrayIcons");
51 m_Settings.mergeBatterys = m_SettingsFile.value("mergeBatterys", true).toBool();
52 m_Settings.colors[UI_COLOR_PEN] = m_SettingsFile.value("textColor", 0).toUInt();
53 m_Settings.colors[UI_COLOR_PEN_FULL] = m_SettingsFile.value("textFullColor", 0).toUInt();
54 m_Settings.colors[UI_COLOR_BRUSH_CHARGED] = m_SettingsFile.value("mainChargedColor", qRgb( 0, 255, 0)).toUInt();
55 m_Settings.colors[UI_COLOR_BRUSH_EMPTY] = m_SettingsFile.value("mainEmptyColor", qRgb(255, 255, 255)).toUInt();
56 m_Settings.colors[UI_COLOR_BRUSH_FULL] = m_SettingsFile.value("mainFullColor", m_Settings.colors[UI_COLOR_BRUSH_CHARGED]).toUInt();
57 m_Settings.colors[UI_COLOR_BRUSH_POLE] = m_SettingsFile.value("poleColor", qRgb(255, 255, 0)).toUInt();
58 m_Settings.colors[UI_COLOR_BRUSH_POLE_FULL] = m_SettingsFile.value("poleFullColor", m_Settings.colors[UI_COLOR_BRUSH_POLE]).toUInt();
59 m_SettingsFile.endGroup();
61 m_SettingsFile.beginGroup("CriticalEvent");
62 m_Settings.handleCritical = m_SettingsFile.value("handle", false).toBool();
63 m_Settings.criticalCapacity = m_SettingsFile.value("criticalCapacity", 7).toUInt();
64 m_Settings.executeCommand = m_SettingsFile.value("executeCommand", false).toBool();
65 m_Settings.criticalCommand = m_SettingsFile.value("command", "").toString();
66 m_Settings.confirmCommand = m_SettingsFile.value("confirmCommand", false).toBool();
67 m_Settings.confirmWithTimeout = m_SettingsFile.value("confirmWithTimeout", false).toBool();
68 m_Settings.timeoutValue = m_SettingsFile.value("timeoutValue", 5).toUInt();
69 m_SettingsFile.endGroup();
72 inline void CPowerManager::writeSettings() {
73 m_SettingsFile.beginGroup("Main");
74 m_SettingsFile.setValue("pollingRate", m_Settings.pollingRate);
75 m_SettingsFile.setValue("showBalloon", m_Settings.showBalloon);
76 m_SettingsFile.endGroup();
78 m_SettingsFile.beginGroup("TrayIcons");
79 m_SettingsFile.setValue("mergeBatterys", m_Settings.mergeBatterys);
80 m_SettingsFile.setValue("textColor", m_Settings.colors[UI_COLOR_PEN]);
81 m_SettingsFile.setValue("textFullColor", m_Settings.colors[UI_COLOR_PEN_FULL]);
82 m_SettingsFile.setValue("mainChargedColor", m_Settings.colors[UI_COLOR_BRUSH_CHARGED]);
83 m_SettingsFile.setValue("mainEmptyColor", m_Settings.colors[UI_COLOR_BRUSH_EMPTY]);
84 m_SettingsFile.setValue("mainFullColor", m_Settings.colors[UI_COLOR_BRUSH_FULL]);
85 m_SettingsFile.setValue("poleColor", m_Settings.colors[UI_COLOR_BRUSH_POLE]);
86 m_SettingsFile.setValue("poleFullColor", m_Settings.colors[UI_COLOR_BRUSH_POLE_FULL]);
87 m_SettingsFile.endGroup();
89 m_SettingsFile.beginGroup("CriticalEvent");
90 m_SettingsFile.setValue("handle", m_Settings.handleCritical);
91 m_SettingsFile.setValue("criticalCapacity", m_Settings.criticalCapacity);
92 m_SettingsFile.setValue("executeCommand", m_Settings.executeCommand);
93 m_SettingsFile.setValue("command", m_Settings.criticalCommand);
94 m_SettingsFile.setValue("confirmCommand", m_Settings.confirmCommand);
95 m_SettingsFile.setValue("confirmWithTimeout", m_Settings.confirmWithTimeout);
96 m_SettingsFile.setValue("timeoutValue", m_Settings.timeoutValue);
97 m_SettingsFile.endGroup();
100 void CPowerManager::timerEvent(QTimerEvent *) {
101 updateData();
104 void CPowerManager::updateData() {
105 if (m_SysfsDir.exists()) {
106 bool acPlug = false;
107 QStringList powerSupplies = m_SysfsDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
109 int chargeFull = 0;
110 int chargeFullDesign = 0;
111 int chargeNow = 0;
112 int currentNow = 0;
113 int status = 0;
115 int voltage = 0;
117 bool energyUnits = false;
119 int relativeCapacity = 100;
121 if (m_Settings.mergeBatterys) {
122 int batteryCount = 0;
123 int voltageBuffer;
124 foreach(QString i, powerSupplies) {
125 string buffer = readStringSysFile(m_SysfsDir.filePath(i + "/type").toAscii().constData());
127 if ((!acPlug) && (buffer == "Mains")) {
128 if (1 == readIntSysFile(m_SysfsDir.filePath(i + "/online").toAscii().constData()))
129 acPlug = true;
131 else if (buffer == "Battery") {
132 energyUnits = m_SysfsDir.exists(i + UI_CAPTION_NOW(UI_CAPTION_ENERGY));
134 voltageBuffer = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_VOLTAGE)).toAscii().constData()) / 10000;
135 if (energyUnits) {
136 double voltageNorm = voltageBuffer / 100.0;
138 chargeFull += qRound(readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_FULL(UI_CAPTION_ENERGY)).toAscii().constData()) / voltageNorm);
139 chargeFullDesign += qRound(readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_DESIGN(UI_CAPTION_ENERGY)).toAscii().constData()) / voltageNorm);
140 chargeNow += qRound(readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_ENERGY)).toAscii().constData()) / voltageNorm);
141 currentNow += qRound(readIntSysFile(m_SysfsDir.filePath(i + "/current_now").toAscii().constData()) / voltageNorm);
143 else {
144 chargeFull += readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_FULL(UI_CAPTION_CHARGE)).toAscii().constData());
145 chargeFullDesign += readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_DESIGN(UI_CAPTION_CHARGE)).toAscii().constData());
146 chargeNow += readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_CHARGE)).toAscii().constData());
147 currentNow += readIntSysFile(m_SysfsDir.filePath(i + "/current_now").toAscii().constData());
149 voltage += voltageBuffer;
151 int statusBuffer = toStatusInt(readStringSysFile(m_SysfsDir.filePath(i + "/status").toAscii().constData()));
153 if ((!status) || (statusBuffer != UI_BATTERY_FULL))
154 status = statusBuffer;
156 batteryCount++;
160 if (batteryCount) {
161 if (m_Settings.handleCritical)
162 relativeCapacity = (int)(100.0 * chargeNow / chargeFull);
164 chargeFull /= batteryCount;
165 chargeFullDesign /= batteryCount;
166 chargeNow /= batteryCount;
167 currentNow /= batteryCount;
168 voltage /= batteryCount;
170 if (!m_BatteryIcons.contains("merged")) {
171 if (!m_BatteryIcons.isEmpty()) {
172 foreach(CBatteryIcon * i, m_BatteryIcons)
173 delete i;
175 m_BatteryIcons.clear();
178 CBatteryIcon * currentBatteryIcon = new CBatteryIcon("average", &m_Settings, &m_ContextMenu, this);
179 currentBatteryIcon->updateData(chargeFull, chargeFullDesign, chargeNow, currentNow, voltage, status, false);
180 m_BatteryIcons.insert("merged", currentBatteryIcon);
182 else
183 m_BatteryIcons["merged"]->updateData(chargeFull, chargeFullDesign, chargeNow, currentNow, voltage, status, false);
185 else {
186 delete m_BatteryIcons.take("merged");
189 else {
190 QList<CBatteryIcon *> newBatteryIcons;
191 CBatteryIcon * currentBatteryIcon;
193 int chargeNowMid = 0;
194 int chargeFullMid = 0;
196 foreach(QString i, powerSupplies) {
197 string buffer = readStringSysFile(m_SysfsDir.filePath(i + "/type").toAscii().constData());
199 if (buffer == "Mains") {
200 if (1 == readIntSysFile(m_SysfsDir.filePath(i + "/online").toAscii().constData()))
201 acPlug = true;
203 else if (buffer == "Battery") {
204 energyUnits = m_SysfsDir.exists(i + UI_CAPTION_NOW(UI_CAPTION_ENERGY));
206 if (energyUnits) {
207 chargeFull = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_FULL(UI_CAPTION_ENERGY)).toAscii().constData());
208 chargeFullDesign = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_DESIGN(UI_CAPTION_ENERGY)).toAscii().constData());
209 chargeNow = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_ENERGY)).toAscii().constData());
211 else {
212 chargeFull = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_FULL(UI_CAPTION_CHARGE)).toAscii().constData());
213 chargeFullDesign = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_DESIGN(UI_CAPTION_CHARGE)).toAscii().constData());
214 chargeNow = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_CHARGE)).toAscii().constData());
216 currentNow = readIntSysFile(m_SysfsDir.filePath(i + "/current_now").toAscii().constData());
217 voltage = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_VOLTAGE)).toAscii().constData()) / 10000;
218 status = toStatusInt(readStringSysFile(m_SysfsDir.filePath(i + "/status").toAscii().constData()));
220 chargeFullMid += chargeFull;
221 chargeNowMid += chargeNow;
223 if (m_BatteryIcons.contains(i)) {
224 currentBatteryIcon = m_BatteryIcons.take(i);
225 currentBatteryIcon->updateData(chargeFull, chargeFullDesign, chargeNow, currentNow, voltage, status, energyUnits);
227 else {
228 currentBatteryIcon = new CBatteryIcon(i, &m_Settings, &m_ContextMenu, this);
229 currentBatteryIcon->updateData(chargeFull, chargeFullDesign, chargeNow, currentNow, voltage, status, energyUnits);
230 m_CriticalHandled = false;
232 newBatteryIcons << currentBatteryIcon;
236 foreach(CBatteryIcon * i, m_BatteryIcons) {
237 delete i;
240 m_BatteryIcons.clear();
242 foreach(CBatteryIcon * i, newBatteryIcons)
243 m_BatteryIcons.insert(i->batteryName(), i);
245 if (!m_BatteryIcons.isEmpty())
246 relativeCapacity = (int)(100.0 * chargeNowMid / chargeFullMid);
249 if (acPlug) {
250 m_DefaultTrayIcon.setToolTip("QBat - " + tr("AC adapter plugged in"));
251 m_CriticalHandled = false;
253 else {
254 if (m_Settings.handleCritical) {
255 if ((relativeCapacity <= m_Settings.criticalCapacity) && (!m_CriticalHandled)) {
256 QString msgTitle = (m_Settings.executeCommand && m_Settings.confirmWithTimeout) ?
257 tr("QBat - critical battery capacity (will automatically choose ok on timeout)"):
258 tr("QBat - critical battery capacity");
259 QString msgText = (m_Settings.executeCommand && m_Settings.confirmCommand) ?
260 tr("WARNING: The attached battery(s) reached the critical mark.\nClick cancel and please make sure to save and shut down soon or provide another source of power\nor:\nClick ok to execute:\n%1").arg(m_Settings.criticalCommand) :
261 tr("WARNING: The attached battery(s) reached the critical mark.\nPlease make sure to save and shut down soon or provide another source of power.");
262 if (m_Settings.executeCommand && (!m_Settings.confirmCommand || ((m_Settings.confirmWithTimeout) ? QTimerMessageBox::warning(NULL, msgTitle, msgText, m_Settings.timeoutValue, QMessageBox::Ok | QMessageBox::Cancel) : QMessageBox::warning(NULL, msgTitle, msgText, QMessageBox::Ok | QMessageBox::Cancel))))
263 QProcess::startDetached(m_Settings.criticalCommand);
264 else {
265 if (m_Settings.showBalloon)
266 m_BatteryIcons.begin().value()->showMessage(msgTitle, msgText, QSystemTrayIcon::Warning, 7000);
267 else
268 QMessageBox::warning(NULL, msgTitle, msgText);
270 m_CriticalHandled = true;
272 else
273 m_CriticalHandled = false;
275 m_DefaultTrayIcon.setToolTip("QBat - " + tr("AC adapter unplugged"));
278 else
279 m_DefaultTrayIcon.setToolTip("QBat - " + tr("no information available"));
281 m_DefaultTrayIcon.setVisible(m_BatteryIcons.isEmpty());
284 void CPowerManager::restartTimer() {
285 killTimer(m_Timer);
286 m_Timer = startTimer(m_Settings.pollingRate);
289 void CPowerManager::showSettings() {
290 CSettings dialog;
292 if (dialog.execute(&m_Settings)) {
293 foreach(CBatteryIcon * i, m_BatteryIcons) {
294 delete i;
297 m_BatteryIcons.clear();
299 updateData();
300 restartTimer();
304 void CPowerManager::showAbout() {
305 if (m_Settings.showBalloon) {
306 if (m_DefaultTrayIcon.isVisible())
307 m_DefaultTrayIcon.showMessage(tr("About QBat"), UI_NAME + "\nv" + QString(UI_VERSION),
308 QSystemTrayIcon::Information, 4000);
309 else
310 m_BatteryIcons.begin().value()->showMessage(tr("About QBat"), UI_NAME + "\nv" + QString(UI_VERSION),
311 QSystemTrayIcon::Information, 4000);
313 else {
314 QMessageBox aboutBox;
316 aboutBox.setWindowIcon(QIcon(UI_ICON_QBAT));
317 aboutBox.setIconPixmap(QPixmap(UI_ICON_QBAT));
318 aboutBox.setWindowTitle(tr("About QBat"));
319 aboutBox.setText(UI_NAME + "\nv" + QString(UI_VERSION));
320 aboutBox.setStandardButtons(QMessageBox::Ok);
322 aboutBox.exec();