Compare commits

..

No commits in common. "master" and "health" have entirely different histories.

66 changed files with 1060 additions and 2735 deletions

3
.gitignore vendored
View file

@ -1,4 +1,3 @@
.vscode/
*.old
*.bak
*.tmp
@ -7,5 +6,3 @@
*.qm
*.spec.*
*.autosave
shadow/
RPMS/

View file

@ -1,13 +1,8 @@
# harbour-batterybuddy
<img src="https://github.com/direc85/harbour-batterybuddy/raw/master/screenshot1.jpg?raw=true" alt="Screenshot 1" style="width: 270px; height: 480px;"> <img src="https://github.com/direc85/harbour-batterybuddy/raw/master/screenshot4.jpg?raw=true" alt="Screenshot 4" style="width: 270px; height: 480px;">
Battery Buddy is a Sailfish OS application that pauses and resumes charging at set percentage values, or alerts the user when the battery charge level gets too high or too low. This helps in increasing the battery lifespan. There are a *lot* of research material on this, the numbers I pulled into the application as a reference were pulled from [Battery Universe online article BU-808](https://batteryuniversity.com/learn/article/how_to_prolong_lithium_based_batteries).
The application consist of three parts: the GUI, the monitoring daemon and the filesystem permission daemon. The filesystem daemon, `harbour-batterybuddy-oneshot.service`, always starts when the device boots. Its sole purpose is to set correct permissions for the charger control file of the device, so that everything else can be started as user `defaultuser` (or `nemo`), minimizing security impact. The monitoring daemon, `harbour-batterybuddy.service`, actually sends the notifications and pauses/resumes charging.
The application logo is a 5 minute craft at the moment, and can be considered a permanent temporary solution. It doesn't look nice in the notification view. If you have the skills to make a better logo using the same idea (a heart inside the battery) and are willing to spend a little time for this project, please feel free to send a new logo to me.
There's a logging feature, too, which writes to a simple text log. Depending on the log level it can log percentage changes, temperature changes and momentary device current draw. Note that the measurement can only be done when the device is not in deep sleep mode, so the power draw reading can never reflect the true lowest possible values.
You can download Battery Buddy using [Storeman](https://openrepos.net/content/olf/storeman-installer), or directly from [Openrepos](https://openrepos.net/content/direc85/battery-buddy). For support, open a ticket or check out the [Battery Buddy support thread](https://forum.sailfishos.org/t/battery-buddy-support-thread/12580/47) over at Sailfish OS forum!
The application consist of three parts: the GUI, the monitoring daemon and the filesystem permission daemon. The filesystem daemon, `harbour-batterybuddy-oneshot.service`, always starts when the device boots. Its sole purpose is to set correct permissions for the charger control file of the device, so that everything else can be started as user `nemo`, minimizing security impact. The monitoring daemon, `harbour-batterybuddy.service`, actually sends the notifications and pauses/resumes charging.
Keep your battery healthy and help our dying planet, even if it is just for a tiny little bit!

View file

@ -12,11 +12,14 @@
# The name of your application
TARGET = harbour-batterybuddy
CONFIG += console sailfishapp sailfishapp_i18n dbus
CONFIG += console sailfishapp sailfishapp_i18n
# Keep this in sync with service.pro and .spec
VERSION = 4.2.5-1
# Keep this in sync with "service.pro"
VER = 3.12
REL = 3
VERSION = $${VER}-$${REL}
$$system(bash update-spec-version.sh $$TARGET $$VER $$REL)
DEFINES += APP_VERSION=\"\\\"$$VERSION\\\"\"
DEFINES += APP_NAME=\"\\\"$$TARGET\\\"\"
@ -27,7 +30,8 @@ DEFINES += QT_NO_DEBUG_OUTPUT
HEADERS += \
src/battery.h \
src/logger.h \
src/settings.h
src/settings.h \
src/process.h
SOURCES += src/harbour-batterybuddy.cpp \
src/battery.cpp \
@ -54,13 +58,18 @@ DISTFILES += qml/harbour-batterybuddy.qml \
qml/pages/SettingsPage.qml \
qml/components/MyDetailItem.qml \
qml/components/AdjustmentButtons.qml \
qml/components/MySlider.qml \
qml/components/SystemdUserService.qml
qml/components/MySlider.qml
SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172
TRANSLATIONS += translations/harbour-batterybuddy.ts \
translations/harbour-batterybuddy-*.ts
translations/harbour-batterybuddy-de_DE.ts \
translations/harbour-batterybuddy-fi.ts \
translations/harbour-batterybuddy-fr.ts \
translations/harbour-batterybuddy-hu.ts \
translations/harbour-batterybuddy-pl.ts \
translations/harbour-batterybuddy-sv.ts \
translations/harbour-batterybuddy-zh_CN.ts
# Executable provided by "service.pro"
# Two services, actually

View file

@ -8,8 +8,3 @@ Name[fi]=Battery Buddy
[X-HarbourBackup]
BackupPathList=.config/harbour-batterybuddy/
[X-Sailjail]
Permissions=AppLaunch
OrganizationName=harbour-batterybuddy
ApplicationName=harbour-batterybuddy

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -15,7 +15,7 @@
*
* Author: Matti Viljanen
*/
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
Label {

View file

@ -1,4 +1,4 @@
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
Row {

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2023 Matti Viljanen
* 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
@ -15,100 +15,44 @@
*
* Author: Matti Viljanen
*/
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
Item {
id: batteryGraph
property real borderSize: width * 0.1
property bool enableLowBatteryAnimation
property int _charge: battery.charge
property real borderSize: width * 0.15
property real charge: battery.charge
property bool chargerConnected: battery.chargerConnected
height: 1.75 * width
// Timer {
// id: debugChargeAnimation
// property int newCharge: -20
// repeat: true
// running: true
// interval: 300
// onTriggered: {
// newCharge = newCharge + 5
// if(newCharge > 120)
// newCharge = -20
// _charge = newCharge < 0 ? 0 : newCharge > 100 ? 100 : newCharge
// }
// }
Timer {
id: lowChargeBlink
property int counter: 0
running: (enableLowBatteryAnimation
&& !battery.chargerConnected
&& !battery.acConnected
&& _charge <= settings.lowAlert)
repeat: true
interval: 400
onTriggered: {
counter = (counter + 1) % 5
if(counter === 0) {
batteryLevel.opacity = 0.0
restoreOpacity.start()
}
}
}
Timer {
id: restoreOpacity
running: false
repeat: false
interval: opacityAnimation.duration
onTriggered: batteryLevel.opacity = 1.0
}
Rectangle {
id: battTip
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
width: 2 * borderSize
height: 1.5 * borderSize
color: Theme.secondaryColor
radius: borderSize / 2
height: borderSize
color: "white"
radius: 0.25 * borderSize
}
Rectangle {
id: battBody
anchors {
top: battTip.verticalCenter
bottom: parent.bottom
horizontalCenter: parent.horizontalCenter
}
width: parent.width * 0.75
color: "transparent"
border.color: Theme.secondaryColor
anchors.top: battTip.verticalCenter
anchors.bottom: parent.bottom
width: parent.width
color: "black"
border.color: "white"
border.width: borderSize
radius: borderSize
radius: 0.25 * borderSize
Rectangle {
id: batteryLevel
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: borderSize * 1.5
width: parent.width - 3 * borderSize
height: (borderSize) + ((parent.height - 4 * borderSize) * _charge / 100.0)
radius: borderSize / 2
opacity: 1.0
color: _charge >= 80 ? Theme.secondaryColor
: _charge >= 50 ? Theme.highlightFromColor("green", Theme.colorScheme)
: _charge >= 20 ? Theme.highlightFromColor("yellow", Theme.colorScheme)
: Theme.highlightFromColor("red", Theme.colorScheme)
Behavior on color {
ColorAnimation {}
}
Behavior on opacity {
NumberAnimation {
id: opacityAnimation
}
}
border.color: "black"
border.width: 0.4 * borderSize
x: borderSize
y: parent.height - x - height
width: parent.width - 2.0 * x
height: (parent.height - 2.0 * x) * charge / 100.0
color: charge >= 80 ? "white" : charge >= 50 ? "green" : charge >= 20 ? "orange" : "red"
}
}
}

View file

@ -1,26 +0,0 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 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
*/
import QtQuick 2.6
import Sailfish.Silica 1.0
Label {
width: parent.width
anchors.topMargin: height / 2
color: Theme.highlightColor
horizontalAlignment: Text.AlignHCenter
}

View file

@ -1,47 +0,0 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 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
*/
import QtQuick 2.0
import Sailfish.Silica 1.0
BackgroundItem {
id: root
property string source
anchors.horizontalCenter: parent.horizontalCenter
width: Theme.iconSizeExtraLarge
height: Theme.iconSizeExtraLarge * (image.baseHeight / image.baseWidth)
contentItem.radius: Theme.paddingMedium
Rectangle {
anchors.fill: parent
radius: Theme.paddingMedium
color: Theme.rgba(Theme.highlightBackgroundColor, Theme.highlightBackgroundOpacity)
Image {
id: image
anchors.centerIn: parent
source: Qt.resolvedUrl(root.source)
property real baseWidth: root.width * 0.85 * (sourceSize.width > sourceSize.height ? 1.0 : (sourceSize.width / sourceSize.height))
property real baseHeight: root.width * 0.85 * (sourceSize.height > sourceSize.width ? 1.0 : (sourceSize.height / sourceSize.width))
width: baseWidth * (root.down ? 0.95 : 1.0)
height: baseHeight * (root.down ? 0.95 : 1.0)
smooth: true
asynchronous: true
}
}
}

View file

@ -34,7 +34,7 @@
// Modified by Matti Viljanen 2020: added text size control
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
Item {

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -15,7 +15,7 @@
*
* Author: Matti Viljanen
*/
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
Label {

View file

@ -1,4 +1,4 @@
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
Slider {

View file

@ -1,134 +0,0 @@
import QtQuick 2.6
import Nemo.DBus 2.0
Item {
id: container
function queryService() { dbusManager.queryService() }
function stopService() { dbusManager.stopService() }
function startService() { dbusManager.startService() }
function enableService() { dbusManager.unmaskService() }
function disableService() { dbusManager.maskService() }
function queryActive() { dbusUnit.queryActiveState() }
function queryEnabled() { dbusUnit.queryMaskedState() }
property string serviceName
property string serviceState: "unknown"
property string serviceMasked: "unknown"
Component.onCompleted: {
dbusManager.queryService()
}
DBusInterface {
id: dbusManager
service: 'org.freedesktop.systemd1'
path: '/org/freedesktop/systemd1'
iface: 'org.freedesktop.systemd1.Manager'
function reload() {
call('Reload')
}
function queryService() {
typedCall('GetUnit',
{ 'type': 's', 'value': serviceName },
function(result) {
//console.log('GetUnit:', result)
dbusUnit.path = result
dbusUnit.queryActiveState()
dbusUnit.queryMaskedState()
},
function(error, message) {
console.log('GetUnit failed:', error)
console.log('GetUnit message:', message)
})
}
function stopService() {
typedCall('StopUnit',
[
{ 'type': 's', 'value': serviceName },
{ 'type': 's', 'value': 'fail' }
],
function(result) {
//console.log("StopUnit:", result)
container.serviceState = "failed"
},
function(error, message) {
console.log("StopUnit failed:", error)
console.log("StopUnit message:", message)
container.serviceState = "error"
})
}
function startService() {
typedCall('StartUnit',
[
{ 'type': 's', 'value': serviceName },
{ 'type': 's', 'value': 'fail' }
],
function(result) {
//console.log("StartUnit:", result)
container.serviceState = "active"
},
function(error, message) {
console.log("StartUnit failed:", error)
console.log("StartUnit message:", message)
container.serviceState = "error"
})
}
function unmaskService() {
typedCall('UnmaskUnitFiles',
[
{ 'type': 'as', 'value': [serviceName] },
{ 'type': 'b', 'value': false },
],
function(install, changes) {
//console.log("UnmaskUnitFiles result:", install)
//console.log("UnmaskUnitFiles changes:", changes)
container.serviceMasked = "loaded"
reload()
},
function(error, message) {
console.log("UnmaskUnitFiles failed:", error)
console.log("UnmaskUnitFiles message:", message)
container.serviceMasked = "error"
})
}
function maskService() {
typedCall('MaskUnitFiles',
[
{ 'type': 'as', 'value': [serviceName] },
{ 'type': 'b', 'value': false },
{ 'type': 'b', 'value': true },
],
function(install, changes) {
//console.log("MaskUnitFiles result:", install)
//console.log("MaskUnitFiles changes:", changes)
container.serviceMasked = "masked"
reload()
},
function(error, message) {
console.log("MaskUnitFiles failed:", error)
console.log("MaskUnitFiles message:", message)
container.serviceMasked = "error"
})
}
}
DBusInterface {
id: dbusUnit
service: 'org.freedesktop.systemd1'
path: '/org/freedesktop/systemd1/unit/harbour_2dbatterybuddy_2eservice'
iface: 'org.freedesktop.systemd1.Unit'
function queryActiveState() {
var result = getProperty('ActiveState')
//console.log('ActiveState:', result)
container.serviceState = result
}
function queryMaskedState() {
var result = getProperty('LoadState')
//console.log('LoadState:', result)
container.serviceMasked = result
}
}
}

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -15,36 +15,53 @@
*
* Author: Matti Viljanen
*/
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
import "../components"
CoverBackground {
id: coverPage
Column {
spacing: coverPage.width / 20
anchors {
left: coverPage.left
right: coverPage.right
verticalCenter: parent.verticalCenter
}
BatteryGraph {
x: coverPage.width * 0.3
y: coverPage.width * 0.25
width: 0.35 * coverPage.width
enableLowBatteryAnimation: coverPage.status === Cover.Active
}
CoverLabel {
id: chargeLabel
text: "🔋 " + battery.charge + "%"
}
CoverLabel {
text: "🔌 " + Math.floor(battery.current / 1000) + " mA"
}
CoverLabel {
height: text === '🌡️ ' ? 0 : chargeLabel.height
text: "🌡️ " + (battery.temperature === 0x7FFFFFFF ? '? °C' : formatTemperature(battery.temperature))
onStatusChanged: batteryGraph.updateView()
BatteryGraph {
id: batteryGraph
x: coverPage.width * 0.3
y: coverPage.width * 0.25
width: 0.4 * coverPage.width
Component.onCompleted: updateView()
onStateChanged: updateView()
onChargerConnectedChanged: updateView()
onChargeChanged: updateView()
function updateView() {
if(charge <= settings.lowerLimit && battery.state === "discharging") {
coverText.text = qsTr("Connect charger")
}
else if(battery.charge >= settings.upperLimit &&
(battery.state === "charging" || battery.state === "idle")) {
coverText.text = qsTr("Disconnect charger")
}
else if(battery.chargerConnected && battery.state === "charging") {
coverText.text = qsTr("Charging")
}
else if(battery.chargerConnected && battery.state === "discharging") {
coverText.text = qsTr("Not charging")
}
else { // Discharging
coverText.text = qsTr("Battery Buddy")
}
}
}
Label {
id: coverText
anchors.top: batteryGraph.bottom
anchors.bottom: coverPage.bottom
anchors.horizontalCenter: coverPage.horizontalCenter
width: coverPage.width * 0.9
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.Wrap
maximumLineCount: 2
}
}

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -15,7 +15,7 @@
*
* Author: Matti Viljanen
*/
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
import Nemo.Notifications 1.0
import "pages"
@ -25,11 +25,4 @@ ApplicationWindow
initialPage: Component { MainPage { } }
cover: Qt.resolvedUrl("cover/CoverPage.qml")
allowedOrientations: Orientation.LandscapeMask | Orientation.Portrait
function formatTemperature(temp) {
if(Qt.locale().measurementSystem === Locale.ImperialUSSystem) {
return Math.floor((battery.temperature / 10) * 1.8 + 32) + " °F"
}
return Math.floor(battery.temperature / 10) + " °C"
}
}

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -15,7 +15,7 @@
*
* Author: Matti Viljanen
*/
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
import "../components"
@ -63,12 +63,6 @@ Page {
text: "Battery Buddy"
}
AboutLabel {
font.pixelSize: Theme.fontSizeLarge
color: Theme.highlightColor
text: app_version
}
AboutLabel {
font.pixelSize: Theme.fontSizeMedium
color: Theme.primaryColor
@ -78,24 +72,30 @@ Page {
AboutLabel {
font.pixelSize: Theme.fontSizeSmall
color: Theme.secondaryColor
text: "Copyright 2019-2022 Matti Viljanen (direc85)"
}
AboutLabel {
font.pixelSize: Theme.fontSizeMedium
color: Theme.primaryColor
text: qsTr("Contributors")
text: qsTr("Version") + " " + app_version
}
AboutLabel {
font.pixelSize: Theme.fontSizeSmall
color: Theme.secondaryColor
text: "Copyright 2021 Peter Gantner (nephros)"
text: "Copyright 2019-2020 Matti Viljanen"
}
ImageButton {
source: Qt.resolvedUrl("/usr/share/harbour-batterybuddy/images/ko-fi.png")
BackgroundItem {
anchors.horizontalCenter: parent.horizontalCenter
width: Theme.iconSizeExtraLarge * 1.2
height: Theme.iconSizeExtraLarge * 1.2
onClicked: Qt.openUrlExternally("https://ko-fi.com/direc85")
contentItem.radius: Theme.paddingSmall
Image {
anchors.centerIn: parent
source: Qt.resolvedUrl("/usr/share/harbour-batterybuddy/images/ko-fi.png")
width: Theme.iconSizeExtraLarge
height: Theme.iconSizeExtraLarge
smooth: true
asynchronous: true
}
}
AboutLabel {
@ -113,14 +113,11 @@ Page {
AboutLabel {
font.pixelSize: Theme.fontSizeSmall
color: Theme.secondaryColor
text: "English: direc85"+
"Suomi: direc85\n"+
text: "Suomi: Matti Viljanen\n"+
"Français: Quenty31\n"+
"简体中文: dashinfantry\n"+
"svensk: eson57\n"+
"Deutsch: dryo, fllp, nephros\n"+
"Polski: atlochowski, wetab73\n"+
"Magyar: 1Zgp"
"Deutsch: dryo, fllp"
}
AboutLabel {
@ -135,30 +132,12 @@ Page {
text: qsTr("Contributions and translations are always appreciated!")
}
ImageButton {
source: Qt.resolvedUrl(
Theme.colorScheme === Theme.LightOnDark
? "/usr/share/harbour-batterybuddy/images/GitHub-Mark-Light-120px-plus.png"
: "/usr/share/harbour-batterybuddy/images/GitHub-Mark-120px-plus.png"
)
Button {
text: "GitHub"
anchors.horizontalCenter: parent.horizontalCenter
onClicked: Qt.openUrlExternally("https://github.com/direc85/harbour-batterybuddy")
}
AboutLabel {
font.pixelSize: Theme.fontSizeSmall
color: Theme.secondaryColor
text: qsTr("A modified version of %1 by %2 in the emoji pack %3 is used in the logo. License: %4")
.arg("Battery emoji")
.arg("Vincent Le Moign")
.arg("Streamline")
.arg("Creative Commons Attribution 4.0")
}
ImageButton {
source: Qt.resolvedUrl("/usr/share/harbour-batterybuddy/images/battery-emoji-clipart-original.png")
onClicked: Qt.openUrlExternally("https://creazilla.com/nodes/49604-battery-emoji-clipart")
}
Item {
width: parent.width
height: Theme.paddingMedium

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -15,7 +15,7 @@
*
* Author: Matti Viljanen
*/
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
import "../components"

View file

@ -1,4 +1,4 @@
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
import "../components"

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -15,50 +15,35 @@
*
* Author: Matti Viljanen
*/
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
import "../components"
Page {
id: logPage
allowedOrientations: Orientation.Portrait | Orientation.Landscape | Orientation.LandscapeInverted
// Invisible; used to determine
// the ColumnView delegate size.
Label {
id: metrics
text: "X"
font.pixelSize: Theme.fontSizeTiny
opacity: 0
enabled: false
}
SilicaFlickable {
id: flickable
id: logFlickable
anchors.fill: parent
contentHeight: header.height
+ flow.height
+ Theme.paddingLarge
+ logView.height
ScrollDecorator {
flickable: flickable
}
contentHeight: header.height + column.height
PageHeader {
id: header
title: qsTr("View log")
}
// Layout the ComboBox and the buttons either
// on top each other (portait) or
// next to each other (landscape)
Flow {
id: flow
anchors.top: header.bottom
width: parent.width
Column {
id: column
anchors {
top: header.bottom
horizontalCenter: parent.horizontalCenter
}
width: parent.width - 2*Theme.horizontalPageMargin
spacing: Theme.paddingLarge
ComboBox {
width: page.isPortrait ? page.width : page.width / 2
label: qsTr("Log level")
currentIndex: 0
menu: ContextMenu {
@ -71,7 +56,10 @@ Page {
}
Row {
width: page.isPortrait ? page.width : page.width / 2
anchors {
left: parent.left
right: parent.right
}
height: updateButton.height
Column {
@ -80,7 +68,7 @@ Page {
id: updateButton
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Update")
onClicked: logView.updateText()
onClicked: logLabel.updateText()
}
}
Column {
@ -89,65 +77,19 @@ Page {
id: daemonStopButton
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Copy")
onClicked: Clipboard.text = logView.text
onClicked: Clipboard.text = logLabel.text
}
}
}
}
ColumnView {
id: logView
anchors {
top: flow.bottom
topMargin: Theme.paddingLarge
left: parent.left
right: parent.right
leftMargin: Theme.horizontalPageMargin
}
itemHeight: metrics.height
clip: true
model: ListModel {}
delegate: Component {
Label {
clip: true
text: line
width: logView.width
wrapMode: TextEdit.NoWrap
truncationMode: TruncationMode.Fade
font.bold: true
font.pixelSize: Theme.fontSizeTiny
color: {
switch (text.split(" ")[1]) {
case "Charger:":
return Theme.highlightFromColor("yellow", Theme.colorScheme)
case "State:":
return Theme.highlightFromColor("red", Theme.colorScheme)
case "Temperature:":
return Theme.highlightFromColor("orange", Theme.colorScheme)
case "Health:":
return Theme.highlightFromColor("blue", Theme.colorScheme)
case "Battery:":
return Theme.highlightFromColor("green", Theme.colorScheme)
}
font.bold = false
return Theme.secondaryColor
}
MyLabel {
id: logLabel
text: logger.readLogfile(settings.logFilename)
font.pixelSize: Theme.fontSizeTiny
function updateText() {
logLabel.text = logger.readLogfile(settings.logFilename)
}
}
// ColumnView only instantiates and renders delegates
// as they are about to be shown, so we can
// simply dump the full log at it.
Component.onCompleted: updateText()
property string text: ""
function updateText() {
model.clear()
logView.text = logger.readLogfile(settings.logFilename)
logView.text.split("\n").forEach(
function(str) {
model.append({ "line": str })
}
);
}
}
}
}

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2023 Matti Viljanen
* 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
@ -15,8 +15,9 @@
*
* Author: Matti Viljanen
*/
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
import Process 1.0
import "../components"
Page {
@ -40,11 +41,6 @@ Page {
}
property bool serviceRunning: true
SystemdUserService {
id: batteryService
serviceName: 'harbour-batterybuddy.service'
}
Timer {
id: startupTimer
interval: 1
@ -52,10 +48,58 @@ Page {
running: true
onTriggered: {
if(logger.debug) logger.log("Startup timer started")
daemonStatus.start()
pageStack.pushAttached(Qt.resolvedUrl("SettingsPage.qml"))
}
}
Timer {
id: daemonControl
interval: 1
running: false
repeat: false
onTriggered: {
var action = serviceRunning ? "stop" : "start"
if(logger.debug) logger.log("Action: " + action)
_controlProcess.start("systemctl", ["--user", action, "harbour-batterybuddy.service"])
}
}
Process {
// Only used by daemonControl timer
id: _controlProcess
onFinished: {
daemonStatus.start()
if(logger.debug) logger.log("Service control return code " + errorCode())
}
}
Timer {
id: daemonStatus
interval: 1
running: false
repeat: false
onTriggered: {
_statusProcess.start("systemctl", ["--user", "status", "harbour-batterybuddy.service"])
}
}
Process {
// Only used by daemonStatus timer
id: _statusProcess
onFinished: {
if(errorCode() === 0) {
serviceRunning = true
daemonStopButton.enabled = true
}
else {
serviceRunning = false
daemonStartButton.enabled = true
}
if(logger.debug) logger.log("Service status return code " + errorCode())
}
}
// To enable PullDownMenu, place our content in a SilicaFlickable
SilicaFlickable {
id: mainFlickable
@ -69,14 +113,6 @@ Page {
text: qsTr("Background", "More to read, background information...")
onClicked: pageStack.push(Qt.resolvedUrl("InfoPage.qml"))
}
MenuItem {
text: qsTr("About", "About this application")
onClicked: pageStack.push(Qt.resolvedUrl("AboutPage.qml"))
}
MenuItem {
text: qsTr("View log")
onClicked: pageStack.push(Qt.resolvedUrl("LogPage.qml"))
}
}
// Place our content in a Column. The PageHeader is always placed at the top
@ -114,7 +150,6 @@ Page {
rotation: 90
width: parent.width * 0.2
anchors.centerIn: parent
enableLowBatteryAnimation: Qt.application.active
}
}
// Detail column
@ -132,15 +167,8 @@ Page {
}
MyDetailItem {
property bool connected: (battery.chargerConnected || battery.acConnected)
property string chargerType: {
if ( battery.chargerConnected && !battery.acConnected) { return qsTr("USB") }
else if (!battery.chargerConnected && battery.acConnected) { return qsTr("AC") }
else if ( battery.chargerConnected && battery.acConnected) { return qsTr("USB") + "/" + qsTr("AC") }
return "unknown power source"
}
label: qsTr("Charger connected:")
value: connected ? (qsTr("yes") + " (" + chargerType + ")") : qsTr("no")
value: battery.chargerConnected ? qsTr("yes") : qsTr("no")
}
MyDetailItem {
label: qsTr("State:")
@ -155,6 +183,13 @@ Page {
label: qsTr("Temperature:")
value: battery.temperature === 0x7FFFFFFF ? healthText["unknown"] : formatTemperature(battery.temperature)
visible: battery.temperature !== 0x7FFFFFFF
function formatTemperature(temp) {
if(Qt.locale().measurementSystem === Locale.ImperialUSSystem) {
return Math.floor((battery.temperature / 10) * 1.8 + 32) + " °F"
}
return Math.floor(battery.temperature / 10) + " °C"
}
}
}
}
@ -188,8 +223,11 @@ Page {
id: daemonStartButton
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Start")
onClicked: batteryService.startService()
enabled: batteryService.serviceState !== "active"
onClicked: {
daemonControl.start()
enabled = false
}
enabled: false
}
}
Column {
@ -198,8 +236,11 @@ Page {
id: daemonStopButton
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Stop")
onClicked: batteryService.stopService()
enabled: batteryService.serviceState === "active"
onClicked: {
daemonControl.start()
enabled = false
}
enabled: false
}
}
}

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -15,20 +15,16 @@
*
* Author: Matti Viljanen
*/
import QtQuick 2.6
import QtQuick 2.2
import Sailfish.Silica 1.0
import Process 1.0
import "../components"
Page {
id: settingsPage
allowedOrientations: Orientation.Portrait | Orientation.Landscape | Orientation.LandscapeInverted
SystemdUserService {
id: batteryService
serviceName: 'harbour-batterybuddy.service'
onServiceMaskedChanged: {
daemonEnabledSwitch.busy = false
}
Component.onCompleted: {
}
//////////////////////////////////////////////////
@ -44,17 +40,62 @@ Page {
running: true
onTriggered: {
autoStopCharging.checked = settings.limitEnabled
maxChargeCurrentSlider.value = settings.maxChargeCurrent
highLimitSlider.value = settings.highLimit
lowLimitSlider.value = settings.lowLimit
highAlertSlider.value = settings.highAlert
healthSelector.currentIndex = settings.healthAlert
lowAlertSlider.value = settings.lowAlert
highIntervalCombo.currentIndex = settings.highNotificationsInterval
lowIntervalCombo.currentIndex = settings.lowNotificationsInterval
healthIntervalCombo.currentIndex = settings.healthNotificationsInterval
highIntervalSlider.value = settings.highNotificationsInterval
lowIntervalSlider.value = settings.lowNotificationsInterval
healthIntervalSlider.value = settings.healthNotificationsInterval
if(logger.debug) logger.log("SettingsPage values updated")
batteryService.queryEnabled()
daemonCheck.start()
}
}
Timer {
id: daemonToggle
interval: 100
running: false
repeat: false
onTriggered: {
var action = daemonEnabledSwitch.checked ? "disable" : "enable"
if(logger.verbose) logger.log("Action: " + action)
_toggleProcess.start("systemctl", ["--user", action, "harbour-batterybuddy.service"])
}
}
Process {
// Only used by daemonToggle timer
id: _toggleProcess
onFinished: {
daemonCheck.start()
if(logger.debug) logger.log("Service toggle " + (errorCode() === 0 ? "succeeded" : "failed"))
}
}
Timer {
id: daemonCheck
interval: 0
running: false
repeat: false
onTriggered: {
_checkProcess.start("systemctl", ["--user", "is-enabled", "harbour-batterybuddy.service"])
}
}
Process {
// Only used by daemonCheck timer
id: _checkProcess
onFinished: {
if(errorCode() === 0) {
daemonEnabledSwitch.checked = true
}
else {
daemonEnabledSwitch.checked = false
}
daemonEnabledSwitch.busy = false
if(logger.verbose) logger.log("Service is " + (errorCode() === 0 ? "enabled" : "disabled"))
}
}
@ -68,6 +109,17 @@ Page {
anchors.fill: parent
contentHeight: flow.height + Theme.horizontalPageMargin
PullDownMenu {
MenuItem {
text: qsTr("View log")
onClicked: pageStack.push(Qt.resolvedUrl("LogPage.qml"))
}
MenuItem {
text: qsTr("About", "About this application")
onClicked: pageStack.push(Qt.resolvedUrl("AboutPage.qml"))
}
}
Flow {
id: flow
anchors {
@ -101,13 +153,11 @@ Page {
TextSwitch {
id: daemonEnabledSwitch
text: qsTr("Start background service at startup")
checked: batteryService.serviceMasked === "loaded"
checked: true
onClicked: {
if(checked)
batteryService.enableService()
else
batteryService.disableService()
busy = true
checked = !checked
daemonToggle.start()
}
}
Label {
@ -182,24 +232,6 @@ Page {
smallChange: 1
largeChange: 5
}
SectionHeader {
text: qsTr("Maximum Charge Current")
visible: settings.maxSupportedChargeCurrent > 0
}
MySlider {
id: maxChargeCurrentSlider
visible: settings.maxSupportedChargeCurrent > 0
minimumValue: 500000
maximumValue: settings.maxSupportedChargeCurrent
stepSize: 100000
valueText: (value / 1000) + "mA"
onReleased: save()
function save() {
settings.maxChargeCurrent = value
}
}
}
//////////////////////////////////////////////////
@ -282,52 +314,60 @@ Page {
SectionHeader { text: qsTr("Battery high notification interval") }
ComboBox {
id: highIntervalCombo
label: qsTr("Battery high notification interval")
menu: ContextMenu {
Repeater {
model: frequencyNames
MenuItem {
enabled: index > 0
visible: index > 0
text: modelData
onClicked: {
highIntervalCombo.currentIndex = index
highIntervalCombo.save()
}
}
}
MySlider {
id: highIntervalSlider
minimumValue: 50
maximumValue: 610
stepSize: 10
valueText: updateValueText()
onValueChanged: updateValueText()
function updateValueText() {
if(value == 50)
return qsTr("Once")
if(value == 610)
return qsTr("Never")
return Math.floor(value / 60) + (value % 60 < 10 ? ":0" + value % 60 : ":" + value % 60)
}
onReleased: save()
function save() {
settings.highNotificationsInterval = currentIndex
settings.highNotificationsInterval = value
}
}
AdjustmentButtons {
targetSlider: highIntervalSlider
smallChange: 10
largeChange: 60
}
SectionHeader { text: qsTr("Battery low notification interval") }
ComboBox {
id: lowIntervalCombo
label: qsTr("Battery low notification interval")
menu: ContextMenu {
Repeater {
model: frequencyNames
MenuItem {
enabled: index > 0
visible: index > 0
text: modelData
onClicked: {
lowIntervalCombo.currentIndex = index
lowIntervalCombo.save()
}
}
}
MySlider {
id: lowIntervalSlider
minimumValue: 50
maximumValue: 610
stepSize: 10
valueText: updateValueText()
onValueChanged: updateValueText()
function updateValueText() {
if(value == 50)
return qsTr("Once")
if(value == 610)
return qsTr("Never")
return Math.floor(value / 60) + (value % 60 < 10 ? ":0" + value % 60 : ":" + value % 60)
}
onReleased: save()
function save() {
settings.lowNotificationsInterval = currentIndex
settings.lowNotificationsInterval = value
}
}
AdjustmentButtons {
targetSlider: lowIntervalSlider
smallChange: 10
largeChange: 60
}
Label {
x: Theme.paddingLarge
text: qsTr("Health notification settings")
@ -351,7 +391,7 @@ Page {
ComboBox {
id: healthSelector
width: parent.width
label: qsTr("Notification threshold")
label: qsTr("Notification treshold")
currentIndex: settings.healthAlert
menu: ContextMenu {
MenuItem { text: qsTr("Never") }
@ -366,27 +406,31 @@ Page {
SectionHeader { text: qsTr("Health notification interval") }
ComboBox {
id: healthIntervalCombo
label: qsTr("Health notification interval")
menu: ContextMenu {
Repeater {
model: frequencyNames
MenuItem {
enabled: index > 0
visible: index > 0
text: modelData
onClicked: {
healthIntervalCombo.currentIndex = index
healthIntervalCombo.save()
}
}
}
MySlider {
id: healthIntervalSlider
minimumValue: 50
maximumValue: 610
stepSize: 10
valueText: updateValueText()
onValueChanged: updateValueText()
function updateValueText() {
if(value == 50)
return qsTr("Once")
if(value == 610)
return qsTr("Never")
return Math.floor(value / 60) + (value % 60 < 10 ? ":0" + value % 60 : ":" + value % 60)
}
onReleased: save()
function save() {
settings.healthNotificationsInterval = currentIndex
settings.healthNotificationsInterval = value
}
}
AdjustmentButtons {
targetSlider: healthIntervalSlider
smallChange: 10
largeChange: 60
}
}
}
}

View file

@ -1,6 +1,6 @@
# Battery Buddy, a Sailfish application to prolong battery lifetime
#
# Copyright (C) 2019-2022 Matti Viljanen
# 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

View file

@ -1,6 +1,6 @@
# Battery Buddy, a Sailfish application to prolong battery lifetime
#
# Copyright (C) 2019-2022 Matti Viljanen
# 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

View file

@ -2,7 +2,7 @@
# Battery Buddy, a Sailfish application to prolong battery lifetime
#
# Copyright (C) 2019-2022 Matti Viljanen
# 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
@ -18,7 +18,5 @@
chmod 644 /sys/class/power_supply/battery/input_suspend 2>/dev/null
chmod 644 /sys/class/power_supply/battery/charging_enabled 2>/dev/null
chmod 644 /sys/class/power_supply/battery/constant_charge_current_max 2>/dev/null
chmod 644 /sys/class/power_supply/usb/charger_disable 2>/dev/null
chmod 644 /sys/class/power_supply/dollar_cove_battery/enable_charging 2>/dev/null
exit 0

View file

@ -2,7 +2,7 @@
# Battery Buddy, a Sailfish application to prolong battery lifetime
#
# Copyright (C) 2019-2022 Matti Viljanen
# 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
@ -18,7 +18,5 @@
chmod 666 /sys/class/power_supply/battery/input_suspend 2>/dev/null
chmod 666 /sys/class/power_supply/battery/charging_enabled 2>/dev/null
chmod 666 /sys/class/power_supply/battery/constant_charge_current_max 2>/dev/null
chmod 666 /sys/class/power_supply/usb/charger_disable 2>/dev/null
chmod 666 /sys/class/power_supply/dollar_cove_battery/enable_charging 2>/dev/null
exit 0

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2023 Matti Viljanen
* 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
@ -21,147 +21,64 @@ Battery::Battery(Settings* newSettings, Logger* newLogger, QObject* parent) : QO
{
settings = newSettings;
logger = newLogger;
const QString notFound = "not found";
// Battery charge percentage, number, e.g. 42
const QStringList batteryFiles = {
"/sys/class/power_supply/battery/capacity",
"/sys/class/power_supply/dollar_cove_battery/capacity"
};
foreach(const QString& file, batteryFiles) {
if(!chargeFile && QFile::exists(file)) {
chargeFile = new QFile(file, this);
break;
}
}
logL("Battery charge file: " + (chargeFile ? chargeFile->fileName() : notFound));
// Number: charge percentage, e.g. 42
chargeFile = new QFile("/sys/class/power_supply/battery/capacity", this);
logE("Capacity file: " + chargeFile->fileName());
// Number: battery/charging current, e.g. -1450000 (-145mA)
const QStringList currentFiles = {
"/sys/class/power_supply/battery/current_now",
"/sys/class/power_supply/dollar_cove_battery/current_now"
};
foreach(const QString& file, currentFiles) {
if(!currentFile && QFile::exists(file)) {
currentFile = new QFile(file, this);
break;
}
}
logL("Charging/discharging current file: " + (currentFile ? currentFile->fileName() : notFound));
currentFile = new QFile("/sys/class/power_supply/battery/current_now", this);
logE("Charge state file: " + currentFile->fileName());
// String: charging, discharging, full, empty, unknown (others?)
const QStringList stateFiles = {
"/sys/class/power_supply/battery/status",
"/sys/class/power_supply/dollar_cove_battery/status"
};
foreach(const QString& file, stateFiles) {
if(!stateFile && QFile::exists(file)) {
stateFile = new QFile(file, this);
break;
}
}
logL("Status file: " + (stateFile ? stateFile->fileName() : notFound));
stateFile = new QFile("/sys/class/power_supply/battery/status", this);
logE("Charger status file: " + stateFile->fileName());
// Number: 0 or 1
const QStringList usbPresentFiles = {
"/sys/class/power_supply/usb/present",
"/sys/class/power_supply/dollar_cove_charger/present"
};
chargerConnectedFile = new QFile("/sys/class/power_supply/usb/present", this);
logE("Reading charger status from" + chargerConnectedFile->fileName());
foreach(const QString& file, usbPresentFiles) {
if(!chargerConnectedFile && QFile::exists(file)) {
chargerConnectedFile = new QFile(file, this);
break;
}
}
logL("Charger status file: " + (chargerConnectedFile ? chargerConnectedFile->fileName() : notFound));
// Number: 0 or 1
const QStringList acPresentFiles = {
"/sys/class/power_supply/ac/present"
};
foreach(const QString& file, acPresentFiles) {
if(!acConnectedFile && QFile::exists(file)) {
acConnectedFile = new QFile(file, this);
break;
}
}
logL("AC status file: " + (acConnectedFile ? acConnectedFile->fileName() : notFound));
QString filename;
// Number: temperature
const QStringList tempFiles = {
"/sys/class/power_supply/battery/temp",
"/sys/class/power_supply/dollar_cove_battery/temp"
};
foreach(const QString& file, tempFiles) {
if(!temperatureFile && QFile::exists(file)) {
temperatureFile = new QFile(file, this);
break;
}
filename = "/sys/class/power_supply/battery/temp";
if(!temperatureFile && QFile::exists(filename)) {
temperatureFile = new QFile(filename, this);
}
logL("Battery temperature file: " + (temperatureFile ? temperatureFile->fileName() : notFound));
// String: health state
const QStringList healthFiles = {
"/sys/class/power_supply/battery/health",
"/sys/class/power_supply/dollar_cove_battery/health"
};
foreach(const QString& file, healthFiles) {
if(!healthFile && QFile::exists(file)) {
healthFile = new QFile(file, this);
break;
}
filename = "/sys/class/power_supply/battery/health";
if(!healthFile && QFile::exists(filename)) {
healthFile = new QFile(filename, this);
}
logL("Battery health file: " + (healthFile ? healthFile->fileName() : notFound));
// Charger control file
const QStringList controlFiles = {
"/sys/class/power_supply/battery/input_suspend", // e.g. Sony Xperia XA2
"/sys/class/power_supply/battery/charging_enabled", // e.g. for Sony Xperia Z3 Compact Tablet
"/sys/class/power_supply/usb/charger_disable", // e.g. for Jolla Phone
"/sys/class/power_supply/dollar_cove_battery/enable_charging" // e.g. for Jolla Tablet
};
foreach(const QString& file, controlFiles) {
if(!chargingEnabledFile && QFile::exists(file)) {
chargingEnabledFile = new QFile(file, this);
break;
}
// e.g. for Sony Xperia XA2
filename = "/sys/class/power_supply/battery/input_suspend";
if(!chargingEnabledFile && QFile::exists(filename)) {
chargingEnabledFile = new QFile(filename, this);
enableChargingValue = 0;
disableChargingValue = 1;
}
// Flip the charging control bits if necessary
if(chargingEnabledFile && chargingEnabledFile->fileName().contains("enable")) {
// e.g. for Sony Xperia Z3 Compact Tablet
filename = "/sys/class/power_supply/battery/charging_enabled";
if(!chargingEnabledFile && QFile::exists(filename)) {
chargingEnabledFile = new QFile(filename, this);
enableChargingValue = 1;
disableChargingValue = 0;
}
// If we found a usable file, check that it is writable
if(chargingEnabledFile) {
logL("Charger control file: " + chargingEnabledFile->fileName());
if(chargingEnabledFile->open(QIODevice::WriteOnly)) {
chargingEnabledFile->close();
}
else {
logL("Charger control file is not writable - feature disabled");
delete chargingEnabledFile;
chargingEnabledFile = Q_NULLPTR;
}
// e.g. for Jolla Phone
filename = "/sys/class/power_supply/usb/charger_disable";
if(!chargingEnabledFile && QFile::exists(filename)) {
chargingEnabledFile = new QFile(filename, this);
enableChargingValue = 0;
disableChargingValue = 1;
}
else {
logL("Charger control file: " + notFound);
logL("Please contact the developer with your device model!");
if(!chargingEnabledFile && !QHostInfo::localHostName().contains("SailfishEmul")) {
logE("Charger control file not found!");
logE("Please contact the developer with your device model!");
}
updateData();
@ -176,81 +93,62 @@ void Battery::updateData()
if(nextCharge != charge) {
charge = nextCharge;
emit chargeChanged(charge);
logM(QString("Battery: %1%").arg(charge));
logV(QString("Battery: %1%").arg(charge));
}
chargeFile->close();
}
if(chargerConnectedFile && chargerConnectedFile->open(QIODevice::ReadOnly)) {
nextChargerConnected = chargerConnectedFile->readLine().trimmed().toInt();
if(nextChargerConnected != chargerConnected) {
chargerConnected = nextChargerConnected;
emit chargerConnectedChanged(chargerConnected);
logM(QString("Charger: %1").arg(chargerConnected ? "connected" : "disconnected"));
logV(QString("Charger: %1").arg(chargerConnected ? "connected" : "disconnected"));
}
chargerConnectedFile->close();
}
if(acConnectedFile && acConnectedFile->open(QIODevice::ReadOnly)) {
nextAcConnected = acConnectedFile->readLine().trimmed().toInt();
if(nextAcConnected != acConnected) {
acConnected = nextAcConnected;
emit acConnectedChanged(acConnected);
logM(QString("AC: %1").arg(acConnected ? "connected" : "disconnected"));
}
acConnectedFile->close();
}
if(stateFile && stateFile->open(QIODevice::ReadOnly)) {
nextState = (QString(stateFile->readLine().trimmed().toLower()));
if(nextState != state) {
state = nextState;
emit stateChanged(state);
logM("State: " + state);
logV("State: " + state);
}
stateFile->close();
}
if(currentFile && currentFile->open(QIODevice::ReadOnly)) {
current = currentFile->readLine().trimmed().toInt();
if(!invertDecided) {
invertCurrent = (!chargerConnected && !acConnected && current > 10);
if(invertCurrent) logL("Battery current inverted");
else logL("Battery current not inverted");
invertDecided = true;
nextCurrent = currentFile->readLine().trimmed().toInt();
if(nextCurrent != current) {
current = nextCurrent;
emit currentChanged(current);
logD(QString("Current: %1mA").arg(current / 1000));
}
current = current * (invertCurrent ? -1 : 1);
emit currentChanged(current);
logH(QString("Current: %1mA").arg(current / 1000));
currentFile->close();
}
if(healthFile && healthFile->open(QIODevice::ReadOnly)) {
nextHealth = (QString(healthFile->readLine().trimmed().toLower()));
if(nextHealth != health) {
health = nextHealth;
emit healthChanged(health);
logM("Health: " + health);
logV("Health: " + health);
}
healthFile->close();
}
if(temperatureFile && temperatureFile->open(QIODevice::ReadOnly)) {
nextTemperature = temperatureFile->readLine().trimmed().toInt();
if(nextTemperature != temperature) {
temperature = nextTemperature;
emit temperatureChanged(temperature);
logH(QString("Temperature: %1°C").arg(temperature / 10));
// TODO: factor might be different depending on device
// X10 has degrees * 10
logD(QString("Temperature: %1°C").arg(temperature / 10));
}
temperatureFile->close();
}
}
int Battery::getCharge() { return charge; }
int Battery::getCharge(){ return charge; }
int Battery::getCurrent() { return current; }
int Battery::getMaxChargeCurrent() { return maxChargeCurrent; }
int Battery::getCurrent(){ return current; }
QString Battery::getState() { return state; }
@ -261,5 +159,3 @@ int Battery::getTemperature(){ return temperature; }
bool Battery::getChargingEnabled() { return chargingEnabled; }
bool Battery::getChargerConnected() { return chargerConnected; }
bool Battery::getAcConnected() { return acConnected; }

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2023 Matti Viljanen
* 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
@ -22,8 +22,9 @@
#include <QString>
#include <QFile>
#include <QStandardPaths>
#include <QSysInfo>
#include <QHostInfo>
#include "settings.h"
#include "process.h"
#include "logger.h"
class Battery : public QObject
@ -31,9 +32,7 @@ class Battery : public QObject
Q_OBJECT
Q_PROPERTY(int charge READ getCharge NOTIFY chargeChanged)
Q_PROPERTY(int current READ getCurrent NOTIFY currentChanged)
Q_PROPERTY(int maxChargeCurrent READ getMaxChargeCurrent)
Q_PROPERTY(bool chargerConnected READ getChargerConnected NOTIFY chargerConnectedChanged)
Q_PROPERTY(bool acConnected READ getAcConnected NOTIFY acConnectedChanged)
Q_PROPERTY(QString state READ getState NOTIFY stateChanged)
Q_PROPERTY(bool chargingEnabled READ getChargingEnabled NOTIFY chargingEnabledChanged)
@ -46,10 +45,8 @@ public:
int getCharge();
int getCurrent();
int getMaxChargeCurrent();
bool getCharging();
bool getChargerConnected();
bool getAcConnected();
QString getState();
QString getHealth();
@ -64,10 +61,8 @@ private:
QFile* chargeFile = nullptr;
QFile* currentFile = nullptr;
QFile* chargerConnectedFile = nullptr;
QFile* acConnectedFile = nullptr;
QFile* stateFile = nullptr;
QFile* chargingEnabledFile = nullptr;
QFile* maxChargeCurrentFile = nullptr;
Settings* settings = nullptr;
Logger* logger = nullptr;
@ -78,10 +73,9 @@ private:
int charge = 100; // 100% full
int current = 0; // Not charging/discharging
bool chargerConnected = false; // Charger plugged in
bool acConnected = false; // AC plugged in
QString state = "idle"; // dis/charging, idle, unknown
bool chargingEnabled = true; // Only ever disabled manually
int maxChargeCurrent = 0; // Charge current limit in micro amps
QString health = "unknown"; // Good, warm, overheat. Might have Cold or Overvoltage depending on driver
int temperature = 0x7FFFFFFF; // This value means "unknown" (32-bit INT_MAX)
@ -91,15 +85,11 @@ private:
bool chargerIsEnabled = true;
int nextCharge = charge;
bool invertCurrent = false;
bool invertDecided = false;
int nextCurrent = current;
bool nextChargerConnected = chargerConnected;
bool nextAcConnected = acConnected;
QString nextState = state;
bool nextChargingEnabled = chargingEnabled;
QString nextHealth = health;
int nextTemperature = temperature;
@ -109,7 +99,6 @@ signals:
void stateChanged(QString);
void chargingEnabledChanged(bool);
void chargerConnectedChanged(bool);
void acConnectedChanged(bool);
void healthChanged(QString);
void temperatureChanged(int);
};

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -26,7 +26,6 @@
#include <QQuickView>
#include <QQmlEngine>
#include <QTimer>
#include <QStringList>
#include "logger.h"
#include "battery.h"
@ -47,7 +46,7 @@ int main(int argc, char *argv[])
bool verbose = false;
bool debug = false;
if(QSysInfo::machineHostName().contains("SailfishEmul")) {
if(QHostInfo::localHostName().contains("SailfishEmul")) {
verbose = true;
debug = true;
}
@ -68,17 +67,14 @@ int main(int argc, char *argv[])
else if(!strcmp(argv[i],"--help")) {
printf("%s %s\n", APP_NAME, APP_VERSION);
printf("Usage:\n");
printf(" --verbose Set log level to medium)\n");
printf(" --debug Set log level to high\n");
printf(" --verbose Enable informational messages\n");
printf(" --debug Enable informational and debugging messages\n");
printf(" --help Print version string and exit\n");
return 0;
}
}
QGuiApplication* app = SailfishApp::application(argc, argv);
app->setApplicationName(APP_NAME);
app->setOrganizationName(APP_NAME);
QQuickView* view = SailfishApp::createView();
Logger *logger = new Logger(verbose, debug, false);
@ -89,28 +85,12 @@ int main(int argc, char *argv[])
QObject::connect(updater, SIGNAL(timeout()), battery, SLOT(updateData()));
updater->start(3000);
const QStringList frequencyNames = {
QObject::tr("Never"),
QObject::tr("30 seconds"),
QObject::tr("2.5 minutes"),
QObject::tr("5 minutes"),
QObject::tr("10 minutes"),
QObject::tr("15 minutes"),
QObject::tr("30 minutes"),
QObject::tr("1 hour"),
QObject::tr("2 hours"),
QObject::tr("4 hours"),
QObject::tr("8 hours"),
QObject::tr("10 hours"),
QObject::tr("12 hours"),
QObject::tr("24 hours"),
};
qmlRegisterType<Process>("Process", 1, 0, "Process");
view->rootContext()->setContextProperty("battery", battery);
view->rootContext()->setContextProperty("settings", settings);
view->rootContext()->setContextProperty("logger", logger);
view->rootContext()->setContextProperty("app_version", APP_VERSION);
view->rootContext()->setContextProperty("frequencyNames", frequencyNames);
view->setSource(SailfishApp::pathTo("qml/harbour-batterybuddy.qml"));
view->showFullScreen();

38
application/src/process.h Normal file
View file

@ -0,0 +1,38 @@
#ifndef PROCESS_H
#define PROCESS_H
// Source: http://www.xargs.com/qml/process.html
// Copyright © 2015 John Temples
#include <QProcess>
#include <QVariant>
class Process : public QProcess {
Q_OBJECT
public:
Process(QObject *parent = nullptr) : QProcess(parent) { }
Q_INVOKABLE void start(const QString &program, const QVariantList &arguments) {
QStringList args;
// convert QVariantList from QML to QStringList for QProcess
for (int i = 0; i < arguments.length(); i++)
args << arguments[i].toString();
QProcess::start(program, args);
QProcess::waitForStarted(1000);
QProcess::waitForFinished(1000);
}
Q_INVOKABLE QByteArray readAll() {
return QProcess::readAll();
}
Q_INVOKABLE int errorCode() {
return QProcess::exitCode();
}
};
#endif // PROCESS_H

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2023 Matti Viljanen
* 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
@ -26,20 +26,18 @@ Settings::Settings(Logger *newLogger, QObject *parent) : QObject(parent)
logger = newLogger;
logM("Using " + mySettings->fileName());
logV("Using " + mySettings->fileName());
// Read in the values
loadInteger(sLowAlert, lowAlert, 5, 99);
loadInteger(sHighAlert, highAlert, 6, 100);
loadInteger(sHealthAlert, healthAlert, 0, 2);
loadInteger(sHighNotificationsInterval, highNotificationsInterval, 0, 13);
loadInteger(sLowNotificationsInterval, lowNotificationsInterval, 0, 13);
loadInteger(sHealthNotificationsInterval, healthNotificationsInterval, 0, 13);
loadInteger(sHighNotificationsInterval, highNotificationsInterval, 50, 610);
loadInteger(sLowNotificationsInterval, lowNotificationsInterval, 50, 610);
loadInteger(sHealthNotificationsInterval, healthNotificationsInterval, 50, 610);
loadInteger(sLimitEnabled, limitEnabled, 0, 1);
loadInteger(sLowLimit, lowLimit, 5, 99);
loadInteger(sHighLimit, highLimit, 6, 100);
loadInteger(sMaxSupportedChargeCurrent, maxSupportedChargeCurrent, 0, 5000000);
loadInteger(sMaxChargeCurrent, maxChargeCurrent, 0, maxSupportedChargeCurrent);
loadInteger(sLogLevel, logLevel, 0, 2);
loadString(sLogFilename, logFilename);
@ -62,7 +60,7 @@ Settings::Settings(Logger *newLogger, QObject *parent) : QObject(parent)
Settings::~Settings()
{
mySettings->sync();
logM(QString("Settings saved: %1").arg(mySettings->status() == QSettings::NoError));
logV(QString("Settings saved: %1").arg(mySettings->status() == QSettings::NoError));
}
// Getters condensed.
@ -74,8 +72,6 @@ int Settings::getLowNotificationsInterval() { return lowNotificationsInte
int Settings::getHealthNotificationsInterval() { return healthNotificationsInterval; }
int Settings::getLowLimit() { return lowLimit; }
int Settings::getHighLimit() { return highLimit; }
int Settings::getMaxChargeCurrent() { return maxChargeCurrent; }
int Settings::getMaxSupportedChargeCurrent() { return maxSupportedChargeCurrent; }
bool Settings::getLimitEnabled() { return limitEnabled == 1; }
QString Settings::getLowAlertFile() { return lowAlertFile; }
QString Settings::getHighAlertFile() { return highAlertFile; }
@ -84,9 +80,9 @@ QString Settings::getLogFilename() { return logFilename; }
QString Settings::getNotificationTitle() { return notificationTitle; }
QString Settings::getNotificationLowText() { return notificationLowText; }
QString Settings::getNotificationHighText() { return notificationHighText; }
QString Settings::getNotificationHealthTitle() { return notificationHealthTitle; }
QString Settings::getNotificationHealthWarnText() { return notificationHealthWarnText; }
QString Settings::getNotificationHealthCritText() { return notificationHealthCritText; }
QString Settings::getNotificationHealthTitle() { return notificationHealthTitle; }
QString Settings::getNotificationHealthWarnText() { return notificationHealthWarnText; }
QString Settings::getNotificationHealthCritText() { return notificationHealthCritText; }
int Settings::getLogLevel() { return logLevel; }
void Settings::setLowAlert(const int newLimit) {
@ -136,11 +132,6 @@ void Settings::setHighLimit(const int newLimit) {
emit highLimitChanged(highLimit);
}
void Settings::setMaxChargeCurrent(const int newCurrent) {
if(saveInteger(sMaxChargeCurrent, newCurrent, maxChargeCurrent))
emit maxChargeCurrentChanged(maxChargeCurrent);
}
void Settings::setLimitEnabled(const bool newEnabled) {
if(saveInteger(sLimitEnabled, (newEnabled ? 1 : 0), limitEnabled))
emit limitEnabledChanged(limitEnabled);
@ -185,33 +176,33 @@ bool Settings::loadInteger(const char *key, int &currValue, const int min, const
int newValue = mySettings->value(key, currValue).toInt();
newValue = (newValue <= min ? min : (newValue >= max ? max : newValue));
if(currValue == newValue) {
logH(QString("Load: %1 %2 (unchanged)").arg(key).arg(currValue));
logD(QString("Load: %1 %2 (unchanged)").arg(key).arg(currValue));
return false;
}
currValue = newValue;
logM(QString("Load: %1 %2").arg(key).arg(currValue));
logV(QString("Load: %1 %2").arg(key).arg(currValue));
return true;
}
bool Settings::loadString(const char *key, QString & currValue) {
QString newValue = mySettings->value(key, currValue).toString();
if(currValue == newValue) {
logH(QString("Load: %1 %2 (unchanged)").arg(key).arg(currValue));
logD(QString("Load: %1 %2 (unchanged)").arg(key).arg(currValue));
return false;
}
currValue = newValue;
logM(QString("Load: %1 %2").arg(key).arg(currValue));
logV(QString("Load: %1 %2").arg(key).arg(currValue));
return true;
}
bool Settings::saveInteger(const char* key, const int &newValue, int &currValue) {
if(currValue == newValue) {
logH(QString("Save: %1 %2 (unchanged)").arg(key).arg(currValue));
logD(QString("Save: %1 %2 (unchanged)").arg(key).arg(currValue));
return false;
}
currValue = newValue;
mySettings->setValue(key, QByteArray::number(newValue));
logM(QString("Save: %1 %2").arg(key).arg(newValue));
logV(QString("Save: %1 %2").arg(key).arg(newValue));
return true;
}
@ -221,6 +212,6 @@ bool Settings::saveString(const char* key, const QString &newValue, QString &cur
}
currValue = newValue;
mySettings->setValue(key, QString(newValue).replace("\"", "\\\"").toUtf8());
logM(QString("Save: %1 %2").arg(key).arg(newValue));
logV(QString("Save: %1 %2").arg(key).arg(newValue));
return true;
}

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -33,8 +33,6 @@ class Settings : public QObject
Q_PROPERTY(int healthNotificationsInterval READ getHealthNotificationsInterval WRITE setHealthNotificationsInterval NOTIFY healthNotificationsIntervalChanged)
Q_PROPERTY(int highLimit READ getHighLimit WRITE setHighLimit NOTIFY highLimitChanged)
Q_PROPERTY(int lowLimit READ getLowLimit WRITE setLowLimit NOTIFY lowLimitChanged)
Q_PROPERTY(int maxChargeCurrent READ getMaxChargeCurrent WRITE setMaxChargeCurrent NOTIFY maxChargeCurrentChanged)
Q_PROPERTY(int maxSupportedChargeCurrent READ getMaxSupportedChargeCurrent NOTIFY maxSupportedChargeCurrentChanged)
Q_PROPERTY(bool limitEnabled READ getLimitEnabled WRITE setLimitEnabled NOTIFY limitEnabledChanged)
Q_PROPERTY(QString highAlertFile READ getHighAlertFile NOTIFY highAlertFileChanged)
Q_PROPERTY(QString lowAlertFile READ getLowAlertFile NOTIFY lowAlertFileChanged)
@ -60,8 +58,6 @@ public:
int getHealthNotificationsInterval();
int getLowLimit();
int getHighLimit();
int getMaxChargeCurrent();
int getMaxSupportedChargeCurrent();
bool getLimitEnabled();
QString getLowAlertFile();
QString getHighAlertFile();
@ -83,7 +79,6 @@ public:
void setHealthNotificationsInterval(const int newInterval);
void setLowLimit(const int newLimit);
void setHighLimit(const int newLimit);
void setMaxChargeCurrent(const int newCurrent);
void setLimitEnabled(const bool newEnabled);
void setNotificationTitle(const QString newText);
void setNotificationLowText(const QString newText);
@ -108,8 +103,6 @@ private:
int limitEnabled = 1; // Converted to boolean for QML
int lowLimit = 65;
int highLimit = 70;
int maxChargeCurrent = 0; // micro amps
int maxSupportedChargeCurrent = 0; // micro amps
QString lowAlertFile = "/usr/share/sounds/jolla-ambient/stereo/general_warning.wav";
QString highAlertFile = "/usr/share/sounds/jolla-ambient/stereo/positive_confirmation.wav";
QString healthAlertFile = lowAlertFile;
@ -132,8 +125,6 @@ private:
const char* sLimitEnabled = "limitEnabled";
const char* sLowLimit = "lowLimit";
const char* sHighLimit = "highLimit";
const char* sMaxSupportedChargeCurrent = "maxSupportedChargeCurrent";
const char* sMaxChargeCurrent = "maxChargeCurrent";
const char* sLowAlertFile = "lowAlertFile";
const char* sHighAlertFile = "highAlertFile";
const char* sHealthAlertFile = "healthAlertFile";
@ -162,8 +153,6 @@ signals:
void limitEnabledChanged(bool);
void lowLimitChanged(int);
void highLimitChanged(int);
void maxChargeCurrentChanged(int);
void maxSupportedChargeCurrentChanged(int);
void lowAlertFileChanged(QString);
void highAlertFileChanged(QString);
void healthAlertFileChanged(QString);

View file

@ -7,6 +7,10 @@
<source>Battery Buddy is a small and simple utility designed to improve the lifetime of the battery.</source>
<translation>Battery Buddy ist ein kleines und einfaches Dienstprogramm, das dazu gedacht ist, die Lebensdauer des Akkus zu verlängern.</translation>
</message>
<message>
<source>Version</source>
<translation>Version</translation>
</message>
<message>
<source>View License</source>
<translation>Lizenz anzeigen</translation>
@ -27,13 +31,30 @@
<source>Translations</source>
<translation>Übersetzungen</translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>Contributors</source>
<translation type="unfinished"></translation>
<source>Charging</source>
<translatorcomment>Ggf. &quot;Wird geladen&quot;</translatorcomment>
<translation>Lade</translation>
</message>
<message>
<source>A modified version of %1 by %2 in the emoji pack %3 is used in the logo. License: %4</source>
<translation type="unfinished"></translation>
<source>Not charging</source>
<translatorcomment>ggf. &quot;Wird nicht geladen&quot;</translatorcomment>
<translation>Kein Ladevorgang</translation>
</message>
<message>
<source>Connect charger</source>
<translation>Ladegerät anschließen</translation>
</message>
<message>
<source>Disconnect charger</source>
<translation>Ladegerät trennen</translation>
</message>
<message>
<source>Battery Buddy</source>
<translation>Battery Buddy</translation>
</message>
</context>
<context>
@ -287,82 +308,6 @@
<comment>Battery is very cold</comment>
<translation>der Batterie ist sehr kalt</translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>Über</translation>
</message>
<message>
<source>View log</source>
<translation>Logdatei ansehen</translation>
</message>
<message>
<source>USB</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AC</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>Never</source>
<translation type="unfinished">Nie</translation>
</message>
<message>
<source>30 seconds</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>2.5 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>5 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>10 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>15 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>30 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>1 hour</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>2 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>4 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>8 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>10 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>12 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>24 hours</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
@ -380,15 +325,15 @@
</message>
<message>
<source>Battery health %1</source>
<translation>Batteriezustand</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery health is not good</source>
<translation>Batteriezustand ist nicht gut</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery health is critical</source>
<translation>Batteriezustand ist kritisch</translation>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -409,6 +354,11 @@
<source>Notification settings</source>
<translation>Benachrichtigungen</translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>Über</translation>
</message>
<message>
<source>Pause charging limit</source>
<translation>Aufladegrenze</translation>
@ -449,10 +399,18 @@
<source>Battery low notification interval</source>
<translation>Intervall bei niedriger Ladung</translation>
</message>
<message>
<source>Once</source>
<translation>Einmalig</translation>
</message>
<message>
<source>Never</source>
<translation>Nie</translation>
</message>
<message>
<source>View log</source>
<translation>Logdatei ansehen</translation>
</message>
<message>
<source>Battery health notification</source>
<translation>Zustandsbenachrichtigung</translation>
@ -471,18 +429,14 @@
</message>
<message>
<source>Display visual and audible notifications when the battery status exceeds safe values.&lt;br /&gt;This usually means high (or low) temperature but can include other parameters depending on the hardware.</source>
<translation>Visuelle und akustische Benachrichtigungen anzeigen, wenn gewisse Schwellwerte erreicht werden. Meistens gilt das für die Temperatur, aber je nach Hardware können auch andere Faktoren zu einer Meldung führen.</translation>
<translation>Visuelle und akustische Benachrichtigungen anzeigen, wenn gewissen Schwellwerte erreicht werden. Meistens gilt das fuer die Temperatur, aber je nach Hardware koennen auch andere Faktoren zu einer Meldung fuehren.</translation>
</message>
<message>
<source>Health notification settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Notification threshold</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Maximum Charge Current</source>
<source>Notification treshold</source>
<translation type="unfinished"></translation>
</message>
</context>

View file

@ -7,6 +7,10 @@
<source>Battery Buddy is a small and simple utility designed to improve the lifetime of the battery.</source>
<translation>Battery Buddy on pieni ja yksinkertainen sovellus, jonka tarkoituksena on pidentää akun elinikää.</translation>
</message>
<message>
<source>Version</source>
<translation>Versio</translation>
</message>
<message>
<source>View License</source>
<translation>Näytä lisenssi</translation>
@ -27,13 +31,28 @@
<source>Translations</source>
<translation>Käännökset</translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>Contributors</source>
<translation>Avustajat</translation>
<source>Charging</source>
<translation>Akku latautuu</translation>
</message>
<message>
<source>A modified version of %1 by %2 in the emoji pack %3 is used in the logo. License: %4</source>
<translation>Logossa käytetään muokattua versiota tekijän %2 kuvasta %1, joka kuuluu emojipakettiin %3. Lisenssi: %4</translation>
<source>Not charging</source>
<translation>Akku ei latauksessa</translation>
</message>
<message>
<source>Connect charger</source>
<translation>Kytke laturi</translation>
</message>
<message>
<source>Disconnect charger</source>
<translation>Irrota laturi</translation>
</message>
<message>
<source>Battery Buddy</source>
<translation>Battery Buddy</translation>
</message>
</context>
<context>
@ -287,82 +306,6 @@
<source>Temperature:</source>
<translation>Lämpötila:</translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>Tietoja</translation>
</message>
<message>
<source>View log</source>
<translation>Näytä loki</translation>
</message>
<message>
<source>USB</source>
<translation>USB</translation>
</message>
<message>
<source>AC</source>
<translation>AC</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>Never</source>
<translation>Ei koskaan</translation>
</message>
<message>
<source>30 seconds</source>
<translation>30 sekuntia</translation>
</message>
<message>
<source>2.5 minutes</source>
<translation>2,5 minuuttia</translation>
</message>
<message>
<source>5 minutes</source>
<translation>5 minuuttia</translation>
</message>
<message>
<source>10 minutes</source>
<translation>10 minuuttia</translation>
</message>
<message>
<source>15 minutes</source>
<translation>15 minuuttia</translation>
</message>
<message>
<source>30 minutes</source>
<translation>30 minuuttia</translation>
</message>
<message>
<source>1 hour</source>
<translation>1 tunti</translation>
</message>
<message>
<source>2 hours</source>
<translation>2 tuntia</translation>
</message>
<message>
<source>4 hours</source>
<translation>4 tuntia</translation>
</message>
<message>
<source>8 hours</source>
<translation>8 tuntia</translation>
</message>
<message>
<source>10 hours</source>
<translation>10 tuntia</translation>
</message>
<message>
<source>12 hours</source>
<translation>12 tuntia</translation>
</message>
<message>
<source>24 hours</source>
<translation>24 tuntia</translation>
</message>
</context>
<context>
<name>Settings</name>
@ -409,6 +352,11 @@
<source>Notification settings</source>
<translation>Ilmoitusasetukset</translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>Tietoja</translation>
</message>
<message>
<source>Pause charging limit</source>
<translation>Latauksen keskeytysraja</translation>
@ -449,10 +397,18 @@
<source>Battery low notification interval</source>
<translation>Matalan varauksen ilmoituksen aikaväli</translation>
</message>
<message>
<source>Once</source>
<translation>Kerran</translation>
</message>
<message>
<source>Never</source>
<translation>Ei koskaan</translation>
</message>
<message>
<source>View log</source>
<translation>Näytä loki</translation>
</message>
<message>
<source>Display visual and audible notifications when the battery status exceeds safe values.&lt;br /&gt;This usually means high (or low) temperature but can include other parameters depending on the hardware.</source>
<translation>Näytä ilmoitukset ja toista hälytysääni, kun akun kunto ylittää normaalit rahat.&lt;br /&gt;Yleensä tämä tarkoittaa liian korkeaa (tai matalaa) lämpötilaa, mutta syitä voi olla muitakin, laitteistosta riippuen.</translation>
@ -478,12 +434,8 @@
<translation>Akun tilan ilmoitusten aikaväli</translation>
</message>
<message>
<source>Notification threshold</source>
<source>Notification treshold</source>
<translation>Ilmoitusten taso</translation>
</message>
<message>
<source>Maximum Charge Current</source>
<translation>Suurin latausvirta</translation>
</message>
</context>
</TS>

View file

@ -11,6 +11,10 @@
<source>Battery Buddy is a small and simple utility designed to improve the lifetime of the battery.</source>
<translation>Battery Buddy est un utilitaire léger et simple créé pour améliorer la durée de vie de la batterie.</translation>
</message>
<message>
<source>Version</source>
<translation>Version</translation>
</message>
<message>
<source>Battery Buddy is open source software licensed under the terms of the GNU General Public License.</source>
<translation>Battery Buddy est un logiciel libre sous licence GNU General Public License</translation>
@ -27,13 +31,28 @@
<source>Translations</source>
<translation>Traductions</translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>Contributors</source>
<translation type="unfinished"></translation>
<source>Connect charger</source>
<translation>Branchez le chargeur</translation>
</message>
<message>
<source>A modified version of %1 by %2 in the emoji pack %3 is used in the logo. License: %4</source>
<translation type="unfinished"></translation>
<source>Disconnect charger</source>
<translation>Débranchez le chargeur</translation>
</message>
<message>
<source>Battery Buddy</source>
<translation>Battery Buddy</translation>
</message>
<message>
<source>Charging</source>
<translation>Charge</translation>
</message>
<message>
<source>Not charging</source>
<translation>Ne charge pas</translation>
</message>
</context>
<context>
@ -287,82 +306,6 @@
<source>Temperature:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>À propos</translation>
</message>
<message>
<source>View log</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>USB</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AC</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>Never</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>30 seconds</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>2.5 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>5 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>10 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>15 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>30 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>1 hour</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>2 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>4 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>8 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>10 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>12 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>24 hours</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
@ -397,6 +340,11 @@
<source>Settings</source>
<translation>Paramètres</translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>À propos</translation>
</message>
<message>
<source>Charging settings</source>
<translation>Paramètres de charge</translation>
@ -449,10 +397,18 @@
<source>Battery low notification interval</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Once</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Never</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>View log</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Health notification settings</source>
<translation type="unfinished"></translation>
@ -465,6 +421,10 @@
<source>Battery health notification</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Notification treshold</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Warning</source>
<translation type="unfinished"></translation>
@ -477,13 +437,5 @@
<source>Health notification interval</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Notification threshold</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Maximum Charge Current</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -5,7 +5,11 @@
<name>AboutPage</name>
<message>
<source>Battery Buddy is a small and simple utility designed to improve the lifetime of the battery.</source>
<translation>A Battery Buddy egy apró és egyszerű segédprogram, amelyet az akkumulátor élettartamának növelése céljából alkottak.</translation>
<translation>A Battery Buddy egy apró és egyszerű segédprogram, amelyet az akkumulátor élethossza megnövelésének céljából alkottak.</translation>
</message>
<message>
<source>Version</source>
<translation>Verzió</translation>
</message>
<message>
<source>View License</source>
@ -27,13 +31,28 @@
<source>Translations</source>
<translation>Fordítások</translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>Contributors</source>
<translation>Közreműködők</translation>
<source>Charging</source>
<translation>Tölt</translation>
</message>
<message>
<source>A modified version of %1 by %2 in the emoji pack %3 is used in the logo. License: %4</source>
<translation>A logóban a(z) %3 emoji csomagban lévő %2 által alkotott %1 módosított változata került felhasználásra. Licenc: %4</translation>
<source>Not charging</source>
<translation>Nem tölt</translation>
</message>
<message>
<source>Connect charger</source>
<translation>Csatlakoztasd a töltőt</translation>
</message>
<message>
<source>Disconnect charger</source>
<translation>Húzd ki a töltőt</translation>
</message>
<message>
<source>Battery Buddy</source>
<translation>Battery Buddy</translation>
</message>
</context>
<context>
@ -44,7 +63,7 @@
</message>
<message>
<source>Battery Buddy is a small and simple utility designed to improve the lifetime of the battery.</source>
<translation>A Battery Buddy egy apró és egyszerű segédprogram, amelyet az akkumulátor élettartamának növelése céljából alkottak.</translation>
<translation>A Battery Buddy egy apró és egyszerű segédprogram, amelyet az akkumulátor élethossza megnövelésének céljából alkottak.</translation>
</message>
<message>
<source>It simply monitors the battery level and if it has been charged above the limit, it plays a sound and displays a notification.</source>
@ -257,112 +276,36 @@
<message>
<source>Good</source>
<comment>Battery is OK</comment>
<translation></translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Warm</source>
<comment>Battery is warm</comment>
<translation>Meleg</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Overheated</source>
<comment>Battery is very hot</comment>
<translation>Túlmelegedett</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cool</source>
<comment>Battery is cool</comment>
<translation>Hűvös</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cold</source>
<comment>Battery is very cold</comment>
<translation>Hideg</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Health:</source>
<translation>Egészség:</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Temperature:</source>
<translation>Hőmérséklet:</translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>Névjegy</translation>
</message>
<message>
<source>View log</source>
<translation>Naplózás megtekintése</translation>
</message>
<message>
<source>USB</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AC</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>Never</source>
<translation>Soha</translation>
</message>
<message>
<source>30 seconds</source>
<translation>30 másodperc</translation>
</message>
<message>
<source>2.5 minutes</source>
<translation>2,5 perc</translation>
</message>
<message>
<source>5 minutes</source>
<translation>5 perc</translation>
</message>
<message>
<source>10 minutes</source>
<translation>10 perc</translation>
</message>
<message>
<source>15 minutes</source>
<translation>15 perc</translation>
</message>
<message>
<source>30 minutes</source>
<translation>30 perc</translation>
</message>
<message>
<source>1 hour</source>
<translation>1 óra</translation>
</message>
<message>
<source>2 hours</source>
<translation>2 óra</translation>
</message>
<message>
<source>4 hours</source>
<translation>4 óra</translation>
</message>
<message>
<source>8 hours</source>
<translation>8 óra</translation>
</message>
<message>
<source>10 hours</source>
<translation>10 óra</translation>
</message>
<message>
<source>12 hours</source>
<translation>12 óra</translation>
</message>
<message>
<source>24 hours</source>
<translation>24 óra</translation>
</message>
</context>
<context>
<name>Settings</name>
@ -380,15 +323,15 @@
</message>
<message>
<source>Battery health %1</source>
<translation>Az akku egészségi állapota %1</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery health is not good</source>
<translation>Az akku egészségi állapota nem </translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery health is critical</source>
<translation>Az akku egészségi állapota kritikus</translation>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -409,6 +352,11 @@
<source>Notification settings</source>
<translation>Értesítés beállításai</translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>Névjegy</translation>
</message>
<message>
<source>Pause charging limit</source>
<translation>Töltés-szüneteltetési limit</translation>
@ -449,40 +397,44 @@
<source>Battery low notification interval</source>
<translation>Alacsony töltöttség értesítési intervalluma</translation>
</message>
<message>
<source>Once</source>
<translation>Egyszer</translation>
</message>
<message>
<source>Never</source>
<translation>Soha</translation>
</message>
<message>
<source>View log</source>
<translation>Napló megtekintése</translation>
</message>
<message>
<source>Health notification settings</source>
<translation>Egészségiállapot-értesítések beállításai</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Display visual and audible notifications when the battery status exceeds safe values.&lt;br /&gt;This usually means high (or low) temperature but can include other parameters depending on the hardware.</source>
<translation>Vizuális- és hangjelzések megjelenítése, ha az akkumulátor állapota túllépi a biztonságos értékeket.&lt;br /&gt;Ez általában magas (vagy alacsony) hőmérsékletet jelent, de a hardvertől függően egyéb paramétereket is tartalmazhat.</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery health notification</source>
<translation>Akku egészségiállapot-értesítés</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Notification treshold</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Warning</source>
<translation>Figyelmeztetés</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Critical</source>
<translation>Kritikus</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Health notification interval</source>
<translation>Egészségiállapot-értesítés intervalluma</translation>
</message>
<message>
<source>Notification threshold</source>
<translation>Értesítés küszöbértéke</translation>
</message>
<message>
<source>Maximum Charge Current</source>
<translation type="unfinished"></translation>
</message>
</context>

View file

@ -7,6 +7,10 @@
<source>Battery Buddy is a small and simple utility designed to improve the lifetime of the battery.</source>
<translation>Battery Buddy to małe i proste narzędzie zaprojektowane w celu wydłużenia żywotności baterii.</translation>
</message>
<message>
<source>Version</source>
<translation>Wersja</translation>
</message>
<message>
<source>View License</source>
<translation>Pokaż licencję</translation>
@ -27,13 +31,28 @@
<source>Translations</source>
<translation>Tłumaczenia</translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>Contributors</source>
<translation type="unfinished"></translation>
<source>Charging</source>
<translation>Ładowanie</translation>
</message>
<message>
<source>A modified version of %1 by %2 in the emoji pack %3 is used in the logo. License: %4</source>
<translation type="unfinished"></translation>
<source>Not charging</source>
<translation>Nie ładuje</translation>
</message>
<message>
<source>Connect charger</source>
<translation>Podłącz ładowarkę</translation>
</message>
<message>
<source>Disconnect charger</source>
<translation>Odłącz ładowarkę</translation>
</message>
<message>
<source>Battery Buddy</source>
<translation>Battery Buddy</translation>
</message>
</context>
<context>
@ -190,7 +209,7 @@
</message>
<message>
<source>Charge:</source>
<translation>Poziom naładowania:</translation>
<translation>Ładowanie:</translation>
</message>
<message>
<source>State:</source>
@ -257,110 +276,34 @@
<message>
<source>Good</source>
<comment>Battery is OK</comment>
<translation>Bateria jest sprawna</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Warm</source>
<comment>Battery is warm</comment>
<translation>Ciepła</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Overheated</source>
<comment>Battery is very hot</comment>
<translation>Gorąca</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cool</source>
<comment>Battery is cool</comment>
<translation>Chłodna</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cold</source>
<comment>Battery is very cold</comment>
<translation>Zamna</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Health:</source>
<translation>Stan:</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Temperature:</source>
<translation>Temperatura:</translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>O Battery Buddy</translation>
</message>
<message>
<source>View log</source>
<translation>Pokaż logi</translation>
</message>
<message>
<source>USB</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AC</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>Never</source>
<translation type="unfinished">Nigdy</translation>
</message>
<message>
<source>30 seconds</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>2.5 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>5 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>10 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>15 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>30 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>1 hour</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>2 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>4 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>8 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>10 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>12 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>24 hours</source>
<translation type="unfinished"></translation>
</message>
</context>
@ -380,15 +323,15 @@
</message>
<message>
<source>Battery health %1</source>
<translation>Stan baterii %1</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery health is not good</source>
<translation>Bateria jest w kiepskim stanie</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery health is critical</source>
<translation>Bateria jest w krytycznym stanie</translation>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -409,6 +352,11 @@
<source>Notification settings</source>
<translation>Ustawienia powiadomień</translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>O Battery Buddy</translation>
</message>
<message>
<source>Pause charging limit</source>
<translation>Wstrzymaj limit ładowania</translation>
@ -449,40 +397,44 @@
<source>Battery low notification interval</source>
<translation>Interwał powiadamiania o niskim poziomie naładowania</translation>
</message>
<message>
<source>Once</source>
<translation>Raz</translation>
</message>
<message>
<source>Never</source>
<translation>Nigdy</translation>
</message>
<message>
<source>View log</source>
<translation>Pokaż logi</translation>
</message>
<message>
<source>Health notification settings</source>
<translation>Ustawienia powiadomień o stanie</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Display visual and audible notifications when the battery status exceeds safe values.&lt;br /&gt;This usually means high (or low) temperature but can include other parameters depending on the hardware.</source>
<translation>Wyświetlaj powiadomienia wizualne i dźwiękowe, gdy stan baterii przekroczy bezpieczne wartości.&lt;br /&gt; Zwykle oznacza to wysoką (lub niską) temperaturę, ale może zawierać inne parametry w zależności od sprzętu. </translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery health notification</source>
<translation>Powiadomienia o stanie baterii</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Notification treshold</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Warning</source>
<translation>Ostrzeżenie</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Critical</source>
<translation>Krytyczny</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Health notification interval</source>
<translation>Interwał powiadomień o stanie</translation>
</message>
<message>
<source>Notification threshold</source>
<translation>Próg powiadomienia</translation>
</message>
<message>
<source>Maximum Charge Current</source>
<translation type="unfinished"></translation>
</message>
</context>

View file

@ -1,489 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="sk_SK">
<context>
<name>AboutPage</name>
<message>
<source>Battery Buddy is a small and simple utility designed to improve the lifetime of the battery.</source>
<translation>Battery Buddy je malá a jednoduchá pomôcka navrhnutá na predĺženie životnosti akumulátora.</translation>
</message>
<message>
<source>View License</source>
<translation>Zobraziť licenciu</translation>
</message>
<message>
<source>Battery Buddy is open source software licensed under the terms of the GNU General Public License.</source>
<translation>Battery Buddy je softvér s otvoreným zdrojovým kódom, na ktorý sa vzťahuje licencia GNU General Public License.</translation>
</message>
<message>
<source>Contributions and translations are always appreciated!</source>
<translation>Námety a preklady vítané!</translation>
</message>
<message>
<source>If you like my work and would like to support me, you can buy me a coffee!</source>
<translation>Ak sa Vám páči moja práca a chete ma podporiť, kúpte mi kávu!</translation>
</message>
<message>
<source>Translations</source>
<translation>Preklady</translation>
</message>
<message>
<source>Contributors</source>
<translation>Prispievatelia</translation>
</message>
<message>
<source>A modified version of %1 by %2 in the emoji pack %3 is used in the logo. License: %4</source>
<translation>Verzia %1 upravená %2 v balíku %3 je použitá v lugu. Licencia: %4</translation>
</message>
</context>
<context>
<name>InfoPage</name>
<message>
<source>What is Battery Buddy?</source>
<translation>Čo je Battery Buddy?</translation>
</message>
<message>
<source>Battery Buddy is a small and simple utility designed to improve the lifetime of the battery.</source>
<translation>Battery Buddy je malá a jednoduchá pomôcka navrhnutá na predĺženie životnosti akumulátora.</translation>
</message>
<message>
<source>It simply monitors the battery level and if it has been charged above the limit, it plays a sound and displays a notification.</source>
<translation>Jednoducho sleduje úroveň nabitia akumulátora a ak bol nabitý nad nastavenú hodotu, oznámi to zvukom a zobrazí oznam.</translation>
</message>
<message>
<source>A different sound is played and notification send when the battery has been discharged under the limit.</source>
<translation>Keď je akumulátor vybitý pod nastavenú hodnotu zaznie odlišný zvukový a obrazový oznam.</translation>
</message>
<message>
<source>Why does it matter?</source>
<translation>Prečo na tom záleží?</translation>
</message>
<message>
<source>Lithium-based batteries do not last forever. Every charge and discharge wear out the battery a small amount. This is normal and currently unavoidable.</source>
<translation>Akumulátory na báze lítia nevydržia večne. Každé nabitie a vybitie akumulátor mierne opotrebuje. To je normálne a momentálne sa tomu nedá vyhnúť.</translation>
</message>
<message>
<source>A full charge from 0% to 100% stresses the battery more than, say, charging from 25% to 75%.</source>
<translation>Úplné nabitie z 0% na 100% spôsobí akumulátoru väčšiu záťaž ako nabitie, povedzme, z 25% na 75%.</translation>
</message>
<message>
<source>Charging and discharging the battery lowers the capacity over time. Small discharge wears out the capacity slower than a deep discharge and a full recharge.</source>
<translation>Nabíjanie a vybíjanie postupne znižuje kapacitu akumulátora. Malé vybitie znižuje kapacitu menej ako výrazné alebo úplné vybitie.</translation>
</message>
<message>
<source>Is it noticable?</source>
<translation>Stojí to za povšimnutie?</translation>
</message>
<message>
<source>Yes, it is. If you always let the battery drain down to 0% and then charge it to 100%, your battery may not see 500 charge cycles.</source>
<translation>Áno. Ak vždy vyčerpáte akumulátor na 0% a potom ho nabijete na 100%, možno nevydrží ani 500 takýchto cyklov.</translation>
</message>
<message>
<source>If you only let the battery charge go down to 50% and then charge it to 70%, it could last several thousands of cycles!</source>
<translation>Ak vybijete akumulátor len na 50% a potom ho nabijete na 70%, môže vydržať niekoľko tisíc takýchto cyklov!</translation>
</message>
<message>
<source>More info</source>
<translation>Viac informácií</translation>
</message>
<message>
<source>Please keep in mind that the numbers are very coarse estimates. There are also other variables that affect the life cycle, such as charge current and battery temperature.</source>
<translation>Majte, prosím, na pamäti, že uvedené čísla iba hrubé odhady. Existuje mnoho ďalších premenných, ktoré majú vplyv na životný cyklus, ako napr. teplota akumulátora počas nabíjania.</translation>
</message>
<message>
<source>Why should I care?</source>
<translation>Prečo by Vás to malo zaujímať?</translation>
</message>
<message>
<source>Every battery produced uses a lot of energy and at least some non-renewable resources.</source>
<translation>Na každý vyrobený akumulátor sa spotrebuje množstvo energie a nie menej neobnoviteľných zdrojov.</translation>
</message>
<message>
<source>By taking care of your devices battery, you don&apos;t have to buy a new battery so soon.</source>
<translation>Ak sa budete starať o akumulátor vo Vašom zariadení, nebudete musieť tak skoro kupovať nový.</translation>
</message>
<message>
<source>Even better; in some devices the battery is very difficult to replace without braking the device, which means you don&apos;t have to pay for the service, either.</source>
<translation>Alebo lepšie, v niektorých zariadeniach sa akumulátor vymieňa veľmi zložito bez porušenia zariadenia, čo znamená, že nebudete musieť platiť za opravu.</translation>
</message>
<message>
<source>What else can I do?</source>
<translation>Čo ešte môžete urobiť?</translation>
</message>
<message>
<source>Uninstall battery-hungry applications you don&apos;t use. Reboot your device every now and then in order to keep it running flawlessly.</source>
<translation>Odinštalujte aplikácie, ktoré spotrebúvajú veľa energie. Z času na čas rešrartujte Vaše zariadenie aby fungovalo bezchybne.</translation>
</message>
<message>
<source>Use flight mode overnight whenever possible in order to cut power usage down. Powering the device off and on again may use a lot more battery than you think!</source>
<translation>Používajte letecký režim vždy, keď chcete znížiť spotrebu energie. Vypnutie a zapnutie zariadenia spotrebuje oveľa viac energie ako by ste si mysleli!</translation>
</message>
<message>
<source>Don&apos;t use your phone in hot or cold environments. In the winter keep the phone in your pocket near your body (but take note of the moisture) and use a handsfree device. Extreme temperatures are bad for the battery.</source>
<translation>Nepoužívajte telefón v príliš teplom a príliš chladnom prostredí. V zime noste telefón vo vrecku na tele (ale dajte pozor na vlhkosť) a používajte bezdrôtovú súpravu. Extrémna teplota škodí akumulátoru.</translation>
</message>
<message>
<source>I want to know more!</source>
<translation>Chcem vedieť viac!</translation>
</message>
<message>
<source>Great! There are a lot of articles to read and papers to study, so click the link to begin!</source>
<translation>Výborne! Existuje množstvo článkov a dokumentov na štúdium, ťuknite na link a začnite!</translation>
</message>
</context>
<context>
<name>LogPage</name>
<message>
<source>View log</source>
<translation>Zobraziť protokol spracovania</translation>
</message>
<message>
<source>Update</source>
<translation>Aktualizovať</translation>
</message>
<message>
<source>Copy</source>
<translation>Kopírovať</translation>
</message>
<message>
<source>Log level</source>
<translation>Úroveň podrobnosti záznamov</translation>
</message>
<message>
<source>Quiet</source>
<comment>Low log setting</comment>
<translation>Nízka</translation>
</message>
<message>
<source>Verbose</source>
<comment>Medium log setting</comment>
<translation>Stredná</translation>
</message>
<message>
<source>Debug</source>
<comment>High log setting</comment>
<translation>Ladiaca</translation>
</message>
</context>
<context>
<name>MainPage</name>
<message>
<source>Battery Buddy</source>
<translation>Battery Buddy</translation>
</message>
<message>
<source>Battery status</source>
<translation>Stav akumulátora</translation>
</message>
<message>
<source>Background</source>
<comment>More to read, background information...</comment>
<translation>Ďalšie informácie</translation>
</message>
<message>
<source>yes</source>
<translation>áno</translation>
</message>
<message>
<source>no</source>
<translation>nie</translation>
</message>
<message>
<source>Charge:</source>
<translation>Nabitie:</translation>
</message>
<message>
<source>State:</source>
<translation>Stav:</translation>
</message>
<message>
<source>idle</source>
<comment>Charger plugged in, not using nor charging battery</comment>
<translation>nečinný</translation>
</message>
<message>
<source>discharging</source>
<comment>Charger not plugged in, battery discharging</comment>
<translation>vybíjanie</translation>
</message>
<message>
<source>charging</source>
<comment>Charger plugged in and battery charging</comment>
<translation>nabíjanie</translation>
</message>
<message>
<source>unknown</source>
<comment>Battery not detected, or faulty, or something</comment>
<translation>neznáme</translation>
</message>
<message>
<source>Charger connected:</source>
<translation>Nabíjačka je pripojená:</translation>
</message>
<message>
<source>full</source>
<comment>Battery fully charged</comment>
<translation>plný</translation>
</message>
<message>
<source>empty</source>
<comment>Battery fully depleted</comment>
<translation>prázdny</translation>
</message>
<message>
<source>You can close Battery Buddy when you are done, notifications and charger control will continue working in the background.</source>
<translation>Ak chcete, môžete Battery Buddy ukončiť ak ste skončili, oznamy a riadenie nabíjania bude pokračovať na pozadí.</translation>
</message>
<message>
<source>Background service</source>
<translation>Proces na pozadí</translation>
</message>
<message>
<source>If notifications misbehave or there are problems with charger control, restarting the background service should help.</source>
<translation>Ak oznamy zmätočné alebo problémy s ovládaním nabíjačky, mal by pomôcť reštart služby na pozadí.</translation>
</message>
<message>
<source>Start</source>
<translation>Spustiť</translation>
</message>
<message>
<source>Stop</source>
<translation>Zastaviť</translation>
</message>
<message>
<source>Current:</source>
<translation>Prúd:</translation>
</message>
<message>
<source>Good</source>
<comment>Battery is OK</comment>
<translation>Dobrá</translation>
</message>
<message>
<source>Warm</source>
<comment>Battery is warm</comment>
<translation>Horúci</translation>
</message>
<message>
<source>Overheated</source>
<comment>Battery is very hot</comment>
<translation>Prehriaty</translation>
</message>
<message>
<source>Cool</source>
<comment>Battery is cool</comment>
<translation>Chladný</translation>
</message>
<message>
<source>Cold</source>
<comment>Battery is very cold</comment>
<translation>Studený</translation>
</message>
<message>
<source>Health:</source>
<translation>Kondícia:</translation>
</message>
<message>
<source>Temperature:</source>
<translation>Teplota:</translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>O aplikácii</translation>
</message>
<message>
<source>View log</source>
<translation>Zobraziť protokol spracovania</translation>
</message>
<message>
<source>USB</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AC</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>Never</source>
<translation>Nikdy</translation>
</message>
<message>
<source>30 seconds</source>
<translation>30 sekúnd</translation>
</message>
<message>
<source>2.5 minutes</source>
<translation>2,5 minúty</translation>
</message>
<message>
<source>5 minutes</source>
<translation>5 minút</translation>
</message>
<message>
<source>10 minutes</source>
<translation>10 minút</translation>
</message>
<message>
<source>15 minutes</source>
<translation>15 minút</translation>
</message>
<message>
<source>30 minutes</source>
<translation>30 minút</translation>
</message>
<message>
<source>1 hour</source>
<translation>1 hodina</translation>
</message>
<message>
<source>2 hours</source>
<translation>2 hodiny</translation>
</message>
<message>
<source>4 hours</source>
<translation>4 hodiny</translation>
</message>
<message>
<source>8 hours</source>
<translation>8 hodín</translation>
</message>
<message>
<source>10 hours</source>
<translation>10 hodín</translation>
</message>
<message>
<source>12 hours</source>
<translation>12 hodín</translation>
</message>
<message>
<source>24 hours</source>
<translation>24 hodín</translation>
</message>
</context>
<context>
<name>Settings</name>
<message>
<source>Battery charge %1%</source>
<translation>Nabitie akumulátora %1%</translation>
</message>
<message>
<source>Please connect the charger.</source>
<translation>Pripojte nabíjačku.</translation>
</message>
<message>
<source>Please disconnect the charger.</source>
<translation>Odpojte nabíjačku.</translation>
</message>
<message>
<source>Battery health %1</source>
<translation>Kondícia akumulátora %1</translation>
</message>
<message>
<source>Battery health is not good</source>
<translation>Kondícia akumulátora nie je dobrá</translation>
</message>
<message>
<source>Battery health is critical</source>
<translation>Kondícia akumulátora je kritická</translation>
</message>
</context>
<context>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Nastavenia</translation>
</message>
<message>
<source>Resume charging limit</source>
<translation>Limit obnovenia nabíjania</translation>
</message>
<message>
<source>Charging settings</source>
<translation>Nastavenia nabíjania</translation>
</message>
<message>
<source>Notification settings</source>
<translation>Nastavenie oznámení</translation>
</message>
<message>
<source>Pause charging limit</source>
<translation>Limit prerušenia nabíjania</translation>
</message>
<message>
<source>Display visual and audible notifications about reached battery charge levels, when the battery charge is below or above desired percentage.</source>
<translation>Zobraziť vizuálne a zvukové oznamy o dosiahnutej úrovni nabitia akumulátora, ak je úroveň nabitia akumulátora nižšia alebo vyššia ako požadované percentá.</translation>
</message>
<message>
<source>Battery low notification</source>
<translation>Oznámenie dolnej úrovne</translation>
</message>
<message>
<source>Battery full notification</source>
<translation>Oznámenie úplného nabitia</translation>
</message>
<message>
<source>Automatic charging control</source>
<translation>Automatické riadenie nabíjania</translation>
</message>
<message>
<source>This option disables charging automatically when the battery has charged above the pausing percentage and enables it again when the battery has depleted below the resuming percentage.</source>
<translation>Táto možnosť automaticky deaktivuje nabíjanie, keď sa akumulátor nabije nad nastavené percentá prerušenia a znova ho zapne, keď sa akumulátor vybije pod nastavené percentá obnovenia nabíjania.</translation>
</message>
<message>
<source>Background service</source>
<translation>Služba na pozadí</translation>
</message>
<message>
<source>Start background service at startup</source>
<translation>Spustiť službu na pozadí pri spustení systému</translation>
</message>
<message>
<source>Battery high notification interval</source>
<translation>Oznámenie hornej úrovne intervalu</translation>
</message>
<message>
<source>Battery low notification interval</source>
<translation>Oznámenie dolnej úrovne intervalu</translation>
</message>
<message>
<source>Never</source>
<translation>Nikdy</translation>
</message>
<message>
<source>Health notification settings</source>
<translation>Nastavenie oznámení o kondícii</translation>
</message>
<message>
<source>Display visual and audible notifications when the battery status exceeds safe values.&lt;br /&gt;This usually means high (or low) temperature but can include other parameters depending on the hardware.</source>
<translation>Zobraziť vizuálne a zvukové oznamy, keď stav batérie prekročí bezpečné hodnoty.&lt;br /&gt;To zvyčajne znamená vysokú alebo nízku teplotu, ale môže zahŕňať ďalšie parametre v závislosti od hardvéru.</translation>
</message>
<message>
<source>Battery health notification</source>
<translation>Oznámenie o kondícii akumulátora</translation>
</message>
<message>
<source>Warning</source>
<translation>Varovanie</translation>
</message>
<message>
<source>Critical</source>
<translation>Kritická</translation>
</message>
<message>
<source>Health notification interval</source>
<translation>Interval oznámení o kondícii</translation>
</message>
<message>
<source>Notification threshold</source>
<translation>Hranica oznamovania</translation>
</message>
<message>
<source>Maximum Charge Current</source>
<translation>Maximálny prúd nabíjania</translation>
</message>
</context>
</TS>

View file

@ -7,6 +7,10 @@
<source>Battery Buddy is a small and simple utility designed to improve the lifetime of the battery.</source>
<translation>Battery Buddy är ett litet och enkelt verktyg, skapat för att förbättra batteriets livslängd.</translation>
</message>
<message>
<source>Version</source>
<translation>Version</translation>
</message>
<message>
<source>View License</source>
<translation>Visa licens</translation>
@ -27,13 +31,28 @@
<source>Translations</source>
<translation>Översättningar</translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>Contributors</source>
<translation>Medverkande</translation>
<source>Charging</source>
<translation>Laddar</translation>
</message>
<message>
<source>A modified version of %1 by %2 in the emoji pack %3 is used in the logo. License: %4</source>
<translation>En modifierad version av %1, av %2 i emojipaket %3, använd i logotypen. Licens: %4</translation>
<source>Not charging</source>
<translation>Laddar inte</translation>
</message>
<message>
<source>Connect charger</source>
<translation>Anslut laddare</translation>
</message>
<message>
<source>Disconnect charger</source>
<translation>Koppla ifrån laddaren</translation>
</message>
<message>
<source>Battery Buddy</source>
<translation>Battery Buddy</translation>
</message>
</context>
<context>
@ -257,112 +276,36 @@
<message>
<source>Good</source>
<comment>Battery is OK</comment>
<translation>Bra</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Warm</source>
<comment>Battery is warm</comment>
<translation>Varm</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Overheated</source>
<comment>Battery is very hot</comment>
<translation>Överhettad</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cool</source>
<comment>Battery is cool</comment>
<translation>Kall</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cold</source>
<comment>Battery is very cold</comment>
<translation>Mycket kall</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Health:</source>
<translation>Hälsa:</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Temperature:</source>
<translation>Temperatur:</translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>Om</translation>
</message>
<message>
<source>View log</source>
<translation>Visa logg</translation>
</message>
<message>
<source>USB</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AC</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>Never</source>
<translation>Aldrig</translation>
</message>
<message>
<source>30 seconds</source>
<translation>30 sekunder</translation>
</message>
<message>
<source>2.5 minutes</source>
<translation>2,5 minuter</translation>
</message>
<message>
<source>5 minutes</source>
<translation>5 minuter</translation>
</message>
<message>
<source>10 minutes</source>
<translation>10 minuter</translation>
</message>
<message>
<source>15 minutes</source>
<translation>15 minuter</translation>
</message>
<message>
<source>30 minutes</source>
<translation>30 minuter</translation>
</message>
<message>
<source>1 hour</source>
<translation>1 timma</translation>
</message>
<message>
<source>2 hours</source>
<translation>2 timmar</translation>
</message>
<message>
<source>4 hours</source>
<translation>4 timmar</translation>
</message>
<message>
<source>8 hours</source>
<translation>8 timmar</translation>
</message>
<message>
<source>10 hours</source>
<translation>10 timmar</translation>
</message>
<message>
<source>12 hours</source>
<translation>12 timmar</translation>
</message>
<message>
<source>24 hours</source>
<translation>24 timmar</translation>
</message>
</context>
<context>
<name>Settings</name>
@ -380,15 +323,15 @@
</message>
<message>
<source>Battery health %1</source>
<translation>Batterihälsa %1</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery health is not good</source>
<translation>Batterihälsan är inte bra</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery health is critical</source>
<translation>Batterihälsan är kritisk</translation>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -409,6 +352,11 @@
<source>Notification settings</source>
<translation>Aviseringsinställningar</translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation>Om</translation>
</message>
<message>
<source>Pause charging limit</source>
<translation>Pausa laddning</translation>
@ -449,41 +397,45 @@
<source>Battery low notification interval</source>
<translation>Aviseringsintervall för låg batterinivå</translation>
</message>
<message>
<source>Once</source>
<translation>En gång</translation>
</message>
<message>
<source>Never</source>
<translation>Aldrig</translation>
</message>
<message>
<source>View log</source>
<translation>Visa logg</translation>
</message>
<message>
<source>Health notification settings</source>
<translation>Hälsoaviseringsinställning</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Display visual and audible notifications when the battery status exceeds safe values.&lt;br /&gt;This usually means high (or low) temperature but can include other parameters depending on the hardware.</source>
<translation>Visa visuella och hörbara meddelanden när batteristatus överstiger säkra värden.&lt;br /&gt;Detta betyder vanligtvis hög (eller låg) temperatur men kan innehålla andra parametrar beroende hårdvaran.</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery health notification</source>
<translation>Avisering för batterihälsa</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Notification treshold</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Warning</source>
<translation>Varning</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Critical</source>
<translation>Kritisk</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Health notification interval</source>
<translation>Aviseringsintervall för batterihälsa</translation>
</message>
<message>
<source>Notification threshold</source>
<translation>Tröskelvärde för avisering</translation>
</message>
<message>
<source>Maximum Charge Current</source>
<translation>Maximal laddningsström</translation>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -11,6 +11,10 @@
<source>Battery Buddy is a small and simple utility designed to improve the lifetime of the battery.</source>
<translation>Battery Buddy 寿</translation>
</message>
<message>
<source>Version</source>
<translation></translation>
</message>
<message>
<source>Battery Buddy is open source software licensed under the terms of the GNU General Public License.</source>
<translation>Battery Buddy GNU </translation>
@ -27,13 +31,29 @@
<source>Translations</source>
<translation></translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>Contributors</source>
<translation type="unfinished"></translation>
<source>Connect charger</source>
<translation></translation>
</message>
<message>
<source>A modified version of %1 by %2 in the emoji pack %3 is used in the logo. License: %4</source>
<translation type="unfinished"></translation>
<source>Disconnect charger</source>
<translation></translation>
</message>
<message>
<source>Battery Buddy</source>
<translation>Battery Buddy
</translation>
</message>
<message>
<source>Charging</source>
<translation></translation>
</message>
<message>
<source>Not charging</source>
<translation></translation>
</message>
</context>
<context>
@ -288,82 +308,6 @@
<source>Temperature:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation></translation>
</message>
<message>
<source>View log</source>
<translation></translation>
</message>
<message>
<source>USB</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AC</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>Never</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>30 seconds</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>2.5 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>5 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>10 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>15 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>30 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>1 hour</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>2 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>4 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>8 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>10 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>12 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>24 hours</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
@ -398,6 +342,11 @@
<source>Settings</source>
<translation></translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation></translation>
</message>
<message>
<source>Charging settings</source>
<translation></translation>
@ -450,10 +399,18 @@
<source>Battery low notification interval</source>
<translation></translation>
</message>
<message>
<source>Once</source>
<translation></translation>
</message>
<message>
<source>Never</source>
<translation></translation>
</message>
<message>
<source>View log</source>
<translation></translation>
</message>
<message>
<source>Health notification settings</source>
<translation type="unfinished"></translation>
@ -466,6 +423,10 @@
<source>Battery health notification</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Notification treshold</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Warning</source>
<translation type="unfinished"></translation>
@ -478,13 +439,5 @@
<source>Health notification interval</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Notification threshold</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Maximum Charge Current</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -7,6 +7,10 @@
<source>Battery Buddy is a small and simple utility designed to improve the lifetime of the battery.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Version</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>View License</source>
<translation type="unfinished"></translation>
@ -27,12 +31,27 @@
<source>Translations</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>Contributors</source>
<source>Charging</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>A modified version of %1 by %2 in the emoji pack %3 is used in the logo. License: %4</source>
<source>Not charging</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Connect charger</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Disconnect charger</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Battery Buddy</source>
<translation type="unfinished"></translation>
</message>
</context>
@ -287,82 +306,6 @@
<source>Temperature:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>View log</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>USB</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AC</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>Never</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>30 seconds</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>2.5 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>5 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>10 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>15 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>30 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>1 hour</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>2 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>4 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>8 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>10 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>12 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>24 hours</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
@ -409,6 +352,11 @@
<source>Notification settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>About</source>
<comment>About this application</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Pause charging limit</source>
<translation type="unfinished"></translation>
@ -449,10 +397,18 @@
<source>Battery low notification interval</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Once</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Never</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>View log</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Display visual and audible notifications when the battery status exceeds safe values.&lt;br /&gt;This usually means high (or low) temperature but can include other parameters depending on the hardware.</source>
<translation type="unfinished"></translation>
@ -478,11 +434,7 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Notification threshold</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Maximum Charge Current</source>
<source>Notification treshold</source>
<translation type="unfinished"></translation>
</message>
</context>

View file

@ -0,0 +1,13 @@
#!/bin/bash
SPEC=../rpm/$1.spec
if [[ $(grep "^Version: $2$" $SPEC | wc -l) = 0 ]]
then
sed -i "/^Version: /c\Version: $2" $SPEC
touch src/$1.cpp
fi
if [[ $(grep "^Release: $3$" $SPEC | wc -l) = 0 ]]
then
sed -i "/^Release: /c\Release: $3" $SPEC
touch src/$1.cpp
fi
echo true

View file

@ -1,114 +0,0 @@
#!/bin/bash
# For clean build, remove $SHADOW folder
# To trigger qmake, remove $SHADOW/*/Makefile
##########
# Configuration
##########
export APP_NAME=$(grep "Name" $(find . -regextype egrep -regex "\.\/rpm\/[a-z0-9_-]*\.(yaml|spec)" -print | head -1) | awk '{print $2}')
export SFOS_VER=4.4.0.58
##########
# Paths and versions
##########
export ORIG_PATH=$PATH
export PROJECT=$PWD
export PRO_FILE=$PROJECT/$APP_NAME.pro
export SHADOW=$PROJECT/shadow
export RPM_DEST_DIR=$PROJECT/RPMS
export APP_VER=$(grep "Version" $(find . -regextype egrep -regex "\.\/rpm\/[a-z0-9_-]*\.(yaml|spec)" -print | head -1) | awk '{print $2}')
export APP_REL=$(grep "Release" $(find . -regextype egrep -regex "\.\/rpm\/[a-z0-9_-]*\.(yaml|spec)" -print | head -1) | awk '{print $2}')
##########
# Build function. Ran once per architecture
##########
function build() {
if [ ! -d "$HOME/SailfishOS/mersdk/targets/SailfishOS-$SFOS_VER-$ARCH.default" ]
then
echo Invalid build target.
echo $HOME/SailfishOS/mersdk/targets/SailfishOS-$SFOS_VER-$ARCH.default
exit 1
fi
export PATH="$HOME/SailfishOS/bin:$HOME/SailfishOS/mersdk/targets/SailfishOS-$SFOS_VER-$ARCH.default/usr/lib/qt5/bin:$HOME/.config/SailfishSDK/libsfdk/build-target-tools/Sailfish SDK Build Engine/SailfishOS-$SFOS_VER-$ARCH.default:$ORIG_PATH"
export SFDK_OPTIONS="-c target=SailfishOS-$SFOS_VER-$ARCH"
sfdk config --global --push no-fix-version
cd $PROJECT
if [ ! -d "$SHADOW" ]
then
mkdir $SHADOW
fi
cd $SHADOW
if [ ! -d "$ARCH" ]
then
mkdir $ARCH
fi
cd $ARCH
if [ ! -f "Makefile" ]
then
sfdk qmake $PROJECT -recursive
fi
sfdk make
sfdk package
# perl-rename -v 's/\+.{29}//g' RPMS/*.rpm
cp -f -v RPMS/*.rpm $RPM_DEST_DIR/
cd $PROJECT
}
##########
# Build the packages
##########
RPM_NOARCH=0
if [ $(grep "^BuildArch:\W*noarch$" $(find . -regextype egrep -regex "\.\/rpm\/[a-z0-9_-]*\.(yaml|spec)" -print) | wc -l) -gt 0 ]
then
RPM_NOARCH=1
fi
if [ ! -d "$RPM_DEST_DIR" ]
then
mkdir $RPM_DEST_DIR
fi
if [ $RPM_NOARCH -eq 0 ]
then
export ARCH=aarch64
build
export ARCH=armv7hl
build
fi
# Use i486 for noarch build
export ARCH=i486
build
##########
# Run the validator only once
##########
if [ $RPM_NOARCH -gt 0 ]
then
RPM_ARCH=noarch
else
RPM_ARCH=$ARCH
fi
export RPM_FILE=$(ls RPMS/*$RPM_ARCH.rpm | head -1)
if [ -f "$RPM_FILE" ]
then
$HOME/SailfishOS/bin/sfdk engine exec rpmvalidation -t SailfishOS-$SFOS_VER-$ARCH.default $(ls RPMS/*$RPM_ARCH.rpm | head -1)
echo
echo "Changelog:"
echo
echo ${APP_VER}-${APP_REL}
sed '/^$/Q' rpm/${APP_NAME}.changes | tail +2 | cut -c3-
echo
else
echo "RPM package not found, not validating."
fi

View file

@ -1,7 +1,3 @@
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS = application service
DISTFILES += \
application/qml/components/CoverLabel.qml \
application/qml/components/ImageButton.qml

View file

@ -1,93 +1,3 @@
* Sun Mar 5 2023 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 4.2.5-1
- Fixup! Include all translation files
* Sun Mar 5 2023 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 4.2.4-1
- Fixup! Fix broken battery health
* Sat Mar 4 2023 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 4.2.3-1
- Add Slovak translation (thanks, okruhliak)
- Update Swedish translation (thanks, eson57)
- Add Support for AC Charger detection (thanks, nephros)
- Be more efficient with handling file paths in constructors
- Fix package dependencies
* Sun Jan 1 2023 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 4.2.2-1
- Restart the permission service on update
* Sun Jan 1 2023 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 4.2.1-1
- Properly read and set values on first startup
* Sat Dec 31 2022 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 4.2.0-1
- Add setting maximum charge current
* Sun Aug 28 2022 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 4.1.1-1
- Fixup! Use correct colors in battery graphic
- Fixup! Enable low battery animation
- Move all subpages to MainPage pull down menu
- Update Swedish translation (thanks, eson57)
- Update Polish translation (thanks, wetab73)
- Update copyrights
* Sun Aug 28 2022 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 4.1.0-1
- Redesign the logo and battery graphic
- Use custom ImageButton in About page
- Use ColumnView to show the log contents with formatting (thanks, nephros!)
- Update Swedish translation (thanks, eson57)
- Rename internal logging functions for clarity
- Invert the charge current sign if necessary
- Assume the charge current value always changes
- Remove unused files
- Print changelog at the end of the build script
- Built with Sailfish OS SDK 3.9 for 4.4.0.68
- Add Jolla Tablet charger control file to permission service
- Initial Jolla Tablet support (beta)
- Log charging/discharging current
- Log temperature changes with resolution of one degree Celsius
- Search for control files using loops
- Don't try to use non-existent files
- Print correct log file name
- Remove unused signals from service
* Sun Mar 20 2022 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 4.0.0-1
- Enable sandboxing with appropriate permissions (GUI only)
- Use QML DBusInterface for user service manipulation
- Drop support for SFOS 4.2 and older
- Clean up systemd service handling during install/update/uninstall
- Built with Sailfish OS SDK 3.8 for 4.3.0.12
* Sun Mar 20 2022 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 3.17.0-1
- Disable sandboxing
- Fix install/upgrade/uninstall scriptlets
- Service binary consumes less resources
- Don't try to close notifications if they are not open
* Wed Nov 24 2021 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 3.16.2-1
- Fix .spec bin file path (thanks, leon and nephros)
- Built with Sailfish OS SDK 3.7 for 4.3.0.12
* Sun Oct 10 2021 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 3.16.1-1
- Fix bogus version number
* Sun Oct 10 2021 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 3.16.0-1
- Built for SFOS 4.2.0.21 using SDK 3.6.6
- Use semantic versioning
- Use `systemctl-user` instead of `systemctl --user`
* Sun Jul 25 2021 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 3.15-1
- Implement BackgroundActivity timed events
* Sun May 30 2021 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 3.14-1
- Use keepalive-tool to mitigate deep sleep
- Update translators and credits
- Update Polish translation (thanks, atlochowski)
- Update Deutch translation (thanks, nephros)
* Sun May 23 2021 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 3.13-1
- Show battery temperature and condition (thanks, nephros)
- Show notifications about abnormal temperature and condition (thanks, nephros)
- Fix broken notifications on SFOS 3.4 and earlier
- Bring back SFOS 2.2 support
* Fri Apr 30 2021 Matti Viljanen (direc85) <matti.viljanen@kapsi.fi> 3.12-3
- Fix missing translations

View file

@ -8,26 +8,24 @@ Name: harbour-batterybuddy
%{!?qtc_make:%define qtc_make make}
%{?qtc_builddir:%define _builddir %qtc_builddir}
# Keep this in sync with .pro files
# Change the version and release strings in .pro file only!
Summary: Battery Buddy
Version: 4.2.5
Release: 1
Version: 3.12
Release: 3
Group: Qt/Qt
License: GPLv3
URL: http://example.org/
Source0: %{name}-%{version}.tar.bz2
Requires: sailfishsilica-qt5 >= 0.10.9
Requires: libkeepalive
Requires: pkgconfig(nemonotifications-qt5)
Requires: sailfish-version >= 4.3
Requires: nemo-qml-plugin-configuration-qt5
Requires: nemo-qml-plugin-notifications-qt5
BuildRequires: pkgconfig(sailfishapp) >= 1.0.2
BuildRequires: pkgconfig(nemonotifications-qt5)
BuildRequires: pkgconfig(Qt5Core)
BuildRequires: pkgconfig(Qt5Qml)
BuildRequires: pkgconfig(Qt5Quick)
BuildRequires: desktop-file-utils
BuildRequires: libkeepalive-devel
%description
Prolong your battery life.
@ -43,7 +41,7 @@ Prolong your battery life.
# >> build pre
# << build pre
%qtc_qmake5
%qtc_qmake5
%qtc_make %{?_smp_mflags}
@ -59,60 +57,57 @@ rm -rf %{buildroot}
# >> install post
# << install post
desktop-file-install --delete-original \
--dir %{buildroot}%{_datadir}/applications \
desktop-file-install --delete-original \
--dir %{buildroot}%{_datadir}/applications \
%{buildroot}%{_datadir}/applications/*.desktop
mkdir -p %{buildroot}%{_unitdir}
mkdir -p %{buildroot}%{_userunitdir}
mv %{buildroot}%{_datadir}/%{name}/service/%{name}-oneshot.service %{buildroot}%{_unitdir}/
mv %{buildroot}%{_datadir}/%{name}/service/%{name}.service %{buildroot}%{_userunitdir}/
%files
%defattr(-,root,root,-)
%{_bindir}/*
%defattr(0644,root,root,-)
%{_bindir}
%{_datadir}/%{name}
%{_datadir}/applications/%{name}.desktop
%{_datadir}/icons/hicolor/*/apps/%{name}.png
%{_userunitdir}/%{name}.service
%{_unitdir}/%{name}-oneshot.service
# >> files
# << files
%posttrans
# Remove old service (quietly)
systemctl stop %{name}.service &>/dev/null
systemctl disable %{name}.service &>/dev/null
rm -f %{_unitdir}/%{name}.service
export SFOSUSER=$(id -un 100000)
export DBUS_USER_ADDRESS=unix:path=/run/user/100000/dbus/user_bus_socket
# Remove old service
systemctl stop %{name}.service
systemctl disable %{name}.service
rm %{_unitdir}/%{name}.service
# Install/update permission daemon (root)
cp %{_datadir}/%{name}/service/%{name}-oneshot.service %{_unitdir}/%{name}-oneshot.service
systemctl daemon-reload
systemctl enable %{name}-oneshot.service
systemctl stop %{name}-oneshot.service
systemctl start %{name}-oneshot.service
# Install/update background daemon (default user)
systemctl-user daemon-reload
systemctl-user enable %{name}.service
systemctl-user stop %{name}.service
systemctl-user start %{name}.service
cp %{_datadir}/%{name}/service/%{name}.service %{_userunitdir}/%{name}.service
su $SFOSUSER -c "DBUS_SESSION_BUS_ADDRESS=$DBUS_USER_ADDRESS systemctl --user daemon-reload"
su $SFOSUSER -c "DBUS_SESSION_BUS_ADDRESS=$DBUS_USER_ADDRESS systemctl --user enable %{name}.service"
su $SFOSUSER -c "DBUS_SESSION_BUS_ADDRESS=$DBUS_USER_ADDRESS systemctl --user stop %{name}.service"
su $SFOSUSER -c "DBUS_SESSION_BUS_ADDRESS=$DBUS_USER_ADDRESS systemctl --user start %{name}.service"
exit 0
%postun
# Run on uninstall, not on upgrade
// Run on uninstall, not on upgrade
if [ $1 -eq 0 ]; then
systemctl-user stop %{name}.service
systemctl-user disable %{name}.service
systemctl-user daemon-reload
# Figure out the default user name
export SFOSUSER=$(id -un 100000)
export DBUS_USER_ADDRESS=unix:path=/run/user/100000/dbus/user_bus_socket
su $SFOSUSER -c "DBUS_SESSION_BUS_ADDRESS=$DBUS_USER_ADDRESS systemctl --user stop %{name}.service"
su $SFOSUSER -c "DBUS_SESSION_BUS_ADDRESS=$DBUS_USER_ADDRESS systemctl --user disable %{name}.service"
rm %{_userunitdir}/%{name}.service
su $SFOSUSER -c "DBUS_SESSION_BUS_ADDRESS=$DBUS_USER_ADDRESS systemctl --user daemon-reload"
systemctl stop %{name}-oneshot.service
systemctl disable %{name}-oneshot.service
rm %{_unitdir}/%{name}-oneshot.service
systemctl daemon-reload
systemctl-user reset-failed
systemctl reset-failed
fi
exit 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 600 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 634 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 616 KiB

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 275 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -1,12 +1,16 @@
TARGET = harbour-batterybuddy-daemon
CONFIG += sailfishapp console
QT = core dbus
PKGCONFIG += nemonotifications-qt5
# Keep this in sync with application.pro and .spec
VERSION = 4.2.5-1
# Keep this in sync with "application.pro"
VER = 3.12
REL = 3
VERSION = $${VER}-$${REL}
DEFINES += APP_VERSION=\"\\\"$$VERSION\\\"\"
DEFINES += APP_NAME=\"\\\"$$TARGET\\\"\"
@ -14,20 +18,18 @@ DEFINES += APP_NAME=\"\\\"$$TARGET\\\"\"
# See main() and logger.h for details.
DEFINES += QT_NO_DEBUG_OUTPUT
LIBS += -lkeepalive -lnemonotifications-qt5
HEADERS += \
src/battery.h \
src/mynotification.h \
src/logger.h \
src/settings.h \
src/mynotification.h
src/settings.h
SOURCES += \
src/battery.cpp \
src/mynotification.cpp \
src/logger.cpp \
src/settings.cpp \
src/harbour-batterybuddy-daemon.cpp \
src/mynotification.cpp
src/harbour-batterybuddy-daemon.cpp
OTHER_FILES += harbour-batterybuddy-daemon.service

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2023 Matti Viljanen
* 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
@ -17,298 +17,143 @@
*/
#include "battery.h"
Battery::Battery(Logger* newLogger, bool loglevelSet, QCoreApplication *app, QObject *parent) : QObject(parent)
Battery::Battery(Logger* newLogger, bool loglevelSet, QObject *parent) : QObject(parent)
{
logger = newLogger;
settings = new Settings(logger, this);
const QString notFound = "not found";
// Read log level from config - if not already set
if(!loglevelSet) {
int logLevel = settings->getLogLevel();
logger->debug = (logLevel == 2);
logger->verbose = (logLevel > 1);
logL(QString("Log level set to %1").arg((logLevel == 0 ? "low" : (logLevel == 1 ? "medium" : "high"))));
logE(QString("Log level set to %1").arg((logLevel == 0 ? "low" : (logLevel == 1 ? "medium" : "high"))));
}
updateTimer = new QTimer(this);
highNotifyTimer = new QTimer(this);
lowNotifyTimer = new QTimer(this);
healthNotifyTimer = new QTimer(this);
chargeNotification = new MyNotification(this);
healthNotification = new MyNotification(this);
// Battery charge percentage, number, e.g. 42
const QStringList capacityFiles = {
"/sys/class/power_supply/battery/capacity",
"/sys/class/power_supply/dollar_cove_battery/capacity"
};
// Number: charge percentage, e.g. 42
chargeFile = new QFile("/sys/class/power_supply/battery/capacity", this);
logE("Capacity file: " + chargeFile->fileName() + (chargeFile->exists() ? " OK" : " doesn't exist"));
foreach(const QString& file, capacityFiles) {
if(!chargeFile && QFile::exists(file)) {
chargeFile = new QFile(file, this);
break;
}
}
// String: charging, discharging, full, empty, unknown (others?)
stateFile = new QFile("/sys/class/power_supply/battery/status", this);
logE("Charge state file: " + stateFile->fileName() + (stateFile->exists() ? " OK" : " doesn't exist"));
logL("Battery charge file: " + (chargeFile ? chargeFile->fileName() : notFound));
// Number: 0 or 1
chargerConnectedFile = new QFile("/sys/class/power_supply/usb/present", this);
logE("Charger status file: " + chargerConnectedFile->fileName() + (chargerConnectedFile->exists() ? " OK" : " doesn't exist"));
// Charging/discharging current in microamps, e.g. -1450000 (-145mA)
const QStringList currentFiles = {
"/sys/class/power_supply/battery/current_now",
"/sys/class/power_supply/dollar_cove_battery/current_now"
};
foreach(const QString& file, currentFiles) {
if(!currentFile && QFile::exists(file)) {
currentFile = new QFile(file, this);
break;
}
}
logL("Charging/discharging current file: " + (currentFile ? currentFile->fileName() : notFound));
// Maximum charge current in microamps, e.g. 3500000 (3500mA)
const QStringList maxCurrentFiles = {
"/sys/class/power_supply/battery/constant_charge_current_max"
};
foreach(const QString& file, maxCurrentFiles) {
if(!maxChargeCurrentFile && QFile::exists(file)) {
maxChargeCurrentFile = new QFile(file, this);
break;
}
}
if(maxChargeCurrentFile) {
logL("Max charge current file: " + maxChargeCurrentFile->fileName());
if(maxChargeCurrentFile->open(QIODevice::WriteOnly)) {
maxChargeCurrentFile->close();
if(maxChargeCurrentFile->open(QIODevice::ReadOnly)) {
// Read and store the default max current
maxSupportedChargeCurrent = maxChargeCurrentFile->readLine().trimmed().toInt();
logL(QString("Maximum supported charge current: %1mA").arg(maxSupportedChargeCurrent / 1000));
maxChargeCurrentFile->close();
settings->setMaxSupportedChargeCurrent(maxSupportedChargeCurrent);
// Read and maybe set the user-set max current
maxChargeCurrent = settings->getMaxChargeCurrent();
if(maxChargeCurrent != maxSupportedChargeCurrent) {
setMaxChargeCurrent(maxChargeCurrent);
}
}
}
else {
logL("Max charge current file is not writable - feature disabled");
delete maxChargeCurrentFile;
maxChargeCurrentFile = Q_NULLPTR;
}
}
else {
logL("Max charge current file: " + notFound);
}
// Battery/charging status: charging, discharging, full, empty, unknown (others?)
const QStringList statusFiles = {
"/sys/class/power_supply/battery/status",
"/sys/class/power_supply/dollar_cove_battery/status"
};
foreach(const QString& file, statusFiles) {
if(!stateFile && QFile::exists(file)) {
stateFile = new QFile(file, this);
break;
}
}
logL("Status file: " + (stateFile ? stateFile->fileName() : notFound));
// Charger connected, bool (number): 0 or 1
const QStringList chargerFiles = {
"/sys/class/power_supply/usb/present",
"/sys/class/power_supply/dollar_cove_charger/present"
};
foreach(const QString& file, chargerFiles) {
if(!chargerConnectedFile && QFile::exists(file)) {
chargerConnectedFile = new QFile(file, this);
break;
}
}
logL("Charger status file: " + (chargerConnectedFile ? chargerConnectedFile->fileName() : notFound));
// Charger connected, bool (number): 0 or 1
const QStringList acFiles = {
"/sys/class/power_supply/ac/present"
};
foreach(const QString& file, acFiles) {
if(!acConnectedFile && QFile::exists(file)) {
acConnectedFile = new QFile(file, this);
break;
}
}
logL("AC status file: " + (acConnectedFile ? acConnectedFile->fileName() : notFound));
QString filename;
// Number: temperature
const QStringList tempFiles = {
"/sys/class/power_supply/battery/temp",
"/sys/class/power_supply/dollar_cove_battery/temp"
};
foreach(const QString& file, tempFiles) {
if(!temperatureFile && QFile::exists(file)) {
temperatureFile = new QFile(file, this);
break;
}
filename = "/sys/class/power_supply/battery/temp";
if(!temperatureFile && QFile::exists(filename)) {
temperatureFile = new QFile(filename, this);
}
logL("Battery temperature file: " + (temperatureFile ? temperatureFile->fileName() : notFound));
logE("Temperature file: " + filename + (QFile::exists(filename) ? " OK" : " doesn't exist"));
// String: health state
const QStringList healthFiles = {
"/sys/class/power_supply/battery/health",
"/sys/class/power_supply/dollar_cove_battery/health"
};
foreach(const QString& file, healthFiles) {
if(!healthFile && QFile::exists(file)) {
healthFile = new QFile(file, this);
break;
}
filename = "/sys/class/power_supply/battery/health";
if(!healthFile && QFile::exists(filename)) {
healthFile = new QFile(filename, this);
}
logE("Battery health file: " + filename + (QFile::exists(filename) ? " OK" : " doesn't exist"));
// e.g. for Sony Xperia XA2
filename = "/sys/class/power_supply/battery/input_suspend";
if(!chargingEnabledFile && QFile::exists(filename)) {
chargingEnabledFile = new QFile(filename, this);
enableChargingValue = 0;
disableChargingValue = 1;
}
logL("Battery health file: " + (healthFile ? healthFile->fileName() : notFound));
// Charger control file
const QStringList controlFiles = {
"/sys/class/power_supply/battery/input_suspend", // e.g. Sony Xperia XA2
"/sys/class/power_supply/battery/charging_enabled", // e.g. for Sony Xperia Z3 Compact Tablet
"/sys/class/power_supply/usb/charger_disable", // e.g. for Jolla Phone
"/sys/class/power_supply/dollar_cove_battery/enable_charging" // e.g. for Jolla Tablet
};
foreach(const QString& file, controlFiles) {
if(!chargingEnabledFile && QFile::exists(file)) {
chargingEnabledFile = new QFile(file, this);
break;
}
}
// Flip the charging control bits if necessary
if(chargingEnabledFile && chargingEnabledFile->fileName().contains("enable")) {
// e.g. for Sony Xperia Z3 Compact Tablet
filename = "/sys/class/power_supply/battery/charging_enabled";
if(!chargingEnabledFile && QFile::exists(filename)) {
chargingEnabledFile = new QFile(filename, this);
enableChargingValue = 1;
disableChargingValue = 0;
}
// e.g. for Jolla Phone
filename = "/sys/class/power_supply/usb/charger_disable";
if(!chargingEnabledFile && QFile::exists(filename)) {
chargingEnabledFile = new QFile(filename, this);
enableChargingValue = 0;
disableChargingValue = 1;
}
// If we found a usable file, check that it is writable
if(chargingEnabledFile) {
logL("Charger control file: " + chargingEnabledFile->fileName());
logE("Charger control file: " + chargingEnabledFile->fileName() + (chargingEnabledFile->exists() ? " OK" : " doesn't exist"));
if(chargingEnabledFile->open(QIODevice::WriteOnly)) {
chargingEnabledFile->close();
}
else {
logL("Charger control file is not writable - feature disabled");
logE("Charger control file" + chargingEnabledFile->fileName() + "is not writable");
logE("Charger control feature disabled");
delete chargingEnabledFile;
chargingEnabledFile = Q_NULLPTR;
}
}
else {
logL("Charger control file not found!");
logL("Please contact the developer with your device model!");
else if(!QHostInfo::localHostName().contains("SailfishEmul")) {
logE("Charger control file not found!");
logE("Please contact the developer with your device model!");
}
connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateData()));
connect(settings, SIGNAL(resetTimers()), this, SLOT(resetTimers()));
connect(settings, SIGNAL(setMaxChargeCurrent(int)), this, SLOT(setMaxChargeCurrent(int)));
updateTimer = new BackgroundActivity(app);
highNotifyTimer = new BackgroundActivity(app);
lowNotifyTimer = new BackgroundActivity(app);
healthNotifyTimer = new BackgroundActivity(app);
connect(updateTimer, SIGNAL(running()), this, SLOT(updateData()));
connect(highNotifyTimer, SIGNAL(running()), this, SLOT(showHighNotification()));
connect(lowNotifyTimer, SIGNAL(running()), this, SLOT(showLowNotification()));
connect(healthNotifyTimer, SIGNAL(running()), this, SLOT(showHealthNotification()));
connect(updateTimer, SIGNAL(running()), updateTimer, SLOT(wait()));
connect(highNotifyTimer, SIGNAL(running()), highNotifyTimer, SLOT(wait()));
connect(lowNotifyTimer, SIGNAL(running()), lowNotifyTimer, SLOT(wait()));
connect(healthNotifyTimer, SIGNAL(running()), healthNotifyTimer, SLOT(wait()));
connect(highNotifyTimer, SIGNAL(timeout()), this, SLOT(showHighNotification()));
connect(lowNotifyTimer, SIGNAL(timeout()), this, SLOT(showLowNotification()));
connect(healthNotifyTimer, SIGNAL(timeout()), this, SLOT(showHealthNotification()));
updateData();
updateTimer->setWakeupFrequency(BackgroundActivity::ThirtySeconds);
updateTimer->wait();
updateTimer->start(5000);
// If updateData() didn't start the timers
// aka. "charging" status didn't change
// (or if both times are disabled, actually)
// manually trigger the timer startup.
if(!highNotifyTimer->isWaiting() && !lowNotifyTimer->isWaiting() && !healthNotifyTimer->isWaiting()) {
if(!highNotifyTimer->isActive() && !lowNotifyTimer->isActive() && !healthNotifyTimer->isActive()) {
resetTimers();
}
}
Battery::~Battery() {
setMaxChargeCurrent(maxSupportedChargeCurrent);
updateTimer->stop();
highNotifyTimer->stop();
lowNotifyTimer->stop();
healthNotifyTimer->stop();
delete updateTimer;
delete highNotifyTimer;
delete lowNotifyTimer;
delete healthNotifyTimer;
}
Battery::~Battery() { }
void Battery::updateData()
{
if(chargeFile && chargeFile->open(QIODevice::ReadOnly)) {
if(chargeFile->open(QIODevice::ReadOnly)) {
nextCharge = chargeFile->readLine().trimmed().toInt();
if(nextCharge != charge) {
charge = nextCharge;
logM(QString("Battery: %1%").arg(charge));
emit chargeChanged(charge);
logV(QString("Battery: %1%").arg(charge));
}
chargeFile->close();
}
if(chargerConnectedFile && chargerConnectedFile->open(QIODevice::ReadOnly)) {
if(chargerConnectedFile->open(QIODevice::ReadOnly)) {
nextChargerConnected = chargerConnectedFile->readLine().trimmed().toInt();
if(nextChargerConnected != chargerConnected) {
chargerConnected = nextChargerConnected;
logM(QString("Charger: %1").arg(chargerConnected ? "connected" : "disconnected"));
emit chargerConnectedChanged(chargerConnected);
logV(QString("Charger: %1").arg(chargerConnected ? "connected" : "disconnected"));
}
chargerConnectedFile->close();
}
if(acConnectedFile && acConnectedFile->open(QIODevice::ReadOnly)) {
nextAcConnected = acConnectedFile->readLine().trimmed().toInt();
if(nextAcConnected != acConnected) {
acConnected = nextAcConnected;
logM(QString("AC: %1").arg(acConnected ? "connected" : "disconnected"));
}
acConnectedFile->close();
}
if(currentFile && currentFile->open(QIODevice::ReadOnly)) {
current = currentFile->readLine().trimmed().toInt();
if(!invertDecided) {
invertCurrent = (!chargerConnected && !acConnected && current > 10);
if(invertCurrent) logL("Battery current inverted");
else logL("Battery current not inverted");
invertDecided = true;
}
current = current * (invertCurrent ? -1 : 1);
logH(QString("Current: %1mA").arg(current / 1000));
currentFile->close();
}
if(stateFile && stateFile->open(QIODevice::ReadOnly)) {
if(stateFile->open(QIODevice::ReadOnly)) {
nextState = (QString(stateFile->readLine().trimmed().toLower()));
if(nextState != state) {
state = nextState;
logM("State: " + state);
emit stateChanged(state);
logV("State: " + state);
// Hide/show notification right away
resetTimers();
@ -319,10 +164,9 @@ void Battery::updateData()
if(temperatureFile && temperatureFile->open(QIODevice::ReadOnly)) {
nextTemperature = temperatureFile->readLine().trimmed().toInt();
if(nextTemperature != temperature) {
if((nextTemperature / 10) != (temperature / 10)) {
logM(QString("Temperature: %1°C").arg(nextTemperature / 10));
}
temperature = nextTemperature;
emit temperatureChanged(temperature);
logV(QString("Temperature: %1°C").arg(temperature / 10));
}
temperatureFile->close();
}
@ -331,7 +175,8 @@ void Battery::updateData()
nextHealth = (QString(healthFile->readLine().trimmed().toLower()));
if(nextHealth != health) {
health = nextHealth;
logM("Health: " + health);
emit healthChanged(health);
logV("Health: " + health);
// Hide/show notification right away
resetTimers();
@ -341,11 +186,11 @@ void Battery::updateData()
if(chargingEnabledFile && settings->getLimitEnabled()) {
if(chargingEnabled && charge >= settings->getHighLimit()) {
logM("Disabling charging...");
logD("Disabling charging...");
setChargingEnabled(false);
}
else if(!chargingEnabled && charge <= settings->getLowLimit()) {
logM("Enabling charging...");
logD("Enabling charging...");
setChargingEnabled(true);
}
}
@ -355,80 +200,66 @@ void Battery::resetTimers() {
highNotifyTimer->stop();
lowNotifyTimer->stop();
healthNotifyTimer->stop();
highNotifyTimer->setInterval(settings->getHighNotificationsInterval() * 1000);
lowNotifyTimer->setInterval(settings->getLowNotificationsInterval() * 1000);
healthNotifyTimer->setInterval(settings->getHealthNotificationsInterval() * 1000);
if(settings->getHighNotificationsInterval() > 0) {
highNotifyTimer->setWakeupFrequency(frequencies[settings->getHighNotificationsInterval()]);
logH(QString("High notifications frequency %1 => %2 seconds")
.arg(settings->getHighNotificationsInterval())
.arg(static_cast<int>(frequencies[settings->getHighNotificationsInterval()])));
logH("Starting high battery timer");
highNotifyTimer->wait();
if(settings->getHighNotificationsInterval() < 610) {
logD("Starting high battery timer");
highNotifyTimer->start();
showHighNotification();
}
else {
logH("High battery timer not started");
logD("High battery timer not started");
}
if(settings->getLowNotificationsInterval() > 0) {
lowNotifyTimer->setWakeupFrequency(frequencies[settings->getLowNotificationsInterval()]);
logH(QString("Low notifications frequency %1 => %2 seconds")
.arg(settings->getLowNotificationsInterval())
.arg(static_cast<int>(frequencies[settings->getLowNotificationsInterval()])));
logH("Start low battery timer");
lowNotifyTimer->wait();
if(settings->getLowNotificationsInterval() < 610) {
logD("Start low battery timer");
lowNotifyTimer->start();
showLowNotification();
}
else {
logH("Low battery timer not started");
logD("Low battery timer not started");
}
if(settings->getHealthNotificationsInterval() > 0) {
healthNotifyTimer->setWakeupFrequency(frequencies[settings->getHealthNotificationsInterval()]);
logH(QString("Health notifications frequency %1 => %2 seconds")
.arg(settings->getHealthNotificationsInterval())
.arg(static_cast<int>(frequencies[settings->getHealthNotificationsInterval()])));
logH("Start health timer");
healthNotifyTimer->wait();
if(settings->getHealthNotificationsInterval() < 610) {
logD("Start health timer");
healthNotifyTimer->start();
showHealthNotification();
}
else {
logH("Health timer not started");
logD("Health timer not started");
}
}
void Battery::showHighNotification() {
if(settings->getHighNotificationsInterval() > 0 && (charge >= settings->getHighAlert() && state != "discharging")
if(settings->getHighNotificationsInterval() < 610 && (charge >= settings->getHighAlert() && state != "discharging")
&& !(charge == 100 && state == "idle")) {
logH(QString("Notification: %1").arg(settings->getNotificationTitle().arg(charge)));
logV(QString("Notification: %1").arg(settings->getNotificationTitle().arg(charge)));
chargeNotification->send(settings->getNotificationTitle().arg(charge), settings->getNotificationHighText(), settings->getHighAlertFile());
unclosedChargeNotification = true;
if(settings->getHighNotificationsInterval() == 50) {
logH("Stop high battery timer");
logD("Stop high battery timer");
highNotifyTimer->stop();
}
}
else if(unclosedChargeNotification && charge > settings->getLowAlert()) {
logH("Close high battery notification");
else if(charge > settings->getLowAlert()) {
logD("Close high battery notification");
chargeNotification->close();
unclosedChargeNotification = true;
}
}
void Battery::showLowNotification() {
if(settings->getLowNotificationsInterval() > 0 && charge <= settings->getLowAlert() && state != "charging") {
logH(QString("Notification: %1").arg(settings->getNotificationTitle().arg(charge)));
if(settings->getLowNotificationsInterval() < 610 && charge <= settings->getLowAlert() && state != "charging") {
logV(QString("Notification: %1").arg(settings->getNotificationTitle().arg(charge)));
chargeNotification->send(settings->getNotificationTitle().arg(charge), settings->getNotificationLowText(), settings->getLowAlertFile());
unclosedChargeNotification = true;
if(settings->getLowNotificationsInterval() == 50) {
logH("Stop low battery timer");
logD("Stop low battery timer");
lowNotifyTimer->stop();
}
}
else if(unclosedChargeNotification && charge < settings->getHighAlert()) {
logH("Close low battery notification");
else if(charge < settings->getHighAlert()) {
logD("Close low battery notification");
chargeNotification->close();
unclosedChargeNotification = true;
}
}
@ -449,7 +280,7 @@ void Battery::showHealthNotification() {
{ "overheat" , HealthThresh["crit"] },
{ "cold" , HealthThresh["crit"] }
};
if(settings->getHealthNotificationsInterval() > 0 && temperature != 0x7FFFFFFF && ( HealthState[health] != HealthThresh["ok"] && HealthState[health] >= settings->getHealthAlert() ) ) {
if(settings->getHealthNotificationsInterval() < 610 && temperature != 0x7FFFFFFF && ( HealthState[health] != HealthThresh["ok"] && HealthState[health] >= settings->getHealthAlert() ) ) {
QString displayTemp = QString::number(temperature / 10.0);
if (QLocale().measurementSystem() == QLocale::ImperialUSSystem)
displayTemp = QString::number((temperature / 10) * 1.8 + 32) + " F";
@ -464,16 +295,15 @@ void Battery::showHealthNotification() {
} else if (HealthState[health] == HealthThresh["crit"]) {
notificationText = settings->getNotificationHealthCritText();
}
logH(QString("Notification: %1").arg(settings->getNotificationHealthTitle().arg(titleArgs)));
logD(QString("Notification: %1").arg(settings->getNotificationHealthTitle().arg(titleArgs)));
healthNotification->send(settings->getNotificationHealthTitle().arg(titleArgs), notificationText, settings->getHealthAlertFile());
unclosedHealthNotification = true;
if(settings->getHealthNotificationsInterval() == 50) {
logH("Stop health timer");
logD("Stop health timer");
healthNotifyTimer->stop();
}
}
else if(unclosedHealthNotification && (HealthState[health] == HealthThresh["ok"] || HealthState[health] < settings->getHealthAlert())) {
logH("Close health notification");
else if(HealthState[health] == HealthThresh["ok"] || HealthState[health] < settings->getHealthAlert()) {
logD("Close health notification");
healthNotification->close();
}
}
@ -494,76 +324,55 @@ bool Battery::setChargingEnabled(const bool isEnabled) {
if(chargingEnabledFile->open(QIODevice::WriteOnly)) {
if(chargingEnabledFile->write(QString("%1").arg(isEnabled ? enableChargingValue : disableChargingValue).toLatin1())) {
chargingEnabled = isEnabled;
emit chargingEnabledChanged(chargingEnabled);
success = true;
if(isEnabled) {
logM("Charging resumed");
logV("Charging resumed");
}
else {
logM("Charging paused");
logV("Charging paused");
}
}
else {
logL("Could not write new charger state");
logE("Could not write new charger state");
}
chargingEnabledFile->close();
}
else {
logL("Could not open charger control file");
logE("Could not open charger control file");
}
}
return success;
}
void Battery::setMaxChargeCurrent(int newCurrent) {
if(maxChargeCurrentFile) {
logM(QString("Max charging current: %1mA").arg(newCurrent / 1000));
if(newCurrent > maxSupportedChargeCurrent) {
newCurrent = maxSupportedChargeCurrent;
}
if(maxChargeCurrentFile->open(QIODevice::WriteOnly)) {
QString data = QString("%1").arg(newCurrent);
if(!maxChargeCurrentFile->write(data.toLocal8Bit())) {
logM("Could not write to max charging current file");
}
}
else {
logM("Could not open max charging current file");
}
maxChargeCurrentFile->close();
}
}
bool Battery::getChargerConnected() {
return chargerConnected;
}
bool Battery::getAcConnected() {
return acConnected;
}
void Battery::shutdown() {
logM("Shutting down...");
logV("Shutting down...");
chargeNotification->close();
blockSignals(true);
if(updateTimer) {
updateTimer->stop();
logH("Update timer stopped");
logD("Update timer stopped");
}
if(highNotifyTimer) {
highNotifyTimer->stop();
logH("High battery notification stopped");
logD("High battery notification stopped");
}
if(lowNotifyTimer) {
lowNotifyTimer->stop();
logH("Low battery notification stopped");
logD("Low battery notification stopped");
}
if(healthNotifyTimer) {
healthNotifyTimer->stop();
logH("Health notification stopped");
logD("Health notification stopped");
}
if(!setChargingEnabled(true) && !QSysInfo::machineHostName().contains("SailfishEmul")) {
logL("ERROR! Could not restore charger status! Your device "
// ENABLE/DISABLE CHARGING
if(!setChargingEnabled(true) && !QHostInfo::localHostName().contains("SailfishEmul")) {
logE("ERROR! Could not restore charger status! Your device "
"may not charge until reboot! If that doesn't help, "
"uninstall Battery Buddy and reboot your device.");
}

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2023 Matti Viljanen
* 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
@ -23,10 +23,8 @@
#include <QString>
#include <QFile>
#include <QStandardPaths>
#include <QSysInfo>
#include <QHostInfo>
#include <QLocale>
#include <QCoreApplication>
#include <keepalive/backgroundactivity.h>
#include "settings.h"
#include "mynotification.h"
#include "logger.h"
@ -36,13 +34,12 @@ class Battery : public QObject
Q_OBJECT
public:
Battery(Logger* newLogger, bool loglevelSet, QCoreApplication *app, QObject *parent = nullptr);
Battery(Logger* newLogger, bool loglevelSet, QObject *parent = nullptr);
~Battery();
int getCharge();
bool getCharging();
bool getChargerConnected();
bool getAcConnected();
QString getState();
bool getChargingEnabled();
@ -56,68 +53,37 @@ public slots:
void shutdown();
private:
bool unclosedChargeNotification = false;
bool unclosedHealthNotification = false;
BackgroundActivity::Frequency frequencies[14] = {
BackgroundActivity::Range,
BackgroundActivity::ThirtySeconds,
BackgroundActivity::TwoAndHalfMinutes,
BackgroundActivity::FiveMinutes,
BackgroundActivity::TenMinutes,
BackgroundActivity::FifteenMinutes,
BackgroundActivity::ThirtyMinutes,
BackgroundActivity::OneHour,
BackgroundActivity::TwoHours,
BackgroundActivity::FourHours,
BackgroundActivity::EightHours,
BackgroundActivity::TenHours,
BackgroundActivity::TwelveHours,
BackgroundActivity::TwentyFourHours
};
Logger *logger;
QFile *chargeFile = nullptr;
QFile *chargerConnectedFile = nullptr;
QFile *acConnectedFile = nullptr;
QFile *currentFile = nullptr;
QFile *stateFile = nullptr;
QFile *chargingEnabledFile = nullptr;
QFile *maxChargeCurrentFile = nullptr;
QFile *temperatureFile = nullptr;
QFile *healthFile = nullptr;
Settings *settings = nullptr;
BackgroundActivity *updateTimer = nullptr;
BackgroundActivity *highNotifyTimer = nullptr;
BackgroundActivity *lowNotifyTimer = nullptr;
BackgroundActivity *healthNotifyTimer = nullptr;
QTimer *updateTimer = nullptr;
QTimer *highNotifyTimer = nullptr;
QTimer *lowNotifyTimer = nullptr;
QTimer *healthNotifyTimer = nullptr;
MyNotification *chargeNotification = nullptr;
MyNotification *healthNotification = nullptr;
// Default values:
int charge = 100; // 100% full
int current = 0; // Charging/discharging current in microamps
bool chargerConnected = false; // Charger plugged in
bool acConnected = false; // AC plugged in
QString state = "idle"; // dis/charging, idle, unknown
bool chargingEnabled = true; // Only ever disabled manually
int maxChargeCurrent = 0;
int maxSupportedChargeCurrent = 0;
QString health = "unknown"; // Good, warm, overheat. Might have Cold or Overvoltage depending on driver
int temperature = 0x7FFFFFFF; // This value means "unknown" (32-bit INT_MAX)
int enableChargingValue = 0;
int disableChargingValue = 1;
int enableChargingValue = 1;
int disableChargingValue = 0;
bool chargerIsEnabled = true;
int nextCharge = charge;
bool invertCurrent = false;
bool invertDecided = false;
bool nextChargerConnected = chargerConnected;
bool nextAcConnected = acConnected;
QString nextState = state;
bool nextChargingEnabled = chargingEnabled;
int nextTemperature = temperature;
@ -126,12 +92,19 @@ private:
QFileDevice::Permissions originalPerms; // Updated in constructor
QFileDevice::Permissions customPerms = static_cast<QFileDevice::Permissions>(0x0666);
signals:
void chargeChanged(int);
void stateChanged(QString);
void chargingEnabledChanged(bool);
void chargerConnectedChanged(bool);
void temperatureChanged(int);
void healthChanged(QString);
public slots:
void resetTimers();
void showHighNotification();
void showLowNotification();
void showHealthNotification();
void setMaxChargeCurrent(int newCurrent);
};
#endif // BATTERY_H

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -17,6 +17,7 @@
*/
#include <QCoreApplication>
#include <QObject>
#include <QTimer>
#include "logger.h"
#include "battery.h"
@ -54,11 +55,11 @@ int main(int argc, char** argv)
else if(!strcmp(argv[i],"--help")) {
printf("%s %s\n", APP_NAME, APP_VERSION);
printf("Usage:\n");
printf(" --verbose Set log level to medium)\n");
printf(" --debug Set log level to high\n");
printf(" --verbose Enable informational messages\n");
printf(" --debug Enable informational and debugging messages\n");
printf(" --help Print version string and exit\n");
printf(" --logfile Write log to a file. Implies --verbose\n\n");
printf("Log file: ~/.cache/harbour-batterybuddy/harbour-batterybuddy-daemon.log\n");
printf("Log file: ~/.cache/harbour-batterybuddy-daemon/harbour-batterybuddy-daemon.log\n");
return 0;
}
}
@ -68,9 +69,9 @@ int main(int argc, char** argv)
app.setApplicationVersion(APP_VERSION);
Logger* logger = new Logger(verbose, debug, logfile);
logL(QString("%1 %2").arg(APP_NAME, APP_VERSION));
logE(QString("%1 %2").arg(APP_NAME, APP_VERSION));
Battery* battery = new Battery(logger, logLevelSet, &app);
Battery* battery = new Battery(logger, logLevelSet);
// Exit gracefully on Ctrl-C and service stop
QObject::connect(&app, SIGNAL(aboutToQuit()), battery, SLOT(shutdown()));

View file

@ -37,7 +37,7 @@ bool Logger::getDebug() { return debug; }
bool Logger::getVerbose() { return verbose; }
void Logger::enableLogFile() {
QString logDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation).replace("-daemon","");
QString logDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
filename = QString(logDir + "/" + APP_NAME + ".log");
std::cout << "Logging to " << filename.toStdString() << std::endl;

View file

@ -10,16 +10,16 @@
#include <fstream>
// Use like this:
// logM("Settings loaded");
// logV("Settings loaded");
// Low setting - always logged
#define logL logger->log
// Errors (always written - for general messages, too!)
#define logE logger->log
// Medium setting - log more values
#define logM if(logger->verbose) logger->log
// Verbose (log, if enabled)
#define logV if(logger->verbose) logger->log
// High setting - log everything
#define logH if(logger->debug) logger->log
// Debug (log, if enabled)
#define logD if(logger->debug) logger->log
class Logger : public QObject
{

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -25,7 +25,7 @@ Settings::Settings(Logger* newLogger, QObject *parent) : QObject(parent)
mySettings = new QSettings(appName, appName, this);
}
logM("Using " + mySettings->fileName());
logV("Using " + mySettings->fileName());
QString logFilename = logger->getLogFilename();
if(mySettings->value(sLogFilename,QString()).toString() != logFilename) {
@ -40,28 +40,28 @@ Settings::Settings(Logger* newLogger, QObject *parent) : QObject(parent)
if(mySettings->contains(key)) {
mySettings->setValue(sLowAlert, mySettings->value(key));
mySettings->remove(key);
logM(migrate.arg(key));
logV(migrate.arg(key));
}
key = "upperLimit";
if(mySettings->contains(key)) {
mySettings->setValue(sHighAlert, mySettings->value(key));
mySettings->remove(key);
logM(migrate.arg(key));
logV(migrate.arg(key));
}
key = "notificationsEnabled";
if(mySettings->contains(key)) {
if(mySettings->value(key).toInt() == 0) {
mySettings->setValue(sHighNotificationsInterval, 2);
mySettings->setValue(sLowNotificationsInterval, 2);
mySettings->setValue(sHighNotificationsInterval, 610);
mySettings->setValue(sLowNotificationsInterval, 610);
}
else {
mySettings->setValue(sHighNotificationsInterval, highNotificationsInterval);
mySettings->setValue(sLowNotificationsInterval, lowNotificationsInterval);
}
mySettings->remove(key);
logM(migrate.arg(key));
logV(migrate.arg(key));
}
key = "interval";
@ -69,23 +69,23 @@ Settings::Settings(Logger* newLogger, QObject *parent) : QObject(parent)
mySettings->setValue(sHighNotificationsInterval, mySettings->value(key));
mySettings->setValue(sLowNotificationsInterval, mySettings->value(key));
mySettings->remove(key);
logM(migrate.arg(key));
logV(migrate.arg(key));
}
key = "highNotificationsEnabled";
if(mySettings->contains(key)) {
if(mySettings->value(key).toInt() == 0)
mySettings->setValue(sHighNotificationsInterval, 2);
mySettings->setValue(sHighNotificationsInterval, 610);
mySettings->remove(key);
logM(migrate.arg(key));
logV(migrate.arg(key));
}
key = "lowNotificationsEnabled";
if(mySettings->contains(key)) {
if(mySettings->value(key).toInt() == 0)
mySettings->setValue(sLowNotificationsInterval, 2);
mySettings->setValue(sLowNotificationsInterval, 610);
mySettings->remove(key);
logM(migrate.arg(key));
logV(migrate.arg(key));
}
// These are updated and localized from the config file
@ -96,12 +96,11 @@ Settings::Settings(Logger* newLogger, QObject *parent) : QObject(parent)
notificationHealthWarnText = "Battery health is not good";
notificationHealthCritText = "Battery health is critical";
// Do this here, because...
watcher = new QFileSystemWatcher(QStringList(mySettings->fileName()), this);
connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateConfig(QString)));
// To trigger setting the initial config value
maxChargeCurrent = 0;
// ...calling this deletes mySettings!
updateConfig(mySettings->fileName());
}
@ -111,11 +110,11 @@ bool Settings::loadInteger(const char *key, int &currValue, const int min, const
int newValue = mySettings->value(key, currValue).toInt();
newValue = (newValue <= min ? min : (newValue >= max ? max : newValue));
if(currValue == newValue) {
logH(QString("Load: %1 %2 (unchanged)").arg(key).arg(currValue));
logD(QString("Load: %1 %2 (unchanged)").arg(key).arg(currValue));
return false;
}
currValue = newValue;
logM(QString("Load: %1 %2").arg(key).arg(currValue));
logV(QString("Load: %1 %2").arg(key).arg(currValue));
return true;
}
@ -124,11 +123,9 @@ void Settings::updateConfig(const QString path) {
// Use the same file location as GUI for data exchange
if(!mySettings) {
mySettings = new QSettings(appName, appName, this);
} else {
mySettings->sync();
}
logH("Updating configuration...");
logD("Updating configuration...");
// Read in the values
bool restartTimers = false;
@ -136,15 +133,12 @@ void Settings::updateConfig(const QString path) {
loadInteger(sLowAlert, lowAlert, 5, 99);
loadInteger(sHighAlert, highAlert, 6, 100);
loadInteger(sHealthAlert, healthAlert, 0, 2);
restartTimers |= loadInteger(sHighNotificationsInterval, highNotificationsInterval, 0, 13);
restartTimers |= loadInteger(sLowNotificationsInterval, lowNotificationsInterval, 0, 13);
restartTimers |= loadInteger(sHealthNotificationsInterval, healthNotificationsInterval, 0, 13);
restartTimers |= loadInteger(sHighNotificationsInterval, highNotificationsInterval, 50, 610);
restartTimers |= loadInteger(sLowNotificationsInterval, lowNotificationsInterval, 50, 610);
restartTimers |= loadInteger(sHealthNotificationsInterval, healthNotificationsInterval, 50, 610);
loadInteger(sLimitEnabled, limitEnabled, 0, 1);
loadInteger(sLowLimit, lowLimit, 5, 99);
loadInteger(sHighLimit, highLimit, 6, 100);
if(loadInteger(sMaxChargeCurrent, maxChargeCurrent, 0, 5000000)) {
emit setMaxChargeCurrent(maxChargeCurrent);
}
notificationTitle = mySettings->value(sNotificationTitle, notificationTitle).toString();
notificationLowText = mySettings->value(sNotificationLowText, notificationLowText).toString();
@ -161,18 +155,21 @@ void Settings::updateConfig(const QString path) {
if(oldLogLevel != logLevel) {
logger->debug = (logLevel == 2);
logger->verbose = (logLevel > 1);
logL(QString("Log level set to %1").arg((logLevel == 0 ? "low" : (logLevel == 1 ? "medium" : "high"))));
logE(QString("Log level set to %1").arg((logLevel == 0 ? "low" : (logLevel == 1 ? "medium" : "high"))));
}
delete mySettings;
mySettings = nullptr;
// Let the file system settle...
QThread::msleep(100);
if(watcher->files().contains(path)) {
logH("Config file already on watchlist");
logD("Config file already on watchlist");
}
else {
watcher->addPath(path);
logH("Config file added to watchlist");
logD("Config file added to watchlist");
}
if(restartTimers) {
@ -183,7 +180,6 @@ void Settings::updateConfig(const QString path) {
// Getters condensed
int Settings::getLowAlert() { return lowAlert; }
int Settings::getHighAlert() { return highAlert; }
int Settings::getMaxChargeCurrent() { return maxChargeCurrent; }
int Settings::getHealthAlert() { return healthAlert; }
int Settings::getHighNotificationsInterval() { return highNotificationsInterval; }
int Settings::getLowNotificationsInterval() { return lowNotificationsInterval; }
@ -201,10 +197,3 @@ QString Settings::getNotificationHealthTitle() { return notificationHealthTi
QString Settings::getNotificationHealthWarnText() { return notificationHealthWarnText; }
QString Settings::getNotificationHealthCritText() { return notificationHealthCritText; }
int Settings::getLogLevel() { return logLevel; }
void Settings::setMaxSupportedChargeCurrent(int newCurrent) {
mySettings->setValue(sMaxSupportedChargeCurrent, QByteArray::number(newCurrent));
if(mySettings->value(sMaxChargeCurrent, QVariant::fromValue(0)).toInt() == 0) {
mySettings->setValue(sMaxChargeCurrent, QByteArray::number(newCurrent));
}
}

View file

@ -1,7 +1,7 @@
/**
* Battery Buddy, a Sailfish application to prolong battery lifetime
*
* Copyright (C) 2019-2022 Matti Viljanen
* 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
@ -34,7 +34,6 @@ public:
int getLowAlert();
int getHighAlert();
int getMaxChargeCurrent();
int getHighNotificationsInterval();
int getLowNotificationsInterval();
int getHealthAlert();
@ -56,8 +55,6 @@ public:
QString getNotificationHealthWarnText();
QString getNotificationHealthCritText();
void setMaxSupportedChargeCurrent(int newCurrent);
private:
Logger* logger;
QSettings* mySettings = nullptr;
@ -73,7 +70,6 @@ private:
// Default values
int lowAlert = 25;
int highAlert = 75;
int maxChargeCurrent = 0;
int healthAlert = 1; // 0=off, 1=warn, 2=crit
int highNotificationsInterval = 60;
int lowNotificationsInterval = 60;
@ -85,9 +81,9 @@ private:
int lowLimit = 65;
int highLimit = 70;
QString lowAlertFile = "/usr/share/sounds/jolla-ambient/stereo/battery_low.wav";
QString lowAlertFile = "/usr/share/sounds/jolla-ambient/stereo/general_warning.wav";
QString highAlertFile = "/usr/share/sounds/jolla-ambient/stereo/positive_confirmation.wav";
QString healthAlertFile = "/usr/share/sounds/jolla-ambient/stereo/general_warning.wav";
QString healthAlertFile = "/usr/share/sounds/jolla-ambient/stereo/battery_low.wav";
QString notificationTitle;
QString notificationLowText;
QString notificationHighText;
@ -105,8 +101,6 @@ private:
const char* sLimitEnabled = "limitEnabled";
const char* sLowLimit = "lowLimit";
const char* sHighLimit = "highLimit";
const char* sMaxChargeCurrent = "maxChargeCurrent";
const char* sMaxSupportedChargeCurrent = "maxSupportedChargeCurrent";
const char* sLowAlertFile = "lowAlertFile";
const char* sHighAlertFile = "highAlertFile";
const char* sHealthAlertFile = "healthAlertFile";
@ -126,7 +120,6 @@ private slots:
signals:
void resetTimers();
void setMaxChargeCurrent(int newCurrent);
};
#endif // SETTINGS_H