diff --git a/application/application.pro b/application/application.pro index d60b630..e4e677a 100644 --- a/application/application.pro +++ b/application/application.pro @@ -23,18 +23,19 @@ $$system(bash update-spec-version.sh $$TARGET $$VER $$REL) DEFINES += APP_VERSION=\"\\\"$$VERSION\\\"\" DEFINES += APP_NAME=\"\\\"$$TARGET\\\"\" -# Do not define QT_NO_DEBUG_OUTPUT! -# Use "--verbose" and "--debug" at runtime instead. -# See main() for details. -#DEFINES += QT_NO_DEBUG_OUTPUT +# Use "--verbose" and "--debug" at runtime. +# See main() and logger.h for details. +DEFINES += QT_NO_DEBUG_OUTPUT HEADERS += \ src/battery.h \ + src/logger.h \ src/settings.h \ src/process.h SOURCES += src/harbour-batterybuddy.cpp \ src/battery.cpp \ + src/logger.cpp \ src/settings.cpp DISTFILES += qml/harbour-batterybuddy.qml \ diff --git a/application/qml/pages/MainPage.qml b/application/qml/pages/MainPage.qml index 6cdcba1..d6cf582 100644 --- a/application/qml/pages/MainPage.qml +++ b/application/qml/pages/MainPage.qml @@ -39,7 +39,7 @@ Page { repeat: false running: true onTriggered: { - console.log("Startup timer started") + if(logger.debug) logger.log("Startup timer started") daemonStatus.start() pageStack.pushAttached(Qt.resolvedUrl("SettingsPage.qml")) } @@ -52,7 +52,7 @@ Page { repeat: false onTriggered: { var action = serviceRunning ? "stop" : "start" - console.log("Action: " + action) + if(logger.debug) logger.log("Action: " + action) _controlProcess.start("systemctl", ["--user", action, "harbour-batterybuddy.service"]) } } @@ -62,7 +62,7 @@ Page { id: _controlProcess onFinished: { daemonStatus.start() - console.debug("Service control return code " + errorCode()) + if(logger.debug) logger.log("Service control return code " + errorCode()) } } @@ -88,7 +88,7 @@ Page { serviceRunning = false daemonStartButton.enabled = true } - console.debug("Service status return code " + errorCode()) + if(logger.debug) logger.log("Service status return code " + errorCode()) } } diff --git a/application/qml/pages/SettingsPage.qml b/application/qml/pages/SettingsPage.qml index 47b001a..2307cb5 100644 --- a/application/qml/pages/SettingsPage.qml +++ b/application/qml/pages/SettingsPage.qml @@ -46,7 +46,7 @@ Page { lowAlertSlider.value = settings.lowAlert highIntervalSlider.value = settings.highNotificationsInterval lowIntervalSlider.value = settings.lowNotificationsInterval - console.debug("SettingsPage values updated") + if(logger.debug) logger.log("SettingsPage values updated") daemonCheck.start() } } @@ -58,7 +58,7 @@ Page { repeat: false onTriggered: { var action = daemonEnabledSwitch.checked ? "disable" : "enable" - console.log("Action: " + action) + if(logger.verbose) logger.log("Action: " + action) _toggleProcess.start("systemctl", ["--user", action, "harbour-batterybuddy.service"]) } } @@ -68,7 +68,7 @@ Page { id: _toggleProcess onFinished: { daemonCheck.start() - console.debug("Service toggle " + (errorCode() === 0 ? "succeeded" : "failed")) + if(logger.debug) logger.log("Service toggle " + (errorCode() === 0 ? "succeeded" : "failed")) } } @@ -93,7 +93,7 @@ Page { daemonEnabledSwitch.checked = false } daemonEnabledSwitch.busy = false - console.info("Service is " + (errorCode() === 0 ? "enabled" : "disabled")) + if(logger.verbose) logger.log("Service is " + (errorCode() === 0 ? "enabled" : "disabled")) } } diff --git a/application/src/battery.cpp b/application/src/battery.cpp index 35b87e1..6e48e31 100644 --- a/application/src/battery.cpp +++ b/application/src/battery.cpp @@ -17,30 +17,31 @@ */ #include "battery.h" -Battery::Battery(Settings* newSettings, QObject* parent) : QObject(parent) +Battery::Battery(Settings* newSettings, Logger* newLogger, QObject* parent) : QObject(parent) { QString filename; settings = newSettings; + logger = newLogger; // Number: charge percentage, e.g. 42 chargeFile = new QFile("/sys/class/power_supply/battery/capacity", this); - qInfo() << "Reading capacity from" << chargeFile->fileName(); + logV("Capacity file: " + chargeFile->fileName()); // Number: battery/charging current, e.g. -1450000 (-145mA) currentFile = new QFile("/sys/class/power_supply/battery/current_now", this); - qInfo() << "Reading current from" << currentFile->fileName(); + logV("Charge state file: " + currentFile->fileName()); // String: charging, discharging, full, empty, unknown (others?) stateFile = new QFile("/sys/class/power_supply/battery/status", this); - qInfo() << "Reading charge state from" << stateFile->fileName(); + logV("Charger status file: " + stateFile->fileName()); // Number: 0 or 1 chargerConnectedFile = new QFile("/sys/class/power_supply/usb/present", this); - qInfo() << "Reading charger status from" << chargerConnectedFile->fileName(); + logV("Reading charger status from" + chargerConnectedFile->fileName()); // ENABLE/DISABLE CHARGING if(QHostInfo::localHostName().contains("SailfishEmul")) { - qInfo() << "Sailfish SDK detected, not using charger control file"; + logV("Sailfish SDK detected, not using charger control file"); } else { // e.g. for Sony Xperia XA2 @@ -69,20 +70,20 @@ Battery::Battery(Settings* newSettings, QObject* parent) : QObject(parent) if(!chargingEnabledFile) { - qWarning() << "Charger control file not found!"; - qWarning() << "Please contact the developer with your device model!"; + logE("Charger control file not found!"); + logE("Please contact the developer with your device model!"); } } // If we found a usable file, check that it is writable if(chargingEnabledFile) { if(chargingEnabledFile->open(QIODevice::WriteOnly)) { - qInfo() << "Controlling charging via" << chargingEnabledFile->fileName(); + logV("Controlling charging via" + chargingEnabledFile->fileName()); chargingEnabledFile->close(); } else { - qWarning() << "Charger control file" << chargingEnabledFile->fileName() << "is not writable"; - qWarning() << "Charger control feature disabled"; + logE("Charger control file" + chargingEnabledFile->fileName() + "is not writable"); + logE("Charger control feature disabled"); delete chargingEnabledFile; chargingEnabledFile = Q_NULLPTR; } @@ -105,7 +106,7 @@ void Battery::updateData() if(nextCharge != charge) { charge = nextCharge; emit chargeChanged(charge); - qDebug() << "Battery:" << charge; + logV(QString("Battery: %1").arg(charge)); } chargeFile->close(); } @@ -114,7 +115,7 @@ void Battery::updateData() if(nextCurrent != current) { current = nextCurrent; emit currentChanged(current); - qDebug() << "Current:" << current; + logV(QString("Current: %1").arg(current)); } currentFile->close(); } @@ -123,7 +124,7 @@ void Battery::updateData() if(nextChargerConnected != chargerConnected) { chargerConnected = nextChargerConnected; emit chargerConnectedChanged(chargerConnected); - qDebug() << "Charger is connected:" << chargerConnected; + logV(QString("Charger is connected: %1").arg(chargerConnected)); } chargerConnectedFile->close(); } @@ -132,7 +133,7 @@ void Battery::updateData() if(nextState != state) { state = nextState; emit stateChanged(state); - qDebug() << "Charging status:" << state; + logV(QString("Charging status: %1").arg(state)); } stateFile->close(); } @@ -146,17 +147,17 @@ QString Battery::getState() { return state; } bool Battery::getChargingEnabled() { return chargingEnabled; } -void Battery::setChargingEnabled(bool isEnabled) { +void Battery::setChargingEnabled(const bool isEnabled) { if(chargingEnabledFile && chargingEnabledFile->open(QIODevice::WriteOnly)) { if(chargingEnabledFile->write(QString("%1").arg(isEnabled ? enableChargingValue : disableChargingValue).toLatin1())) { chargingEnabled = isEnabled; emit chargingEnabledChanged(chargingEnabled); if(isEnabled) { - qInfo() << "Charging resumed"; + logD("Charging resumed"); } else { - qInfo() << "Charging paused"; + logD("Charging paused"); } } chargingEnabledFile->close(); diff --git a/application/src/battery.h b/application/src/battery.h index bd8b159..508b0e3 100644 --- a/application/src/battery.h +++ b/application/src/battery.h @@ -23,9 +23,9 @@ #include #include #include -#include #include "settings.h" #include "process.h" +#include "logger.h" class Battery : public QObject { @@ -37,7 +37,7 @@ class Battery : public QObject Q_PROPERTY(bool chargingEnabled READ getChargingEnabled WRITE setChargingEnabled NOTIFY chargingEnabledChanged) public: - Battery(Settings* newSettings, QObject* parent = nullptr); + Battery(Settings* newSettings, Logger* newLogger, QObject* parent = nullptr); ~Battery(); int getCharge(); @@ -47,7 +47,7 @@ public: QString getState(); bool getChargingEnabled(); - void setChargingEnabled(bool); + void setChargingEnabled(const bool isEnabled); public slots: void updateData(); @@ -59,6 +59,7 @@ private: QFile* stateFile = nullptr; QFile* chargingEnabledFile = nullptr; Settings* settings = nullptr; + Logger* logger = nullptr; // Default values: int charge = 100; // 100% full diff --git a/application/src/harbour-batterybuddy.cpp b/application/src/harbour-batterybuddy.cpp index 919c939..20532a9 100644 --- a/application/src/harbour-batterybuddy.cpp +++ b/application/src/harbour-batterybuddy.cpp @@ -26,8 +26,8 @@ #include #include #include -#include +#include "logger.h" #include "battery.h" #include "settings.h" @@ -43,16 +43,26 @@ int main(int argc, char *argv[]) // // To display the view, call "show()" (will show fullscreen on device). - const char* logEnvVar = "QT_LOGGING_RULES"; - for(int i = 1; i < argc; i++) { + bool verbose = false; + bool debug = false; + + for(int i = 0; i < argc; i++) { if(!strcmp(argv[i],"-v")) { printf("%s %s\n", APP_NAME, APP_VERSION); return 0; } - else if(!strcmp(argv[i],"--verbose")) - qputenv(logEnvVar, "*.info=true;*.debug=false"); - else if(!strcmp(argv[i],"--debug")) - qputenv(logEnvVar, "*.info=true"); + else if(QHostInfo::localHostName().contains("SailfishEmul")) { + verbose = true; + debug = true; + } + else if(!strcmp(argv[i],"--verbose")) { + verbose = true; + debug = false; + } + else if(!strcmp(argv[i],"--debug")) { + verbose = true; + debug = true; + } else if(!strcmp(argv[i],"--help")) { printf("%s %s\n", APP_NAME, APP_VERSION); printf("Usage:\n"); @@ -62,19 +72,13 @@ int main(int argc, char *argv[]) return 0; } } - if(!qEnvironmentVariableIsSet(logEnvVar)) { - if(!QHostInfo::localHostName().contains("SailfishEmul")) - qputenv(logEnvVar, "*.info=false;*.debug=false"); - else - qputenv(logEnvVar, "*.info=true"); - } - QGuiApplication* app = SailfishApp::application(argc, argv); QQuickView* view = SailfishApp::createView(); - Settings* settings = new Settings(); - Battery* battery = new Battery(settings); + Logger *logger = new Logger(verbose, debug, false); + Settings* settings = new Settings(logger); + Battery* battery = new Battery(settings, logger); QTimer* updater = new QTimer(); QObject::connect(updater, SIGNAL(timeout()), battery, SLOT(updateData())); @@ -84,16 +88,17 @@ int main(int argc, char *argv[]) view->rootContext()->setContextProperty("battery", battery); view->rootContext()->setContextProperty("settings", settings); + view->rootContext()->setContextProperty("logger", logger); view->rootContext()->setContextProperty("app_version", APP_VERSION); view->setSource(SailfishApp::pathTo("qml/harbour-batterybuddy.qml")); view->showFullScreen(); - qInfo() << "Launching GUI..."; + logV("Launching GUI..."); int retval = app->exec(); - qInfo() << "Exiting..."; + logV("Exiting..."); updater->stop(); @@ -101,7 +106,9 @@ int main(int argc, char *argv[]) delete battery; delete settings; - qInfo() << "Goodbye!"; + logV("Goodbye!"); + + delete logger; return retval; } diff --git a/application/src/logger.cpp b/application/src/logger.cpp new file mode 120000 index 0000000..5b7f510 --- /dev/null +++ b/application/src/logger.cpp @@ -0,0 +1 @@ +../../service/src/logger.cpp \ No newline at end of file diff --git a/application/src/logger.h b/application/src/logger.h new file mode 120000 index 0000000..c22570d --- /dev/null +++ b/application/src/logger.h @@ -0,0 +1 @@ +../../service/src/logger.h \ No newline at end of file diff --git a/application/src/process.h b/application/src/process.h index aebb7b0..bc0a06d 100644 --- a/application/src/process.h +++ b/application/src/process.h @@ -6,15 +6,12 @@ #include #include -//#include class Process : public QProcess { Q_OBJECT public: - Process(QObject *parent = nullptr) : QProcess(parent) { - - } + Process(QObject *parent = nullptr) : QProcess(parent) { } Q_INVOKABLE void start(const QString &program, const QVariantList &arguments) { QStringList args; @@ -24,7 +21,6 @@ public: for (int i = 0; i < arguments.length(); i++) args << arguments[i].toString(); - //qDebug() << program + " " + args.join(" "); QProcess::start(program, args); QProcess::waitForStarted(1000); QProcess::waitForFinished(1000); diff --git a/application/src/settings.cpp b/application/src/settings.cpp index 48b7a94..f0c38bb 100644 --- a/application/src/settings.cpp +++ b/application/src/settings.cpp @@ -17,13 +17,17 @@ */ #include "settings.h" -Settings::Settings(QObject *parent) : QObject(parent) +Settings::Settings(Logger *newLogger, QObject *parent) : QObject(parent) { // Use the same file location as GUI for data exchange if(!mySettings) { mySettings = new QSettings(appName, appName, this); } + logger = newLogger; + + logV("Using " + mySettings->fileName()); + // Read in the values loadInteger(sLowAlert, &lowAlert, 5, 99); loadInteger(sHighAlert, &highAlert, 6, 100); @@ -51,7 +55,7 @@ Settings::~Settings() mySettings->setValue(sNotificationLowText, notificationLowText); mySettings->setValue(sNotificationHighText, notificationHighText); mySettings->sync(); - qInfo() << "Settings saved:" << (mySettings->status() == QSettings::NoError); + logV(QString("Settings saved: %1").arg((mySettings->status() == QSettings::NoError) ? "true" : "false")); } // Getters condensed. @@ -74,7 +78,7 @@ void Settings::setLowAlert(int newLimit) { // Lows and highs are always saved in pairs! //mySettings->sync(); emit lowAlertChanged(lowAlert); - qDebug() << sLowAlert << newLimit; + logD(QString("%1 %2").arg(sLowAlert).arg(newLimit)); } void Settings::setHighAlert(int newLimit) { @@ -82,7 +86,6 @@ void Settings::setHighAlert(int newLimit) { saveInteger(sHighAlert, &highAlert); mySettings->sync(); emit highAlertChanged(highAlert); - qDebug() << sHighAlert << newLimit; } void Settings::setHighNotificationsInterval(int newInterval) { @@ -90,7 +93,6 @@ void Settings::setHighNotificationsInterval(int newInterval) { saveInteger(sHighNotificationsInterval, &highNotificationsInterval); mySettings->sync(); emit highNotificationsIntervalChanged(highNotificationsInterval); - qDebug() << sHighNotificationsInterval << newInterval; } void Settings::setLowNotificationsInterval(int newInterval) { @@ -98,7 +100,6 @@ void Settings::setLowNotificationsInterval(int newInterval) { saveInteger(sLowNotificationsInterval, &lowNotificationsInterval); mySettings->sync(); emit highNotificationsIntervalChanged(lowNotificationsInterval); - qDebug() << sLowNotificationsInterval << newInterval; } void Settings::setLowLimit(int newLimit) { @@ -107,7 +108,6 @@ void Settings::setLowLimit(int newLimit) { // Lows and highs are always saved in pairs! //mySettings->sync(); emit lowLimitChanged(lowLimit); - qDebug() << sLowLimit << newLimit; } void Settings::setHighLimit(int newLimit) { @@ -115,7 +115,6 @@ void Settings::setHighLimit(int newLimit) { saveInteger(sHighLimit, &highLimit); mySettings->sync(); emit highLimitChanged(highLimit); - qDebug() << sHighLimit << newLimit; } void Settings::setLimitEnabled(bool newEnabled) { @@ -123,7 +122,6 @@ void Settings::setLimitEnabled(bool newEnabled) { saveInteger(sLimitEnabled, &limitEnabled); mySettings->sync(); emit limitEnabledChanged(limitEnabled); - qDebug() << sLimitEnabled << newEnabled; } void Settings::setNotificationTitle(QString newText) { @@ -131,7 +129,6 @@ void Settings::setNotificationTitle(QString newText) { mySettings->setValue(sNotificationTitle, notificationTitle); mySettings->sync(); emit notificationTitleChanged(notificationTitle); - qDebug() << sNotificationTitle << notificationTitle; } void Settings::setNotificationLowText(QString newText) { @@ -139,7 +136,6 @@ void Settings::setNotificationLowText(QString newText) { mySettings->setValue(sNotificationLowText, notificationLowText); mySettings->sync(); emit notificationLowTextChanged(notificationLowText); - qDebug() << sNotificationLowText << notificationLowText; } void Settings::setNotificationHighText(QString newText) { @@ -147,19 +143,18 @@ void Settings::setNotificationHighText(QString newText) { mySettings->setValue(sNotificationHighText, notificationHighText); mySettings->sync(); emit notificationHighTextChanged(notificationHighText); - qDebug() << sNotificationHighText << notificationHighText; } int Settings::bound(int value, int min, int max) { return (value <= min ? min : (value >= max ? max : value)); + logV(QString("Load: %1 %2").arg(key).arg(value)); } void Settings::loadInteger(const char* key, int *value, int min, int max) { *value = bound(mySettings->value(key, *value).toInt(), min, max); - qInfo() << "Loaded" << key << *value; } void Settings::saveInteger(const char* key, int *value) { mySettings->setValue(key, QByteArray::number(*value)); - qInfo() << "Saved" << key << *value; + logV(QString("Save: %1 %2").arg(key).arg(value)); } diff --git a/application/src/settings.h b/application/src/settings.h index bd0b4d2..19a0106 100644 --- a/application/src/settings.h +++ b/application/src/settings.h @@ -20,7 +20,7 @@ #include #include -#include +#include "logger.h" class Settings : public QObject { @@ -39,7 +39,7 @@ class Settings : public QObject Q_PROPERTY(QString notificationHighText READ getNotificationHighText WRITE setNotificationHighText NOTIFY notificationHighTextChanged) public: - Settings(QObject* parent = nullptr); + Settings(Logger* newLogger, QObject* parent = nullptr); ~Settings(); int getLowAlert(); @@ -69,6 +69,7 @@ public: private: QSettings *mySettings = nullptr; const char* appName = APP_NAME; + Logger* logger = nullptr; // Default values int lowAlert = 25; diff --git a/service/service.pro b/service/service.pro index 61a0e95..0d4fa29 100644 --- a/service/service.pro +++ b/service/service.pro @@ -14,16 +14,22 @@ VERSION = $${VER}-$${REL} DEFINES += APP_VERSION=\"\\\"$$VERSION\\\"\" DEFINES += APP_NAME=\"\\\"$$TARGET\\\"\" +# Use "--verbose" and "--debug" at runtime. +# See main() and logger.h for details. +DEFINES += QT_NO_DEBUG_OUTPUT + HEADERS += \ src/battery.h \ src/mynotification.h \ src/profile.h \ + src/logger.h \ src/settings.h SOURCES += \ src/battery.cpp \ src/mynotification.cpp \ src/profile.cpp \ + src/logger.cpp \ src/settings.cpp \ src/harbour-batterybuddy-daemon.cpp diff --git a/service/src/battery.cpp b/service/src/battery.cpp index 10299b6..df8e8a6 100644 --- a/service/src/battery.cpp +++ b/service/src/battery.cpp @@ -17,30 +17,31 @@ */ #include "battery.h" -Battery::Battery(QObject *parent) : QObject(parent) +Battery::Battery(Logger* newLogger, QObject *parent) : QObject(parent) { + logger = newLogger; QString filename; - settings = new Settings(this); + settings = new Settings(logger, this); updateTimer = new QTimer(this); highNotifyTimer = new QTimer(this); lowNotifyTimer = new QTimer(this); - notification = new MyNotification(this); + notification = new MyNotification(logger, this); // Number: charge percentage, e.g. 42 chargeFile = new QFile("/sys/class/power_supply/battery/capacity", this); - qInfo() << "Capacity file: " << chargeFile->fileName(); + logV("Capacity file: " + chargeFile->fileName()); // String: charging, discharging, full, empty, unknown (others?) stateFile = new QFile("/sys/class/power_supply/battery/status", this); - qInfo() << "Charge state file: " << stateFile->fileName(); + logV("Charge state file: " + stateFile->fileName()); // Number: 0 or 1 chargerConnectedFile = new QFile("/sys/class/power_supply/usb/present", this); - qInfo() << "Charger status file: " << chargerConnectedFile->fileName(); + logV("Charger status file: " + chargerConnectedFile->fileName()); // ENABLE/DISABLE CHARGING if(QHostInfo::localHostName().contains("SailfishEmul")) { - qInfo() << "Sailfish SDK detected, not using charger control file"; + logV("Sailfish SDK detected, not using charger control file"); } else { // e.g. for Sony Xperia XA2 @@ -68,8 +69,8 @@ Battery::Battery(QObject *parent) : QObject(parent) } if(!chargingEnabledFile) { - qWarning() << "Charger control file not found!"; - qWarning() << "Please contact the developer with your device model!"; + logger->log("Charger control file not found!"); + logger->log("Please contact the developer with your device model!"); } } @@ -79,7 +80,7 @@ Battery::Battery(QObject *parent) : QObject(parent) chargingEnabledFile->close(); } else { - qWarning() << "Charger control file" << chargingEnabledFile->fileName() << "is not writable"; + logger->log("Charger control file" + chargingEnabledFile->fileName() + "is not writable"); } } @@ -109,7 +110,7 @@ void Battery::updateData() if(nextCharge != charge) { charge = nextCharge; emit chargeChanged(charge); - qDebug() << "Battery:" << charge; + logD(QString("Battery: %1%").arg(charge)); } chargeFile->close(); } @@ -118,7 +119,7 @@ void Battery::updateData() if(nextChargerConnected != chargerConnected) { chargerConnected = nextChargerConnected; emit chargerConnectedChanged(chargerConnected); - qDebug() << "Charger is connected:" << chargerConnected; + logD(QString("Charger was %1").arg(chargerConnected ? "connected" : "disconnected")); } chargerConnectedFile->close(); } @@ -127,7 +128,7 @@ void Battery::updateData() if(nextState != state) { state = nextState; emit stateChanged(state); - qDebug() << "Charging status:" << state; + logD("Charging status:" + state); // Hide/show notification right away resetTimers(); @@ -136,11 +137,11 @@ void Battery::updateData() } if(chargingEnabledFile && settings->getLimitEnabled()) { if(chargingEnabled && charge >= settings->getHighLimit()) { - qDebug() << "Disabling"; + logD("Disabling"); setChargingEnabled(false); } else if(!chargingEnabled && charge <= settings->getLowLimit()) { - qDebug() << "Enabling"; + logD("Enabling"); setChargingEnabled(true); } } @@ -152,50 +153,50 @@ void Battery::resetTimers() { highNotifyTimer->setInterval(settings->getHighNotificationsInterval() * 1000); lowNotifyTimer->setInterval(settings->getLowNotificationsInterval() * 1000); if(settings->getHighNotificationsInterval() < 610) { - qDebug() << "Starting high level notification timer"; + logD("Starting high level notification timer"); highNotifyTimer->start(); showHighNotification(); } else { - qDebug() << "High level notification timer not started"; + logD("High level notification timer not started"); } if(settings->getLowNotificationsInterval() < 610) { - qDebug() << "Starting low level notification timer"; + logD("Starting low level notification timer"); lowNotifyTimer->start(); showLowNotification(); } else { - qDebug() << "Low level notification timer not started"; + logD("Low level notification timer not started"); } } void Battery::showHighNotification() { if(settings->getHighNotificationsInterval() < 610 && (charge >= settings->getHighAlert() && state != "discharging") && !(charge == 100 && state == "idle")) { - qDebug() << "High notification timer: full enough battery"; + logD("High notification timer: full enough battery"); notification->send(settings->getNotificationTitle().arg(charge), settings->getNotificationHighText(), settings->getHighAlertFile()); if(settings->getHighNotificationsInterval() == 50) { - qDebug() << "Stop high notification timer (show only once)"; + logD("Stop high notification timer (show only once)"); highNotifyTimer->stop(); } } else if(charge > settings->getLowAlert()) { - qDebug() << "High notification timer: close notification"; + logD("High notification timer: close notification"); notification->close(); } } void Battery::showLowNotification() { if(settings->getLowNotificationsInterval() < 610 && charge <= settings->getLowAlert() && state != "charging") { - qDebug() << "Battery notification timer: empty enough battery"; + logD("Battery notification timer: empty enough battery"); notification->send(settings->getNotificationTitle().arg(charge), settings->getNotificationLowText(), settings->getLowAlertFile()); if(settings->getLowNotificationsInterval() == 50) { - qDebug() << "Stop low notification timer (show only once)"; + logD("Stop low notification timer (show only once)"); lowNotifyTimer->stop(); } } else if(charge < settings->getHighAlert()) { - qDebug() << "Low notification timer: close notification"; + logD("Low notification timer: close notification"); notification->close(); } } @@ -216,19 +217,19 @@ bool Battery::setChargingEnabled(bool isEnabled) { success = true; if(isEnabled) { - qInfo() << "Charging resumed"; + logV("Charging resumed"); } else { - qInfo() << "Charging paused"; + logV("Charging paused"); } } else { - qWarning() << "Could not write new charger state"; + logger->log("Could not write new charger state"); } chargingEnabledFile->close(); } else { - qWarning() << "Could not open charger control file"; + logger->log("Could not open charger control file"); } } return success; @@ -239,25 +240,25 @@ bool Battery::getChargerConnected() { } void Battery::shutdown() { - qDebug() << "Preparing for exit..."; + logD("Preparing for exit..."); blockSignals(true); if(updateTimer) { updateTimer->stop(); - qDebug() << "Update timer stopped"; + logD("Update timer stopped"); } notification->close(); if(highNotifyTimer) { highNotifyTimer->stop(); - qDebug() << "High battery notification stopped"; + logD("High battery notification stopped"); } if(lowNotifyTimer) { lowNotifyTimer->stop(); - qDebug() << "Low battery notification stopped"; + logD("Low battery notification stopped"); } // ENABLE/DISABLE CHARGING if(!QHostInfo::localHostName().contains("SailfishEmul") && !setChargingEnabled(true)) { - qWarning() << "ERROR! Could not restore charger status! Your device" << endl - << "may not start until reboot! If that doesn't help," << endl - << "uninstall Battery Buddy and reboot your device."; + logger->log("ERROR! Could not restore charger status! Your device\n" + "may not start until reboot! If that doesn't help,\n" + "uninstall Battery Buddy and reboot your device."); } } diff --git a/service/src/battery.h b/service/src/battery.h index a228211..ed012c5 100644 --- a/service/src/battery.h +++ b/service/src/battery.h @@ -24,16 +24,16 @@ #include #include #include -#include #include "settings.h" #include "mynotification.h" +#include "logger.h" class Battery : public QObject { Q_OBJECT public: - Battery(QObject *parent = nullptr); + Battery(Logger* newLogger, QObject *parent = nullptr); ~Battery(); int getCharge(); @@ -49,6 +49,7 @@ public slots: void shutdown(); private: + Logger *logger; QFile *chargeFile = nullptr; QFile *chargerConnectedFile = nullptr; QFile *stateFile = nullptr; diff --git a/service/src/harbour-batterybuddy-daemon.cpp b/service/src/harbour-batterybuddy-daemon.cpp index 2e391eb..14b3fcf 100644 --- a/service/src/harbour-batterybuddy-daemon.cpp +++ b/service/src/harbour-batterybuddy-daemon.cpp @@ -18,50 +18,70 @@ #include #include #include + +#include "logger.h" #include "battery.h" -#include + #include int main(int argc, char** argv) { - const char* logEnvVar = "QT_LOGGING_RULES"; - for(int i = 1; i < argc; i++) { + bool logLevelSet = false; + bool verbose = false; + bool debug = false; + bool logfile = false; + + for(int i = 0; i < argc; i++) { if(!strcmp(argv[i],"-v")) { printf("%s %s\n", APP_NAME, APP_VERSION); - return EXIT_SUCCESS; + return 0; + } + else if(!strcmp(argv[i],"--verbose")) { + verbose = true; + debug = false; + logLevelSet = true; + } + else if(!strcmp(argv[i],"--debug")) { + verbose = true; + debug = true; + logLevelSet = true; + } + else if(!logLevelSet && QHostInfo::localHostName().contains("SailfishEmul")) { + verbose = true; + debug = true; + logLevelSet = true; + } + else if(!strcmp(argv[i],"--logfile")) { + logfile = true; } - else if(!strcmp(argv[i],"--verbose")) - qputenv(logEnvVar, "*.info=true;*.debug=false"); - else if(!strcmp(argv[i],"--debug")) - qputenv(logEnvVar, "*.info=true"); else if(!strcmp(argv[i],"--help")) { - printf("%s %s\n\n", APP_NAME, APP_VERSION); - printf("This binary is meant to run as a service as normal user,\n"); - printf("but it can be run manually for debugging purposes, too.\n\n"); + printf("%s %s\n", APP_NAME, APP_VERSION); printf("Usage:\n"); printf(" --verbose Enable informational messages\n"); printf(" --debug Enable informational and debugging messages\n"); printf(" --help Print version string and exit\n"); - return EXIT_SUCCESS; + return 0; } } - if(!qEnvironmentVariableIsSet(logEnvVar)) { - if(!QHostInfo::localHostName().contains("SailfishEmul")) - qputenv(logEnvVar, "*.info=false;*.debug=false"); - else - qputenv(logEnvVar, "*.info=true"); - } QCoreApplication app(argc, argv); + app.setApplicationName(APP_NAME); + app.setApplicationVersion(APP_VERSION); - Battery battery; + Logger* logger = new Logger(verbose, debug, logfile); + logE(QString("%1 %2").arg(APP_NAME, APP_VERSION)); + + Battery* battery = new Battery(logger); // Exit gracefully on Ctrl-C and service stop - QObject::connect(&app, SIGNAL(aboutToQuit()), &battery, SLOT(shutdown())); + QObject::connect(&app, SIGNAL(aboutToQuit()), battery, SLOT(shutdown())); signal(SIGINT, app.exit); signal(SIGTERM, app.exit); int retval = app.exec(); + delete battery; + delete logger; + return retval; } diff --git a/service/src/logger.cpp b/service/src/logger.cpp new file mode 100644 index 0000000..60eb3f3 --- /dev/null +++ b/service/src/logger.cpp @@ -0,0 +1,60 @@ +#include "logger.h" + +Logger::Logger(const bool enableVerbose, const bool enableDebug, + const bool useLogFile) { + buffer.resize(512); + verbose = enableVerbose; + debug = enableDebug; + if(useLogFile) { + enableLogFile(); + } +} + +Logger::~Logger() { + if(logFile.is_open()) { + logFile.close(); + } +} + +void Logger::log(const QString message) { + buffer = QString("[%1] %2\n").arg(QTime::currentTime().toString("HH:mm:ss"), message); + if(logFileEnabled && logFile.is_open()) { + logFile << buffer.toStdString(); + std::flush(logFile); + } + else { + std::cout << buffer.toStdString(); + std::flush(std::cout); + } +}; + +void Logger::log(const char* message) { + log(QString(message)); +}; + +bool Logger::getDebug() { return debug; } + +bool Logger::getVerbose() { return verbose; } + +void Logger::enableLogFile() { + QString logDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); + filename = QString(logDir + "/" + APP_NAME + ".log"); + + std::cout << "Logging to " << filename.toStdString() << std::endl; + + QDir qDir; + if(!qDir.exists(logDir)) { + qDir.mkpath(logDir); + } + + logFile.open(filename.toLocal8Bit().constData()); + + logFileEnabled = logFile.is_open(); + if(!logFileEnabled) { + std::cout << "Could not open log file. Logging disabled." << std::endl; + } +} + +QString Logger::getLogFilename() { + return filename; +} diff --git a/service/src/logger.h b/service/src/logger.h new file mode 100644 index 0000000..5eee3fb --- /dev/null +++ b/service/src/logger.h @@ -0,0 +1,53 @@ +#ifndef LOGGER_H +#define LOGGER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +// Use like this: +// logV("Settings loaded"); + +// Errors (always written - for general messages, too!) +#define logE logger->log + +// Verbose (log, if enabled) +#define logV if(logger->verbose) logger->log + +// Debug (log, if enabled) +#define logD if(logger->debug) logger->log + +class Logger : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool debug READ getDebug) + Q_PROPERTY(bool verbose READ getVerbose) +public: + Logger(const bool enableVerbose = false, + const bool enableDebug = false, + const bool useLogFile = false); + ~Logger(); + + Q_INVOKABLE void log(const QString message); + bool getDebug(); + bool getVerbose(); + void enableLogFile(); + QString getLogFilename(); + + void log(const char* message); + bool verbose = false; + bool debug = false; + +private: + std::ofstream logFile; + bool logFileEnabled = false; + QString buffer; + QString filename; +}; + +#endif diff --git a/service/src/mynotification.cpp b/service/src/mynotification.cpp index 687e121..fc78ea8 100644 --- a/service/src/mynotification.cpp +++ b/service/src/mynotification.cpp @@ -17,10 +17,12 @@ */ #include "mynotification.h" -MyNotification::MyNotification(QObject* parent) : QObject(parent) +MyNotification::MyNotification(Logger* newLogger, QObject* parent) : QObject(parent) { + logger = newLogger; notification.setAppName("Battery Buddy"); - notification.setAppIcon(APP_NAME); + // Set this manually, so that the correct icon is used. + notification.setAppIcon("harbour-batterybuddy"); playSound = false; sound.setAudioRole(QAudio::NotificationRole); connect(&sound, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), diff --git a/service/src/mynotification.h b/service/src/mynotification.h index 517ad15..aad6ea0 100644 --- a/service/src/mynotification.h +++ b/service/src/mynotification.h @@ -23,14 +23,14 @@ #include #include #include "profile.h" -#include +#include "logger.h" class MyNotification : public QObject { Q_OBJECT public: - MyNotification(QObject* parent = nullptr); + MyNotification(Logger* newLogger, QObject* parent = nullptr); ~MyNotification(); public slots: @@ -38,11 +38,12 @@ public slots: void close(); private: + Logger* logger; QString noteID = "1"; Notification notification; QMediaPlayer sound; bool playSound; - Profile profile; + Profile* profile; private slots: void soundLoadedChanged(QMediaPlayer::MediaStatus newStatus); diff --git a/service/src/profile.cpp b/service/src/profile.cpp index 5a9392b..5bc9054 100644 --- a/service/src/profile.cpp +++ b/service/src/profile.cpp @@ -17,9 +17,9 @@ */ #include "profile.h" -Profile::Profile(QObject *parent) : QObject(parent) +Profile::Profile(Logger* newLogger, QObject *parent) : QObject(parent) { - + logger = newLogger; } uint Profile::getRingtoneVolume() { @@ -30,16 +30,16 @@ uint Profile::getRingtoneVolume() { QDBusMessage message = interface.call("get_profile"); QString profile = message.arguments().at(0).toString(); - qDebug() << "Active profile:" << profile; + logD("Active profile:" + profile); if(profile == "silent") { - qDebug() << "Returning volume: 0"; + logD("Returning volume: 0"); return 0; } message = interface.call("get_value", "profile", "ringing.alert.volume"); int volume = message.arguments().at(0).toInt(); - qDebug() << "Ringtone volume:" << volume; + logD(QString("Ringtone volume: %1").arg(volume)); return (volume >= 0 && volume <= 100 ? volume : 0); } diff --git a/service/src/profile.h b/service/src/profile.h index f3e4b86..4520c26 100644 --- a/service/src/profile.h +++ b/service/src/profile.h @@ -20,15 +20,17 @@ #include #include +#include "logger.h" class Profile : public QObject { Q_OBJECT public: - explicit Profile(QObject *parent = nullptr); uint getRingtoneVolume(); + explicit Profile(Logger* newLogger, QObject *parent = nullptr); private: + Logger* logger; QDBusConnection connection = QDBusConnection::sessionBus(); }; diff --git a/service/src/settings.cpp b/service/src/settings.cpp index 2c6c363..1b5b383 100644 --- a/service/src/settings.cpp +++ b/service/src/settings.cpp @@ -17,64 +17,79 @@ */ #include "settings.h" -Settings::Settings(QObject *parent) : QObject(parent) +Settings::Settings(Logger* newLogger, QObject *parent) : QObject(parent) { + logger = newLogger; // Use the same file location as GUI for data exchange if(!mySettings) { mySettings = new QSettings(appName, appName, this); } - qDebug() << "Using" << mySettings->fileName(); + logV("Using " + mySettings->fileName()); + + QString migrate = "Migrated value %1"; + QString key = ""; // Migrate old settings - if(mySettings->contains("lowerLimit")) { - mySettings->setValue(sLowAlert, mySettings->value("lowerLimit")); - mySettings->remove("lowerLimit"); - qInfo() << "Migrated old lowerLimit value"; + key = "lowerLimit"; + if(mySettings->contains(key)) { + mySettings->setValue(sLowAlert, mySettings->value(key)); + mySettings->remove(key); + logV(migrate.arg(key)); } - if(mySettings->contains("upperLimit")) { - mySettings->setValue(sHighAlert, mySettings->value("upperLimit")); - mySettings->remove("upperLimit"); - qInfo() << "Migrated old upperLimit value"; + key = "upperLimit"; + if(mySettings->contains(key)) { + mySettings->setValue(sHighAlert, mySettings->value(key)); + mySettings->remove(key); + logV(migrate.arg(key)); } - if(mySettings->contains("notificationsEnabled")) { - mySettings->setValue("highNotificationsEnabled", mySettings->value("notificationsEnabled")); - mySettings->remove("notificationsEnabled"); - qInfo() << "Migrated old notificationsEnabled value"; - } - - if(mySettings->contains("interval")) { - mySettings->setValue(sHighNotificationsInterval, mySettings->value("interval")); - mySettings->setValue(sLowNotificationsInterval, mySettings->value("interval")); - mySettings->remove("interval"); - qInfo() << "Migrated old notification interval value"; - } - - if(mySettings->contains("highNotificationsEnabled")) { - if(mySettings->value("highNotificationsEnabled").toInt() == 0) + key = "notificationsEnabled"; + if(mySettings->contains(key)) { + if(mySettings->value(key).toInt() == 0) { mySettings->setValue(sHighNotificationsInterval, 610); - mySettings->remove("highNotificationsEnabled"); - qInfo() << "Migrated old highNotificationsEnabled value"; + mySettings->setValue(sLowNotificationsInterval, 610); + } + else { + mySettings->setValue(sHighNotificationsInterval, highNotificationsInterval); + mySettings->setValue(sLowNotificationsInterval, lowNotificationsInterval); + } + mySettings->remove(key); + logV(migrate.arg(key)); } - if(mySettings->contains("lowNotificationsEnabled")) { - if(mySettings->value("lowNotificationsEnabled").toInt() == 0) + key = "interval"; + if(mySettings->contains(key)) { + mySettings->setValue(sHighNotificationsInterval, mySettings->value(key)); + mySettings->setValue(sLowNotificationsInterval, mySettings->value(key)); + mySettings->remove(key); + logV(migrate.arg(key)); + } + + key = "highNotificationsEnabled"; + if(mySettings->contains(key)) { + if(mySettings->value(key).toInt() == 0) + mySettings->setValue(sHighNotificationsInterval, 610); + mySettings->remove(key); + logV(migrate.arg(key)); + } + + key = "lowNotificationsEnabled"; + if(mySettings->contains(key)) { + if(mySettings->value(key).toInt() == 0) mySettings->setValue(sLowNotificationsInterval, 610); - mySettings->remove("lowNotificationsEnabled"); - qInfo() << "Migrated old lowNotificationsEnabled value"; + mySettings->remove(key); + logV(migrate.arg(key)); } // Do this here, because... - watcher = new QFileSystemWatcher(QStringList(mySettings->fileName())); + watcher = new QFileSystemWatcher(QStringList(mySettings->fileName()), this); connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateConfig(QString))); // ...calling this deletes mySettings! updateConfig(mySettings->fileName()); - qInfo() << "Loaded" << sLimitEnabled << limitEnabled; - // Battery Buddy GUI application changes the settings file, // so we must monitor it and update when it changes. } @@ -85,7 +100,7 @@ bool Settings::loadInteger(const char* key, int *value, int min, int max) { oldValue = *value; *value = bound(mySettings->value(key, *value).toInt(), min, max); if(oldValue != *value) { - qInfo() << "Loaded" << key << *value; + logV(QString("Load: %1 %2").arg(key).arg(value)); } return oldValue != *value; } @@ -97,7 +112,7 @@ void Settings::updateConfig(QString path) { mySettings = new QSettings(appName, appName, this); } - qDebug() << "Reading values..."; + logV("Loading values..."); // Read in the values bool restartTimers = false; @@ -115,20 +130,25 @@ void Settings::updateConfig(QString path) { notificationLowText = mySettings->value(sNotificationLowText, "Please connect the charger.").toString(); notificationHighText = mySettings->value(sNotificationHighText, "Please disconnect the charger.").toString(); - qDebug() << "Values read."; + QString logFilename = logger->getLogFilename(); + if(mySettings->value(sLogFilename,QString()).toString() != logFilename) { + mySettings->setValue(sLogFilename, logFilename); + } + + logV("Values loaded."); delete mySettings; mySettings = nullptr; // Let the file system settle... - QThread::msleep(50); + QThread::msleep(100); if(watcher->files().contains(path)) { - qDebug() << "File OK"; + logD("Config file already on watchlist"); } else { - qDebug() << "File replaced, re-adding."; watcher->addPath(path); + logD("Config file added to watchlist."); } if(restartTimers) { diff --git a/service/src/settings.h b/service/src/settings.h index 829839d..28c08e0 100644 --- a/service/src/settings.h +++ b/service/src/settings.h @@ -22,14 +22,14 @@ #include #include #include -#include +#include "logger.h" class Settings : public QObject { Q_OBJECT public: - Settings(QObject* parent = nullptr); + Settings(Logger* newLogger, QObject* parent = nullptr); ~Settings(); int getLowAlert(); @@ -48,9 +48,13 @@ public: QString getNotificationHighText(); private: + Logger* logger; QSettings* mySettings = nullptr; QFileSystemWatcher *watcher = nullptr; - const char* appName = APP_NAME; + + // Set this manually, because we want to use + // the same config file as the GUI application + const char* appName = "harbour-batterybuddy"; int oldValue; @@ -85,6 +89,7 @@ private: const char* sNotificationTitle = "notificationTitle"; const char* sNotificationLowText = "notificationLowText"; const char* sNotificationHighText = "notificationHighText"; + const char* sLogFilename = "logFilename"; int bound(int value, int min, int max); bool loadInteger(const char *key, int *value, int min, int max);