plugins: add colorblindness correction effect

Colorblindness correction shader with adjustable intensity. Can correct for:

- Protanopia (Greatly reduced reds)
- Deuteranopia (Greatly reduced greens)
- Tritanopia (Greatly reduced blues)

FEATURE: 474470
FIXED-IN: 6.0
master
Fushan Wen 12 months ago
parent 8d3b4a21c8
commit b80741d531
No known key found for this signature in database
GPG Key ID: 2E48D1487C91DCAA

@ -51,6 +51,7 @@ add_subdirectory(backgroundcontrast)
add_subdirectory(blendchanges)
add_subdirectory(blur)
add_subdirectory(buttonrebinds)
add_subdirectory(colorblindnesscorrection)
add_subdirectory(colord-integration)
add_subdirectory(colorpicker)
add_subdirectory(desktopchangeosd)

@ -0,0 +1,36 @@
# SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com>
# SPDX-License-Identifier: BSD-3-Clause
kwin_add_builtin_effect(colorblindnesscorrection
colorblindnesscorrection.cpp
colorblindnesscorrection.qrc
main.cpp
)
kconfig_add_kcfg_files(colorblindnesscorrection colorblindnesscorrection_settings.kcfgc GENERATE_MOC)
target_link_libraries(colorblindnesscorrection PRIVATE
kwineffects
kwinglutils
KF6::ConfigCore
KF6::ConfigGui
)
# Config
if (NOT KWIN_BUILD_KCMS)
return()
endif()
kcmutils_add_qml_kcm(kwin_colorblindnesscorrection_config SOURCES colorblindnesscorrection_config.cpp INSTALL_NAMESPACE "kwin/effects/configs" DISABLE_DESKTOP_FILE_GENERATION)
kcmutils_generate_module_data(kwin_colorblindnesscorrection_config
MODULE_DATA_HEADER colorblindnesscorrection_settingsdata.h
MODULE_DATA_CLASS_NAME ColorBlindnessCorrectionSettingsData
SETTINGS_HEADERS colorblindnesscorrection_settings.h
SETTINGS_CLASSES ColorBlindnessCorrectionSettings
)
kconfig_add_kcfg_files(kwin_colorblindnesscorrection_config colorblindnesscorrection_settings.kcfgc GENERATE_MOC)
target_link_libraries(kwin_colorblindnesscorrection_config
KF6::ConfigCore
KF6::KCMUtils
KF6::KCMUtilsQuick
KWinEffectsInterface
)

@ -0,0 +1,136 @@
/*
SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "colorblindnesscorrection.h"
#include <KSharedConfig>
#include "libkwineffects/glshader.h"
#include "libkwineffects/kwineffects.h"
#include "colorblindnesscorrection_settings.h"
Q_LOGGING_CATEGORY(KWIN_COLORBLINDNESS_CORRECTION, "kwin_effect_colorblindnesscorrection", QtWarningMsg)
static void ensureResources()
{
// Must initialize resources manually because the effect is a static lib.
Q_INIT_RESOURCE(colorblindnesscorrection);
}
namespace KWin
{
ColorBlindnessCorrectionEffect::ColorBlindnessCorrectionEffect()
: OffscreenEffect()
, m_mode(static_cast<Mode>(ColorBlindnessCorrectionSettings().mode()))
{
loadData();
}
ColorBlindnessCorrectionEffect::~ColorBlindnessCorrectionEffect()
{
}
bool ColorBlindnessCorrectionEffect::supported()
{
return effects->isOpenGLCompositing();
}
void ColorBlindnessCorrectionEffect::loadData()
{
ensureResources();
QString fragPath;
switch (m_mode) {
case Deuteranopia:
fragPath = QStringLiteral(":/effects/colorblindnesscorrection/shaders/Deutranopia.frag");
break;
case Tritanopia:
fragPath = QStringLiteral(":/effects/colorblindnesscorrection/shaders/Tritanopia.frag");
break;
case Protanopia: // Most common, use it as fallback
default:
fragPath = QStringLiteral(":/effects/colorblindnesscorrection/shaders/Protanopia.frag");
break;
}
m_shader = ShaderManager::instance()->generateShaderFromFile(ShaderTrait::MapTexture, QString(), fragPath);
if (!m_shader->isValid()) {
qCCritical(KWIN_COLORBLINDNESS_CORRECTION) << "Failed to load the shader!";
return;
}
for (const auto windows = effects->stackingOrder(); EffectWindow * w : windows) {
correctColor(w);
}
effects->addRepaintFull();
connect(effects, &EffectsHandler::windowDeleted, this, &ColorBlindnessCorrectionEffect::slotWindowDeleted);
connect(effects, &EffectsHandler::windowAdded, this, &ColorBlindnessCorrectionEffect::correctColor);
}
void ColorBlindnessCorrectionEffect::correctColor(KWin::EffectWindow *w)
{
if (m_windows.contains(w)) {
return;
}
redirect(w);
setShader(w, m_shader.get());
m_windows.insert(w);
}
void ColorBlindnessCorrectionEffect::slotWindowDeleted(EffectWindow *w)
{
if (auto it = m_windows.find(w); it != m_windows.end()) {
m_windows.erase(it);
}
}
bool ColorBlindnessCorrectionEffect::isActive() const
{
return !m_windows.empty();
}
bool ColorBlindnessCorrectionEffect::provides(Feature f)
{
return f == Contrast;
}
void ColorBlindnessCorrectionEffect::reconfigure(ReconfigureFlags flags)
{
if (flags != Effect::ReconfigureAll) {
return;
}
auto newMode = static_cast<Mode>(ColorBlindnessCorrectionSettings().mode());
if (m_mode == newMode) {
return;
}
m_mode = newMode;
disconnect(effects, &EffectsHandler::windowDeleted, this, &ColorBlindnessCorrectionEffect::slotWindowDeleted);
disconnect(effects, &EffectsHandler::windowAdded, this, &ColorBlindnessCorrectionEffect::correctColor);
for (EffectWindow *w : m_windows) {
unredirect(w);
}
m_windows.clear();
loadData();
}
int ColorBlindnessCorrectionEffect::requestedEffectChainPosition() const
{
return 98;
}
} // namespace
#include "moc_colorblindnesscorrection.cpp"

@ -0,0 +1,56 @@
/*
SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <unordered_set>
#include "libkwineffects/glshadermanager.h"
#include "libkwineffects/kwinoffscreeneffect.h"
namespace KWin
{
/**
* The color filter supports protanopia, deuteranopia and tritanopia.
*/
class ColorBlindnessCorrectionEffect : public OffscreenEffect
{
Q_OBJECT
public:
enum Mode {
Protanopia = 0, //<Greatly reduced reds
Deuteranopia, //<Greatly reduced greens
Tritanopia, //<Greatly reduced blues
};
explicit ColorBlindnessCorrectionEffect();
~ColorBlindnessCorrectionEffect() override;
bool isActive() const override;
bool provides(Feature) override;
void reconfigure(ReconfigureFlags flags) override;
int requestedEffectChainPosition() const override;
static bool supported();
public Q_SLOTS:
void slotWindowDeleted(KWin::EffectWindow *w);
private Q_SLOTS:
void correctColor(KWin::EffectWindow *w);
private:
void loadData();
Mode m_mode = Protanopia;
std::unordered_set<KWin::EffectWindow *> m_windows;
std::unique_ptr<GLShader> m_shader;
};
} // namespace

@ -0,0 +1,10 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/effects/colorblindnesscorrection/">
<file>shaders/Deutranopia.frag</file>
<file>shaders/Deutranopia_core.frag</file>
<file>shaders/Protanopia.frag</file>
<file>shaders/Protanopia_core.frag</file>
<file>shaders/Tritanopia.frag</file>
<file>shaders/Tritanopia_core.frag</file>
</qresource>
</RCC>

@ -0,0 +1,59 @@
/*
SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "colorblindnesscorrection_config.h"
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusPendingCall>
#include <KPluginFactory>
#include "colorblindnesscorrection_settings.h"
#include "colorblindnesscorrection_settingsdata.h"
#include "kwineffects_interface.h"
K_PLUGIN_CLASS_WITH_JSON(KWin::ColorBlindnessCorrectionEffectConfig, "kwin_colorblindnesscorrection_config.json")
namespace KWin
{
ColorBlindnessCorrectionEffectConfig::ColorBlindnessCorrectionEffectConfig(QObject *parent, const KPluginMetaData &metaData)
: KQuickManagedConfigModule(parent, metaData)
, m_data(new ColorBlindnessCorrectionSettingsData(this))
{
qmlRegisterUncreatableType<ColorBlindnessCorrectionSettings>("org.kde.plasma.kwin.colorblindnesscorrectioneffect.kcm",
1,
0,
"ColorBlindnessCorrectionSettings",
QStringLiteral("Only for enums"));
setButtons(Apply | Default);
}
ColorBlindnessCorrectionEffectConfig::~ColorBlindnessCorrectionEffectConfig()
{
}
ColorBlindnessCorrectionSettings *ColorBlindnessCorrectionEffectConfig::settings() const
{
return m_data->settings();
}
void ColorBlindnessCorrectionEffectConfig::save()
{
KQuickManagedConfigModule::save();
OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"),
QStringLiteral("/Effects"),
QDBusConnection::sessionBus());
interface.reconfigureEffect(QStringLiteral("colorblindnesscorrection"));
}
} // namespace
#include "colorblindnesscorrection_config.moc"
#include "moc_colorblindnesscorrection_config.cpp"

@ -0,0 +1,35 @@
/*
SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <KQuickManagedConfigModule>
class ColorBlindnessCorrectionSettings;
class ColorBlindnessCorrectionSettingsData;
namespace KWin
{
class ColorBlindnessCorrectionEffectConfig : public KQuickManagedConfigModule
{
Q_OBJECT
Q_PROPERTY(ColorBlindnessCorrectionSettings *settings READ settings CONSTANT)
public:
explicit ColorBlindnessCorrectionEffectConfig(QObject *parent, const KPluginMetaData &metaData);
~ColorBlindnessCorrectionEffectConfig() override;
ColorBlindnessCorrectionSettings *settings() const;
public Q_SLOTS:
void save() override;
private:
ColorBlindnessCorrectionSettingsData *m_data;
}; // namespace
}

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
# SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com>
# SPDX-License-Identifier: GPL-2.0-or-later
-->
<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="kwinrc" />
<group name="Effect-colorblindnesscorrection">
<entry name="Mode" type="UInt">
<default>0</default>
</entry>
</group>
</kcfg>

@ -0,0 +1,9 @@
# SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com>
# SPDX-License-Identifier: GPL-2.0-or-later
File=colorblindnesscorrection_settings.kcfg
ClassName=ColorBlindnessCorrectionSettings
Mutators=true
DefaultValueGetters=true
GenerateProperties=true
ParentInConstructor=true

@ -0,0 +1,6 @@
{
"KPlugin": {
"License": "GPL-2.0+",
"Name": "Colorblindness Correction"
}
}

@ -0,0 +1,2 @@
# SPDX-FileCopyrightText: None
# SPDX-License-Identifier: CC0-1.0

@ -0,0 +1,16 @@
/*
SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "colorblindnesscorrection.h"
namespace KWin
{
KWIN_EFFECT_FACTORY_SUPPORTED(ColorBlindnessCorrectionEffect, "metadata.json.stripped", return ColorBlindnessCorrectionEffect::supported();)
} // namespace KWin
#include "main.moc"

@ -0,0 +1,10 @@
{
"KPlugin": {
"Category": "Accessibility",
"Description": "Enhances color perception for color blindness",
"EnabledByDefault": false,
"License": "GPL-2.0+",
"Name": "Colorblindness Correction"
},
"X-KDE-ConfigModule": "kwin_colorblindnesscorrection_config"
}

@ -0,0 +1,2 @@
# SPDX-FileCopyrightText: None
# SPDX-License-Identifier: CC0-1.0

@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: None
// SPDX-License-Identifier: CC0-1.0
uniform sampler2D sampler;
uniform vec4 modulation;
uniform float saturation;
varying vec2 texcoord0;
void main()
{
vec4 tex = texture2D(sampler, texcoord0);
if (saturation != 1.0) {
vec3 desaturated = tex.rgb * vec3( 0.30, 0.59, 0.11 );
desaturated = vec3(dot( desaturated, tex.rgb ));
tex.rgb = tex.rgb * vec3(saturation) + desaturated * vec3(1.0 - saturation);
}
float L = (17.8824 * tex.r) + (43.5161 * tex.g) + (4.11935 * tex.b);
float M = (3.45565 * tex.r) + (27.1554 * tex.g) + (3.86714 * tex.b);
float S = (0.0299566 * tex.r) + (0.184309 * tex.g) + (1.46709 * tex.b);
// Deuteranopia
float l = 1.0 * L + 0.0 * M + 0.0 * S;
float m = 0.494207 * L + 0.0 * M + 1.24827 * S;
float s = 0.0 * L + 0.0 * M + 1.0 * S;
vec4 error;
error.r = (0.0809444479 * l) + (-0.130504409 * m) + (0.116721066 * s);
error.g = (-0.0102485335 * l) + (0.0540193266 * m) + (-0.113614708 * s);
error.b = (-0.000365296938 * l) + (-0.00412161469 * m) + (0.693511405 * s);
error.a = 1.0;
vec4 diff = tex - error;
vec4 correction;
correction.r = 0.0;
correction.g = (diff.r * 0.7) + (diff.g * 1.0);
correction.b = (diff.r * 0.7) + (diff.b * 1.0);
correction = tex + correction;
gl_FragColor = correction * modulation;
}

@ -0,0 +1,43 @@
#version 140
// SPDX-FileCopyrightText: None
// SPDX-License-Identifier: CC0-1.0
uniform sampler2D sampler;
uniform vec4 modulation;
uniform float saturation;
in vec2 texcoord0;
out vec4 fragColor;
void main()
{
vec4 tex = texture2D(sampler, texcoord0);
if (saturation != 1.0) {
vec3 desaturated = tex.rgb * vec3( 0.30, 0.59, 0.11 );
desaturated = vec3(dot( desaturated, tex.rgb ));
tex.rgb = tex.rgb * vec3(saturation) + desaturated * vec3(1.0 - saturation);
}
float L = (17.8824 * tex.r) + (43.5161 * tex.g) + (4.11935 * tex.b);
float M = (3.45565 * tex.r) + (27.1554 * tex.g) + (3.86714 * tex.b);
float S = (0.0299566 * tex.r) + (0.184309 * tex.g) + (1.46709 * tex.b);
// Deuteranopia
float l = 1.0 * L + 0.0 * M + 0.0 * S;
float m = 0.494207 * L + 0.0 * M + 1.24827 * S;
float s = 0.0 * L + 0.0 * M + 1.0 * S;
vec4 error;
error.r = (0.0809444479 * l) + (-0.130504409 * m) + (0.116721066 * s);
error.g = (-0.0102485335 * l) + (0.0540193266 * m) + (-0.113614708 * s);
error.b = (-0.000365296938 * l) + (-0.00412161469 * m) + (0.693511405 * s);
error.a = 1.0;
vec4 diff = tex - error;
vec4 correction;
correction.r = 0.0;
correction.g = (diff.r * 0.7) + (diff.g * 1.0);
correction.b = (diff.r * 0.7) + (diff.b * 1.0);
correction = tex + correction;
fragColor = correction * modulation;
}

@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: None
// SPDX-License-Identifier: CC0-1.0
uniform sampler2D sampler;
uniform vec4 modulation;
uniform float saturation;
varying vec2 texcoord0;
void main()
{
vec4 tex = texture2D(sampler, texcoord0);
if (saturation != 1.0) {
vec3 desaturated = tex.rgb * vec3( 0.30, 0.59, 0.11 );
desaturated = vec3(dot( desaturated, tex.rgb ));
tex.rgb = tex.rgb * vec3(saturation) + desaturated * vec3(1.0 - saturation);
}
float L = (17.8824 * tex.r) + (43.5161 * tex.g) + (4.11935 * tex.b);
float M = (3.45565 * tex.r) + (27.1554 * tex.g) + (3.86714 * tex.b);
float S = (0.0299566 * tex.r) + (0.184309 * tex.g) + (1.46709 * tex.b);
// Protanopia
float l = 0.0 * L + 2.02344 * M + -2.52581 * S;
float m = 0.0 * L + 1.0 * M + 0.0 * S;
float s = 0.0 * L + 0.0 * M + 1.0 * S;
vec4 error;
error.r = (0.0809444479 * l) + (-0.130504409 * m) + (0.116721066 * s);
error.g = (-0.0102485335 * l) + (0.0540193266 * m) + (-0.113614708 * s);
error.b = (-0.000365296938 * l) + (-0.00412161469 * m) + (0.693511405 * s);
error.a = 1.0;
vec4 diff = tex - error;
vec4 correction;
correction.r = 0.0;
correction.g = (diff.r * 0.7) + (diff.g * 1.0);
correction.b = (diff.r * 0.7) + (diff.b * 1.0);
correction = tex + correction;
gl_FragColor = correction * modulation;
}

@ -0,0 +1,43 @@
#version 140
// SPDX-FileCopyrightText: None
// SPDX-License-Identifier: CC0-1.0
uniform sampler2D sampler;
uniform vec4 modulation;
uniform float saturation;
in vec2 texcoord0;
out vec4 fragColor;
void main()
{
vec4 tex = texture2D(sampler, texcoord0);
if (saturation != 1.0) {
vec3 desaturated = tex.rgb * vec3( 0.30, 0.59, 0.11 );
desaturated = vec3(dot( desaturated, tex.rgb ));
tex.rgb = tex.rgb * vec3(saturation) + desaturated * vec3(1.0 - saturation);
}
float L = (17.8824 * tex.r) + (43.5161 * tex.g) + (4.11935 * tex.b);
float M = (3.45565 * tex.r) + (27.1554 * tex.g) + (3.86714 * tex.b);
float S = (0.0299566 * tex.r) + (0.184309 * tex.g) + (1.46709 * tex.b);
// Protanopia
float l = 0.0 * L + 2.02344 * M + -2.52581 * S;
float m = 0.0 * L + 1.0 * M + 0.0 * S;
float s = 0.0 * L + 0.0 * M + 1.0 * S;
vec4 error;
error.r = (0.0809444479 * l) + (-0.130504409 * m) + (0.116721066 * s);
error.g = (-0.0102485335 * l) + (0.0540193266 * m) + (-0.113614708 * s);
error.b = (-0.000365296938 * l) + (-0.00412161469 * m) + (0.693511405 * s);
error.a = 1.0;
vec4 diff = tex - error;
vec4 correction;
correction.r = 0.0;
correction.g = (diff.r * 0.7) + (diff.g * 1.0);
correction.b = (diff.r * 0.7) + (diff.b * 1.0);
correction = tex + correction;
fragColor = correction * modulation;
}

@ -0,0 +1,8 @@
ColorBlindness correction shader with adjustable intensity. Can correct for:
* Protanopia (Greatly reduced reds)
* Deuteranopia (Greatly reduced greens)
* Tritanopia (Greatly reduced blues)
The correction algorithm is taken from http://www.daltonize.org/search/label/Daltonize
This shader is released under the CC0 license. Feel free to use, improve and change this shader and consider sharing the modified result.

@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: None
// SPDX-License-Identifier: CC0-1.0
uniform sampler2D sampler;
uniform vec4 modulation;
uniform float saturation;
varying vec2 texcoord0;
in vec2 texcoord0;
out vec4 fragColor;
void main()
{
vec4 tex = texture2D(sampler, texcoord0);
if (saturation != 1.0) {
vec3 desaturated = tex.rgb * vec3( 0.30, 0.59, 0.11 );
desaturated = vec3(dot( desaturated, tex.rgb ));
tex.rgb = tex.rgb * vec3(saturation) + desaturated * vec3(1.0 - saturation);
}
float L = (17.8824 * tex.r) + (43.5161 * tex.g) + (4.11935 * tex.b);
float M = (3.45565 * tex.r) + (27.1554 * tex.g) + (3.86714 * tex.b);
float S = (0.0299566 * tex.r) + (0.184309 * tex.g) + (1.46709 * tex.b);
// Tritanopia
float l = 1.0 * L + 0.0 * M + 0.0 * S;
float m = 0.0 * L + 1.0 * M + 0.0 * S;
float s = -0.395913 * L + 0.801109 * M + 0.0 * S;
vec4 error;
error.r = (0.0809444479 * l) + (-0.130504409 * m) + (0.116721066 * s);
error.g = (-0.0102485335 * l) + (0.0540193266 * m) + (-0.113614708 * s);
error.b = (-0.000365296938 * l) + (-0.00412161469 * m) + (0.693511405 * s);
error.a = 1.0;
vec4 diff = tex - error;
vec4 correction;
correction.r = 0.0;
correction.g = (diff.r * 0.7) + (diff.g * 1.0);
correction.b = (diff.r * 0.7) + (diff.b * 1.0);
correction = tex + correction;
gl_FragColor = correction * modulation;
}

@ -0,0 +1,43 @@
#version 140
// SPDX-FileCopyrightText: None
// SPDX-License-Identifier: CC0-1.0
uniform sampler2D sampler;
uniform vec4 modulation;
uniform float saturation;
in vec2 texcoord0;
out vec4 fragColor;
void main()
{
vec4 tex = texture2D(sampler, texcoord0);
if (saturation != 1.0) {
vec3 desaturated = tex.rgb * vec3( 0.30, 0.59, 0.11 );
desaturated = vec3(dot( desaturated, tex.rgb ));
tex.rgb = tex.rgb * vec3(saturation) + desaturated * vec3(1.0 - saturation);
}
float L = (17.8824 * tex.r) + (43.5161 * tex.g) + (4.11935 * tex.b);
float M = (3.45565 * tex.r) + (27.1554 * tex.g) + (3.86714 * tex.b);
float S = (0.0299566 * tex.r) + (0.184309 * tex.g) + (1.46709 * tex.b);
// Tritanopia
float l = 1.0 * L + 0.0 * M + 0.0 * S;
float m = 0.0 * L + 1.0 * M + 0.0 * S;
float s = -0.395913 * L + 0.801109 * M + 0.0 * S;
vec4 error;
error.r = (0.0809444479 * l) + (-0.130504409 * m) + (0.116721066 * s);
error.g = (-0.0102485335 * l) + (0.0540193266 * m) + (-0.113614708 * s);
error.b = (-0.000365296938 * l) + (-0.00412161469 * m) + (0.693511405 * s);
error.a = 1.0;
vec4 diff = tex - error;
vec4 correction;
correction.r = 0.0;
correction.g = (diff.r * 0.7) + (diff.g * 1.0);
correction.b = (diff.r * 0.7) + (diff.b * 1.0);
correction = tex + correction;
fragColor = correction * modulation;
}

@ -0,0 +1,83 @@
/*
SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick
import QtQuick.Controls as QQC
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kcmutils as KCM
import org.kde.plasma.kwin.colorblindnesscorrectioneffect.kcm
KCM.SimpleKCM {
id: root
implicitWidth: Kirigami.Units.gridUnit * 30
implicitHeight: Kirigami.Units.gridUnit * 22
RowLayout {
id: previewArea
Layout.fillWidth: true
spacing: Kirigami.Units.smallSpacing
Item {
Layout.fillWidth: true
}
Repeater {
model: [
{ name: i18n("Red"), colors: ["Red", "Orange", "Yellow"] },
{ name: i18n("Green"), colors: ["Green", "LimeGreen", "Lime"] },
{ name: i18n("Blue"), colors: ["Blue", "DeepSkyBlue", "Aqua"] },
{ name: i18n("Purple"), colors: ["Purple", "Fuchsia", "Violet"] },
]
delegate: Column {
spacing: 0
Repeater {
model: modelData.colors
delegate: Rectangle {
width: Kirigami.Units.gridUnit * 5
height: Kirigami.Units.gridUnit * 5
color: modelData
}
}
QQC.Label {
anchors.horizontalCenter: parent.horizontalCenter
text: modelData.name
}
}
}
Item {
Layout.fillWidth: true
}
}
Kirigami.FormLayout {
id: formLayout
anchors {
top: previewArea.bottom
topMargin: Kirigami.Units.largeSpacing
}
QQC.ComboBox {
Kirigami.FormData.label: i18nc("@label", "Mode:")
currentIndex: kcm.settings.mode
textRole: "text"
valueRole: "value"
model: [
{ value: 0, text: i18nc("@option", "Protanopia (red weak)") },
{ value: 1, text: i18nc("@option", "Deuteranopia (green weak)") },
{ value: 2, text: i18nc("@option", "Tritanopia (blue-yellow)") },
]
onActivated: kcm.settings.mode = currentValue
}
}
}
Loading…
Cancel
Save