File indexing completed on 2021-12-21 13:28:00
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 <QIcon> 0024 #include <KLocalizedString> 0025 0026 #include <QAction> 0027 #include <QContextMenuEvent> 0028 #include <QFontMetrics> 0029 #include <QMenu> 0030 #include <QPainter> 0031 #include <QStyle> 0032 #include <QStyleOptionSlider> 0033 0034 Slider::Slider( Qt::Orientation orientation, uint max, QWidget *parent ) 0035 : QSlider( orientation, parent ) 0036 { 0037 setMouseTracking( true ); 0038 setRange( 0, max ); 0039 setAttribute( Qt::WA_NoMousePropagation, true ); 0040 setAttribute( Qt::WA_Hover, true ); 0041 if ( orientation == Qt::Vertical ) 0042 { 0043 setInvertedAppearance( true ); 0044 setInvertedControls( true ); 0045 } 0046 } 0047 0048 QRectF 0049 Slider::sliderHandleRect( const QRectF &slider, qreal percent ) const 0050 { 0051 QRectF rect; 0052 const bool inverse = ( orientation() == Qt::Horizontal ) ? 0053 ( invertedAppearance() != (layoutDirection() == Qt::RightToLeft) ) : 0054 ( !invertedAppearance() ); 0055 0056 if(m_usingCustomStyle) 0057 { 0058 rect = The::svgHandler()->sliderKnobRect( slider, percent, inverse ); 0059 } 0060 else 0061 { 0062 if ( inverse ) 0063 percent = 1.0 - percent; 0064 const int handleSize = style()->pixelMetric( QStyle::PM_SliderControlThickness ); 0065 rect = QRect( 0, 0, handleSize, handleSize ); 0066 rect.moveTo( slider.x() + qRound( ( slider.width() - handleSize ) * percent ), slider.y() + 1 ); 0067 } 0068 0069 return rect; 0070 } 0071 0072 void 0073 Slider::wheelEvent( QWheelEvent *e ) 0074 { 0075 if( orientation() == Qt::Vertical ) 0076 { 0077 // Will be handled by the parent widget 0078 e->ignore(); 0079 return; 0080 } 0081 0082 // Position Slider (horizontal) 0083 // only used for progress slider now! 0084 int step = e->angleDelta().y() * 24; 0085 int nval = value() + step; 0086 nval = qMax(nval, minimum()); 0087 nval = qMin(nval, maximum()); 0088 0089 QSlider::setValue( nval ); 0090 } 0091 0092 void Slider::paintCustomSlider( QPainter *p ) 0093 { 0094 qreal percent = 0.0; 0095 if ( maximum() > minimum() ) 0096 percent = ((qreal)value()) / ( maximum() - minimum() ); 0097 QStyleOptionSlider opt; 0098 initStyleOption( &opt ); 0099 if ( this->isSliderDown() || 0100 ( underMouse() && sliderHandleRect( rect(), percent ).contains( mapFromGlobal(QCursor::pos()) ) ) ) 0101 { 0102 opt.activeSubControls |= QStyle::SC_SliderHandle; 0103 } 0104 The::svgHandler()->setDevicePixelRatioF(devicePixelRatioF()); 0105 The::svgHandler()->paintCustomSlider( p, &opt, percent ); 0106 } 0107 0108 ////////////////////////////////////////////////////////////////////////////////////////// 0109 /// CLASS VolumeSlider 0110 ////////////////////////////////////////////////////////////////////////////////////////// 0111 0112 VolumeSlider::VolumeSlider( uint max, QWidget *parent, bool customStyle ) 0113 : Slider( customStyle ? Qt::Horizontal : Qt::Vertical, max, parent ) 0114 { 0115 m_usingCustomStyle = customStyle; 0116 setFocusPolicy( Qt::NoFocus ); 0117 setInvertedAppearance( false ); 0118 setInvertedControls( false ); 0119 0120 connect(this, &QAbstractSlider::valueChanged, this, &VolumeSlider::emitVolumeChanged); 0121 } 0122 0123 void 0124 VolumeSlider::contextMenuEvent( QContextMenuEvent *e ) 0125 { 0126 QMenu menu; 0127 menu.setTitle( i18n( "Volume" ) ); 0128 menu.addAction( i18n( "100%" ) )->setData( 100 ); 0129 menu.addAction( i18n( "80%" ) )->setData( 80 ); 0130 menu.addAction( i18n( "60%" ) )->setData( 60 ); 0131 menu.addAction( i18n( "40%" ) )->setData( 40 ); 0132 menu.addAction( i18n( "20%" ) )->setData( 20 ); 0133 menu.addAction( i18n( "0%" ) )->setData( 0 ); 0134 0135 QAction* a = menu.exec( mapToGlobal( e->pos() ) ); 0136 if( a ) 0137 { 0138 const int n = a->data().toInt(); 0139 if( n >= 0 ) 0140 { 0141 this->setValue( n ); 0142 } 0143 } 0144 } 0145 0146 void 0147 VolumeSlider::wheelEvent( QWheelEvent *e ) 0148 { 0149 static const int volumeSensitivity = 30; 0150 const uint step = e->angleDelta().y() / volumeSensitivity; 0151 this->setValue( this->value() + step ); 0152 } 0153 0154 void 0155 VolumeSlider::paintEvent( QPaintEvent *event ) 0156 { 0157 if( m_usingCustomStyle ) 0158 { 0159 QPainter p( this ); 0160 paintCustomSlider( &p ); 0161 p.end(); 0162 return; 0163 } 0164 0165 Slider::paintEvent( event ); 0166 } 0167 0168 void 0169 VolumeSlider::emitVolumeChanged( int value ) 0170 { 0171 emit volumeChanged( float( value ) / float( maximum() ) ); 0172 } 0173 0174 0175 ////////////////////////////////////////////////////////////////////////////////////////// 0176 ////////////////////////////////// TIMESLIDER //////////////////////////////////////////// 0177 ////////////////////////////////////////////////////////////////////////////////////////// 0178 0179 TimeSlider::TimeSlider( QWidget *parent ) 0180 : Slider( Qt::Horizontal, 0, parent ) 0181 , m_knobX( 0.0 ) 0182 { 0183 m_usingCustomStyle = true; 0184 setFocusPolicy( Qt::NoFocus ); 0185 } 0186 0187 void 0188 TimeSlider::paintEvent( QPaintEvent *pe ) 0189 { 0190 QPainter p( this ); 0191 p.setClipRegion( pe->region() ); 0192 paintCustomSlider( &p ); 0193 p.end(); 0194 } 0195 0196 void TimeSlider::sliderChange( SliderChange change ) 0197 { 0198 if ( change == SliderValueChange || change == SliderRangeChange ) 0199 { 0200 int oldKnobX = m_knobX; 0201 qreal percent = 0.0; 0202 if ( maximum() > minimum() ) 0203 percent = ((qreal)value()) / ( maximum() - minimum() ); 0204 QRectF knob = sliderHandleRect( rect(), percent ); 0205 m_knobX = knob.x(); 0206 0207 if (oldKnobX < m_knobX) 0208 update( oldKnobX, knob.y(), knob.right() + 1 - oldKnobX, knob.height() ); 0209 else if (oldKnobX > m_knobX) 0210 update( m_knobX, knob.y(), oldKnobX + knob.width(), knob.height() ); 0211 } 0212 else 0213 Slider::sliderChange( change ); // calls update() 0214 }