Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b11fe06276 | ||
|
|
33dd983463 | ||
|
|
b040eb8c47 |
@@ -10,19 +10,21 @@ Three display styles, configurable in the settings dialog:
|
|||||||
| Style | Description |
|
| Style | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
| *Plain text* | Trend-colored text (green/red/grey) |
|
| *Plain text* | Trend-colored text (green/red/grey) |
|
||||||
| *Split-flap board* | Airport board: white characters on black flaps, cascading flip animation on price changes, trend LED |
|
| *Split-flap board* | Airport board: white digit flaps, white € sign and a trend arrow in the default font. On a price change all flaps first reset to 0 (swept over ~2 s), then take their new values — the whole cycle spreads over the configured cascade time |
|
||||||
| *Nixie tubes* | Retro amber glowing digits in glass tubes (with a soft flicker), trend LED |
|
| *Nixie tubes* | Retro amber glowing digits in glass tubes with configurable random flicker, white € sign and a trend arrow in the default font |
|
||||||
|
|
||||||
In the split-flap and nixie styles the digits keep their display color and the
|
In the split-flap and nixie styles a trend arrow sits right of the € sign:
|
||||||
trend (up/down/unchanged) is shown on a small LED next to the display.
|
green ▲ when the price went up, red ▼ when it went down. When the price is
|
||||||
Display style changes apply immediately, without restarting the shell.
|
unchanged the last arrow stays; on the very first reading (and on API errors)
|
||||||
|
no arrow is shown. Display style changes apply immediately, without
|
||||||
|
restarting the shell.
|
||||||
|
|
||||||
| Situation | Plain text color | Trend LED |
|
| Situation | Plain text color | Arrow in flip/nixie modes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Price up | green | green |
|
| Price up | green | green ▲ |
|
||||||
| Price down | red | red |
|
| Price down | red | red ▼ |
|
||||||
| Price unchanged / first reading | grey | grey |
|
| Price unchanged | grey | last arrow stays |
|
||||||
| API failure (network error, 4xx/5xx, rate limit 429) | `--` | grey |
|
| First reading / API failure | grey / `--` | no arrow |
|
||||||
|
|
||||||
Format: `68,969 €` (thousands separators follow the system locale, rounded to
|
Format: `68,969 €` (thousands separators follow the system locale, rounded to
|
||||||
whole euros) preceded by the bundled Bitcoin icon in the compact and full
|
whole euros) preceded by the bundled Bitcoin icon in the compact and full
|
||||||
@@ -35,7 +37,10 @@ representations.
|
|||||||
5 minutes. A hint text in the config dialog explains this.
|
5 minutes. A hint text in the config dialog explains this.
|
||||||
- **Split-flap cascade (seconds)** — default 3, range 1–15. Spreads the flip
|
- **Split-flap cascade (seconds)** — default 3, range 1–15. Spreads the flip
|
||||||
animation of a price change evenly over this many seconds (applies to the
|
animation of a price change evenly over this many seconds (applies to the
|
||||||
split-flap display style).
|
split-flap display style). Only shown when that style is selected.
|
||||||
|
- **Nixie flicker (0 = off)** — default 40, range 0–100. Random cathode-dropout
|
||||||
|
flicker of the nixie tubes; 0 disables it, higher values flicker more often
|
||||||
|
and deeper. Only shown when the nixie style is selected.
|
||||||
|
|
||||||
Configurable via right-click on the widget → *Configure Bitcoin Price…* → *General*.
|
Configurable via right-click on the widget → *Configure Bitcoin Price…* → *General*.
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -20,6 +20,12 @@
|
|||||||
<min>1</min>
|
<min>1</min>
|
||||||
<max>15</max>
|
<max>15</max>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry name="nixieFlicker" type="Int">
|
||||||
|
<label>Nixie tube flicker intensity (0 = off, 100 = frequent and deep)</label>
|
||||||
|
<default>40</default>
|
||||||
|
<min>0</min>
|
||||||
|
<max>100</max>
|
||||||
|
</entry>
|
||||||
<entry name="refreshMinutes" type="Int">
|
<entry name="refreshMinutes" type="Int">
|
||||||
<label>Refresh interval in minutes (minimum 5 because of the CoinGecko rate limit)</label>
|
<label>Refresh interval in minutes (minimum 5 because of the CoinGecko rate limit)</label>
|
||||||
<default>5</default>
|
<default>5</default>
|
||||||
|
|||||||
+103
-37
@@ -1,7 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Split-flap display mode — airport departure board style.
|
* Split-flap display mode — airport departure board style.
|
||||||
* White characters on black cells with a flap split line;
|
* Only digits are shown as flaps; the euro sign is rendered as plain
|
||||||
* changed characters flip with a cascading animation.
|
* text (default font, white) next to the board, followed by a trend
|
||||||
|
* arrow (green up / red down; unchanged keeps the last arrow).
|
||||||
|
* On a price change the board first resets every flap to "0" (swept
|
||||||
|
* over ~2 s), then takes the new values (swept over the remainder of
|
||||||
|
* the cascade setting).
|
||||||
* Pure QtQuick so it can be tested outside the plasmoid shell.
|
* Pure QtQuick so it can be tested outside the plasmoid shell.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -12,12 +16,36 @@ Row {
|
|||||||
|
|
||||||
// wired by the parent loader
|
// wired by the parent loader
|
||||||
property string display: "--"
|
property string display: "--"
|
||||||
property color trendColor: "#9e9e9e"
|
// 1 = up, -1 = down, 0 = unchanged -> keep showing the last arrow
|
||||||
// seconds over which the cascade to a new price is spread
|
property int trendDir: 0
|
||||||
|
property int lastDir: 0
|
||||||
|
onTrendDirChanged: {
|
||||||
|
if (trendDir !== 0) {
|
||||||
|
lastDir = trendDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// total seconds over which the reset-to-zero + new value cycle spreads
|
||||||
property int flapSeconds: 3
|
property int flapSeconds: 3
|
||||||
|
|
||||||
spacing: height * 0.06
|
spacing: height * 0.06
|
||||||
|
|
||||||
|
function digitsOf(s) {
|
||||||
|
var out = "";
|
||||||
|
for (var i = 0; i < s.length; i++) {
|
||||||
|
var ch = s.charAt(i);
|
||||||
|
if ((ch >= "0" && ch <= "9") || ch === "-") {
|
||||||
|
out += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UI-only derived values (euro/arrow visibility); logic must not rely
|
||||||
|
// on these — QML gives no ordering guarantee between a change handler
|
||||||
|
// and the re-evaluation of dependent bindings.
|
||||||
|
readonly property string digitsOnly: digitsOf(display)
|
||||||
|
readonly property string boardText: digitsOnly.length > 0 ? digitsOnly : "--"
|
||||||
|
|
||||||
property var chars: []
|
property var chars: []
|
||||||
property bool ready: false
|
property bool ready: false
|
||||||
readonly property real cellFont: height * 0.72
|
readonly property real cellFont: height * 0.72
|
||||||
@@ -26,7 +54,7 @@ Row {
|
|||||||
readonly property int flapDuration: 260
|
readonly property int flapDuration: 260
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
chars = display.split("");
|
chars = boardText.split("");
|
||||||
ready = true;
|
ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,23 +62,26 @@ Row {
|
|||||||
if (!ready) {
|
if (!ready) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var nc = display.split("");
|
// compute from display directly: derived bindings may still be
|
||||||
|
// stale at this point (QML makes no ordering guarantee)
|
||||||
|
var digits = digitsOf(display);
|
||||||
|
var nc = (digits.length > 0 ? digits : "--").split("");
|
||||||
var n = Math.max(chars.length, nc.length);
|
var n = Math.max(chars.length, nc.length);
|
||||||
// spread the changed cells evenly across flapSeconds
|
|
||||||
var changed = [];
|
// Phase 1: every flap resets to "0", swept over ~2 s.
|
||||||
|
// Phase 2: every flap takes its new value, swept over the
|
||||||
|
// remainder of the total cascade time.
|
||||||
|
var total = Math.max(1, flapSeconds) * 1000;
|
||||||
|
var resetSpan = Math.min(2000, Math.floor(total * 2 / 3));
|
||||||
|
var valueStart = resetSpan;
|
||||||
|
var resetStep = n > 1 ? Math.floor(Math.max(0, resetSpan - flapDuration) / (n - 1)) : 0;
|
||||||
|
var valueStep = n > 1 ? Math.floor(Math.max(0, total - valueStart - flapDuration) / (n - 1)) : 0;
|
||||||
|
|
||||||
for (var i = 0; i < n; i++) {
|
for (var i = 0; i < n; i++) {
|
||||||
var from = i < chars.length ? chars[i] : "";
|
var cell = rep.itemAt(i);
|
||||||
var to = i < nc.length ? nc[i] : "";
|
var to = i < nc.length ? nc[i] : "";
|
||||||
if (from !== to) {
|
|
||||||
changed.push([i, to]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var span = Math.max(1, flapSeconds) * 1000 - flapDuration;
|
|
||||||
var step = changed.length > 1 ? Math.max(0, Math.floor(span / (changed.length - 1))) : 0;
|
|
||||||
for (var j = 0; j < changed.length; j++) {
|
|
||||||
var cell = rep.itemAt(changed[j][0]);
|
|
||||||
if (cell) {
|
if (cell) {
|
||||||
cell.flipTo(changed[j][1], j * step);
|
cell.schedule(to, i * resetStep, valueStart + i * valueStep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chars = nc;
|
chars = nc;
|
||||||
@@ -70,28 +101,43 @@ Row {
|
|||||||
border.color: "#26262b"
|
border.color: "#26262b"
|
||||||
border.width: 1
|
border.width: 1
|
||||||
|
|
||||||
// plain property (not a binding) so the flip animation
|
// plain properties (not bindings) so the animations control
|
||||||
// controls when the character actually changes
|
// when the character actually changes
|
||||||
property string ch: ""
|
property string ch: ""
|
||||||
property string pendingCh: ""
|
property string targetCh: ""
|
||||||
|
property string animCh: ""
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
ch = root.chars[index] !== undefined ? root.chars[index] : "";
|
ch = root.chars[index] !== undefined ? root.chars[index] : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function flipTo(newCh, delay) {
|
// schedule the two-phase cycle: reset to "0", then target
|
||||||
|
function schedule(t, resetDelay, valueDelay) {
|
||||||
|
targetCh = t;
|
||||||
|
resetTimer.interval = Math.max(0, resetDelay);
|
||||||
|
resetTimer.restart();
|
||||||
|
valueTimer.interval = Math.max(0, valueDelay);
|
||||||
|
valueTimer.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
function startFlip(newCh) {
|
||||||
if (newCh === ch) {
|
if (newCh === ch) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pendingCh = newCh;
|
animCh = newCh;
|
||||||
delayTimer.interval = Math.max(0, delay);
|
flipAnim.restart();
|
||||||
delayTimer.restart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: delayTimer
|
id: resetTimer
|
||||||
interval: 0
|
interval: 0
|
||||||
onTriggered: flipAnim.start()
|
onTriggered: cell.startFlip("0")
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: valueTimer
|
||||||
|
interval: 0
|
||||||
|
onTriggered: cell.startFlip(cell.targetCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
transform: Scale {
|
transform: Scale {
|
||||||
@@ -110,7 +156,7 @@ Row {
|
|||||||
easing.type: Easing.InQuad
|
easing.type: Easing.InQuad
|
||||||
}
|
}
|
||||||
ScriptAction {
|
ScriptAction {
|
||||||
script: cell.ch = cell.pendingCh
|
script: cell.ch = cell.animCh
|
||||||
}
|
}
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
target: scaleTransform
|
target: scaleTransform
|
||||||
@@ -141,15 +187,35 @@ Row {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// trend LED (green/red/grey) — boards are monochrome, so the
|
// breathing room between the board and the currency sign
|
||||||
// trend shows here instead of in the letter color
|
Item {
|
||||||
Rectangle {
|
width: root.height * 0.22
|
||||||
width: root.height * 0.14
|
height: 1
|
||||||
height: width
|
}
|
||||||
radius: width / 2
|
|
||||||
|
// euro sign in the plain-text font, white
|
||||||
|
Text {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
color: root.trendColor
|
text: "\u20AC"
|
||||||
border.color: "#26262b"
|
visible: root.digitsOnly.length > 0
|
||||||
border.width: 1
|
color: "#ffffff"
|
||||||
|
font.family: Qt.application.font.family
|
||||||
|
font.pixelSize: root.height * 0.85
|
||||||
|
}
|
||||||
|
|
||||||
|
// same breathing room between the euro sign and the arrow
|
||||||
|
Item {
|
||||||
|
width: root.height * 0.22
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// trend arrow: green up / red down; unchanged keeps the last arrow
|
||||||
|
Text {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: root.lastDir > 0 ? "\u25B2" : "\u25BC"
|
||||||
|
visible: root.digitsOnly.length > 0 && root.lastDir !== 0
|
||||||
|
color: root.lastDir > 0 ? "#2ecc71" : "#e74c3c"
|
||||||
|
font.family: Qt.application.font.family
|
||||||
|
font.pixelSize: root.height * 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Nixie tube display mode — retro amber glowing digits in glass tubes.
|
* Nixie tube display mode — retro amber glowing digits in glass tubes.
|
||||||
* Glow is faked with layered text copies, so no QtGraphicalEffects
|
* Glow is faked with layered text copies, so no QtGraphicalEffects
|
||||||
* dependency. Pure QtQuick: testable outside the plasmoid shell.
|
* dependency. Tubes flicker randomly (nixie cathode style); the
|
||||||
|
* flicker intensity is configurable (0 = off, 100 = nervous).
|
||||||
|
* The euro sign is plain text (default font, white), followed by a
|
||||||
|
* trend arrow (green up / red down; unchanged keeps the last arrow).
|
||||||
|
* Pure QtQuick: testable outside the plasmoid shell.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
@@ -11,13 +15,34 @@ Row {
|
|||||||
|
|
||||||
// wired by the parent loader
|
// wired by the parent loader
|
||||||
property string display: "--"
|
property string display: "--"
|
||||||
property color trendColor: "#9e9e9e"
|
// 1 = up, -1 = down, 0 = unchanged -> keep showing the last arrow
|
||||||
|
property int trendDir: 0
|
||||||
|
property int lastDir: 0
|
||||||
|
onTrendDirChanged: {
|
||||||
|
if (trendDir !== 0) {
|
||||||
|
lastDir = trendDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 0 = no flicker, 100 = frequent and deep flicker
|
||||||
|
property int flickerIntensity: 40
|
||||||
|
|
||||||
spacing: height * 0.05
|
spacing: height * 0.05
|
||||||
|
|
||||||
readonly property string digits: display.replace(/[^0-9]/g, "")
|
function digitsOf(s) {
|
||||||
|
var out = "";
|
||||||
|
for (var i = 0; i < s.length; i++) {
|
||||||
|
var ch = s.charAt(i);
|
||||||
|
if (ch >= "0" && ch <= "9") {
|
||||||
|
out += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property string digits: digitsOf(display)
|
||||||
readonly property real tubeWidth: height * 0.52
|
readonly property real tubeWidth: height * 0.52
|
||||||
readonly property real glowFont: height * 0.80
|
readonly property real glowFont: height * 0.80
|
||||||
|
readonly property bool flickerOn: flickerIntensity > 0 && digits.length > 0
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: root.digits.length
|
model: root.digits.length
|
||||||
@@ -48,6 +73,11 @@ Row {
|
|||||||
opacity: 0.06
|
opacity: 0.06
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// digit + glow layers, flickered as one group
|
||||||
|
Item {
|
||||||
|
id: glowGroup
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: glowText
|
id: glowText
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -73,46 +103,81 @@ Row {
|
|||||||
font: parent.font
|
font: parent.font
|
||||||
scale: 1.10
|
scale: 1.10
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// occasional gentle nixie flicker
|
// nixie flicker: random dropout of the cathode glow.
|
||||||
|
// repeat: true keeps the cycle alive; each trigger reschedules
|
||||||
|
// the next interval (intensity 40 -> ~4 s between flicks,
|
||||||
|
// 100 -> ~1.5 s).
|
||||||
Timer {
|
Timer {
|
||||||
interval: 2200 + Math.random() * 3200
|
id: flickTimer
|
||||||
repeat: false
|
repeat: true
|
||||||
running: root.visible && root.digits.length > 0
|
running: root.flickerOn
|
||||||
|
interval: 1500
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
flick.stop();
|
flick.restart();
|
||||||
flick.start();
|
scheduleNext();
|
||||||
interval = 2200 + Math.random() * 3200;
|
|
||||||
restart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function scheduleNext() {
|
||||||
|
var base = 6000 - root.flickerIntensity * 45;
|
||||||
|
interval = Math.max(700, base * (0.6 + Math.random() * 0.8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: scheduleNext()
|
||||||
|
}
|
||||||
|
|
||||||
SequentialAnimation {
|
SequentialAnimation {
|
||||||
id: flick
|
id: flick
|
||||||
NumberAnimation {
|
ScriptAction {
|
||||||
target: glowText
|
script: {
|
||||||
property: "opacity"
|
var range = root.flickerIntensity / 100 * 0.75;
|
||||||
to: 0.82
|
glowGroup.opacity = 1 - (0.15 + Math.random() * range);
|
||||||
duration: 70
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
PauseAnimation { duration: 40 + Math.random() * 140 }
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
target: glowText
|
target: glowGroup
|
||||||
property: "opacity"
|
property: "opacity"
|
||||||
to: 1.0
|
to: 1.0
|
||||||
duration: 140
|
duration: 90 + Math.random() * 160
|
||||||
}
|
easing.type: Easing.OutQuad
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// currency indicator, dim amber like an indicator lamp
|
// breathing room between the tubes and the currency sign
|
||||||
|
Item {
|
||||||
|
width: root.height * 0.22
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// euro sign in the plain-text font, white
|
||||||
Text {
|
Text {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: "\u20AC"
|
text: "\u20AC"
|
||||||
color: "#8a5a20"
|
|
||||||
font.family: "DejaVu Serif"
|
|
||||||
font.pixelSize: root.glowFont * 0.6
|
|
||||||
visible: root.digits.length > 0
|
visible: root.digits.length > 0
|
||||||
|
color: "#ffffff"
|
||||||
|
font.family: Qt.application.font.family
|
||||||
|
font.pixelSize: root.height * 0.85
|
||||||
|
}
|
||||||
|
|
||||||
|
// same breathing room between the euro sign and the arrow
|
||||||
|
Item {
|
||||||
|
width: root.height * 0.22
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// trend arrow: green up / red down; unchanged keeps the last arrow
|
||||||
|
Text {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: root.lastDir > 0 ? "\u25B2" : "\u25BC"
|
||||||
|
visible: root.digits.length > 0 && root.lastDir !== 0
|
||||||
|
color: root.lastDir > 0 ? "#2ecc71" : "#e74c3c"
|
||||||
|
font.family: Qt.application.font.family
|
||||||
|
font.pixelSize: root.height * 0.9
|
||||||
}
|
}
|
||||||
|
|
||||||
// error / empty state
|
// error / empty state
|
||||||
@@ -124,15 +189,4 @@ Row {
|
|||||||
font.pixelSize: root.glowFont * 0.8
|
font.pixelSize: root.glowFont * 0.8
|
||||||
visible: root.digits.length === 0
|
visible: root.digits.length === 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// trend LED (green/red/grey)
|
|
||||||
Rectangle {
|
|
||||||
width: root.height * 0.11
|
|
||||||
height: width
|
|
||||||
radius: width / 2
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
color: root.trendColor
|
|
||||||
border.color: "#4a2e12"
|
|
||||||
border.width: 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* Config page for nl.a14r.bitcoinprice.
|
* Config page for nl.a14r.bitcoinprice.
|
||||||
* Follows the canonical Plasma 5 config dialog pattern:
|
* Follows the canonical Plasma 5 config dialog pattern:
|
||||||
* Kirigami.FormLayout + cfg_ prefixed property aliases.
|
* Kirigami.FormLayout + cfg_ prefixed property aliases.
|
||||||
|
* Mode-specific settings are only visible for the matching style.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
@@ -15,6 +16,7 @@ Kirigami.FormLayout {
|
|||||||
property alias cfg_displayMode: modeCombo.currentIndex
|
property alias cfg_displayMode: modeCombo.currentIndex
|
||||||
property alias cfg_refreshMinutes: intervalSpin.value
|
property alias cfg_refreshMinutes: intervalSpin.value
|
||||||
property alias cfg_flapSeconds: flapSpin.value
|
property alias cfg_flapSeconds: flapSpin.value
|
||||||
|
property alias cfg_nixieFlicker: flickSpin.value
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
Kirigami.FormData.isSection: true
|
Kirigami.FormData.isSection: true
|
||||||
@@ -28,6 +30,7 @@ Kirigami.FormLayout {
|
|||||||
|
|
||||||
QQC2.SpinBox {
|
QQC2.SpinBox {
|
||||||
id: flapSpin
|
id: flapSpin
|
||||||
|
visible: modeCombo.currentIndex === 1
|
||||||
Kirigami.FormData.label: i18n("Split-flap cascade (seconds):")
|
Kirigami.FormData.label: i18n("Split-flap cascade (seconds):")
|
||||||
from: 1
|
from: 1
|
||||||
to: 15
|
to: 15
|
||||||
@@ -35,6 +38,16 @@ Kirigami.FormLayout {
|
|||||||
editable: true
|
editable: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QQC2.SpinBox {
|
||||||
|
id: flickSpin
|
||||||
|
visible: modeCombo.currentIndex === 2
|
||||||
|
Kirigami.FormData.label: i18n("Nixie flicker (0 = off):")
|
||||||
|
from: 0
|
||||||
|
to: 100
|
||||||
|
stepSize: 10
|
||||||
|
editable: true
|
||||||
|
}
|
||||||
|
|
||||||
QQC2.SpinBox {
|
QQC2.SpinBox {
|
||||||
id: intervalSpin
|
id: intervalSpin
|
||||||
Kirigami.FormData.label: i18n("Refresh interval (minutes):")
|
Kirigami.FormData.label: i18n("Refresh interval (minutes):")
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ Item {
|
|||||||
// Seconds over which the split-flap display cascades to a new price
|
// Seconds over which the split-flap display cascades to a new price
|
||||||
readonly property int flapSeconds: Math.max(1, plasmoid.configuration.flapSeconds)
|
readonly property int flapSeconds: Math.max(1, plasmoid.configuration.flapSeconds)
|
||||||
|
|
||||||
|
// Nixie tube flicker intensity (0 = off, 100 = frequent and deep)
|
||||||
|
readonly property int nixieFlicker: Math.max(0, Math.min(100, plasmoid.configuration.nixieFlicker))
|
||||||
|
|
||||||
// 0 = plain text, 1 = split-flap board, 2 = nixie tubes
|
// 0 = plain text, 1 = split-flap board, 2 = nixie tubes
|
||||||
property int displayMode: 0
|
property int displayMode: 0
|
||||||
readonly property string modeSource: displayMode === 1 ? "DisplayFlip.qml"
|
readonly property string modeSource: displayMode === 1 ? "DisplayFlip.qml"
|
||||||
@@ -139,10 +142,18 @@ Item {
|
|||||||
source: root.modeSource
|
source: root.modeSource
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
item.display = Qt.binding(function () { return root.displayText; });
|
item.display = Qt.binding(function () { return root.displayText; });
|
||||||
|
if (item.trendColor !== undefined) {
|
||||||
item.trendColor = Qt.binding(function () { return root.priceColor; });
|
item.trendColor = Qt.binding(function () { return root.priceColor; });
|
||||||
|
}
|
||||||
|
if (item.trendDir !== undefined) {
|
||||||
|
item.trendDir = Qt.binding(function () { return root.trend; });
|
||||||
|
}
|
||||||
if (item.flapSeconds !== undefined) {
|
if (item.flapSeconds !== undefined) {
|
||||||
item.flapSeconds = Qt.binding(function () { return root.flapSeconds; });
|
item.flapSeconds = Qt.binding(function () { return root.flapSeconds; });
|
||||||
}
|
}
|
||||||
|
if (item.flickerIntensity !== undefined) {
|
||||||
|
item.flickerIntensity = Qt.binding(function () { return root.nixieFlicker; });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,10 +188,18 @@ Item {
|
|||||||
source: root.modeSource
|
source: root.modeSource
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
item.display = Qt.binding(function () { return root.displayText; });
|
item.display = Qt.binding(function () { return root.displayText; });
|
||||||
|
if (item.trendColor !== undefined) {
|
||||||
item.trendColor = Qt.binding(function () { return root.priceColor; });
|
item.trendColor = Qt.binding(function () { return root.priceColor; });
|
||||||
|
}
|
||||||
|
if (item.trendDir !== undefined) {
|
||||||
|
item.trendDir = Qt.binding(function () { return root.trend; });
|
||||||
|
}
|
||||||
if (item.flapSeconds !== undefined) {
|
if (item.flapSeconds !== undefined) {
|
||||||
item.flapSeconds = Qt.binding(function () { return root.flapSeconds; });
|
item.flapSeconds = Qt.binding(function () { return root.flapSeconds; });
|
||||||
}
|
}
|
||||||
|
if (item.flickerIntensity !== undefined) {
|
||||||
|
item.flickerIntensity = Qt.binding(function () { return root.nixieFlicker; });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ X-KDE-ServiceTypes=Plasma/Applet
|
|||||||
X-KDE-PluginInfo-Author=Arnold Cordewiner
|
X-KDE-PluginInfo-Author=Arnold Cordewiner
|
||||||
X-KDE-PluginInfo-Email=hermes@a14r.be
|
X-KDE-PluginInfo-Email=hermes@a14r.be
|
||||||
X-KDE-PluginInfo-Name=nl.a14r.bitcoinprice
|
X-KDE-PluginInfo-Name=nl.a14r.bitcoinprice
|
||||||
X-KDE-PluginInfo-Version=1.3.0
|
X-KDE-PluginInfo-Version=1.5.1
|
||||||
X-KDE-PluginInfo-Website=https://gitea.a14r.be/hermes/plasma-bitcoin-price
|
X-KDE-PluginInfo-Website=https://gitea.a14r.be/hermes/plasma-bitcoin-price
|
||||||
X-KDE-PluginInfo-Category=Utilities
|
X-KDE-PluginInfo-Category=Utilities
|
||||||
X-KDE-PluginInfo-License=MIT
|
X-KDE-PluginInfo-License=MIT
|
||||||
|
|||||||
Reference in New Issue
Block a user