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 }