Skip to content
Snippets Groups Projects
Commit 5ad1c0b4 authored by enlroma's avatar enlroma
Browse files

First alpha version.

parent 06aba981
No related branches found
No related tags found
1 merge request!1First alpha version.
import QtQuick 2.0
import org.kde.plasma.configuration 2.0
ConfigModel {
ConfigCategory {
name: i18n("General")
icon: "configure"
source: "configGeneral.qml"
}
}
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
<kcfgfile name="configGeneral"/>
<group name="General">
<entry name="batteryHelthConfigFile" type="String">
<default/>
</entry>
<entry name="iconSize" type="Int">
<default>32</default>
</entry>
</group>
</kcfg>
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-06-19 20:28+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: contents/ui/configGeneral.qml
msgid ""
msgstr ""
#: contents/ui/main.qml
msgid ""
msgstr ""
#: contents/config/config.qml
msgid "General"
msgstr ""
# Spanish translations for PACKAGE package
# Traducciones al espaol para el paquete PACKAGE.
# Copyright (C) 2023 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Eniel Rodríguez Machado <eniel160990@gmail.com>, 2023.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-06-19 20:28+0200\n"
"PO-Revision-Date: 2023-06-19 22:40+0200\n"
"Last-Translator: Eniel Rodríguez Machado <eniel160990@gmail.com>\n"
"Language-Team: Spanish\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: contents/ui/configGeneral.qml
msgid ""
msgstr ""
#: contents/ui/main.qml
msgid ""
msgstr ""
#: contents/config/config.qml
msgid "General"
msgstr "General"
import QtQuick 2.0
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.12
import org.kde.kirigami 2.4 as Kirigami
import org.kde.plasma.core 2.0 as PlasmaCore
Kirigami.FormLayout {
id: configGeneral
property alias cfg_batteryHelthConfigFile: batteryHelthConfigFileField.text
property alias cfg_iconSize: iconSizeComboBox.currentValue
TextField {
id: batteryHelthConfigFileField
Kirigami.FormData.label: i18n("Battery Health config file (if the plugin works don't touch this):")
}
ComboBox {
id: iconSizeComboBox
Kirigami.FormData.label: i18n("Icon size:")
model: [
{text: "small", value: units.iconSizes.small},
{text: "small-medium", value: units.iconSizes.smallMedium},
{text: "medium", value: units.iconSizes.medium},
{text: "large", value: units.iconSizes.large},
{text: "huge", value: units.iconSizes.huge}
]
textRole: "text"
valueRole: "value"
currentIndex: model.findIndex((element) => element.value === plasmoid.configuration.iconSize)
}
}
contents/ui/image/error.png

1.62 KiB

contents/ui/image/off.png

9.45 KiB

contents/ui/image/on.png

9.43 KiB

import QtQuick 2.0
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.plasmoid 2.0
Item {
id: root
property string pkexecPath: "/usr/bin/pkexec"
property string batteryHelthConfigPath
readonly property string const_ZERO_TIMEOUT_NOTIFICATION: " -t 0"
readonly property var const_COMMANDS: ({
"query": "cat " + root.batteryHelthConfigPath,
"on": "echo 60 | " + root.pkexecPath + " tee " + root.batteryHelthConfigPath + " 1>/dev/null",
"off": "echo 100 | " + root.pkexecPath + " tee " + root.batteryHelthConfigPath + " 1>/dev/null",
"findBatteryHelthConfigFile": "find /sys -name \"charge_control_end_threshold\"",
"findNotificationTool": "find /usr -type f -executable \\( -name \"notify-send\" -o -name \"zenity\" \\)",
// defined in findNotificationTool Connection
"sendNotification": () => ""
})
property var icons: ({
"on": Qt.resolvedUrl("./image/on.png"),
"off": Qt.resolvedUrl("./image/off.png"),
"error": Qt.resolvedUrl("./image/error.png")
})
// This values can change after the execution of onCompleted().
property string currentStatus: "off"
property bool isCompatible: false
property string desiredStatus
property bool loading: false
property string icon: root.icons[root.currentStatus]
Plasmoid.icon: root.icon
Connections {
target: Plasmoid.configuration
}
Component.onCompleted: {
findNotificationTool()
findBatteryHelthConfigFile()
}
PlasmaCore.DataSource {
id: queryStatusDataSource
engine: "executable"
connectedSources: []
onNewData: {
var exitCode = data["exit code"]
var exitStatus = data["exit status"]
var stdout = data["stdout"]
var stderr = data["stderr"]
exited(exitCode, exitStatus, stdout, stderr)
disconnectSource(sourceName)
}
function exec(cmd) {
connectSource(cmd)
}
signal exited(int exitCode, int exitStatus, string stdout, string stderr)
}
PlasmaCore.DataSource {
id: setStatusDataSource
engine: "executable"
connectedSources: []
onNewData: {
var exitCode = data["exit code"]
var exitStatus = data["exit status"]
var stdout = data["stdout"]
var stderr = data["stderr"]
exited(exitCode, exitStatus, stdout, stderr)
disconnectSource(sourceName)
}
function exec(cmd) {
connectSource(cmd)
}
signal exited(int exitCode, int exitStatus, string stdout, string stderr)
}
PlasmaCore.DataSource {
id: findNotificationToolDataSource
engine: "executable"
connectedSources: []
onNewData: {
var exitCode = data["exit code"]
var exitStatus = data["exit status"]
var stdout = data["stdout"]
// stderr output can contain "permission denied" errors
var stderr = data["stderr"]
exited(exitCode, exitStatus, stdout, stderr)
disconnectSource(sourceName)
}
function exec(cmd) {
connectSource(cmd)
}
signal exited(int exitCode, int exitStatus, string stdout, string stderr)
}
PlasmaCore.DataSource {
id: findBatteryHelthConfigFileDataSource
engine: "executable"
connectedSources: []
onNewData: {
var exitCode = data["exit code"]
var exitStatus = data["exit status"]
var stdout = data["stdout"]
// stderr output can contain "permission denied" errors
var stderr = data["stderr"]
exited(exitCode, exitStatus, stdout, stderr)
disconnectSource(sourceName)
}
function exec(cmd) {
connectSource(cmd)
}
signal exited(int exitCode, int exitStatus, string stdout, string stderr)
}
PlasmaCore.DataSource {
id: sendNotification
engine: "executable"
connectedSources: []
onNewData: {
disconnectSource(sourceName)
}
function exec(cmd) {
connectSource(cmd)
}
}
Connections {
target: queryStatusDataSource
function onExited(exitCode, exitStatus, stdout, stderr){
if (stderr) {
root.icon = root.icons.error
showNotification(root.icons.error, stderr, stderr)
} else {
var status = stdout.trim()
root.currentStatus = status === "60"? "on" : "off"
root.isCompatible = true
root.loading = false
}
}
}
Connections {
target: setStatusDataSource
function onExited(exitCode, exitStatus, stdout, stderr){
root.loading = false
if (stderr) {
showNotification(root.icons.error, stderr, stdout)
} else {
root.currentStatus = root.desiredStatus
showNotification(root.icons[root.currentStatus], i18n("Status switched to %1.", root.currentStatus.toUpperCase()))
}
}
}
Connections {
target: findNotificationToolDataSource
function onExited(exitCode, exitStatus, stdout, stderr){
if (stdout) {
// Many Linux distros have two notification tools
var paths = stdout.trim().split("\n")
var path1 = paths[0]
var path2 = paths[1]
// prefer notify-send because it allows to use icon, zenity v3.44.0 does not accept icon option
if (path1 && path1.trim().endsWith("notify-send")) {
const_COMMANDS.sendNotification = (title, message, iconURL, options) => path1.trim() + " -i " + iconURL + " '" + title + "' '" + message + "'" + options
}if (path2 && path2.trim().endsWith("notify-send")) {
const_COMMANDS.sendNotification = (title, message, iconURL, options) => path2.trim() + " -i " + iconURL + " '" + title + "' '" + message + "'" + options
}else if (path1 && path1.trim().endsWith("zenity")) {
const_COMMANDS.sendNotification = (title, message, iconURL, options) => path1.trim() + " --notification --text='" + title + "\\n" + message + "'"
}
}
}
}
Connections {
target: findBatteryHelthConfigFileDataSource
function onExited(exitCode, exitStatus, stdout, stderr){
// We assume that there can only be a single charge_control_end_threshold file.
if (stdout.trim()) {
root.batteryHelthConfigPath = stdout.trim()
queryStatus()
}else {
root.isCompatible = false
root.icon = root.icons.error
}
}
}
// Get the current status
function queryStatus() {
root.loading = true
queryStatusDataSource.exec(const_COMMANDS.query)
}
// status = "on"|"off"
function switchStatus(status: string) {
root.desiredStatus = status
root.loading = true
showNotification(root.icons[status], i18n("Switching status to %1.", status.toUpperCase()))
setStatusDataSource.exec(const_COMMANDS[status])
}
function showNotification(iconURL: string, message: string, title = i18n("Battery Health Switcher"), options = const_ZERO_TIMEOUT_NOTIFICATION){
sendNotification.exec(const_COMMANDS.sendNotification(title, message, iconURL, options))
}
function findNotificationTool() {
findNotificationToolDataSource.exec(const_COMMANDS.findNotificationTool)
}
function findBatteryHelthConfigFile() {
// Check if the user defined the file path manually and use it if he did.
if(Plasmoid.configuration.batteryHelthConfigFile){
root.batteryHelthConfigPath = Plasmoid.configuration.batteryHelthConfigFile
}else{
findBatteryHelthConfigFileDataSource.exec(const_COMMANDS.findBatteryHelthConfigFile)
}
}
Plasmoid.preferredRepresentation: Plasmoid.compactRepresentation
Plasmoid.compactRepresentation: Item {
PlasmaCore.IconItem {
height: Plasmoid.configuration.iconSize
width: Plasmoid.configuration.iconSize
anchors.centerIn: parent
source: root.icon
active: compactMouse.containsMouse
MouseArea {
id: compactMouse
anchors.fill: parent
hoverEnabled: true
onClicked: {
plasmoid.expanded = !plasmoid.expanded
}
}
}
}
Plasmoid.fullRepresentation: Item {
Layout.preferredWidth: 400 * PlasmaCore.Units.devicePixelRatio
Layout.preferredHeight: 300 * PlasmaCore.Units.devicePixelRatio
ColumnLayout {
anchors.centerIn: parent
Image {
id: mode_image
source: root.icon
Layout.alignment: Qt.AlignCenter
Layout.preferredHeight: 64
fillMode: Image.PreserveAspectFit
}
PlasmaComponents3.Label {
Layout.alignment: Qt.AlignCenter
text: root.isCompatible ? i18n("Battery Health Charging is %1.", root.currentStatus.toUpperCase()) : i18n("The Battery Health Charging feature is not available.")
}
PlasmaComponents3.Switch {
Layout.alignment: Qt.AlignCenter
enabled: !root.loading && root.isCompatible
checked: root.currentStatus === "on"
onClicked: {
switchStatus(checked ? "on" : "off")
}
}
BusyIndicator {
id: loadingIndicator
Layout.alignment: Qt.AlignCenter
running: root.loading
}
}
}
Plasmoid.toolTipMainText: i18n("Switch Battery Health Charging.")
Plasmoid.toolTipSubText: root.isCompatible ? i18n("Battery Health Charging is %1.", root.currentStatus.toUpperCase()) : i18n("The Battery Health Charging feature is not available.")
}
[Desktop Entry]
Name=Asus Battery Health Switcher
Comment=Widget to turn on/off the Battery Health Charging feature in compatible Asus laptops.
Comment[es]=Widget para apagar/encender el modo Battery Health Charging en laptops Asus compatibles.
Type=Service
Icon=battery
ServiceTypes=Plasma/Applet
X-Plasma-API=declarativeappletscript
X-Plasma-MainScript=ui/main.qml
X-KDE-PluginInfo-Author=Eniel
X-KDE-PluginInfo-Email=eniel160990@gmail.com
X-KDE-PluginInfo-Website=
X-KDE-PluginInfo-Name=asus-battery-health-switcher
X-KDE-PluginInfo-Version=0.0.1
X-KDE-PluginInfo-License=GPL3
X-KDE-PluginInfo-Category=Hardware
X-Plasma-NotificationArea=true
X-Plasma-NotificationAreaCategory=Hardware
X-KDE-PluginInfo-EnabledByDefault=true
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment