From 660868df06f9ce810066fca75de6b43e5b1b0f72 Mon Sep 17 00:00:00 2001 From: David Brenn Date: Tue, 12 Aug 2025 14:18:12 +0200 Subject: [PATCH] feat: add gradent selector --- qt/aqt/forms/preferences.ui | 3 +++ qt/aqt/preferences.py | 12 +++++++++--- qt/aqt/profiles.py | 6 ++++++ qt/aqt/stats.py | 3 +++ ts/routes/graphs/future-due.ts | 27 ++++++++++++++++++++++++++- 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/qt/aqt/forms/preferences.ui b/qt/aqt/forms/preferences.ui index a5d677328..aceb9454f 100644 --- a/qt/aqt/forms/preferences.ui +++ b/qt/aqt/forms/preferences.ui @@ -180,6 +180,9 @@ + + + diff --git a/qt/aqt/preferences.py b/qt/aqt/preferences.py index 2f12e7f4b..e3a92c3c6 100644 --- a/qt/aqt/preferences.py +++ b/qt/aqt/preferences.py @@ -373,16 +373,22 @@ class Preferences(QDialog): qconnect(self.form.resetWindowSizes.clicked, self.on_reset_window_sizes) self.form.color_blind.setChecked(self.mw.pm.color_blind()) - qconnect(self.form.color_blind.stateChanged, self.on_my_checkbox_changed) + qconnect(self.form.color_blind.stateChanged, self.on_color_blind_checkbox_changed) + self.form.gradient_selector.setVisible(not is_win) + self.form.gradient_selector.addItems(["Default","Viridis","Inferno","Magma","Plasma","Cividis",]) + self.form.gradient_selector.setCurrentIndex(self.mw.pm.get_gradient_index()) + qconnect( + self.form.gradient_selector.currentIndexChanged, + self.mw.pm.set_gradient_index, + ) self.setup_language() self.setup_video_driver() self.setupOptions() - def on_my_checkbox_changed(self, state: int) -> None: - print("color_blind state changed", state) + def on_color_blind_checkbox_changed(self, state: int) -> None: if state == 2: # checkbox is checked self.mw.pm.set_color_blind(True) diff --git a/qt/aqt/profiles.py b/qt/aqt/profiles.py index 7c3a8bb57..8c28d35b6 100644 --- a/qt/aqt/profiles.py +++ b/qt/aqt/profiles.py @@ -540,6 +540,12 @@ create table if not exists profiles def color_blind(self) -> bool: return self.meta.get("color_blind", False) + + def set_gradient_index(self, index: int) -> None: + self.meta["gradient_index"] = index + + def get_gradient_index(self) -> int: + return self.meta.get("gradient_index", 0) def reduce_motion(self) -> bool: return self.meta.get("reduce_motion", True) diff --git a/qt/aqt/stats.py b/qt/aqt/stats.py index e080c18d4..ec15e1251 100644 --- a/qt/aqt/stats.py +++ b/qt/aqt/stats.py @@ -142,6 +142,9 @@ class NewDeckStats(QDialog): def on_load_finished(success: bool) -> None: if success: is_color_blind = self.mw.pm.color_blind() + selected_gradient = self.mw.pm.get_gradient_index() + js_code = f"window.selectedGradient = {str(selected_gradient).lower()};" + self.form.web.eval(js_code) js_code = f"window.colorBlindMode = {str(is_color_blind).lower()};" self.form.web.eval(js_code) # Disconnect after running once to avoid multiple triggers diff --git a/ts/routes/graphs/future-due.ts b/ts/routes/graphs/future-due.ts index d38c176d9..a025e7ecf 100644 --- a/ts/routes/graphs/future-due.ts +++ b/ts/routes/graphs/future-due.ts @@ -10,7 +10,7 @@ import * as tr from "@generated/ftl"; import { localizedNumber } from "@tslib/i18n"; import { dayLabel } from "@tslib/time"; import type { Bin } from "d3"; -import { bin, extent, interpolateGreens, scaleLinear, scaleSequential, sum, interpolateViridis } from "d3"; +import { bin, extent, interpolateGreens, scaleLinear, scaleSequential, sum, interpolateViridis, interpolateInferno, interpolateMagma, interpolatePlasma,interpolateCividis } from "d3"; import type { SearchDispatch, TableDatum } from "./graph-helpers"; import { getNumericMapBinValue, GraphRange, numericMap } from "./graph-helpers"; @@ -123,7 +123,32 @@ export function buildHistogram( adjustedRange = scaleLinear().range([0.7, 0.3]); } + const selectedGradient = (window as any).selectedGradient; + console.log("Gradient selector:", selectedGradient); + switch (selectedGradient) { + case 0: + colourScale = scaleSequential((n) => interpolateGreens(adjustedRange(n)!)).domain([xMin!, xMax!]); + break; + case 1: + colourScale = scaleSequential((n) => interpolateViridis(adjustedRange(n)!)).domain([xMin!, xMax!]); + break; + case 2: + colourScale = scaleSequential((n) => interpolateInferno(adjustedRange(n)!)).domain([xMin!, xMax!]); + break; + case 3: + colourScale = scaleSequential((n) => interpolateMagma(adjustedRange(n)!)).domain([xMin!, xMax!]); + break; + case 4: + colourScale = scaleSequential((n) => interpolatePlasma(adjustedRange(n)!)).domain([xMin!, xMax!]); + break; + case 5: + colourScale = scaleSequential((n) => interpolateCividis(adjustedRange(n)!)).domain([xMin!, xMax!]); + break; + default: + colourScale = scaleSequential((n) => interpolateGreens(adjustedRange(n)!)).domain([xMin!, xMax!]); + break; + } const total = sum(bins as any, getNumericMapBinValue);