File indexing completed on 2023-05-30 11:30:51
0001 /** 0002 * Copyright (c) 2003-2009 Mark Kretschmann <kretschmann@kde.org> 0003 * Copyright (c) 2005 Gabor Lehel <illissius@gmail.com> 0004 * Copyright (c) 2008 Dan Meltzer <parallelgrapefruit@gmail.com> 0005 * Copyright (c) 2021 Michael Pyne <mpyne@kde.org> 0006 * 0007 * This program is free software; you can redistribute it and/or modify it under 0008 * the terms of the GNU General Public License as published by the Free Software 0009 * Foundation; either version 2 of the License, or (at your option) any later 0010 * version. 0011 * 0012 * This program is distributed in the hope that it will be useful, but WITHOUT ANY 0013 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 0014 * PARTICULAR PURPOSE. See the GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License along with 0017 * this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "slider.h" 0021 #include "svghandler.h" 0022 0023 #include <KLocalizedString> 0024 0025 #include <QAction> 0026 #include <QContextMenuEvent> 0027 #include <QMenu> 0028 #include <QPainter> 0029 #include <QStyle> 0030 #include <QStyleOptionSlider> 0031 0032 Slider::Slider( Qt::Orientation orientation, uint max, QWidget *parent ) 0033 : QSlider( orientation, parent ) 0034 { 0035 setMouseTracking( true ); 0036 setRange( 0, max ); 0037 setAttribute( Qt::WA_NoMousePropagation, true ); 0038 setAttribute( Qt::WA_Hover, true ); 0039 if ( orientation == Qt::Vertical ) 0040 { 0041 setInvertedAppearance( true ); 0042 setInvertedControls( true ); 0043 } 0044 } 0045 0046 QRectF 0047 Slider::sliderHandleRect( const QRectF &slider, qreal percent ) const 0048 { 0049 QRectF rect; 0050 const bool inverse = ( orientation() == Qt::Horizontal ) ? 0051 ( invertedAppearance() != (layoutDirection() == Qt::RightToLeft) ) : 0052 ( !invertedAppearance() ); 0053 0054 if(m_usingCustomStyle) 0055 { 0056 rect = The::svgHandler()->sliderKnobRect( slider, percent, inverse ); 0057 } 0058 else 0059 { 0060 if ( inverse ) 0061 percent = 1.0 - percent; 0062 const int handleSize = style()->pixelMetric( QStyle::PM_SliderControlThickness ); 0063 rect = QRect( 0, 0, handleSize, handleSize ); 0064 rect.moveTo( slider.x() + qRound( ( slider.width() - handleSize ) * percent ), slider.y() + 1 ); 0065 } 0066 0067 return rect; 0068 } 0069 0070 void 0071 Slider::wheelEvent( QWheelEvent *e ) 0072 { 0073 if( orientation() == Qt::Vertical ) 0074 { 0075 // Will be handled by the parent widget 0076 e->ignore(); 0077 return; 0078 } 0079 0080 // Position Slider (horizontal) 0081 // only used for progress slider now! 0082 int step = e->angleDelta().y() * 24; 0083 int nval = value() + step; 0084 nval = qMax(nval, minimum()); 0085 nval = qMin(nval, maximum()); 0086 0087 QSlider::setValue( nval ); 0088 } 0089 0090 void Slider::paintCustomSlider( QPainter *p ) 0091 { 0092 qreal percent = 0.0; 0093 if ( maximum() > minimum() ) 0094 percent = ((qreal)value()) / ( maximum() - minimum() ); 0095 QStyleOptionSlider opt; 0096 initStyleOption( &opt ); 0097 if ( this->isSliderDown() || 0098 ( underMouse() && sliderHandleRect( rect(), percent ).contains( mapFromGlobal(QCursor::pos()) ) ) ) 0099 { 0100 opt.activeSubControls |= QStyle::SC_SliderHandle; 0101 } 0102 The::svgHandler()->setDevicePixelRatioF(devicePixelRatioF()); 0103 The::svgHandler()->paintCustomSlider( p, &opt, percent ); 0104 } 0105 0106 ////////////////////////////////////////////////////////////////////////////////////////// 0107 /// CLASS VolumeSlider 0108 ////////////////////////////////////////////////////////////////////////////////////////// 0109 0110 VolumeSlider::VolumeSlider( uint max, QWidget *parent, bool customStyle ) 0111 : Slider( customStyle ? Qt::Horizontal : Qt::Vertical, max, parent ) 0112 { 0113 m_usingCustomStyle = customStyle; 0114 setFocusPolicy( Qt::NoFocus ); 0115 setInvertedAppearance( false ); 0116 setInvertedControls( false ); 0117 0118 connect(this, &QAbstractSlider::valueChanged, this, &VolumeSlider::emitVolumeChanged); 0119 } 0120 0121 void 0122 VolumeSlider::contextMenuEvent( QContextMenuEvent *e ) 0123 { 0124 QMenu menu; 0125 menu.setTitle( i18n( "Volume" ) ); 0126 menu.addAction( i18n( "100%" ) )->setData( 100 ); 0127 menu.addAction( i18n( "80%" ) )->setData( 80 ); 0128 menu.addAction( i18n( "60%" ) )->setData( 60 ); 0129 menu.addAction( i18n( "40%" ) )->setData( 40 ); 0130 menu.addAction( i18n( "20%" ) )->setData( 20 ); 0131 menu.addAction( i18n( "0%" ) )->setData( 0 ); 0132 0133 QAction* a = menu.exec( mapToGlobal( e->pos() ) ); 0134 if( a ) 0135 { 0136 const int n = a->data().toInt(); 0137 if( n >= 0 ) 0138 { 0139 this->setValue( n ); 0140 } 0141 } 0142 } 0143 0144 void 0145 VolumeSlider::wheelEvent( QWheelEvent *e ) 0146 { 0147 static const int volumeSensitivity = 30; 0148 const uint step = e->angleDelta().y() / volumeSensitivity; 0149 this->setValue( this->value() + step ); 0150 } 0151 0152 void 0153 VolumeSlider::paintEvent( QPaintEvent *event ) 0154 { 0155 if( m_usingCustomStyle ) 0156 { 0157 QPainter p( this ); 0158 paintCustomSlider( &p ); 0159 p.end(); 0160 return; 0161 } 0162 0163 Slider::paintEvent( event ); 0164 } 0165 0166 void 0167 VolumeSlider::emitVolumeChanged( int value ) 0168 { 0169 emit volumeChanged( float( value ) / float( maximum() ) ); 0170 } 0171 0172 0173 ////////////////////////////////////////////////////////////////////////////////////////// 0174 ////////////////////////////////// TIMESLIDER //////////////////////////////////////////// 0175 ////////////////////////////////////////////////////////////////////////////////////////// 0176 0177 TimeSlider::TimeSlider( QWidget *parent ) 0178 : Slider( Qt::Horizontal, 0, parent ) 0179 , m_knobX( 0.0 ) 0180 { 0181 m_usingCustomStyle = true; 0182 setFocusPolicy( Qt::NoFocus ); 0183 } 0184 0185 void 0186 TimeSlider::paintEvent( QPaintEvent *pe ) 0187 { 0188 QPainter p( this ); 0189 p.setClipRegion( pe->region() ); 0190 paintCustomSlider( &p ); 0191 p.end(); 0192 } 0193 0194 void TimeSlider::sliderChange( SliderChange change ) 0195 { 0196 if ( change == SliderValueChange || change == SliderRangeChange ) 0197 { 0198 int oldKnobX = m_knobX; 0199 qreal percent = 0.0; 0200 if ( maximum() > minimum() ) 0201 percent = ((qreal)value()) / ( maximum() - minimum() ); 0202 QRectF knob = sliderHandleRect( rect(), percent ); 0203 m_knobX = knob.x(); 0204 0205 if (oldKnobX < m_knobX) 0206 update( oldKnobX, knob.y(), knob.right() + 1 - oldKnobX, knob.height() ); 0207 else if (oldKnobX > m_knobX) 0208 update( m_knobX, knob.y(), oldKnobX + knob.width(), knob.height() ); 0209 } 0210 else 0211 Slider::sliderChange( change ); // calls update() 0212 }