File indexing completed on 2024-12-22 04:14:39

0001 /*
0002  *  SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_equalizer_slider.h"
0008 
0009 #include <QStyle>
0010 #include <QPainter>
0011 #include <QMouseEvent>
0012 #include <QApplication>
0013 #include <QStyleOptionSlider>
0014 
0015 #include "kis_global.h"
0016 #include "kis_debug.h"
0017 
0018 #include "KisAnimTimelineColors.h"
0019 
0020 
0021 struct KisEqualizerSlider::Private
0022 {
0023     Private(KisEqualizerSlider *_q) : q(_q), isRightmost(false), toggleState(true) {}
0024 
0025     KisEqualizerSlider *q;
0026     bool isRightmost;
0027     bool toggleState;
0028 
0029 
0030     QRect boundingRect() const;
0031     QRect sliderRect() const;
0032 
0033     int mousePosToValue(const QPoint &pt, bool round) const;
0034 };
0035 
0036 KisEqualizerSlider::KisEqualizerSlider(QWidget *parent)
0037     : QAbstractSlider(parent),
0038       m_d(new Private(this))
0039 {
0040     setOrientation(Qt::Vertical);
0041     setFocusPolicy(Qt::WheelFocus);
0042     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0043 }
0044 
0045 KisEqualizerSlider::~KisEqualizerSlider()
0046 {
0047 }
0048 
0049 void KisEqualizerSlider::setRightmost(bool value)
0050 {
0051     m_d->isRightmost = value;
0052 }
0053 
0054 void KisEqualizerSlider::setToggleState(bool value)
0055 {
0056     m_d->toggleState = value;
0057     update();
0058 
0059 }
0060 
0061 QRect KisEqualizerSlider::Private::boundingRect() const
0062 {
0063     QRect bounds = q->rect().adjusted(0, 0, -static_cast<int>(isRightmost), -1);
0064     return bounds;
0065 }
0066 
0067 QRect KisEqualizerSlider::Private::sliderRect() const
0068 {
0069     const int offset = 3;
0070     QRect filling = boundingRect().adjusted(offset + 1, offset + 1,
0071                                             -offset, -offset);
0072 
0073     return filling;
0074 }
0075 
0076 int KisEqualizerSlider::Private::mousePosToValue(const QPoint &pt,  bool round) const
0077 {
0078     const QRect areaRect = sliderRect();
0079 
0080     int rawValue = -pt.y() + (areaRect.top() + areaRect.height());
0081     int maxRawValue = areaRect.height();
0082 
0083     int value = QStyle::sliderValueFromPosition(q->minimum(), q->maximum(), rawValue, maxRawValue);
0084 
0085     if (round) {
0086         const int singleStep = q->singleStep();
0087         value = ((value + singleStep / 2) / singleStep) * singleStep;
0088     }
0089 
0090     return value;
0091 }
0092 
0093 void KisEqualizerSlider::mousePressEvent(QMouseEvent *ev)
0094 {
0095     if (maximum() == minimum() || (ev->buttons() ^ ev->button())) {
0096         ev->ignore();
0097         return;
0098     }
0099 
0100     const bool precise = ev->modifiers() & Qt::ControlModifier ||
0101         ev->button() == Qt::RightButton;
0102 
0103     int value = m_d->mousePosToValue(ev->pos(), !precise);
0104     setSliderPosition(value);
0105     triggerAction(SliderMove);
0106     setRepeatAction(SliderNoAction);
0107 }
0108 
0109 void KisEqualizerSlider::mouseMoveEvent(QMouseEvent *ev)
0110 {
0111     if (ev->modifiers() & Qt::ShiftModifier &&
0112         !rect().contains(ev->pos())) {
0113 
0114         ev->ignore();
0115         return;
0116     }
0117 
0118     const bool precise = ev->modifiers() & Qt::ControlModifier ||
0119         ev->buttons() & Qt::RightButton;
0120 
0121     int value = m_d->mousePosToValue(ev->pos(), !precise);
0122     setSliderPosition(value);
0123     triggerAction(SliderMove);
0124     setRepeatAction(SliderNoAction);
0125 }
0126 
0127 void KisEqualizerSlider::mouseReleaseEvent(QMouseEvent *ev)
0128 {
0129     Q_UNUSED(ev);
0130 }
0131 
0132 QSize KisEqualizerSlider::sizeHint() const
0133 {
0134     return QSize(25, 150);
0135 }
0136 
0137 QSize KisEqualizerSlider::minimumSizeHint() const
0138 {
0139     return QSize(10, 40);
0140 }
0141 
0142 void KisEqualizerSlider::paintEvent(QPaintEvent *event)
0143 {
0144     Q_UNUSED(event);
0145 
0146     const QRect bounds = m_d->boundingRect();
0147     const QColor backgroundColor = palette().color(QPalette::Base);
0148 
0149 
0150     QPainter p(this);
0151 
0152     { // draw border
0153 
0154         QStyleOptionViewItem option; // empty!
0155         const int gridHint = style()->styleHint(QStyle::SH_Table_GridLineColor, &option, this);
0156         const QColor gridColor = static_cast<QRgb>(gridHint);
0157         const QPen gridPen(gridColor);
0158 
0159         p.setPen(gridPen);
0160         p.setBrush(backgroundColor);
0161         p.drawRect(bounds);
0162     }
0163 
0164     { // draw slider
0165         QRect sliderRect = m_d->sliderRect();
0166         const int sliderPos =  QStyle::sliderPositionFromValue(minimum(), maximum(), value(), sliderRect.height());
0167         sliderRect.adjust(0, sliderRect.height() - sliderPos, 0, 0);
0168 
0169         p.setPen(Qt::transparent);
0170 
0171         QColor color = m_d->toggleState ?
0172                     KisAnimTimelineColors::instance()->onionSkinsSliderEnabledColor() :
0173                     KisAnimTimelineColors::instance()->onionSkinsSliderDisabledColor();
0174         p.setBrush(color);
0175 
0176         p.drawRect(sliderRect);
0177     }
0178 
0179     QString textValue = QString::number(value());
0180 
0181     /*  Text isn't really needed for onion skinning and makes it look a bit cluttered. Uncomment this out of that changes.
0182     { // draw text
0183         QPalette::ColorRole textRole = QPalette::Text;
0184 
0185         //Draw text shadow, This will increase readability when the background of same color
0186         QRect shadowRect(bounds);
0187         shadowRect.translate(1,1);
0188         QColor textColor = palette().color(textRole);
0189         QColor shadowColor = (textColor.value() <= 128)
0190             ? QColor(255,255,255,160) : QColor(0,0,0,160);
0191 
0192         p.setPen(shadowColor);
0193         p.drawText(shadowRect, Qt::AlignCenter, textValue);
0194 
0195         p.setPen(textColor);
0196         p.drawText(bounds, Qt::AlignCenter, textValue);
0197     }
0198     */
0199 
0200     // draw focus rect
0201     if (hasFocus()) {
0202         QStyleOptionFocusRect fropt;
0203         fropt.initFrom(this);
0204         fropt.backgroundColor = backgroundColor;
0205 
0206         int dfw1 = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &fropt, this) + 1,
0207             dfw2 = dfw1 * 2;
0208         fropt.rect = kisGrowRect(bounds, -dfw1 - dfw2);
0209 
0210         style()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, &p, this);
0211     }
0212 }