v1.1.0: English UI + docs, bundled Bitcoin icon, canonical config page, gitea.a14r.be website URL, journal diagnostics

This commit is contained in:
ArnoldCordewiner
2026-09-05 20:07:12 +02:00
parent e3934f33b6
commit d3641469b0
8 changed files with 160 additions and 85 deletions
+57 -42
View File
@@ -1,77 +1,92 @@
# plasma-bitcoin-price
# Bitcoin Price (Plasma 5 widget)
KDE Plasma 5 widget die de bitcoinprijs in EUR toont, opgehaald bij de
KDE Plasma 5 widget that shows the bitcoin price in EUR, fetched from the
[CoinGecko API](https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=eur).
## Weergave
## Display
| Situatie | Weergave |
| Situation | Display |
|---|---|
| Prijs gestegen t.o.v. vorige meting | groen |
| Prijs gedaald t.o.v. vorige meting | rood |
| Prijs gelijk gebleven (of eerste meting) | grijs |
| API-fout (netwerkfout, 4xx/5xx, rate limit 429) | `--` |
| Price up compared to the previous reading | green |
| Price down compared to the previous reading | red |
| Price unchanged (or first reading) | grey |
| API failure (network error, 4xx/5xx, rate limit 429) | `--` |
Formaat: `68.969 €` — duizendtallen volgens de systeemlocale, afgerond op hele euro's.
Format: `68,969 €` (thousands separators follow the system locale, rounded to
whole euros) preceded by the bundled Bitcoin icon in the compact and full
representations.
## Configuratie
## Configuration
- **Vernieuwinterval (minuten)** — standaard 5, minimaal **5**, maximaal 1440.
Het minimum van 5 minuten komt door de CoinGecko rate limit van 1 call per 5 minuten.
- **Refresh interval (minutes)** — default 5, minimum **5**, maximum 1440.
The 5-minute floor exists because the CoinGecko API allows one request per
5 minutes. A hint text in the config dialog explains this.
Instelbaar via rechtsklik op de widget → *Configureer Bitcoin-prijs**Algemeen*.
Configurable via right-click on the widget → *Configure Bitcoin Price…**General*.
## Installatie
## Installation
### Grafisch
Dubbelklik op `dist/bitcoin-price-1.0.0.plasmoid` in Dolphin (Plasma installeert
dan automatisch naar `~/.local/share/plasma/plasmoids/`).
### Graphical
Double-click `bitcoin-price-1.1.0.plasmoid` in Dolphin (Plasma installs it to
`~/.local/share/plasma/plasmoids/` automatically). The latest build is attached
to the [v1.1.0 release](../../releases/tag/v1.1.0).
### Terminal
```bash
kpackagetool5 --type Plasma/Applet --install dist/bitcoin-price-1.0.0.plasmoid
# widget toevoegen via Add Widgets; bij twijfel plasma herladen:
kpackagetool5 --type Plasma/Applet --upgrade bitcoin-price-1.1.0.plasmoid
# Then restart the shell if needed:
plasmashell --replace &
```
Verwijderen:
Upgrading an already-installed widget requires `--upgrade` (`--install` fails
when the plugin id already exists).
Uninstall:
```bash
kpackagetool5 --type Plasma/Applet --remove nl.a14r.bitcoinprice
```
## Notities
## Notes
- De API-URL gebruikt `vs_currencies=eur`. In de oorspronkelijke opdracht stond
een `usd`-URL, maar de eis was "prijs t.o.v. de euro" met een `€`-teken; een
dollarwaarde onder een €-teken zou foutief zijn.
- De trendvergelijking gebeurt tegen de laatst bekend geraakte prijs. Na een
API-fout blijft die referentie staan, zodat de kleur klopt zodra er weer
data binnenkomt.
- Zonder CoinGecko API-key kan de API ook tussendoor een 429 geven; de widget
toont dan `--` tot de eerstvolgende geslaagde poll.
- Getest op Debian 12 / Plasma 5 (Qt 5.15). Plasma 6 werkt vermoedelijk ook,
maar is niet getest.
- The API URL uses `vs_currencies=eur`. The original request referenced a
`usd` URL, but the requirement was "price versus the euro" with a €-sign;
showing a dollar amount under a € sign would be wrong.
- The trend comparison is made against the last known price. After an API
failure that reference is kept, so the color is correct again as soon as
fresh data arrives.
- Without a CoinGecko API key the API may occasionally return 429; the widget
shows `--` until the next successful poll.
- Tested on Plasma 5.27 / Qt 5.15. Plasma 6 is expected to work but is untested.
## Repository-layout
## Debugging
The widget logs to the plasmashell journal:
```bash
journalctl --user -u plasma-plasmashell.service | grep bitcoinprice
```
Expected lines: `started, refresh interval: N minutes`, `fetched EUR <price>`,
or `fetch failed, HTTP status: <code>`.
## Repository layout
```
metadata.desktop
contents/
├── config/main.xml # config-schema (refreshMinutes, min 5, max 1440)
├── config/main.xml # config schema (refreshMinutes, min 5, max 1440)
├── images/bitcoin.svg # bundled Bitcoin icon
└── ui/
├── main.qml # widget + fetch/vergelijk-logica
├── config.qml # configuratievenster (categorieën)
└── configGeneral.qml # interval-instelling
├── main.qml # widget + fetch/compare logic
├── config.qml # config dialog (categories)
└── configGeneral.qml # interval setting
```
Het kant-en-klare installatiebestand (`bitcoin-price-1.0.0.plasmoid`) staat als
bijlage bij de [v1.0.0-release](../../releases/tag/v1.0.0).
Zelf (her)packagen:
Repackage yourself:
```bash
zip -r bitcoin-price.plasmoid metadata.desktop contents
```
## Licentie
## License
MIT — zie [LICENSE](LICENSE).
MIT — see [LICENSE](LICENSE).
Binary file not shown.
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="6.82666in" height="6.82666in" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
viewBox="0 0 6.82666 6.82666"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Layer_x0020_1">
<g id="_372402152">
<circle id="_372402800" fill="#FF9800" cx="3.41333" cy="3.41333" r="2.56"/>
<path id="_372402824" fill="#FFFFFE" d="M3.87171 3.18776c0.0803346,0 0.155882,-0.0312795 0.212665,-0.0880945 0.0568189,-0.0568465 0.0880945,-0.132335 0.0880945,-0.212665 0,-0.0803425 -0.0312756,-0.155886 -0.088122,-0.212701 -0.0567795,-0.0567913 -0.132303,-0.0880669 -0.212638,-0.0880669l-0.827106 0 0 0.601528 0.827106 0zm0.0249606 1.50341l0 0.225992 -0.451146 0 0 -0.225575 -0.200461 0 0 0.225575 -0.45115 0 0 -0.225575 -0.350843 0 0 -0.45115 0.150382 0 0 -1.6542 -0.150382 0 0 -0.45115 0.350843 0 0 -0.225575 0.45115 0 0 0.225575 0.200461 0 0 -0.225575 0.451146 0 0 0.225992c0.191488,0.00620866 0.37061,0.0837126 0.506701,0.219803 0.142051,0.142051 0.220244,0.330874 0.220244,0.531697 0,0.198319 -0.0762953,0.384929 -0.214953,0.526335 0.138697,0.141421 0.214953,0.328024 0.214953,0.526339 0,0.200823 -0.0782205,0.389646 -0.220217,0.531661 -0.136118,0.136122 -0.31524,0.213626 -0.506728,0.219835zm-0.852067 -0.450732l0.827106 0c0.0803346,0 0.155882,-0.0312835 0.212665,-0.0880906 0.0568189,-0.0568465 0.0880945,-0.132343 0.0880945,-0.212673 0,-0.0803346 -0.0312756,-0.155886 -0.088122,-0.212705 -0.0567795,-0.0567795 -0.132303,-0.088063 -0.212638,-0.088063l-0.827106 0 0 0.601531z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

+1 -1
View File
@@ -3,7 +3,7 @@ import org.kde.plasma.configuration 2.0
ConfigModel {
ConfigCategory {
name: i18n("Algemeen")
name: i18n("General")
icon: "preferences-desktop"
source: "configGeneral.qml"
}
+22 -3
View File
@@ -1,16 +1,35 @@
/*
* Config page for nl.a14r.bitcoinprice.
* Follows the canonical Plasma 5 config dialog pattern:
* Kirigami.FormLayout + cfg_ prefixed property aliases.
*/
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls 2.15 as QQC2
import org.kde.kirigami 2.5 as Kirigami
Kirigami.FormLayout {
id: generalPage
// The cfg_ prefix is what Plasma uses to read/write plasmoid.configuration
property alias cfg_refreshMinutes: intervalSpin.value
SpinBox {
Item {
Kirigami.FormData.isSection: true
}
QQC2.SpinBox {
id: intervalSpin
Kirigami.FormData.label: i18n("Refresh interval (minutes):")
from: 5
to: 1440
stepSize: 5
editable: true
Kirigami.FormData.label: i18n("Vernieuwinterval (minuten):")
}
QQC2.Label {
text: i18n("CoinGecko allows one request per 5 minutes; lower values are not possible.")
font.italic: true
opacity: 0.7
}
}
+55 -24
View File
@@ -1,14 +1,14 @@
/*
* nl.a14r.bitcoinprice — KDE Plasma 5 widget
*
* Toont de bitcoinprijs in EUR (CoinGecko API).
* - Groen : prijs gestegen t.o.v. vorige meting
* - Rood : prijs gedaald t.o.v. vorige meting
* - Grijs : gelijk gebleven (of eerste meting)
* - "--" : API-fout (netwerkfout, 4xx/5xx, rate limit 429)
* Shows the bitcoin price in EUR (CoinGecko API).
* - Green : price up compared to the previous reading
* - Red : price down compared to the previous reading
* - Grey : unchanged (or first reading)
* - "--" : API failure (network error, 4xx/5xx, 429 rate limit)
*
* Vernieuwinterval: configureerbaar, minimaal 5 minuten
* (CoinGecko limiet: 1 call per 5 minuten).
* Refresh interval: configurable, minimum 5 minutes
* (CoinGecko limit: 1 call per 5 minutes).
*/
import QtQuick 2.15
@@ -22,42 +22,47 @@ Item {
readonly property int refreshMinutes: Math.max(5, plasmoid.configuration.refreshMinutes)
readonly property string apiUrl: "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=eur"
// -1 = gedaald, 0 = gelijk / nog geen vorige meting, 1 = gestegen
// -1 = down, 0 = unchanged / no previous reading yet, 1 = up
property int trend: 0
property double lastPrice: NaN // laatste succesvol opgehaalde prijs
property double lastPrice: NaN // last successfully fetched price
property string state: "init" // init | ok | error
property string lastUpdated: "" // HH:mm:ss van laatste succesvolle update
property string lastUpdated: "" // HH:mm:ss of the last successful update
readonly property string displayText: {
if (state !== "ok" || isNaN(lastPrice)) {
return "--";
}
return "\u20BF " + Number(lastPrice).toLocaleString(Qt.locale(), "f", 0) + " \u20AC";
return Number(lastPrice).toLocaleString(Qt.locale(), "f", 0) + " \u20AC";
}
readonly property color priceColor: {
if (state !== "ok" || isNaN(lastPrice)) {
return PlasmaCore.Theme.disabledTextColor; // "--" bij fout/init
return PlasmaCore.Theme.disabledTextColor; // "--" on error/init
}
if (trend > 0) {
return "#2ecc71"; // groen
return "#2ecc71"; // green
}
if (trend < 0) {
return "#e74c3c"; // rood
return "#e74c3c"; // red
}
return "#9e9e9e"; // grijs
return "#9e9e9e"; // grey
}
readonly property string statusText: {
if (state === "error") {
return lastUpdated === ""
? i18n("API-fout")
: i18n("API-fout — laatste geldige prijs: %1", lastUpdated);
? i18n("API error")
: i18n("API error — last known price: %1", lastUpdated);
}
if (lastUpdated === "") {
return i18n("Bezig met ophalen\u2026");
return i18n("Fetching\u2026");
}
return i18n("Laatst bijgewerkt: %1", lastUpdated);
return i18n("Last updated: %1", lastUpdated);
}
Component.onCompleted: {
console.log("[bitcoinprice] started, refresh interval:",
refreshMinutes, "minutes");
}
Plasmoid.backgroundHints: PlasmaCore.Types.StandardBackground
@@ -70,12 +75,27 @@ Item {
Item {
id: compact
Layout.minimumWidth: priceLabel.implicitWidth + PlasmaCore.Units.smallSpacing * 2
Layout.minimumWidth: row.implicitWidth + PlasmaCore.Units.smallSpacing * 2
Layout.minimumHeight: PlasmaCore.Units.iconSizes.smallMedium
Row {
id: row
anchors.centerIn: parent
spacing: PlasmaCore.Units.smallSpacing
Image {
id: btcIcon
source: "../images/bitcoin.svg"
sourceSize.width: PlasmaCore.Units.iconSizes.smallMedium
sourceSize.height: PlasmaCore.Units.iconSizes.smallMedium
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
visible: root.state === "ok"
}
Text {
id: priceLabel
anchors.centerIn: parent
anchors.verticalCenter: parent.verticalCenter
text: root.displayText
color: root.priceColor
textFormat: Text.PlainText
@@ -89,18 +109,28 @@ Item {
}
}
}
}
Plasmoid.fullRepresentation: Component {
Item {
id: fullRep
implicitWidth: PlasmaCore.Units.gridUnit * 14
implicitHeight: PlasmaCore.Units.gridUnit * 7
implicitHeight: PlasmaCore.Units.gridUnit * 9
Column {
anchors.centerIn: parent
spacing: PlasmaCore.Units.smallSpacing
Image {
anchors.horizontalCenter: parent.horizontalCenter
source: "../images/bitcoin.svg"
sourceSize.width: PlasmaCore.Units.iconSizes.large
sourceSize.height: PlasmaCore.Units.iconSizes.large
fillMode: Image.PreserveAspectFit
visible: root.state === "ok"
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: root.displayText
@@ -141,14 +171,15 @@ Item {
try {
var price = JSON.parse(xhr.responseText).bitcoin.eur;
if (typeof price === "number" && !isNaN(price)) {
console.log("[bitcoinprice] fetched EUR", price);
root.applyPrice(price);
return;
}
} catch (e) {
// ongeldige JSON → val door naar de foutafhandeling
// invalid JSON → fall through to error handling
}
}
// API-fout (netwerk, 4xx/5xx, rate limit 429, onverwachte payload)
console.log("[bitcoinprice] fetch failed, HTTP status:", xhr.status);
root.state = "error";
};
xhr.send();
Binary file not shown.
+2 -4
View File
@@ -1,8 +1,6 @@
[Desktop Entry]
Name=Bitcoin Price
Name[nl]=Bitcoin-prijs
Comment=Shows the bitcoin price in EUR, color-coded by trend
Comment[nl]=Toont de bitcoinprijs in EUR, kleurcodering op trend
Type=Service
Icon=bitcoin
@@ -12,8 +10,8 @@ X-KDE-ServiceTypes=Plasma/Applet
X-KDE-PluginInfo-Author=Arnold Cordewiner
X-KDE-PluginInfo-Email=hermes@a14r.be
X-KDE-PluginInfo-Name=nl.a14r.bitcoinprice
X-KDE-PluginInfo-Version=1.0.0
X-KDE-PluginInfo-Website=http://192.168.110.5:40004/hermes/plasma-bitcoin-price
X-KDE-PluginInfo-Version=1.1.0
X-KDE-PluginInfo-Website=https://gitea.a14r.be/hermes/plasma-bitcoin-price
X-KDE-PluginInfo-Category=Utilities
X-KDE-PluginInfo-License=MIT
X-KDE-PluginInfo-EnabledByDefault=true