mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-09-30 14:54:13 +02:00
4e43cde063
Hovering a tool button changed only its frame, and on the dark palette Fusion's hover frame is too faint to notice, so nothing told the user which button was under the pointer (GitHub #870, PR 3 of the plan). QETStyle wraps the running style. For QIcon::Active it returns line-art icons tinted in the palette's highlight color, lightened until the tint reads at 3:1 on the Light role, which is the top of Fusion's hover gradient. Colored icons keep their colors, using the same line-art rule as misc/make_icon_themes.py. Every other mode goes to the base style. Fusion also asks for QIcon::Active for the icon of a highlighted menu item and paints it on the highlight bar, where the tint would vanish. The generated pixmap is cached per icon and cannot tell a menu from a toolbar, so drawControl(CE_MenuItem) hands the base style an icon whose Active pixmap is in the HighlightedText color instead. QETApp::initStyle() installs the proxy on every platform, keeping the base style's object name so the Fusion checks still match. tests/qttest/tst_qeticons: hovering changes the icon ink to the tint and stays at 3:1 on both palettes, on a raised button and on a checked one drawn sunken, where the frame gives no hover cue at all; a colored icon is unchanged on hover; a highlighted menu item's icon reads at 3:1 on the highlight bar. inkcontrast.h gains background() and ink() helpers for those checks.
104 lines
3.2 KiB
C++
104 lines
3.2 KiB
C++
/*
|
|
Copyright 2006-2026 The QElectroTech Team
|
|
This file is part of QElectroTech.
|
|
|
|
QElectroTech 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 of the License, or
|
|
(at your option) any later version.
|
|
|
|
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#ifndef QET_TEST_INKCONTRAST_H
|
|
#define QET_TEST_INKCONTRAST_H
|
|
|
|
#include <QHash>
|
|
#include <QImage>
|
|
#include <QRect>
|
|
#include <QString>
|
|
#include <QTest>
|
|
#include <QWidget>
|
|
|
|
#include "qetpalette.h"
|
|
|
|
/**
|
|
Shared helpers for the rendering tests: paint a widget on the offscreen
|
|
platform and measure the ink against the background.
|
|
*/
|
|
namespace QET {
|
|
namespace Test {
|
|
/**
|
|
Grab a widget for measuring. With QET_TEST_DUMP_DIR set, the
|
|
image is also written there as <row>-<name>.png so a failure
|
|
can be looked at.
|
|
*/
|
|
inline QImage dump(const QImage &image, const char *name)
|
|
{
|
|
const QByteArray dir = qgetenv("QET_TEST_DUMP_DIR");
|
|
if (!dir.isEmpty())
|
|
image.save(QString("%1/%2-%3.png").arg(QString::fromLocal8Bit(dir),
|
|
QTest::currentDataTag(), name));
|
|
return image;
|
|
}
|
|
|
|
inline QImage grab(QWidget *widget, const char *name)
|
|
{
|
|
return dump(widget->grab().toImage(), name);
|
|
}
|
|
|
|
/**
|
|
Contrast between the background of a rendered widget (its most
|
|
frequent color) and the ink drawn on it (the pixel whose
|
|
luminance differs most from the background), inside rect.
|
|
*/
|
|
inline QHash<QRgb, int> histogram(const QImage &image, const QRect &rect)
|
|
{
|
|
QHash<QRgb, int> counts;
|
|
for (int y = rect.top(); y <= rect.bottom(); ++y)
|
|
for (int x = rect.left(); x <= rect.right(); ++x)
|
|
++counts[image.pixel(x, y)];
|
|
return counts;
|
|
}
|
|
|
|
/// The most frequent color inside rect.
|
|
inline QRgb background(const QImage &image, const QRect &rect)
|
|
{
|
|
const QHash<QRgb, int> counts = histogram(image, rect);
|
|
QRgb color = 0;
|
|
int best = -1;
|
|
for (auto it = counts.cbegin(); it != counts.cend(); ++it)
|
|
if (it.value() > best) { best = it.value(); color = it.key(); }
|
|
return color;
|
|
}
|
|
|
|
/// The color inside rect that contrasts most with the background: the ink.
|
|
inline QRgb ink(const QImage &image, const QRect &rect)
|
|
{
|
|
const QHash<QRgb, int> counts = histogram(image, rect);
|
|
const QColor bg(background(image, rect));
|
|
QRgb color = bg.rgb();
|
|
double contrast = 1.0;
|
|
for (auto it = counts.cbegin(); it != counts.cend(); ++it)
|
|
{
|
|
const double c = QET::Palette::contrastRatio(bg, QColor(it.key()));
|
|
if (c > contrast) { contrast = c; color = it.key(); }
|
|
}
|
|
return color;
|
|
}
|
|
|
|
inline double inkContrast(const QImage &image, const QRect &rect)
|
|
{
|
|
return QET::Palette::contrastRatio(QColor(background(image, rect)),
|
|
QColor(ink(image, rect)));
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|