diff --git a/src/plugins/platformthemes/gtk3/qgtk3json.cpp b/src/plugins/platformthemes/gtk3/qgtk3json.cpp index a5af2ae9af8..a517fec63ff 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3json.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3json.cpp @@ -211,6 +211,15 @@ const QJsonDocument QGtk3Json::save(const QGtk3Storage::PaletteMap &map) } break; + case QGtk3Storage::SourceType::Mixed: { + sourceObject.insert(ceColorGroup, fromColorGroup(s.mix.sourceGroup)); + QJsonArray colorRoles; + colorRoles << fromColorRole(s.mix.colorRole1) + << fromColorRole(s.mix.colorRole2); + sourceObject.insert(ceColorRole, colorRoles); + } + break; + case QGtk3Storage::SourceType::Invalid: break; } @@ -387,6 +396,26 @@ bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc) } break; + case QGtk3Storage::SourceType::Mixed: { + if (!sourceObject[ceColorRole].isArray()) { + qCInfo(lcQGtk3Interface) << "Mixed brush missing the array of color roles for palette:" << paletteName + << "Brush" << colorRoleName; + return false; + } + QJsonArray colorRoles = sourceObject[ceColorRole].toArray(); + if (colorRoles.size() < 2) { + qCInfo(lcQGtk3Interface) << "Mixed brush missing enough color roles for palette" << paletteName + << "Brush" << colorRoleName; + return false; + } + const QPalette::ColorRole colorRole1 = toColorRole(colorRoles[0].toString()); + const QPalette::ColorRole colorRole2 = toColorRole(colorRoles[1].toString()); + GETSTR(sourceObject, ceColorGroup); + const QPalette::ColorGroup sourceGroup = toColorGroup(value); + s = QGtk3Storage::Source(sourceGroup, colorRole1, colorRole2); + } + break; + case QGtk3Storage::SourceType::Invalid: qInfo(lcQGtk3Interface) << "Invalid source type for palette" << paletteName << "Brush." << colorRoleName; diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp index 2877b285901..2991212d033 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp @@ -75,6 +75,31 @@ QBrush QGtk3Storage::brush(const Source &source, const BrushMap &map) const return b; } + case SourceType::Mixed: { + // check the mixing source to be valid and be a Gtk source + constexpr auto check_source = [](const Source &source) -> bool + { + return source.isValid() && (source.sourceType == SourceType::Gtk); + }; + + const Source source1 = brush(TargetBrush(source.mix.sourceGroup, + source.mix.colorRole1), map); + if (!check_source(source1)) + return QBrush(); + + const Source source2 = brush(TargetBrush(source.mix.sourceGroup, + source.mix.colorRole2), map); + if (!check_source(source2)) + return QBrush(); + + const QBrush brush2 = brush(source2, map); + // the output brush is a copy of the brush from the first source + QBrush brush1 = brush(source1, map); + // only color is mixed + brush1.setColor(MixSources::mixColors(brush1.color(), brush2.color())); + return brush1; + } + case SourceType::Fixed: return source.fix.fixedBrush; @@ -413,6 +438,7 @@ const QGtk3Storage::PaletteMap QGtk3Storage::savePalettes() const break; case SourceType::Fixed: case SourceType::Modified: + case SourceType::Mixed: case SourceType::Invalid: break; } @@ -554,10 +580,22 @@ void QGtk3Storage::createMapping() GTK(button, Foreground, ACTIVE); ADD(Inactive, WindowText); - LIGHTER(Normal, WindowText, 50); - ADD(Disabled, Text); - ADD(Disabled, WindowText); - ADD(Disabled, ButtonText); + + auto ADD_MIX = [&map](QPalette::ColorGroup targetGroup, + QPalette::ColorRole targetRole, + QPalette::ColorGroup sourceGroup, + QPalette::ColorRole role1, + QPalette::ColorRole role2) + { + const Source source{sourceGroup, role1, role2}; + map.insert(TargetBrush(targetGroup, targetRole), source); + }; + ADD_MIX(QPalette::Disabled, QPalette::Text, + QPalette::Normal, QPalette::Base, QPalette::Text); + ADD_MIX(QPalette::Disabled, QPalette::WindowText, + QPalette::Normal, QPalette::Window, QPalette::WindowText); + ADD_MIX(QPalette::Disabled, QPalette::ButtonText, + QPalette::Normal, QPalette::Button, QPalette::ButtonText); GTK(button, Text, NORMAL); ADD(Inactive, ButtonText); diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage_p.h b/src/plugins/platformthemes/gtk3/qgtk3storage_p.h index 45192263a91..cd40ae18e41 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3storage_p.h +++ b/src/plugins/platformthemes/gtk3/qgtk3storage_p.h @@ -41,6 +41,7 @@ class QGtk3Storage Gtk, Fixed, Modified, + Mixed, Invalid }; Q_ENUM(SourceType) @@ -80,6 +81,27 @@ class QGtk3Storage } }; + // Mixed source: Populate a brush by mixing two brushes. + // Useful for creating disabled color by mixing, + // for example the background and foreground colors. + struct MixSources { + QPalette::ColorGroup sourceGroup; // source group of the mixing color roles + QPalette::ColorRole colorRole1; + QPalette::ColorRole colorRole2; + QDebug operator<<(QDebug dbg) + { + return dbg << "QGtkStorage::MixSources(sourceGroup=" << sourceGroup + << ", colorRole1=" << colorRole1 + << ", colorRole2=" << colorRole2 << ")"; + } + static inline QColor mixColors(const QColor &color1, const QColor &color2) + { + return QColor{ (color1.red() + color2.red()) / 2, + (color1.green() + color2.green()) / 2, + (color1.blue() + color2.blue()) / 2 }; + } + }; + // Fixed source: Populate a brush with fixed values rather than reading GTK struct FixedSource { QBrush fixedBrush; @@ -95,6 +117,7 @@ class QGtk3Storage Gtk3Source gtk3; RecursiveSource rec; FixedSource fix; + MixSources mix; // GTK constructor Source(QGtk3Interface::QGtkWidget wtype, QGtk3Interface::QGtkColorSource csource, @@ -118,7 +141,7 @@ class QGtk3Storage rec.lighter = p_lighter; } - // Recursive ocnstructor for color modification + // Recursive constructor for color modification Source(QPalette::ColorGroup group, QPalette::ColorRole role, Qt::ColorScheme scheme, int p_red, int p_green, int p_blue) : sourceType(SourceType::Modified) @@ -145,6 +168,16 @@ class QGtk3Storage rec.deltaBlue = p_blue; } + // Mixed constructor for color modification + Source(QPalette::ColorGroup sourceGroup, + QPalette::ColorRole role1, QPalette::ColorRole role2) + : sourceType(SourceType::Mixed) + { + mix.sourceGroup = sourceGroup; + mix.colorRole1 = role1; + mix.colorRole2 = role2; + } + // Fixed Source constructor Source(const QBrush &brush) : sourceType(SourceType::Fixed) {