From d0e536306f4b84de96d078355ad7be3ed2bd86bf Mon Sep 17 00:00:00 2001 From: Joachim Kohlhammer Date: Sun, 7 Apr 2024 13:36:33 +0200 Subject: [PATCH] Added a configurable grayscale filter to RideMapWindow (#4417) * Added a CSS-grayscale filter to OSM based maps in RideMapWindow * Added a configuration-option for the intensity level (0..10) * Configuration is persisted per Tile-Server * Fixed the visibility of Google/OSM specific settings (previously the settings were only correct after selection of the other Maptype) --- src/Charts/RideMapWindow.cpp | 99 ++++++++++++++++++++++++++++++++++++ src/Charts/RideMapWindow.h | 4 ++ src/Core/Settings.h | 4 ++ 3 files changed, 107 insertions(+) diff --git a/src/Charts/RideMapWindow.cpp b/src/Charts/RideMapWindow.cpp index 4ea818657..251c68d10 100644 --- a/src/Charts/RideMapWindow.cpp +++ b/src/Charts/RideMapWindow.cpp @@ -100,6 +100,13 @@ RideMapWindow::RideMapWindow(Context *context, int mapType) : GcChartWindow(cont osmTSUrl = new QLineEdit(""); osmTSUrl->setFixedWidth(600); + osmGrayLabel = new QLabel(tr("Map Grayscale Filter")); + osmGraySlider = new QSlider(); + osmGraySlider->setOrientation(Qt::Horizontal); + osmGraySlider->setRange(0, 10); + osmGraySlider->setTickInterval(1); + osmGraySlider->setTickPosition(QSlider::TicksBelow); + gkey = new QLineEdit(""); gkeylabel = new QLabel(tr("Google API key")); @@ -110,6 +117,7 @@ RideMapWindow::RideMapWindow(Context *context, int mapType) : GcChartWindow(cont commonLayout->addRow(osmTSTitle); commonLayout->addRow(osmTSLabel, tileCombo); commonLayout->addRow(osmTSUrlLabel, osmTSUrl); + commonLayout->addRow(osmGrayLabel, osmGraySlider); commonLayout->addRow(gkeylabel, gkey); connect(mapCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(mapTypeSelected(int))); @@ -120,6 +128,7 @@ RideMapWindow::RideMapWindow(Context *context, int mapType) : GcChartWindow(cont connect(hideYellowLineCk, SIGNAL(stateChanged(int)), this, SLOT(hideYellowLineChanged(int))); connect(hideRouteLineOpacityCk, SIGNAL(stateChanged(int)), this, SLOT(hideRouteLineOpacityChanged(int))); connect(osmTSUrl, SIGNAL(editingFinished()), this, SLOT(osmCustomTSURLEditingFinished())); + connect(osmGraySlider, SIGNAL(valueChanged(int)), this, SLOT(osmGrayValueChanged(int))); connect(tileCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(tileTypeSelected(int))); setControls(settingsWidget); @@ -183,6 +192,8 @@ RideMapWindow::RideMapWindow(Context *context, int mapType) : GcChartWindow(cont layout->addWidget(smallPlot); layout->setStretch(1, 20); + setCustomTSWidgetVisible(mapCombo->currentIndex() == 0); + configChanged(CONFIG_APPEARANCE); } @@ -192,6 +203,7 @@ RideMapWindow::~RideMapWindow() if (view) delete view->page(); } + void RideMapWindow::mapTypeSelected(int x) { @@ -231,6 +243,8 @@ RideMapWindow::setCustomTSWidgetVisible(bool value) osmTSLabel->setVisible(value); osmTSUrlLabel->setVisible(value); osmTSUrl->setVisible(value); + osmGrayLabel->setVisible(value); + osmGraySlider->setVisible(value); tileCombo->setVisible(value); gkeylabel->setVisible(!value); gkey->setVisible(!value); @@ -278,13 +292,59 @@ RideMapWindow::setTileServerUrlForTileType(int x) osmTSUrl->setText(ts); } + +void +RideMapWindow::setGrayscaleForTileType +(int x) +{ + int gray = 0; + switch (x) { + case 0: + gray = appsettings->cvalue(context->athlete->cyclist, GC_OSM_DEFAULT_GRAY, "-1").toInt(); + // set/save the default if necessary + if (gray < 0) { + gray = 0; + appsettings->setCValue(context->athlete->cyclist, GC_OSM_DEFAULT_GRAY, gray); + } + break; + case 10: + gray = appsettings->cvalue(context->athlete->cyclist, GC_OSM_A_GRAY, "-1").toInt(); + // set/save the default if necessary + if (gray < 0) { + gray = 0; + appsettings->setCValue(context->athlete->cyclist, GC_OSM_A_GRAY, gray); + } + break; + case 20: + gray = appsettings->cvalue(context->athlete->cyclist, GC_OSM_B_GRAY, "-1").toInt(); + // set/save the default if necessary + if (gray < 0) { + gray = 0; + appsettings->setCValue(context->athlete->cyclist, GC_OSM_B_GRAY, gray); + } + break; + case 30: + gray = appsettings->cvalue(context->athlete->cyclist, GC_OSM_C_GRAY, "-1").toInt(); + // set/save the default if necessary + if (gray < 0) { + gray = 0; + appsettings->setCValue(context->athlete->cyclist, GC_OSM_C_GRAY, gray); + } + break; + } + osmGraySlider->setValue(gray); +} + + void RideMapWindow::tileTypeSelected(int x) { setTileServerUrlForTileType(tileCombo->itemData(x).toInt()); + setGrayscaleForTileType(tileCombo->itemData(x).toInt()); forceReplot(); } + void RideMapWindow::showMarkersChanged(int value) { @@ -368,6 +428,36 @@ RideMapWindow::osmCustomTSURLEditingFinished() forceReplot(); } + +void +RideMapWindow::osmGrayValueChanged +(int value) +{ + switch (osmTS()) { + case 0: + appsettings->setCValue(context->athlete->cyclist, GC_OSM_DEFAULT_GRAY, value); + break; + case 10: + appsettings->setCValue(context->athlete->cyclist, GC_OSM_A_GRAY, value); + break; + case 20: + appsettings->setCValue(context->athlete->cyclist, GC_OSM_B_GRAY, value); + break; + case 30: + appsettings->setCValue(context->athlete->cyclist, GC_OSM_C_GRAY, value); + break; + } + + // Only update the filter if the tile pane is already available + view->page()->runJavaScript(QString("{\n" + " const elems = document.getElementsByClassName('leaflet-tile-pane');\n" + " if (elems.length > 0 && elems[0] !== null && elems[0].style !== undefined) {\n" + " elems[0].style.filter = 'grayscale(%1)';\n" + " }\n" + "}\n").arg(value / 10.0)); +} + + void RideMapWindow::configChanged(qint32 value) { @@ -508,6 +598,15 @@ void RideMapWindow::createHtml() // Load leaflet (1.9.4) API currentPage += QString(" \n" "\n"); + + // Add grayscale filter if required + if (osmGraySlider->value() > 0) { + currentPage += QString("\n").arg(osmGraySlider->value() / 10.0); + } } else if (mapCombo->currentIndex() == GOOGLE) { // Load Google Map v3 API currentPage += QString(" \n").arg(gkey->text()); diff --git a/src/Charts/RideMapWindow.h b/src/Charts/RideMapWindow.h index b22b09a6d..56687a445 100644 --- a/src/Charts/RideMapWindow.h +++ b/src/Charts/RideMapWindow.h @@ -181,6 +181,7 @@ class RideMapWindow : public GcChartWindow void hideRouteLineOpacityChanged(int value); void showIntervalsChanged(int value); void osmCustomTSURLEditingFinished(); + void osmGrayValueChanged(int value); void forceReplot(); @@ -208,6 +209,8 @@ class RideMapWindow : public GcChartWindow QCheckBox* hideShadedZonesCk, * hideYellowLineCk, * hideRouteLineOpacityCk; QLabel *osmTSTitle, *osmTSLabel, *osmTSUrlLabel; QLineEdit *osmTSUrl; + QLabel *osmGrayLabel; + QSlider *osmGraySlider; QLineEdit *gkey; QLabel *gkeylabel; @@ -249,6 +252,7 @@ class RideMapWindow : public GcChartWindow void setCustomTSWidgetVisible(bool value); void setTileServerUrlForTileType(int x); + void setGrayscaleForTileType(int x); }; #endif diff --git a/src/Core/Settings.h b/src/Core/Settings.h index 3c9dea934..1fe1a7a92 100644 --- a/src/Core/Settings.h +++ b/src/Core/Settings.h @@ -309,9 +309,13 @@ // OSM Tileserver #define GC_OSM_TS_DEFAULT "osmts/default" +#define GC_OSM_DEFAULT_GRAY "osm/default_gray" #define GC_OSM_TS_A "osmts/a" +#define GC_OSM_A_GRAY "osm/a_gray" #define GC_OSM_TS_B "osmts/b" +#define GC_OSM_B_GRAY "osm/b_gray" #define GC_OSM_TS_C "osmts/c" +#define GC_OSM_C_GRAY "osm/c_gray" // BodyMeasures Download #define GC_BM_LAST_TYPE "bm/last_type"