bugfix release 0.1.7
[qbat.git] / powermanager.cpp
blob8236f3b6c7a3e665c13d78bcfb2d014c4a293b98
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 bool energyUnits = false;
117 int relativeCapacity = 100;
119 if (m_Settings.mergeBatterys) {
120 int batteryCount = 0;
121 foreach(QString i, powerSupplies) {
122 string buffer = readStringSysFile(m_SysfsDir.filePath(i + "/type").toAscii().constData());
124 if ((!acPlug) && (buffer == "Mains")) {
125 if (1 == readIntSysFile(m_SysfsDir.filePath(i + "/online").toAscii().constData()))
126 acPlug = true;
128 else if (buffer == "Battery") {
129 energyUnits = m_SysfsDir.exists(i + UI_CAPTION_NOW(UI_CAPTION_ENERGY));
131 if (energyUnits) {
132 double voltage = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_VOLTAGE)).toAscii().constData()) / 1000000.0;
134 chargeFull += qRound(readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_FULL(UI_CAPTION_ENERGY)).toAscii().constData()) / voltage);
135 chargeFullDesign += qRound(readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_DESIGN(UI_CAPTION_ENERGY)).toAscii().constData()) / voltage);
136 chargeNow += qRound(readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_ENERGY)).toAscii().constData()) / voltage);
137 currentNow += qRound(readIntSysFile(m_SysfsDir.filePath(i + "/current_now").toAscii().constData()) / voltage);
139 else {
140 chargeFull += readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_FULL(UI_CAPTION_CHARGE)).toAscii().constData());
141 chargeFullDesign += readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_DESIGN(UI_CAPTION_CHARGE)).toAscii().constData());
142 chargeNow += readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_CHARGE)).toAscii().constData());
143 currentNow += readIntSysFile(m_SysfsDir.filePath(i + "/current_now").toAscii().constData());
146 int statusBuffer = toStatusInt(readStringSysFile(m_SysfsDir.filePath(i + "/status").toAscii().constData()));
148 if ((!status) || (statusBuffer != UI_BATTERY_FULL))
149 status = statusBuffer;
151 batteryCount++;
155 if (batteryCount) {
156 if (m_Settings.handleCritical)
157 relativeCapacity = (int)(100.0 * chargeNow / chargeFull);
159 chargeFull /= batteryCount;
160 chargeFullDesign /= batteryCount;
161 chargeNow /= batteryCount;
162 currentNow /= batteryCount;
164 if (!m_BatteryIcons.contains("merged")) {
165 if (!m_BatteryIcons.isEmpty()) {
166 foreach(CBatteryIcon * i, m_BatteryIcons) {
167 delete i;
170 m_BatteryIcons.clear();
173 CBatteryIcon * currentBatteryIcon = new CBatteryIcon("average", &m_Settings, &m_ContextMenu, this);
174 currentBatteryIcon->updateData(chargeFull, chargeFullDesign, chargeNow, currentNow, status, false);
175 m_BatteryIcons.insert("merged", currentBatteryIcon);
177 else
178 m_BatteryIcons["merged"]->updateData(chargeFull, chargeFullDesign, chargeNow, currentNow, status, false);
180 else {
181 delete m_BatteryIcons.take("merged");
184 else {
185 QList<CBatteryIcon *> newBatteryIcons;
186 CBatteryIcon * currentBatteryIcon;
188 int chargeNowMid = 0;
189 int chargeFullMid = 0;
191 foreach(QString i, powerSupplies) {
192 string buffer = readStringSysFile(m_SysfsDir.filePath(i + "/type").toAscii().constData());
194 if (buffer == "Mains") {
195 if (1 == readIntSysFile(m_SysfsDir.filePath(i + "/online").toAscii().constData()))
196 acPlug = true;
198 else if (buffer == "Battery") {
199 energyUnits = m_SysfsDir.exists(i + UI_CAPTION_NOW(UI_CAPTION_ENERGY));
201 if (energyUnits) {
202 chargeFull = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_FULL(UI_CAPTION_ENERGY)).toAscii().constData());
203 chargeFullDesign = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_DESIGN(UI_CAPTION_ENERGY)).toAscii().constData());
204 chargeNow = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_ENERGY)).toAscii().constData());
206 else {
207 chargeFull = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_FULL(UI_CAPTION_CHARGE)).toAscii().constData());
208 chargeFullDesign = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_DESIGN(UI_CAPTION_CHARGE)).toAscii().constData());
209 chargeNow = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_CHARGE)).toAscii().constData());
211 currentNow = readIntSysFile(m_SysfsDir.filePath(i + "/current_now").toAscii().constData());
212 status = toStatusInt(readStringSysFile(m_SysfsDir.filePath(i + "/status").toAscii().constData()));
214 chargeFullMid += chargeFull;
215 chargeNowMid += chargeNow;
217 if (!m_BatteryIcons.contains(i)) {
218 currentBatteryIcon = new CBatteryIcon(i, &m_Settings, &m_ContextMenu, this);
219 currentBatteryIcon->updateData(chargeFull, chargeFullDesign, chargeNow, currentNow, status, energyUnits);
221 else {
222 currentBatteryIcon = m_BatteryIcons.take(i);
223 currentBatteryIcon->updateData(chargeFull, chargeFullDesign, chargeNow, currentNow, status, energyUnits);
225 newBatteryIcons << currentBatteryIcon;
229 foreach(CBatteryIcon * i, m_BatteryIcons) {
230 delete i;
233 m_BatteryIcons.clear();
235 foreach(CBatteryIcon * i, newBatteryIcons)
236 m_BatteryIcons.insert(i->batteryName(), i);
238 if (!m_BatteryIcons.isEmpty())
239 relativeCapacity = (int)(100.0 * chargeNowMid / chargeFullMid);
243 if (acPlug)
244 m_DefaultTrayIcon.setToolTip("QBat - " + tr("AC adapter plugged in"));
245 else {
246 if (m_Settings.handleCritical) {
247 if ((relativeCapacity <= m_Settings.criticalCapacity) && (!m_CriticalHandled)) {
248 QString msgTitle = (m_Settings.executeCommand && m_Settings.confirmWithTimeout) ?
249 tr("QBat - critical battery capacity (will automatically choose ok on timeout)"):
250 tr("QBat - critical battery capacity");
251 QString msgText = (m_Settings.executeCommand && m_Settings.confirmCommand) ?
252 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) :
253 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.");
254 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))))
255 QProcess::startDetached(m_Settings.criticalCommand);
256 else {
257 if (m_Settings.showBalloon)
258 m_BatteryIcons.begin().value()->showMessage(msgTitle, msgText, QSystemTrayIcon::Warning, 7000);
259 else
260 QMessageBox::warning(NULL, msgTitle, msgText);
262 m_CriticalHandled = true;
264 else
265 m_CriticalHandled = false;
267 m_DefaultTrayIcon.setToolTip("QBat - " + tr("AC adapter unplugged"));
270 else
271 m_DefaultTrayIcon.setToolTip("QBat - " + tr("no information available"));
273 m_DefaultTrayIcon.setVisible(m_BatteryIcons.isEmpty());
276 void CPowerManager::restartTimer() {
277 killTimer(m_Timer);
278 m_Timer = startTimer(m_Settings.pollingRate);
281 void CPowerManager::showSettings() {
282 CSettings dialog;
283 connect(&dialog, SIGNAL(settingsChanged()), this, SLOT(updateData()));
284 connect(&dialog, SIGNAL(settingsChanged()), this, SLOT(restartTimer()));
286 dialog.execute(&m_Settings);
289 void CPowerManager::showAbout() {
290 if (m_Settings.showBalloon) {
291 if (m_DefaultTrayIcon.isVisible())
292 m_DefaultTrayIcon.showMessage(tr("About QBat"), UI_NAME + "\nv" + QString(UI_VERSION),
293 QSystemTrayIcon::Information, 4000);
294 else
295 m_BatteryIcons.begin().value()->showMessage(tr("About QBat"), UI_NAME + "\nv" + QString(UI_VERSION),
296 QSystemTrayIcon::Information, 4000);
298 else {
299 QMessageBox aboutBox;
301 aboutBox.setWindowIcon(QIcon(UI_ICON_QBAT));
302 aboutBox.setIconPixmap(QPixmap(UI_ICON_QBAT));
303 aboutBox.setWindowTitle(tr("About QBat"));
304 aboutBox.setText(UI_NAME + "\nv" + QString(UI_VERSION));
305 aboutBox.setStandardButtons(QMessageBox::Ok);
307 aboutBox.exec();