Files
OmaPhoto/src/UI/CameraRawSlider.cpp
T

100 lines
3.7 KiB
C++

#include "UI/CameraRawSlider.h"
#include <QMouseEvent>
#include <QPainter>
#include <QPainterPath>
#include <QStyleOptionSlider>
#include <cmath>
namespace {
// Thousandths of the range, as the filter sheet's sliders.
constexpr int travel = 1000;
QColor hsb(double degrees, double saturation, double brightness)
{
double turns = degrees / 360;
turns -= std::floor(turns);
return QColor::fromHsvF(float(turns), float(saturation), float(brightness));
}
}
std::optional<std::pair<QColor, QColor>> CameraRawSliderTrack::colors() const
{
switch (kind) {
case Kind::plain: return std::nullopt;
case Kind::temperature: return std::pair(QColor::fromRgbF(0.22f, 0.46f, 0.95f), QColor::fromRgbF(0.98f, 0.82f, 0.18f));
case Kind::tint: return std::pair(QColor::fromRgbF(0.28f, 0.70f, 0.34f), QColor::fromRgbF(0.70f, 0.40f, 0.64f));
case Kind::chroma: return std::pair(QColor::fromRgbF(0.62f, 0.62f, 0.64f), QColor::fromRgbF(0.86f, 0.18f, 0.20f));
case Kind::hue: return std::pair(hsb(degrees - 50, 0.85, 0.9), hsb(degrees + 50, 0.85, 0.9));
case Kind::saturation: return std::pair(QColor::fromRgbF(0.55f, 0.55f, 0.56f), hsb(degrees, 0.9, 0.9));
case Kind::luminance: return std::pair(hsb(degrees, 0.55, 0.18), hsb(degrees, 0.35, 0.95));
}
throw std::logic_error("unknown slider track");
}
CameraRawSlider::CameraRawSlider(double low, double high, CameraRawSliderTrack track, const QString &help, std::function<void(double)> change,
std::function<void()> reset, QWidget *parent)
: QSlider(Qt::Horizontal, parent), m_low(low), m_high(high), m_track(track), m_change(std::move(change)), m_reset(std::move(reset))
{
setRange(0, travel);
setMinimumWidth(60);
setFixedHeight(22);
setToolTip(help);
setAccessibleName(help);
connect(this, &QSlider::valueChanged, this, [this] { m_change(shown()); });
}
void CameraRawSlider::display(double value)
{
// Swift's isTrackingValue: a drag keeps its own knob.
if (isSliderDown())
return;
const QSignalBlocker quiet(this);
setValue(int(std::lround((value - m_low) / (m_high - m_low) * travel)));
}
double CameraRawSlider::shown() const
{
return m_low + (m_high - m_low) * value() / travel;
}
bool CameraRawSlider::isOnKnob(QPoint point) const
{
QStyleOptionSlider option;
initStyleOption(&option);
return style()->subControlRect(QStyle::CC_Slider, &option, QStyle::SC_SliderHandle, this).adjusted(-2, -2, 2, 2).contains(point);
}
// Swift's GradientSliderCell: the whole track shows the colours.
void CameraRawSlider::paintEvent(QPaintEvent *event)
{
const std::optional<std::pair<QColor, QColor>> colors = m_track.colors();
if (!colors) {
QSlider::paintEvent(event);
return;
}
QStyleOptionSlider option;
initStyleOption(&option);
const QRect groove = style()->subControlRect(QStyle::CC_Slider, &option, QStyle::SC_SliderGroove, this);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
const double height = 4;
const QRectF bar(groove.left(), groove.center().y() + 0.5 - height / 2, groove.width(), height);
QLinearGradient gradient(bar.topLeft(), bar.topRight());
gradient.setColorAt(0, colors->first);
gradient.setColorAt(1, colors->second);
QPainterPath shape;
shape.addRoundedRect(bar, height / 2, height / 2);
painter.fillPath(shape, gradient);
option.subControls = QStyle::SC_SliderHandle;
style()->drawComplexControl(QStyle::CC_Slider, &option, &painter, this);
}
void CameraRawSlider::mouseDoubleClickEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && isOnKnob(event->position().toPoint())) {
m_reset();
return;
}
QSlider::mouseDoubleClickEvent(event);
}