added QTimerMessageBox
[qbat.git] / powermanager.cpp
blobb69840d78fb703545f643f08a32ef5e7d3da6448
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"
14 namespace qbat {
15 using namespace std;
17 CPowerManager::CPowerManager(QObject * parent) :
18 QObject(parent),
19 m_CriticalHandled(false),
20 m_SysfsDir(UI_PATH_SYSFS_DIR),
21 m_SettingsFile(UI_FILE_CONFIG, QSettings::IniFormat, this),
22 m_DefaultTrayIcon(QIcon(UI_ICON_QBAT), this)
24 readSettings();
25 m_ContextMenu.addAction(tr("&Settings"), this, SLOT(showSettings()))->setEnabled(m_SysfsDir.exists());
26 m_ContextMenu.addAction(tr("&About"), this, SLOT(showAbout()));
27 m_ContextMenu.addSeparator();
28 m_ContextMenu.addAction(tr("&Quit"), qApp, SLOT(quit()));
30 m_DefaultTrayIcon.setContextMenu(&m_ContextMenu);
32 timerEvent(NULL);
33 if (m_SysfsDir.exists()) {
34 m_Timer = startTimer(m_Settings.pollingRate);
38 CPowerManager::~CPowerManager() {
39 killTimer(m_Timer);
40 writeSettings();
43 inline void CPowerManager::readSettings() {
44 m_SettingsFile.beginGroup("Main");
45 m_Settings.pollingRate = m_SettingsFile.value("pollingRate", 3000).toUInt();
46 m_Settings.showBalloon = m_SettingsFile.value("showBalloon", false).toBool();
47 m_SettingsFile.endGroup();
49 m_SettingsFile.beginGroup("TrayIcons");
50 m_Settings.mergeBatterys = m_SettingsFile.value("mergeBatterys", true).toBool();
51 m_Settings.colors[UI_COLOR_PEN] = m_SettingsFile.value("textColor", 0).toUInt();
52 m_Settings.colors[UI_COLOR_PEN_FULL] = m_SettingsFile.value("textFullColor", 0).toUInt();
53 m_Settings.colors[UI_COLOR_BRUSH_CHARGED] = m_SettingsFile.value("mainChargedColor", qRgb( 0, 255, 0)).toUInt();
54 m_Settings.colors[UI_COLOR_BRUSH_EMPTY] = m_SettingsFile.value("mainEmptyColor", qRgb(255, 255, 255)).toUInt();
55 m_Settings.colors[UI_COLOR_BRUSH_FULL] = m_SettingsFile.value("mainFullColor", m_Settings.colors[UI_COLOR_BRUSH_CHARGED]).toUInt();
56 m_Settings.colors[UI_COLOR_BRUSH_POLE] = m_SettingsFile.value("poleColor", qRgb(255, 255, 0)).toUInt();
57 m_Settings.colors[UI_COLOR_BRUSH_POLE_FULL] = m_SettingsFile.value("poleFullColor", m_Settings.colors[UI_COLOR_BRUSH_POLE]).toUInt();
58 m_SettingsFile.endGroup();
60 m_SettingsFile.beginGroup("CriticalEvent");
61 m_Settings.handleCritical = m_SettingsFile.value("handle", false).toBool();
62 m_Settings.criticalCapacity = m_SettingsFile.value("criticalCapacity", 7).toUInt();
63 m_Settings.executeCommand = m_SettingsFile.value("executeCommand", false).toBool();
64 m_Settings.criticalCommand = m_SettingsFile.value("command", "").toString();
65 m_SettingsFile.endGroup();
68 inline void CPowerManager::writeSettings() {
69 m_SettingsFile.beginGroup("Main");
70 m_SettingsFile.setValue("pollingRate", m_Settings.pollingRate);
71 m_SettingsFile.setValue("showBalloon", m_Settings.showBalloon);
72 m_SettingsFile.endGroup();
74 m_SettingsFile.beginGroup("TrayIcons");
75 m_SettingsFile.setValue("mergeBatterys", m_Settings.mergeBatterys);
76 m_SettingsFile.setValue("textColor", m_Settings.colors[UI_COLOR_PEN]);
77 m_SettingsFile.setValue("textFullColor", m_Settings.colors[UI_COLOR_PEN_FULL]);
78 m_SettingsFile.setValue("mainChargedColor", m_Settings.colors[UI_COLOR_BRUSH_CHARGED]);
79 m_SettingsFile.setValue("mainEmptyColor", m_Settings.colors[UI_COLOR_BRUSH_EMPTY]);
80 m_SettingsFile.setValue("mainFullColor", m_Settings.colors[UI_COLOR_BRUSH_FULL]);
81 m_SettingsFile.setValue("poleColor", m_Settings.colors[UI_COLOR_BRUSH_POLE]);
82 m_SettingsFile.setValue("poleFullColor", m_Settings.colors[UI_COLOR_BRUSH_POLE_FULL]);
83 m_SettingsFile.endGroup();
85 m_SettingsFile.beginGroup("CriticalEvent");
86 m_SettingsFile.setValue("handle", m_Settings.handleCritical);
87 m_SettingsFile.setValue("criticalCapacity", m_Settings.criticalCapacity);
88 m_SettingsFile.setValue("executeCommand", m_Settings.executeCommand);
89 m_SettingsFile.setValue("command", m_Settings.criticalCommand);
90 m_SettingsFile.endGroup();
93 void CPowerManager::timerEvent(QTimerEvent *) {
94 updateData();
97 void CPowerManager::updateData() {
98 if (m_SysfsDir.exists()) {
99 bool acPlug = false;
100 QStringList powerSupplies = m_SysfsDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
102 int chargeFull = 0;
103 int chargeFullDesign = 0;
104 int chargeNow = 0;
105 int currentNow = 0;
106 int status = 0;
108 bool energyUnits = false;
110 int relativeCapacity = 100;
112 if (m_Settings.mergeBatterys) {
113 int batteryCount = 0;
114 foreach(QString i, powerSupplies) {
115 string buffer = readStringSysFile(m_SysfsDir.filePath(i + "/type").toAscii().constData());
117 if ((!acPlug) && (buffer == "Mains")) {
118 if (1 == readIntSysFile(m_SysfsDir.filePath(i + "/online").toAscii().constData()))
119 acPlug = true;
121 else if (buffer == "Battery") {
122 energyUnits = m_SysfsDir.exists(i + UI_CAPTION_NOW(UI_CAPTION_ENERGY));
124 if (energyUnits) {
125 double voltage = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_VOLTAGE)).toAscii().constData()) / 1000000.0;
127 chargeFull += qRound(readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_FULL(UI_CAPTION_ENERGY)).toAscii().constData()) / voltage);
128 chargeFullDesign += qRound(readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_DESIGN(UI_CAPTION_ENERGY)).toAscii().constData()) / voltage);
129 chargeNow += qRound(readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_ENERGY)).toAscii().constData()) / voltage);
130 currentNow += qRound(readIntSysFile(m_SysfsDir.filePath(i + "/current_now").toAscii().constData()) / voltage);
132 else {
133 chargeFull += readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_FULL(UI_CAPTION_CURRENT)).toAscii().constData());
134 chargeFullDesign += readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_DESIGN(UI_CAPTION_CURRENT)).toAscii().constData());
135 chargeNow += readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_CURRENT)).toAscii().constData());
136 currentNow += readIntSysFile(m_SysfsDir.filePath(i + "/current_now").toAscii().constData());
139 int statusBuffer = toStatusInt(readStringSysFile(m_SysfsDir.filePath(i + "/status").toAscii().constData()));
141 if ((!status) || (statusBuffer != UI_BATTERY_FULL))
142 status = statusBuffer;
144 batteryCount++;
148 if (batteryCount) {
149 if (m_Settings.handleCritical)
150 relativeCapacity = (int)(100.0 * chargeNow / chargeFull);
152 chargeFull /= batteryCount;
153 chargeFullDesign /= batteryCount;
154 chargeNow /= batteryCount;
155 currentNow /= batteryCount;
157 if (!m_BatteryIcons.contains("merged")) {
158 if (!m_BatteryIcons.isEmpty()) {
159 foreach(CBatteryIcon * i, m_BatteryIcons) {
160 delete i;
163 m_BatteryIcons.clear();
166 CBatteryIcon * currentBatteryIcon = new CBatteryIcon("average", &m_Settings, &m_ContextMenu, this);
167 currentBatteryIcon->updateData(chargeFull, chargeFullDesign, chargeNow, currentNow, status, false);
168 m_BatteryIcons.insert("merged", currentBatteryIcon);
170 else
171 m_BatteryIcons["merged"]->updateData(chargeFull, chargeFullDesign, chargeNow, currentNow, status, false);
173 else {
174 delete m_BatteryIcons.take("merged");
177 else {
178 QList<CBatteryIcon *> newBatteryIcons;
179 CBatteryIcon * currentBatteryIcon;
181 int chargeNowMid = 0;
182 int chargeFullMid = 0;
184 foreach(QString i, powerSupplies) {
185 string buffer = readStringSysFile(m_SysfsDir.filePath(i + "/type").toAscii().constData());
187 if (buffer == "Mains") {
188 if (1 == readIntSysFile(m_SysfsDir.filePath(i + "/online").toAscii().constData()))
189 acPlug = true;
191 else if (buffer == "Battery") {
192 energyUnits = m_SysfsDir.exists(i + UI_CAPTION_NOW(UI_CAPTION_ENERGY));
194 if (energyUnits) {
195 chargeFull = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_FULL(UI_CAPTION_ENERGY)).toAscii().constData());
196 chargeFullDesign = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_DESIGN(UI_CAPTION_ENERGY)).toAscii().constData());
197 chargeNow = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_ENERGY)).toAscii().constData());
199 else {
200 chargeFull = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_FULL(UI_CAPTION_CURRENT)).toAscii().constData());
201 chargeFullDesign = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_DESIGN(UI_CAPTION_CURRENT)).toAscii().constData());
202 chargeNow = readIntSysFile(m_SysfsDir.filePath(i + UI_CAPTION_NOW(UI_CAPTION_CURRENT)).toAscii().constData());
204 currentNow = readIntSysFile(m_SysfsDir.filePath(i + "/current_now").toAscii().constData());
205 status = toStatusInt(readStringSysFile(m_SysfsDir.filePath(i + "/status").toAscii().constData()));
207 chargeFullMid += chargeFull;
208 chargeNowMid += chargeNow;
210 if (!m_BatteryIcons.contains(i)) {
211 currentBatteryIcon = new CBatteryIcon(i, &m_Settings, &m_ContextMenu, this);
212 currentBatteryIcon->updateData(chargeFull, chargeFullDesign, chargeNow, currentNow, status, energyUnits);
214 else {
215 currentBatteryIcon = m_BatteryIcons.take(i);
216 currentBatteryIcon->updateData(chargeFull, chargeFullDesign, chargeNow, currentNow, status, energyUnits);
218 newBatteryIcons << currentBatteryIcon;
222 foreach(CBatteryIcon * i, m_BatteryIcons) {
223 delete i;
226 m_BatteryIcons.clear();
228 foreach(CBatteryIcon * i, newBatteryIcons)
229 m_BatteryIcons.insert(i->batteryName(), i);
231 if (!m_BatteryIcons.isEmpty())
232 relativeCapacity = (int)(100.0 * chargeNowMid / chargeFullMid);
236 if (acPlug)
237 m_DefaultTrayIcon.setToolTip("QBat - " + tr("AC adapter plugged in"));
238 else {
239 if ((m_Settings.handleCritical) && (relativeCapacity <= m_Settings.criticalCapacity) && (!m_CriticalHandled)) {
240 if (m_Settings.executeCommand)
241 QProcess::startDetached(m_Settings.criticalCommand);
242 else {
243 if (m_Settings.showBalloon) {
244 m_BatteryIcons.begin().value()->showMessage(tr("QBat - critical battery capacity"),
245 tr("WARNING: The attached battery(s) reached the critical mark.\n Please make sure to save and shut down soon or provide another source of power."),
246 QSystemTrayIcon::Warning, 7000);
248 else
249 QMessageBox::warning(NULL, tr("QBat - critical battery capacity"),
250 tr("WARNING: The attached battery(s) reached the critical mark.\n Please make sure to save and shut down soon or provide another source of power."));
252 m_CriticalHandled = true;
254 m_DefaultTrayIcon.setToolTip("QBat - " + tr("AC adapter unplugged"));
257 else
258 m_DefaultTrayIcon.setToolTip("QBat - " + tr("no information available"));
260 m_DefaultTrayIcon.setVisible(m_BatteryIcons.isEmpty());
263 void CPowerManager::restartTimer() {
264 killTimer(m_Timer);
265 m_Timer = startTimer(m_Settings.pollingRate);
268 void CPowerManager::showSettings() {
269 CSettings dialog;
270 connect(&dialog, SIGNAL(settingsChanged()), this, SLOT(updateData()));
271 connect(&dialog, SIGNAL(settingsChanged()), this, SLOT(restartTimer()));
273 dialog.execute(&m_Settings);
276 void CPowerManager::showAbout() {
277 if (m_Settings.showBalloon) {
278 if (m_DefaultTrayIcon.isVisible())
279 m_DefaultTrayIcon.showMessage(tr("About QBat"), UI_NAME + "\nv" + QString(UI_VERSION),
280 QSystemTrayIcon::Information, 4000);
281 else
282 m_BatteryIcons.begin().value()->showMessage(tr("About QBat"), UI_NAME + "\nv" + QString(UI_VERSION),
283 QSystemTrayIcon::Information, 4000);
285 else {
286 QMessageBox aboutBox;
288 aboutBox.setWindowIcon(QIcon(UI_ICON_QBAT));
289 aboutBox.setIconPixmap(QPixmap(UI_ICON_QBAT));
290 aboutBox.setWindowTitle(tr("About QBat"));
291 aboutBox.setText(UI_NAME + "\nv" + QString(UI_VERSION));
292 aboutBox.setStandardButtons(QMessageBox::Ok);
294 aboutBox.exec();