summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qpalette.cpp
diff options
context:
space:
mode:
authorAxel Spoerl <axel.spoerl@qt.io>2023-05-15 17:32:28 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-05-21 18:36:37 +0200
commit17c589df94a2245ee92d45839c2cba73566d7310 (patch)
tree9c9c5e9366be2ed065f3e2b3cff09b40cb27fc66 /src/gui/kernel/qpalette.cpp
parent0328e4297e339de8a2acd84979c667936f6fadf8 (diff)
Shoehorn AccentColor into QPalette and keep existing 64bit resolve mask
It is necessary to add an AccentColor role to QPalette. QPalette currently has 21 color roles and 3 color groups, which require 63 bits to resolve. The resolve mask is implemented with a qint64, which doesn't provide spare bits for another color role. The color role NoRole is used as a default value, marking that a role has not (yet) been defined. The enum value does not represent a valid brush, even though it can theoretically be stored in QPalette's shared data. This patch adds the enum value AccentColor to QPalette::ColorRole, increasing the available color roles to 22. To keep the resolve mask at 63 bits, AccentColor is mapped to NoRole in static constexpr bitPosition. As the enum range would exceed 64 bits without this tweak, 3 additional bits are substracted in the respective static assertion. With NoRole having no bit in the resolve mask, the following adaptions have been implemented: - QPalette::resolve() is adapted to explicitly ignore NoRole. - QPalette::isBrushSet() always returns false for NoRole. - tst_QPalette::setAllPossibleBrushes() to verify the latter - operator== ignores NoRole (documentation updated) AccentColor is added in tst_QPalette::roleValues and enum documentation is adapted. In QPalette's default constructor, the AccentColor brush is defaulting to the Highlight brush, it this is available. Otherwise it is made 30% darker or lighter than the Base brush, depending on dark/light mode heuristics. QPalette's data stram functions have been extended from QDataStream Version Qt_6_6. If earlier versions are de-serialised, the AccentColor defaults to Highlight. An autotest function dataStream() has been added to tst_QPalette. The QDataStream Version Qt_6_6 has been bumped to 21. tst_QDataStream has been adapted to the new version and the new color Role. Change-Id: I98bbf9de95fb83bda921e9614a0db3a3c0ebdf75 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/gui/kernel/qpalette.cpp')
-rw-r--r--src/gui/kernel/qpalette.cpp68
1 files changed, 64 insertions, 4 deletions
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index 4abbcd5e65..bc5ebeb4de 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -16,12 +16,17 @@ static int qt_palette_count = 1;
static constexpr QPalette::ResolveMask colorRoleOffset(QPalette::ColorGroup colorGroup)
{
- return qToUnderlying(QPalette::NColorRoles) * qToUnderlying(colorGroup);
+ // Exclude NoRole; that bit is used for AccentColor
+ return (qToUnderlying(QPalette::NColorRoles) - 1) * qToUnderlying(colorGroup);
}
static constexpr QPalette::ResolveMask bitPosition(QPalette::ColorGroup colorGroup,
QPalette::ColorRole colorRole)
{
+ // Map AccentColor into NoRole for resolving purposes
+ if (colorRole == QPalette::AccentColor)
+ colorRole = QPalette::NoRole;
+
return colorRole + colorRoleOffset(colorGroup);
}
@@ -100,6 +105,24 @@ static void qt_placeholder_from_text(QPalette &pal, int alpha = 50)
}
}
+static void qt_ensure_default_accent_color(QPalette &pal)
+{
+ // have a lighter/darker factor handy, depending on dark/light heuristics
+ const int lighter = pal.base().color().lightness() > pal.text().color().lightness() ? 130 : 70;
+
+ // Act only for color groups where no accent color is set
+ for (int i = 0; i < QPalette::NColorGroups; ++i) {
+ const QPalette::ColorGroup group = static_cast<QPalette::ColorGroup>(i);
+ if (!pal.isBrushSet(group, QPalette::AccentColor)) {
+ // Default to highlight if available, otherwise use a shade of base
+ const QBrush accentBrush = pal.isBrushSet(group, QPalette::Highlight)
+ ? pal.brush(group, QPalette::Highlight)
+ : pal.brush(group, QPalette::Base).color().lighter(lighter);
+ pal.setBrush(group, QPalette::AccentColor, accentBrush);
+ }
+ }
+}
+
static void qt_palette_from_color(QPalette &pal, const QColor &button)
{
int h, s, v;
@@ -124,6 +147,7 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button)
whiteBrush, buttonBrush, buttonBrush);
qt_placeholder_from_text(pal);
+ qt_ensure_default_accent_color(pal);
}
/*!
@@ -524,6 +548,13 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button)
item. By default, the highlight color is
Qt::darkBlue.
+ \value AccentColor A color that typically contrasts or compliments
+ Base, Window and Button colors. It usually represents
+ the users' choice of desktop personalisation.
+ Styling of interactive components is a typical use case.
+ Unless explicitly set, it defaults to Highlight.
+ This enum value has been introduced in Qt 6.6.
+
\value HighlightedText A text color that contrasts with \c Highlight.
By default, the highlighted text color is Qt::white.
@@ -613,6 +644,7 @@ QPalette::QPalette(const QBrush &windowText, const QBrush &button,
base, window);
qt_placeholder_from_text(*this);
+ qt_ensure_default_accent_color(*this);
}
@@ -670,6 +702,7 @@ QPalette::QPalette(const QColor &button, const QColor &window)
whiteBrush, baseBrush, windowBrush);
qt_placeholder_from_text(*this);
+ qt_ensure_default_accent_color(*this);
}
/*!
@@ -837,6 +870,10 @@ void QPalette::setBrush(ColorGroup cg, ColorRole cr, const QBrush &b)
*/
bool QPalette::isBrushSet(ColorGroup cg, ColorRole cr) const
{
+ // NoRole has no resolve mask and should never be set anyway
+ if (cr == NoRole)
+ return false;
+
if (cg == Current)
cg = currentGroup;
@@ -885,8 +922,11 @@ void QPalette::detach()
Returns \c true (usually quickly) if this palette is equal to \a p;
otherwise returns \c false (slowly).
- \note The current ColorGroup is not taken into account when
- comparing palettes
+ \note The following is not taken into account when comparing palettes:
+ \list
+ \li the \c current ColorGroup
+ \li ColorRole NoRole \since 6.6
+ \endlist
\sa operator!=()
*/
@@ -896,6 +936,9 @@ bool QPalette::operator==(const QPalette &p) const
return true;
for(int grp = 0; grp < (int)NColorGroups; grp++) {
for(int role = 0; role < (int)NColorRoles; role++) {
+ // Dont't verify NoRole, because it has no resolve bit
+ if (role == NoRole)
+ continue;
if (d->data->br[grp][role] != p.d->data->br[grp][role])
return false;
}
@@ -979,6 +1022,10 @@ QPalette QPalette::resolve(const QPalette &other) const
palette.detach();
for (int role = 0; role < int(NColorRoles); ++role) {
+ // Don't resolve NoRole, its bits are needed for AccentColor (see bitPosition)
+ if (role == NoRole)
+ continue;
+
for (int grp = 0; grp < int(NColorGroups); ++grp) {
if (!(d->resolveMask & (ResolveMask(1) << bitPosition(ColorGroup(grp), ColorRole(role))))) {
palette.d->data.detach();
@@ -1054,6 +1101,9 @@ QDataStream &operator<<(QDataStream &s, const QPalette &p)
max = QPalette::AlternateBase + 1;
else if (s.version() <= QDataStream::Qt_5_11)
max = QPalette::ToolTipText + 1;
+ else if (s.version() <= QDataStream::Qt_6_5)
+ max = QPalette::PlaceholderText + 1;
+
for (int r = 0; r < max; r++)
s << p.d->data->br[grp][r];
}
@@ -1097,15 +1147,25 @@ QDataStream &operator>>(QDataStream &s, QPalette &p)
} else if (s.version() <= QDataStream::Qt_5_11) {
p = QPalette();
max = QPalette::ToolTipText + 1;
+ } else if (s.version() <= QDataStream::Qt_6_5) {
+ p = QPalette();
+ max = QPalette::PlaceholderText + 1;
}
+
QBrush tmp;
for(int grp = 0; grp < (int)QPalette::NColorGroups; ++grp) {
+ const QPalette::ColorGroup group = static_cast<QPalette::ColorGroup>(grp);
for(int role = 0; role < max; ++role) {
s >> tmp;
- p.setBrush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role, tmp);
+ p.setBrush(group, (QPalette::ColorRole)role, tmp);
}
+
+ // AccentColor defaults to Highlight for stream versions that don't have it.
+ if (s.version() < QDataStream::Qt_6_6)
+ p.setBrush(group, QPalette::AccentColor, p.brush(group, QPalette::Highlight));
}
+
}
return s;
}