From 34483a1287d8a7d6edbbf0eda344ac3fa41ac2cb Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Sat, 11 Apr 2020 17:01:50 +0200 Subject: [PATCH] Add central colour palette for widget states. Hard-coded widget state colours (error, warning, health etc.) are replace by a central palette class, which also takes care of determining if KeePassXC is in dark or light mode. Colours expected to be used as background for normal text were tested for WCAG level A compliance. Health colours were adjusted for better harmony with the application theme and tested for sufficient contrast with a colour blindness simulator. --- src/CMakeLists.txt | 1 + src/gui/PasswordEdit.cpp | 11 ++-- src/gui/PasswordGeneratorWidget.cpp | 22 +++---- src/gui/reports/ReportsWidgetHealthcheck.cpp | 11 ++-- src/gui/styles/StateColorPalette.cpp | 57 +++++++++++++++++ src/gui/styles/StateColorPalette.h | 66 ++++++++++++++++++++ 6 files changed, 142 insertions(+), 26 deletions(-) create mode 100644 src/gui/styles/StateColorPalette.cpp create mode 100644 src/gui/styles/StateColorPalette.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1ed089fbc..a147b9d36 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -88,6 +88,7 @@ set(keepassx_SOURCES format/OpVaultReaderBandEntry.cpp format/OpVaultReaderSections.cpp gui/styles/styles.qrc + gui/styles/StateColorPalette.cpp gui/styles/base/phantomcolor.cpp gui/styles/base/BaseStyle.cpp gui/styles/dark/DarkStyle.cpp diff --git a/src/gui/PasswordEdit.cpp b/src/gui/PasswordEdit.cpp index 627f79c5e..83b5de36f 100644 --- a/src/gui/PasswordEdit.cpp +++ b/src/gui/PasswordEdit.cpp @@ -20,19 +20,15 @@ #include "core/Config.h" #include "core/Resources.h" -#include "gui/Application.h" #include "gui/Font.h" #include "gui/PasswordGeneratorWidget.h" +#include "gui/styles/StateColorPalette.h" #include #include namespace { - const QColor CorrectSoFarColor(255, 205, 15); - const QColor CorrectSoFarColorDark(115, 104, 46); - const QColor ErrorColor(255, 125, 125); - const QColor ErrorColorDark(128, 45, 45); } // namespace @@ -147,9 +143,10 @@ void PasswordEdit::updateRepeatStatus() const auto password = text(); if (otherPassword != password) { bool isCorrect = false; - QColor color = kpxcApp->isDarkTheme() ? ErrorColorDark : ErrorColor; + StateColorPalette statePalette; + QColor color = statePalette.color(StateColorPalette::ColorRole::Error); if (!password.isEmpty() && otherPassword.startsWith(password)) { - color = kpxcApp->isDarkTheme() ? CorrectSoFarColorDark : CorrectSoFarColor; + color = statePalette.color(StateColorPalette::ColorRole::Incomplete); isCorrect = true; } setStyleSheet(stylesheetTemplate.arg(color.name())); diff --git a/src/gui/PasswordGeneratorWidget.cpp b/src/gui/PasswordGeneratorWidget.cpp index cb1931372..669a96d33 100644 --- a/src/gui/PasswordGeneratorWidget.cpp +++ b/src/gui/PasswordGeneratorWidget.cpp @@ -27,8 +27,8 @@ #include "core/PasswordGenerator.h" #include "core/PasswordHealth.h" #include "core/Resources.h" -#include "gui/Application.h" #include "gui/Clipboard.h" +#include "gui/styles/StateColorPalette.h" PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent) : QWidget(parent) @@ -376,34 +376,28 @@ void PasswordGeneratorWidget::colorStrengthIndicator(const PasswordHealth& healt QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption); style.replace(re, "\\1 %1;"); - // Set the color and background based on entropy - QList qualityColors; - if (kpxcApp->isDarkTheme()) { - qualityColors << QStringLiteral("#C43F31") << QStringLiteral("#DB9837") << QStringLiteral("#608A22") - << QStringLiteral("#1F8023"); - } else { - qualityColors << QStringLiteral("#C43F31") << QStringLiteral("#E09932") << QStringLiteral("#5EA10E") - << QStringLiteral("#118f17"); - } + StateColorPalette statePalette; switch (health.quality()) { case PasswordHealth::Quality::Bad: case PasswordHealth::Quality::Poor: - m_ui->entropyProgressBar->setStyleSheet(style.arg(qualityColors[0])); + m_ui->entropyProgressBar->setStyleSheet( + style.arg(statePalette.color(StateColorPalette::HealthCritical).name())); m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Poor", "Password quality"))); break; case PasswordHealth::Quality::Weak: - m_ui->entropyProgressBar->setStyleSheet(style.arg(qualityColors[1])); + m_ui->entropyProgressBar->setStyleSheet(style.arg(statePalette.color(StateColorPalette::HealthBad).name())); m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Weak", "Password quality"))); break; case PasswordHealth::Quality::Good: - m_ui->entropyProgressBar->setStyleSheet(style.arg(qualityColors[2])); + m_ui->entropyProgressBar->setStyleSheet(style.arg(statePalette.color(StateColorPalette::HealthOk).name())); m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Good", "Password quality"))); break; case PasswordHealth::Quality::Excellent: - m_ui->entropyProgressBar->setStyleSheet(style.arg(qualityColors[3])); + m_ui->entropyProgressBar->setStyleSheet( + style.arg(statePalette.color(StateColorPalette::HealthExcellent).name())); m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Excellent", "Password quality"))); break; } diff --git a/src/gui/reports/ReportsWidgetHealthcheck.cpp b/src/gui/reports/ReportsWidgetHealthcheck.cpp index 1212a5970..6fa8e78a6 100644 --- a/src/gui/reports/ReportsWidgetHealthcheck.cpp +++ b/src/gui/reports/ReportsWidgetHealthcheck.cpp @@ -23,10 +23,10 @@ #include "core/Group.h" #include "core/PasswordHealth.h" #include "core/Resources.h" +#include "gui/styles/StateColorPalette.h" #include #include -#include namespace { @@ -124,29 +124,30 @@ void ReportsWidgetHealthcheck::addHealthRow(QSharedPointer healt { QString descr, tip; QColor qualityColor; + StateColorPalette statePalette; const auto quality = health->quality(); switch (quality) { case PasswordHealth::Quality::Bad: descr = tr("Bad", "Password quality"); tip = tr("Bad — password must be changed"); - qualityColor.setNamedColor("red"); + qualityColor = statePalette.color(StateColorPalette::HealthCritical); break; case PasswordHealth::Quality::Poor: descr = tr("Poor", "Password quality"); tip = tr("Poor — password should be changed"); - qualityColor.setNamedColor("orange"); + qualityColor = statePalette.color(StateColorPalette::HealthBad); break; case PasswordHealth::Quality::Weak: descr = tr("Weak", "Password quality"); tip = tr("Weak — consider changing the password"); - qualityColor.setNamedColor("yellow"); + qualityColor = statePalette.color(StateColorPalette::HealthWeak); break; case PasswordHealth::Quality::Good: case PasswordHealth::Quality::Excellent: - qualityColor.setNamedColor("green"); + qualityColor = statePalette.color(StateColorPalette::HealthOk); break; } diff --git a/src/gui/styles/StateColorPalette.cpp b/src/gui/styles/StateColorPalette.cpp new file mode 100644 index 000000000..c729e3269 --- /dev/null +++ b/src/gui/styles/StateColorPalette.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2020 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "StateColorPalette.h" + +#include "gui/Application.h" + +StateColorPalette::StateColorPalette() +{ + if (kpxcApp->isDarkTheme()) { + initDefaultPaletteDark(); + } else { + initDefaultPaletteLight(); + } +} + +void StateColorPalette::initDefaultPaletteLight() +{ + setColor(ColorRole::Error, QStringLiteral("#FF7D7D")); + setColor(ColorRole::Warning, QStringLiteral("#FFD30F")); + setColor(ColorRole::Info, QStringLiteral("#84D0E1")); + setColor(ColorRole::Incomplete, QStringLiteral("#FFD30F")); + + setColor(ColorRole::HealthCritical, QStringLiteral("#C43F31")); + setColor(ColorRole::HealthBad, QStringLiteral("#E07F16")); + setColor(ColorRole::HealthWeak, QStringLiteral("#FFD30F")); + setColor(ColorRole::HealthOk, QStringLiteral("#5EA10E")); + setColor(ColorRole::HealthExcellent, QStringLiteral("#118f17")); +} + +void StateColorPalette::initDefaultPaletteDark() +{ + setColor(ColorRole::Error, QStringLiteral("#802D2D")); + setColor(ColorRole::Warning, QStringLiteral("#73682E")); + setColor(ColorRole::Info, QStringLiteral("#207183")); + setColor(ColorRole::Incomplete, QStringLiteral("#665124")); + + setColor(ColorRole::HealthCritical, QStringLiteral("#C43F31")); + setColor(ColorRole::HealthBad, QStringLiteral("#DB9837")); + setColor(ColorRole::HealthWeak, QStringLiteral("#F0C400")); + setColor(ColorRole::HealthOk, QStringLiteral("#608A22")); + setColor(ColorRole::HealthExcellent, QStringLiteral("#1F8023")); +} diff --git a/src/gui/styles/StateColorPalette.h b/src/gui/styles/StateColorPalette.h new file mode 100644 index 000000000..408fe032a --- /dev/null +++ b/src/gui/styles/StateColorPalette.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2020 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_STATECOLORPALETTE_H +#define KEEPASSXC_STATECOLORPALETTE_H + +#include +#include +#include + +/** + * Extended color palette for indicating custom widget states. + */ +class StateColorPalette +{ + Q_GADGET + +public: + StateColorPalette(); + + enum ColorRole + { + Error, + Warning, + Info, + Incomplete, + HealthCritical, + HealthBad, + HealthPoor, + HealthWeak, + HealthOk, + HealthExcellent + }; + + inline void setColor(ColorRole role, const QColor& color) + { + m_colorMap[role] = color; + } + + inline QColor color(ColorRole role) const + { + return m_colorMap.value(role); + } + +private: + void initDefaultPaletteLight(); + void initDefaultPaletteDark(); + + QHash m_colorMap; +}; + +#endif // KEEPASSXC_STATECOLORPALETTE_H