Implement notifications and sounds using the daemon

This commit is contained in:
Matti Viljanen 2020-04-26 18:20:28 +03:00
parent d1139f4754
commit 30653a1c11
No known key found for this signature in database
GPG key ID: CF32A1495158F888
16 changed files with 375 additions and 173 deletions

View file

@ -43,7 +43,10 @@ Settings::Settings(QObject *parent) : QObject(parent)
loadInteger(sNotificationsEnabled, &notificationsEnabled, 0, 1); loadInteger(sNotificationsEnabled, &notificationsEnabled, 0, 1);
loadInteger(sLowLimit, &lowLimit, 20, 94); loadInteger(sLowLimit, &lowLimit, 20, 94);
loadInteger(sHighLimit, &highLimit, 21, 95); loadInteger(sHighLimit, &highLimit, 21, 95);
qInfo() << "Loaded" << sLimitEnabled << limitEnabled;
notificationTitle = tr("Battery charge %1%");
notificationLowText = tr("Please connect the charger.");
notificationHighText = tr("Please disconnect the charger.");
} }
Settings::~Settings() Settings::~Settings()
@ -55,45 +58,26 @@ Settings::~Settings()
saveInteger(sNotificationsEnabled, &notificationsEnabled); saveInteger(sNotificationsEnabled, &notificationsEnabled);
saveInteger(sLowLimit, &lowLimit); saveInteger(sLowLimit, &lowLimit);
saveInteger(sHighLimit, &highLimit); saveInteger(sHighLimit, &highLimit);
mySettings->setValue(sNotificationTitle, notificationTitle);
mySettings->setValue(sNotificationLowText, notificationLowText);
mySettings->setValue(sNotificationHighText, notificationHighText);
mySettings->sync(); mySettings->sync();
qInfo() << "Settings saved:" << (mySettings->status() == QSettings::NoError); qInfo() << "Settings saved:" << (mySettings->status() == QSettings::NoError);
} }
int Settings::getLowAlert() { // Getters condensed.
return lowAlert; int Settings::getLowAlert() { return lowAlert; }
} int Settings::getHighAlert() { return highAlert; }
int Settings::getInterval() { return interval; }
int Settings::getHighAlert() { int Settings::getLowLimit() { return lowLimit; }
return highAlert; int Settings::getHighLimit() { return highLimit; }
} bool Settings::getLimitEnabled() { return limitEnabled == 1; }
bool Settings::getNotificationsEnabled() { return notificationsEnabled == 1; }
int Settings::getInterval() { QString Settings::getLowAlertFile() { return lowAlertFile; }
return interval; QString Settings::getHighAlertFile() { return highAlertFile; }
} QString Settings::getNotificationTitle() { return notificationTitle; }
QString Settings::getNotificationLowText() { return notificationLowText; }
int Settings::getLowLimit() { QString Settings::getNotificationHighText() { return notificationHighText; }
return lowLimit;
}
int Settings::getHighLimit() {
return highLimit;
}
bool Settings::getLimitEnabled() {
return limitEnabled == 1;
}
bool Settings::getNotificationsEnabled() {
return notificationsEnabled == 1;
}
QString Settings::getLowAlertFile() {
return lowAlertFile;
}
QString Settings::getHighAlertFile() {
return highAlertFile;
}
void Settings::setLowAlert(int newLimit) { void Settings::setLowAlert(int newLimit) {
lowAlert = newLimit; lowAlert = newLimit;
@ -151,6 +135,29 @@ void Settings::setNotificationsEnabled(bool newEnabled) {
qDebug() << "Change" << sNotificationsEnabled << newEnabled; qDebug() << "Change" << sNotificationsEnabled << newEnabled;
} }
void Settings::setNotificationTitle(QString newText) {
notificationTitle = newText;
mySettings->setValue(sNotificationTitle, notificationTitle);
mySettings->sync();
emit notificationTitleChanged(notificationTitle);
qDebug() << sNotificationTitle << notificationTitle;
}
void Settings::setNotificationLowText(QString newText) {
notificationLowText = newText;
mySettings->setValue(sNotificationLowText, notificationLowText);
mySettings->sync();
emit notificationLowTextChanged(notificationLowText);
qDebug() << sNotificationLowText << notificationLowText;
}
void Settings::setNotificationHighText(QString newText) {
notificationHighText = newText;
mySettings->setValue(sNotificationHighText, notificationHighText);
mySettings->sync();
emit notificationHighTextChanged(notificationHighText);
qDebug() << sNotificationHighText << notificationHighText;
}
int Settings::bound(int value, int min, int max) { int Settings::bound(int value, int min, int max) {
return (value <= min ? min : (value >= max ? max : value)); return (value <= min ? min : (value >= max ? max : value));

View file

@ -34,6 +34,9 @@ class Settings : public QObject
Q_PROPERTY(bool notificationsEnabled READ getNotificationsEnabled WRITE setNotificationsEnabled NOTIFY notificationsEnabledChanged) Q_PROPERTY(bool notificationsEnabled READ getNotificationsEnabled WRITE setNotificationsEnabled NOTIFY notificationsEnabledChanged)
Q_PROPERTY(QString lowAlertFile READ getLowAlertFile NOTIFY lowAlertFileChanged) Q_PROPERTY(QString lowAlertFile READ getLowAlertFile NOTIFY lowAlertFileChanged)
Q_PROPERTY(QString highAlertFile READ getHighAlertFile NOTIFY highAlertFileChanged) Q_PROPERTY(QString highAlertFile READ getHighAlertFile NOTIFY highAlertFileChanged)
Q_PROPERTY(QString notificationTitle READ getNotificationTitle WRITE setNotificationTitle NOTIFY notificationTitleChanged)
Q_PROPERTY(QString notificationLowText READ getNotificationLowText WRITE setNotificationLowText NOTIFY notificationLowTextChanged)
Q_PROPERTY(QString notificationHighText READ getNotificationHighText WRITE setNotificationHighText NOTIFY notificationHighTextChanged)
public: public:
Settings(QObject* parent = nullptr); Settings(QObject* parent = nullptr);
@ -48,6 +51,9 @@ public:
bool getNotificationsEnabled(); bool getNotificationsEnabled();
QString getLowAlertFile(); QString getLowAlertFile();
QString getHighAlertFile(); QString getHighAlertFile();
QString getNotificationTitle();
QString getNotificationLowText();
QString getNotificationHighText();
void setLowAlert(int newLimit); void setLowAlert(int newLimit);
void setHighAlert(int newLimit); void setHighAlert(int newLimit);
@ -56,7 +62,9 @@ public:
void setHighLimit(int newLimit); void setHighLimit(int newLimit);
void setLimitEnabled(bool newEnabled); void setLimitEnabled(bool newEnabled);
void setNotificationsEnabled(bool newEnabled); void setNotificationsEnabled(bool newEnabled);
void setNotificationTitle(QString newText);
void setNotificationLowText(QString newText);
void setNotificationHighText(QString newText);
private: private:
QSettings *mySettings; QSettings *mySettings;
@ -71,6 +79,9 @@ private:
int highLimit = 70; int highLimit = 70;
QString lowAlertFile = "/usr/share/sounds/jolla-ambient/stereo/general_warning.wav"; QString lowAlertFile = "/usr/share/sounds/jolla-ambient/stereo/general_warning.wav";
QString highAlertFile = "/usr/share/sounds/jolla-ambient/stereo/positive_confirmation.wav"; QString highAlertFile = "/usr/share/sounds/jolla-ambient/stereo/positive_confirmation.wav";
QString notificationTitle;
QString notificationLowText;
QString notificationHighText;
// To avoid repeating the same string over and over and over... // To avoid repeating the same string over and over and over...
const char* sLowAlert = "lowAlert"; const char* sLowAlert = "lowAlert";
@ -82,6 +93,9 @@ private:
const char* sHighLimit = "highLimit"; const char* sHighLimit = "highLimit";
const char* sLowAlertFile = "lowAlertFile"; const char* sLowAlertFile = "lowAlertFile";
const char* sHighAlertFile = "highAlertFile"; const char* sHighAlertFile = "highAlertFile";
const char* sNotificationTitle = "notificationTitle";
const char* sNotificationLowText = "notificationLowText";
const char* sNotificationHighText = "notificationHighText";
int bound(int value, int min, int max); int bound(int value, int min, int max);
void loadInteger(const char *key, int *value, int min, int max); void loadInteger(const char *key, int *value, int min, int max);
@ -97,6 +111,9 @@ signals:
void highLimitChanged(int); void highLimitChanged(int);
void lowAlertFileChanged(QString); void lowAlertFileChanged(QString);
void highAlertFileChanged(QString); void highAlertFileChanged(QString);
void notificationTitleChanged(QString);
void notificationLowTextChanged(QString);
void notificationHighTextChanged(QString);
}; };
#endif // SETTINGS_H #endif // SETTINGS_H

View file

@ -23,6 +23,10 @@
<source>Contributions and translations are always appreciated!</source> <source>Contributions and translations are always appreciated!</source>
<translation>Sovelluksen kehittämiseen osallistuminen sekä uusien käännösten lisääminen ovat aina tervetulleita!</translation> <translation>Sovelluksen kehittämiseen osallistuminen sekä uusien käännösten lisääminen ovat aina tervetulleita!</translation>
</message> </message>
<message>
<source>If you like my work and would like to support me, you can buy me a coffee!</source>
<translation>Jos pidät työstäni ja haluat tukea minua, voit ostaa minulle kahvin!</translation>
</message>
</context> </context>
<context> <context>
<name>CoverPage</name> <name>CoverPage</name>
@ -232,6 +236,21 @@ Buddy</translation>
<translation>Näiden painikkeiden käyttö poistaa latausautomatiikan käytöstä.</translation> <translation>Näiden painikkeiden käyttö poistaa latausautomatiikan käytöstä.</translation>
</message> </message>
</context> </context>
<context>
<name>Settings</name>
<message>
<source>Battery charge %1%</source>
<translation>Akun lataus %1%</translation>
</message>
<message>
<source>Please connect the charger.</source>
<translation>Ole hyvä ja kytke laturi.</translation>
</message>
<message>
<source>Please disconnect the charger.</source>
<translation>Ole hyvä ja irrota laturi.</translation>
</message>
</context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>
<message> <message>
@ -288,28 +307,4 @@ Buddy</translation>
<translation>Tämä valinta keskeyttää akun latauksen automaattisesti, kun akku on latautunut keskeytysrajaan asti, ja jatkaa latausta uudelleen, kun akku on purkautunut jatkamisrajaan asti.</translation> <translation>Tämä valinta keskeyttää akun latauksen automaattisesti, kun akku on latautunut keskeytysrajaan asti, ja jatkaa latausta uudelleen, kun akku on purkautunut jatkamisrajaan asti.</translation>
</message> </message>
</context> </context>
<context>
<name>harbour-batterybuddy</name>
<message>
<source>Battery Buddy</source>
<translation>Battery Buddy</translation>
</message>
<message>
<source>Battery charge</source>
<comment>Battery charge 20%</comment>
<translation>Akun varaus</translation>
</message>
<message>
<source>This is a test.</source>
<translation>Tämä on testi.</translation>
</message>
<message>
<source>Please disconnect the charger.</source>
<translation>Ole hyvä ja irrota laturi.</translation>
</message>
<message>
<source>Please connect the charger.</source>
<translation>Ole hyvä ja kytke laturi.</translation>
</message>
</context>
</TS> </TS>

View file

@ -23,6 +23,10 @@
<source>Contributions and translations are always appreciated!</source> <source>Contributions and translations are always appreciated!</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>If you like my work and would like to support me, you can buy me a coffee!</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>CoverPage</name> <name>CoverPage</name>
@ -231,6 +235,21 @@ Buddy</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>Settings</name>
<message>
<source>Battery charge %1%</source>
<translation>Niveau batterie %1%</translation>
</message>
<message>
<source>Please connect the charger.</source>
<translation>Merci de brancher le chargeur.</translation>
</message>
<message>
<source>Please disconnect the charger.</source>
<translation>Merci de débrancher le chargeur.</translation>
</message>
</context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>
<message> <message>
@ -287,28 +306,4 @@ Buddy</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>harbour-batterybuddy</name>
<message>
<source>Battery Buddy</source>
<translation type="unfinished">Battery Buddy</translation>
</message>
<message>
<source>Battery charge</source>
<comment>Battery charge 20%</comment>
<translation type="unfinished">Niveau batterie</translation>
</message>
<message>
<source>This is a test.</source>
<translation type="unfinished">Ceci est un essai.</translation>
</message>
<message>
<source>Please disconnect the charger.</source>
<translation type="unfinished">Merci de débrancher le chargeur.</translation>
</message>
<message>
<source>Please connect the charger.</source>
<translation type="unfinished">Merci de brancher le chargeur.</translation>
</message>
</context>
</TS> </TS>

View file

@ -23,6 +23,10 @@
<source>Contributions and translations are always appreciated!</source> <source>Contributions and translations are always appreciated!</source>
<translation>Kodbidrag och översättningar är alltid uppskattat!</translation> <translation>Kodbidrag och översättningar är alltid uppskattat!</translation>
</message> </message>
<message>
<source>If you like my work and would like to support me, you can buy me a coffee!</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>CoverPage</name> <name>CoverPage</name>
@ -234,6 +238,21 @@ Buddy</translation>
<translation>Dessa kontroller åsidosätter de automatiserade inställningarna.</translation> <translation>Dessa kontroller åsidosätter de automatiserade inställningarna.</translation>
</message> </message>
</context> </context>
<context>
<name>Settings</name>
<message>
<source>Battery charge %1%</source>
<translation>Batteriladdning %1%</translation>
</message>
<message>
<source>Please connect the charger.</source>
<translation>Anslut laddaren.</translation>
</message>
<message>
<source>Please disconnect the charger.</source>
<translation>Koppla ifrån laddaren.</translation>
</message>
</context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>
<message> <message>
@ -290,28 +309,4 @@ Buddy</translation>
<translation>Detta alternativ inaktiverar laddningen automatiskt, när batteriet har laddats upp över pausprocenten och aktiverar det igen, när batteriet har laddats ur under återupptagandeprocent.</translation> <translation>Detta alternativ inaktiverar laddningen automatiskt, när batteriet har laddats upp över pausprocenten och aktiverar det igen, när batteriet har laddats ur under återupptagandeprocent.</translation>
</message> </message>
</context> </context>
<context>
<name>harbour-batterybuddy</name>
<message>
<source>Battery Buddy</source>
<translation>Battery Buddy</translation>
</message>
<message>
<source>Battery charge</source>
<comment>Battery charge 20%</comment>
<translation>Batteriladdning</translation>
</message>
<message>
<source>This is a test.</source>
<translation>Detta är ett test.</translation>
</message>
<message>
<source>Please disconnect the charger.</source>
<translation>Koppla ifrån laddaren.</translation>
</message>
<message>
<source>Please connect the charger.</source>
<translation>Anslut laddaren.</translation>
</message>
</context>
</TS> </TS>

View file

@ -23,6 +23,10 @@
<source>Contributions and translations are always appreciated!</source> <source>Contributions and translations are always appreciated!</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>If you like my work and would like to support me, you can buy me a coffee!</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>CoverPage</name> <name>CoverPage</name>
@ -232,6 +236,21 @@ Buddy电池搭档</translation>
<translation></translation> <translation></translation>
</message> </message>
</context> </context>
<context>
<name>Settings</name>
<message>
<source>Battery charge %1%</source>
<translation> %1%</translation>
</message>
<message>
<source>Please connect the charger.</source>
<translation></translation>
</message>
<message>
<source>Please disconnect the charger.</source>
<translation></translation>
</message>
</context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>
<message> <message>
@ -288,28 +307,4 @@ Buddy电池搭档</translation>
<translation></translation> <translation></translation>
</message> </message>
</context> </context>
<context>
<name>harbour-batterybuddy</name>
<message>
<source>Battery Buddy</source>
<translation>Battery Buddy</translation>
</message>
<message>
<source>Battery charge</source>
<comment>Battery charge 20%</comment>
<translation> 20%</translation>
</message>
<message>
<source>This is a test.</source>
<translation></translation>
</message>
<message>
<source>Please disconnect the charger.</source>
<translation></translation>
</message>
<message>
<source>Please connect the charger.</source>
<translation></translation>
</message>
</context>
</TS> </TS>

View file

@ -23,6 +23,10 @@
<source>Contributions and translations are always appreciated!</source> <source>Contributions and translations are always appreciated!</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>If you like my work and would like to support me, you can buy me a coffee!</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>CoverPage</name> <name>CoverPage</name>
@ -231,6 +235,21 @@ Buddy</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>Settings</name>
<message>
<source>Battery charge %1%</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please connect the charger.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please disconnect the charger.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>
<message> <message>
@ -287,28 +306,4 @@ Buddy</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>harbour-batterybuddy</name>
<message>
<source>Battery Buddy</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery charge</source>
<comment>Battery charge 20%</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>This is a test.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please disconnect the charger.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please connect the charger.</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS> </TS>

View file

@ -17,8 +17,8 @@ Group: Qt/Qt
License: GPLv3 License: GPLv3
URL: http://example.org/ URL: http://example.org/
Source0: %{name}-%{version}.tar.bz2 Source0: %{name}-%{version}.tar.bz2
Source100: harbour-batterybuddy.yaml
Requires: sailfishsilica-qt5 >= 0.10.9 Requires: sailfishsilica-qt5 >= 0.10.9
Requires: lipstick-qt5-tools
BuildRequires: pkgconfig(sailfishapp) >= 1.0.2 BuildRequires: pkgconfig(sailfishapp) >= 1.0.2
BuildRequires: pkgconfig(Qt5Core) BuildRequires: pkgconfig(Qt5Core)
BuildRequires: pkgconfig(Qt5Qml) BuildRequires: pkgconfig(Qt5Qml)

View file

@ -14,10 +14,12 @@ DEFINES += APP_NAME=\"\\\"$$TARGET\\\"\"
HEADERS += \ HEADERS += \
src/battery.h \ src/battery.h \
src/notification.h \
src/settings.h src/settings.h
SOURCES += \ SOURCES += \
src/battery.cpp \ src/battery.cpp \
src/notification.cpp \
src/settings.cpp \ src/settings.cpp \
src/harbour-batterybuddy-daemon.cpp src/harbour-batterybuddy-daemon.cpp

View file

@ -17,10 +17,13 @@
*/ */
#include "battery.h" #include "battery.h"
Battery::Battery(Settings* newSettings, QObject* parent) : QObject(parent) Battery::Battery(Settings *newSettings, QTimer *newUpdater, QTimer *newNotifier, Notification *newNotification, QObject *parent) : QObject(parent)
{ {
QString filename; QString filename;
settings = newSettings; settings = newSettings;
updateTimer = newUpdater;
notifyTimer = newNotifier;
notification = newNotification;
// Number: charge percentage, e.g. 42 // Number: charge percentage, e.g. 42
chargeFile = new QFile("/sys/class/power_supply/battery/capacity", this); chargeFile = new QFile("/sys/class/power_supply/battery/capacity", this);
@ -103,6 +106,19 @@ Battery::Battery(Settings* newSettings, QObject* parent) : QObject(parent)
// thingamabob - it is deprecated anyway. // thingamabob - it is deprecated anyway.
updateData(); updateData();
connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateData()));
connect(settings, SIGNAL(configChanged()), this, SLOT(updateConfig()));
connect(notifyTimer, SIGNAL(timeout()), this, SLOT(showNotification()));
updateConfig();
updateTimer->setInterval(5000);
updateTimer->start();
if(settings->getNotificationsEnabled()) {
showNotification();
}
} }
Battery::~Battery() { } Battery::~Battery() { }
@ -148,7 +164,34 @@ void Battery::updateData()
} }
} }
int Battery::getCharge(){ return charge; } void Battery::updateConfig() {
notifyTimer->stop();
notifyTimer->setInterval(settings->getInterval() * 1000);
if(settings->getNotificationsEnabled())
notifyTimer->start();
}
void Battery::showNotification() {
if(!settings->getNotificationsEnabled())
return;
qDebug() << "battery" << charge << "low" << settings->getLowAlert() << "high" << settings->getHighAlert() << "state" << state;
if(charge <= settings->getLowAlert() && state.compare("charging")) {
qInfo() << "Battery notification timer: empty enough battery";
notification->send(settings->getNotificationTitle().arg(charge), settings->getNotificationLowText(), settings->getLowAlertFile());
}
else if((charge >= settings->getHighAlert() && state.compare("discharging"))
|| (charge == 100 && !state.compare("idle"))) {
qInfo() << "Battery notification timer: full enough battery";
notification->send(settings->getNotificationTitle().arg(charge), settings->getNotificationHighText(), settings->getHighAlertFile());
}
else {
qInfo() << "Battery notification timer: close notification";
notification->close();
}
}
int Battery::getCharge() { return charge; }
QString Battery::getState() { return state; } QString Battery::getState() { return state; }
@ -176,6 +219,13 @@ bool Battery::getChargerConnected() {
} }
void Battery::shutdown() { void Battery::shutdown() {
qDebug() << "\nPreparing for exit...";
blockSignals(true);
if(updateTimer) {
updateTimer->stop();
qDebug() << "Timer stopped";
}
setChargingEnabled(true);
chargingEnabledFile->setPermissions(originalPerms); chargingEnabledFile->setPermissions(originalPerms);
qDebug() << "Charger control file permissions updated."; qDebug() << "Charger control file permissions restored.";
} }

View file

@ -19,12 +19,14 @@
#define BATTERY_H #define BATTERY_H
#include <QObject> #include <QObject>
#include <QTimer>
#include <QString> #include <QString>
#include <QFile> #include <QFile>
#include <QStandardPaths> #include <QStandardPaths>
#include <QHostInfo> #include <QHostInfo>
#include <QDebug> #include <QDebug>
#include "settings.h" #include "settings.h"
#include "notification.h"
class Battery : public QObject class Battery : public QObject
{ {
@ -35,7 +37,7 @@ class Battery : public QObject
Q_PROPERTY(bool chargingEnabled READ getChargingEnabled WRITE setChargingEnabled NOTIFY chargingEnabledChanged) Q_PROPERTY(bool chargingEnabled READ getChargingEnabled WRITE setChargingEnabled NOTIFY chargingEnabledChanged)
public: public:
Battery(Settings* newSettings, QObject* parent = nullptr); Battery(Settings *newSettings, QTimer *newUpdater, QTimer *newNotifier, Notification *newNotification, QObject *parent = nullptr);
~Battery(); ~Battery();
int getCharge(); int getCharge();
@ -56,6 +58,9 @@ private:
QFile* stateFile; QFile* stateFile;
QFile* chargingEnabledFile = Q_NULLPTR; QFile* chargingEnabledFile = Q_NULLPTR;
Settings* settings; Settings* settings;
QTimer *updateTimer = nullptr;
QTimer *notifyTimer = nullptr;
Notification *notification = nullptr;
// Default values: // Default values:
int charge = 100; // 100% full int charge = 100; // 100% full
@ -80,6 +85,10 @@ signals:
void stateChanged(QString); void stateChanged(QString);
void chargingEnabledChanged(bool); void chargingEnabledChanged(bool);
void chargerConnectedChanged(bool); void chargerConnectedChanged(bool);
public slots:
void updateConfig();
void showNotification();
}; };
#endif // BATTERY_H #endif // BATTERY_H

View file

@ -5,6 +5,7 @@
#include "settings.h" #include "settings.h"
#include <iostream> #include <iostream>
#include <signal.h> #include <signal.h>
#include "notification.h"
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
@ -38,12 +39,11 @@ int main(int argc, char** argv)
QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);
Settings* settings = new Settings(); QTimer *updater = new QTimer();
Battery* battery = new Battery(settings); QTimer *notifier = new QTimer();
Settings *settings = new Settings();
QTimer* updater = new QTimer(); Notification *notification = new Notification();
QObject::connect(updater, SIGNAL(timeout()), battery, SLOT(updateData())); Battery *battery = new Battery(settings, updater, notifier, notification);
updater->start(3000);
// Exit gracefully on Ctrl-C and service stop // Exit gracefully on Ctrl-C and service stop
QObject::connect(&app, SIGNAL(aboutToQuit()), battery, SLOT(shutdown())); QObject::connect(&app, SIGNAL(aboutToQuit()), battery, SLOT(shutdown()));
@ -52,5 +52,9 @@ int main(int argc, char** argv)
int retval = app.exec(); int retval = app.exec();
delete updater;
delete settings;
delete battery;
return retval; return retval;
} }

View file

@ -0,0 +1,74 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2020 Matti Viljanen
*
* Battery Buddy is free software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Battery Buddy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details. You should have received a copy of the GNU
* General Public License along with Battery Buddy. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Matti Viljanen
*/
#include "notification.h"
Notification::Notification(QObject* parent) : QObject(parent)
{
}
Notification::~Notification()
{
close();
}
void Notification::send(QString title, QString body, QString soundFile)
{
title = title.replace("\"", "\\\"");
body = body.replace("\"", "\\\"");
QStringList args;
QString command;
// Using 'update' works always; it creates a new one if needed
command = QString("notificationtool -o update -i %1 -I /usr/share/icons/hicolor/128x128/apps/harbour-batterybuddy.png -A \"Battery Buddy\" \"%2\" \"%3\" \"%2\" \"%3\"").arg(noteID).arg(title).arg(body);
args << "-l" << "nemo" << "-c" << command;
QProcess aplay;
if(!soundFile.isEmpty()) {
QStringList aplayArgs;
aplayArgs << "-l" << "nemo" << "-c" << QString("paplay %1").arg(soundFile);
aplay.start("runuser", aplayArgs);
qDebug() << "runuser" << aplayArgs;
}
QProcess notificationtool;
notificationtool.start("runuser", args);
qDebug() << "runuser" << args;
notificationtool.waitForFinished();
aplay.waitForFinished();
QString result(notificationtool.readAll());
if(!result.isEmpty())
noteID = result.split(' ').last().trimmed();
return;
}
void Notification::close()
{
if(noteID.compare("1") == 0)
return;
QStringList args;
args << "-o" << "remove" << "-i" << noteID;
QProcess proc;
proc.start("runuser", args);
proc.waitForFinished();
return;
}

View file

@ -0,0 +1,42 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019 Matti Viljanen
*
* Battery Buddy is free software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Battery Buddy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details. You should have received a copy of the GNU
* General Public License along with Battery Buddy. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Matti Viljanen
*/
#ifndef NOTIFICATION_H
#define NOTIFICATION_H
#include <QObject>
#include <QProcess>
#include <QTimer>
#include <QDebug>
class Notification : public QObject
{
Q_OBJECT
public:
Notification(QObject* parent = nullptr);
~Notification();
public slots:
void send(QString title, QString body, QString soundFile);
void close();
private:
QString noteID = "1";
};
#endif // NOTIFICATION_H

View file

@ -23,6 +23,7 @@ Settings::Settings(QObject *parent) : QObject(parent)
if(!mySettings) { if(!mySettings) {
mySettings = new QSettings("harbour-batterybuddy", "harbour-batterybuddy"); mySettings = new QSettings("harbour-batterybuddy", "harbour-batterybuddy");
} }
qDebug() << "Using" << mySettings->fileName(); qDebug() << "Using" << mySettings->fileName();
// Migrate old settings // Migrate old settings
@ -40,16 +41,15 @@ Settings::Settings(QObject *parent) : QObject(parent)
// Do this here, because... // Do this here, because...
watcher = new QFileSystemWatcher(QStringList(mySettings->fileName())); watcher = new QFileSystemWatcher(QStringList(mySettings->fileName()));
connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(configChanged(QString))); connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateConfig(QString)));
// ...calling this deletes mySettings! // ...calling this deletes mySettings!
configChanged(mySettings->fileName()); updateConfig(mySettings->fileName());
qInfo() << "Loaded" << sLimitEnabled << limitEnabled; qInfo() << "Loaded" << sLimitEnabled << limitEnabled;
// Battery Buddy GUI application changes the settings file, // Battery Buddy GUI application changes the settings file,
// so we must monitor it and update when it changes. // so we must monitor it and update when it changes.
} }
Settings::~Settings() Settings::~Settings()
@ -66,7 +66,7 @@ void Settings::loadInteger(const char* key, int *value, int min, int max) {
qInfo() << "Loaded" << key << *value; qInfo() << "Loaded" << key << *value;
} }
void Settings::configChanged(QString path) { void Settings::updateConfig(QString path) {
// Use the same file location as GUI for data exchange // Use the same file location as GUI for data exchange
if(!mySettings) { if(!mySettings) {
@ -82,6 +82,13 @@ void Settings::configChanged(QString path) {
loadInteger(sNotificationsEnabled, &notificationsEnabled, 0, 1); loadInteger(sNotificationsEnabled, &notificationsEnabled, 0, 1);
loadInteger(sLowLimit, &lowLimit, 20, 94); loadInteger(sLowLimit, &lowLimit, 20, 94);
loadInteger(sHighLimit, &highLimit, 21, 95); loadInteger(sHighLimit, &highLimit, 21, 95);
// These are translated in the GUI application
// and delivered here via the config file
notificationTitle = mySettings->value(sNotificationTitle, "Battery charge %1%").toString();
notificationLowText = mySettings->value(sNotificationLowText, "Please connect the charger.").toString();
notificationHighText = mySettings->value(sNotificationHighText, "Please disconnect the charger.").toString();
qDebug() << "Values read."; qDebug() << "Values read.";
delete mySettings; delete mySettings;
@ -109,3 +116,6 @@ bool Settings::getLimitEnabled() { return limitEnabled == 1; }
bool Settings::getNotificationsEnabled() { return notificationsEnabled == 1; } bool Settings::getNotificationsEnabled() { return notificationsEnabled == 1; }
QString Settings::getLowAlertFile() { return lowAlertFile; } QString Settings::getLowAlertFile() { return lowAlertFile; }
QString Settings::getHighAlertFile() { return highAlertFile; } QString Settings::getHighAlertFile() { return highAlertFile; }
QString Settings::getNotificationTitle() { return notificationTitle; }
QString Settings::getNotificationLowText() { return notificationLowText; }
QString Settings::getNotificationHighText() { return notificationHighText; }

View file

@ -41,6 +41,9 @@ public:
bool getNotificationsEnabled(); bool getNotificationsEnabled();
QString getLowAlertFile(); QString getLowAlertFile();
QString getHighAlertFile(); QString getHighAlertFile();
QString getNotificationTitle();
QString getNotificationLowText();
QString getNotificationHighText();
private: private:
QSettings* mySettings = nullptr; QSettings* mySettings = nullptr;
@ -60,6 +63,9 @@ private:
int highLimit = 70; int highLimit = 70;
QString lowAlertFile = "/usr/share/sounds/jolla-ambient/stereo/general_warning.wav"; QString lowAlertFile = "/usr/share/sounds/jolla-ambient/stereo/general_warning.wav";
QString highAlertFile = "/usr/share/sounds/jolla-ambient/stereo/positive_confirmation.wav"; QString highAlertFile = "/usr/share/sounds/jolla-ambient/stereo/positive_confirmation.wav";
QString notificationTitle;
QString notificationLowText;
QString notificationHighText;
// To avoid repeating the same string over and over and over... // To avoid repeating the same string over and over and over...
const char* sLowAlert = "lowAlert"; const char* sLowAlert = "lowAlert";
@ -71,12 +77,18 @@ private:
const char* sHighLimit = "highLimit"; const char* sHighLimit = "highLimit";
const char* sLowAlertFile = "lowAlertFile"; const char* sLowAlertFile = "lowAlertFile";
const char* sHighAlertFile = "highAlertFile"; const char* sHighAlertFile = "highAlertFile";
const char* sNotificationTitle = "notificationTitle";
const char* sNotificationLowText = "notificationLowText";
const char* sNotificationHighText = "notificationHighText";
int bound(int value, int min, int max); int bound(int value, int min, int max);
void loadInteger(const char *key, int *value, int min, int max); void loadInteger(const char *key, int *value, int min, int max);
private slots: private slots:
void configChanged(QString path); void updateConfig(QString path);
signals:
void configChanged();
}; };
#endif // SETTINGS_H #endif // SETTINGS_H