added dis-/charging colors
[qbat.git] / powermanager.cpp
blobb09a2aa371152604506c3844406070daac11ba31
1 //
2 // C++ Implementation: powermanager
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_Timer(-1),
21 m_DataTimer(-1),
22 // m_RelativeCapacity(100),
23 m_ACPlug(false),
24 m_CriticalHandled(false),
25 m_SettingsFile(UI_FILE_CONFIG, QSettings::IniFormat, this)
27 readSettings();
28 m_ContextMenu.addAction(tr("&Settings"), this, SLOT(showSettings()))->setEnabled(CBatteryIcon::sysfsDir.exists());
29 m_ContextMenu.addAction(tr("&About"), this, SLOT(showAbout()));
30 m_ContextMenu.addSeparator();
31 m_ContextMenu.addAction(tr("&Quit"), qApp, SLOT(quit()));
33 m_DefaultIcon = new CBatteryIcon(&m_Settings, tr("merged"), this);
34 m_DefaultIcon->setContextMenu(&m_ContextMenu);
36 if (CBatteryIcon::sysfsDir.exists()) {
37 m_DataTimer = startTimer(15000);
38 m_Timer = startTimer(m_Settings.pollingRate);
40 updateSupplies();
43 CPowerManager::~CPowerManager() {
44 killTimer(m_Timer);
45 killTimer(m_DataTimer);
46 writeSettings();
49 inline void CPowerManager::readSettings() {
50 m_SettingsFile.beginGroup("Main");
51 m_Settings.pollingRate = m_SettingsFile.value("pollingRate", 3000).toUInt();
52 m_Settings.showBalloon = m_SettingsFile.value("showBalloon", false).toBool();
53 m_SettingsFile.endGroup();
55 m_SettingsFile.beginGroup("TrayIcons");
56 m_Settings.mergeBatteries = m_SettingsFile.value("mergeBatteries", false).toBool();
57 m_Settings.colors[UI_COLOR_PEN_CHARGE] = m_SettingsFile.value("textChargingColor", 0).toUInt();
58 m_Settings.colors[UI_COLOR_PEN_DISCHARGE] = m_SettingsFile.value("textDischargingColor", 0).toUInt();
59 m_Settings.colors[UI_COLOR_PEN_FULL] = m_SettingsFile.value("textFullColor", 0).toUInt();
60 m_Settings.colors[UI_COLOR_BRUSH_CHARGED] = m_SettingsFile.value("mainChargedColor", qRgb( 0, 255, 0)).toUInt();
61 m_Settings.colors[UI_COLOR_BRUSH_EMPTY] = m_SettingsFile.value("mainEmptyColor", qRgb(255, 255, 255)).toUInt();
62 m_Settings.colors[UI_COLOR_BRUSH_FULL] = m_SettingsFile.value("mainFullColor", m_Settings.colors[UI_COLOR_BRUSH_CHARGED]).toUInt();
63 m_Settings.colors[UI_COLOR_BRUSH_POLE_CHARGE] = m_SettingsFile.value("poleChargingColor", qRgb(255, 255, 0)).toUInt();
64 m_Settings.colors[UI_COLOR_BRUSH_POLE_DISCHARGE] = m_SettingsFile.value("poleDischargingColor", qRgb(255, 255, 0)).toUInt();
65 m_Settings.colors[UI_COLOR_BRUSH_POLE_FULL] = m_SettingsFile.value("poleFullColor", m_Settings.colors[UI_COLOR_BRUSH_POLE_CHARGE]).toUInt();
66 m_SettingsFile.endGroup();
68 m_SettingsFile.beginGroup("CriticalEvent");
69 m_Settings.handleCritical = m_SettingsFile.value("handle", false).toBool();
70 m_Settings.criticalCapacity = m_SettingsFile.value("criticalCapacity", 7).toUInt();
71 m_Settings.executeCommand = m_SettingsFile.value("executeCommand", false).toBool();
72 m_Settings.criticalCommand = m_SettingsFile.value("command", "").toString();
73 m_Settings.confirmCommand = m_SettingsFile.value("confirmCommand", false).toBool();
74 m_Settings.confirmWithTimeout = m_SettingsFile.value("confirmWithTimeout", false).toBool();
75 m_Settings.timeoutValue = m_SettingsFile.value("timeoutValue", 5).toUInt();
76 m_SettingsFile.endGroup();
79 inline void CPowerManager::writeSettings() {
80 m_SettingsFile.beginGroup("Main");
81 m_SettingsFile.setValue("pollingRate", m_Settings.pollingRate);
82 m_SettingsFile.setValue("showBalloon", m_Settings.showBalloon);
83 m_SettingsFile.endGroup();
85 m_SettingsFile.beginGroup("TrayIcons");
86 m_SettingsFile.setValue("mergeBatteries", m_Settings.mergeBatteries);
87 m_SettingsFile.setValue("textChargingColor", m_Settings.colors[UI_COLOR_PEN_CHARGE]);
88 m_SettingsFile.setValue("textDischargingColor", m_Settings.colors[UI_COLOR_PEN_DISCHARGE]);
89 m_SettingsFile.setValue("textFullColor", m_Settings.colors[UI_COLOR_PEN_FULL]);
90 m_SettingsFile.setValue("mainChargedColor", m_Settings.colors[UI_COLOR_BRUSH_CHARGED]);
91 m_SettingsFile.setValue("mainEmptyColor", m_Settings.colors[UI_COLOR_BRUSH_EMPTY]);
92 m_SettingsFile.setValue("mainFullColor", m_Settings.colors[UI_COLOR_BRUSH_FULL]);
93 m_SettingsFile.setValue("poleChargingColor", m_Settings.colors[UI_COLOR_BRUSH_POLE_CHARGE]);
94 m_SettingsFile.setValue("poleDischargingColor", m_Settings.colors[UI_COLOR_BRUSH_POLE_DISCHARGE]);
95 m_SettingsFile.setValue("poleFullColor", m_Settings.colors[UI_COLOR_BRUSH_POLE_FULL]);
96 m_SettingsFile.endGroup();
98 m_SettingsFile.beginGroup("CriticalEvent");
99 m_SettingsFile.setValue("handle", m_Settings.handleCritical);
100 m_SettingsFile.setValue("criticalCapacity", m_Settings.criticalCapacity);
101 m_SettingsFile.setValue("executeCommand", m_Settings.executeCommand);
102 m_SettingsFile.setValue("command", m_Settings.criticalCommand);
103 m_SettingsFile.setValue("confirmCommand", m_Settings.confirmCommand);
104 m_SettingsFile.setValue("confirmWithTimeout", m_Settings.confirmWithTimeout);
105 m_SettingsFile.setValue("timeoutValue", m_Settings.timeoutValue);
106 m_SettingsFile.endGroup();
109 void CPowerManager::timerEvent(QTimerEvent * event) {
110 if (event->timerId() == m_Timer)
111 updateSupplies();
112 else if (event->timerId() == m_DataTimer)
113 updateBatteryData();
116 void CPowerManager::updateSupplies() {
117 if (CBatteryIcon::sysfsDir.exists()) {
118 bool oldAC = m_ACPlug;
119 m_ACPlug = false;
121 QStringList powerSupplies = CBatteryIcon::sysfsDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
123 QList<CBatteryIcon *> newBatteryIcons;
124 CBatteryIcon * currentBatteryIcon;
126 foreach(QString i, powerSupplies) {
127 // this is possibly not very reliable
128 if (CBatteryIcon::sysfsDir.exists(i + "/online")) {
129 if (readIntSysFile(CBatteryIcon::sysfsDir.filePath(i + "/online").toAscii().constData()) == 1) {
130 m_ACPlug = true;
131 m_CriticalHandled = false;
134 else {
135 if (m_BatteryIcons.contains(i)) {
136 currentBatteryIcon = m_BatteryIcons.take(i);
138 else {
139 // qDebug("new battery: %s", i.toAscii().constData());
140 currentBatteryIcon = new CBatteryIcon(&m_Settings, i, this);
141 currentBatteryIcon->setContextMenu(&m_ContextMenu);
142 currentBatteryIcon->updateData();
143 currentBatteryIcon->updateIcon();
144 currentBatteryIcon->updateToolTip();
146 if (!m_Settings.mergeBatteries)
147 currentBatteryIcon->show();
149 m_CriticalHandled = false;
151 newBatteryIcons << currentBatteryIcon;
155 foreach(CBatteryIcon * i, m_BatteryIcons)
156 delete i;
158 m_BatteryIcons.clear();
160 foreach(CBatteryIcon * i, newBatteryIcons)
161 m_BatteryIcons.insert(i->data().name, i);
163 if (oldAC != m_ACPlug)
164 updateBatteryData();
165 else
166 updateMergedData();
168 if (m_BatteryIcons.isEmpty()) {
169 if (!m_DefaultIcon->isVisible()) {
170 m_DefaultIcon->setVisible(true);
171 m_DefaultIcon->setIcon(QIcon(UI_ICON_QBAT_SMALL));
173 if (m_ACPlug)
174 m_DefaultIcon->setMessage(tr("AC adapter plugged in"));
175 else
176 m_DefaultIcon->setMessage(tr("AC adapter unplugged"));
179 else {
180 if (!m_DefaultIcon->isVisible()) {
181 m_DefaultIcon->updateData();
182 m_DefaultIcon->updateIcon();
184 m_DefaultIcon->setVisible(m_Settings.mergeBatteries);
187 checkCritical();
189 else {
190 m_DefaultIcon->setMessage(tr("no information available"));
191 m_DefaultIcon->setVisible(true);
196 void CPowerManager::updateMergedData() {
197 if (!m_BatteryIcons.isEmpty()) {
198 int fullCount = 0;
199 int rateCount = 0;
200 int voltageCount = 0;
202 int fullCapacity = 0;
203 int currentCapacity = 0;
204 int rate = 0;
205 int voltage = 0;
206 int status = 0;
208 foreach (CBatteryIcon * battery, m_BatteryIcons) {
209 if (battery->data().voltage) {
210 voltage += battery->data().voltage;
211 voltageCount++;
214 if (!battery->data().energyUnits) {
215 currentCapacity += battery->data().currentCapacity;
217 if (battery->data().fullCapacity) {
218 fullCapacity += battery->data().fullCapacity;
219 fullCount++;
222 if (battery->data().rate) {
223 rate += battery->data().rate;
224 rateCount++;
227 else if (battery->data().voltage) {
228 double voltageNorm = battery->data().voltage / 100.0;
229 currentCapacity += qRound(battery->data().currentCapacity / voltageNorm);
231 if (battery->data().fullCapacity) {
232 fullCapacity += qRound(battery->data().fullCapacity / voltageNorm);
233 fullCount++;
236 if (battery->data().rate) {
237 rate += qRound(battery->data().rate / voltageNorm);
238 rateCount++;
242 if ((!status) || (battery->data().status != UI_BATTERY_FULL))
243 status = battery->data().status;
246 if (fullCount)
247 fullCapacity /= fullCount;
249 if (rateCount)
250 rate /= rateCount;
252 if (voltageCount)
253 voltage /= voltageCount;
255 currentCapacity /= m_BatteryIcons.count();
257 m_DefaultIcon->updateData(currentCapacity, fullCapacity, 0, rate, voltage, status, false);
261 void CPowerManager::checkCritical() {
262 if (m_ACPlug || m_CriticalHandled ||
263 m_DefaultIcon->data().relativeCharge == -1 || !m_Settings.handleCritical ||
264 m_DefaultIcon->data().relativeCharge > m_Settings.criticalCapacity)
265 return;
267 QString msgTitle = (m_Settings.executeCommand && m_Settings.confirmWithTimeout) ?
268 tr("QBat - critical battery capacity (will automatically choose ok on timeout)"):
269 tr("QBat - critical battery capacity");
270 QString msgText = (m_Settings.executeCommand && m_Settings.confirmCommand) ?
271 tr("WARNING: The attached battery(s) reached the critical mark.\n"
272 "Click cancel and please make sure to save and shut down soon or provide another source of power\n"
273 "or:\n"
274 "Click ok to execute:\n%1").arg(m_Settings.criticalCommand) :
275 tr("WARNING: The attached battery(s) reached the critical mark.\n"
276 "Please make sure to save and shut down soon or provide another source of power.");
277 if (m_Settings.executeCommand && (!m_Settings.confirmCommand || (QTimerMessageBox::warning(NULL, msgTitle, msgText,
278 (m_Settings.confirmWithTimeout) ? m_Settings.timeoutValue : -1, QMessageBox::Ok | QMessageBox::Cancel))))
279 QProcess::startDetached(m_Settings.criticalCommand);
280 else {
281 if (m_Settings.showBalloon)
282 m_BatteryIcons.begin().value()->showMessage(msgTitle, msgText, QSystemTrayIcon::Warning, 7000);
283 else
284 QMessageBox::warning(NULL, msgTitle, msgText);
286 m_CriticalHandled = true;
289 void CPowerManager::updateBatteryData() {
290 foreach (CBatteryIcon * battery, m_BatteryIcons)
291 battery->updateData();
293 updateMergedData();
294 checkCritical();
297 void CPowerManager::restartTimer() {
298 killTimer(m_Timer);
299 m_Timer = startTimer(m_Settings.pollingRate);
300 killTimer(m_DataTimer);
301 m_DataTimer = startTimer(15000);
304 void CPowerManager::showSettings() {
305 CSettings dialog;
307 if (dialog.execute(&m_Settings)) {
308 foreach (CBatteryIcon * i, m_BatteryIcons) {
309 delete i;
312 m_BatteryIcons.clear();
313 m_DefaultIcon->updateData(0, 0, 0, 0, 0, 0, false);
315 updateSupplies();
316 restartTimer();
320 void CPowerManager::showAbout() {
321 if (m_Settings.showBalloon) {
322 if (m_DefaultIcon->isVisible())
323 m_DefaultIcon->showMessage(tr("About QBat"), UI_NAME + "\nv" + QString(UI_VERSION),
324 QSystemTrayIcon::Information, 4000);
325 else
326 m_BatteryIcons.begin().value()->showMessage(tr("About QBat"), UI_NAME + "\nv" + QString(UI_VERSION),
327 QSystemTrayIcon::Information, 4000);
329 else {
330 QMessageBox aboutBox;
332 aboutBox.setWindowIcon(QIcon(UI_ICON_QBAT_SMALL));
333 aboutBox.setIconPixmap(QPixmap(UI_ICON_QBAT_LARGE));
334 aboutBox.setWindowTitle(tr("About QBat"));
335 aboutBox.setText(UI_NAME + "\nv" + QString(UI_VERSION));
336 aboutBox.setStandardButtons(QMessageBox::Ok);
338 aboutBox.exec();