Warning, file /multimedia/juk/svghandler.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /** 0002 * Copyright (c) 2008 Nikolaj Hald Nielsen <nhn@kde.org> 0003 * Copyright (c) 2008 Jeff Mitchell <kde-dev@emailgoeshere.com> 0004 * Copyright (c) 2009 Mark Kretschmann <kretschmann@kde.org> 0005 * 0006 * This program is free software; you can redistribute it and/or modify it under 0007 * the terms of the GNU General Public License as published by the Free Software 0008 * Foundation; either version 2 of the License, or (at your option) any later 0009 * version. 0010 * 0011 * This program is distributed in the hope that it will be useful, but WITHOUT ANY 0012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 0013 * PARTICULAR PURPOSE. See the GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License along with 0016 * this program. If not, see <http://www.gnu.org/licenses/>. 0017 */ 0018 0019 #include "svghandler.h" 0020 #include "juk_debug.h" 0021 0022 #include <QPainter> 0023 #include <QReadLocker> 0024 #include <QStandardPaths> 0025 #include <QStyleOptionSlider> 0026 #include <QSvgRenderer> 0027 #include <QWriteLocker> 0028 0029 namespace The { 0030 static SvgHandler* s_SvgHandler_instance = 0; 0031 0032 SvgHandler* svgHandler() 0033 { 0034 if( !s_SvgHandler_instance ) 0035 s_SvgHandler_instance = new SvgHandler(); 0036 0037 return s_SvgHandler_instance; 0038 } 0039 } 0040 0041 0042 SvgHandler::SvgHandler( QObject* parent ) 0043 : QObject( parent ) 0044 , m_renderer( 0 ) 0045 , m_themeFile( "juk/pics/theme.svg" ) 0046 { 0047 } 0048 0049 SvgHandler::~SvgHandler() 0050 { 0051 delete m_renderer; 0052 0053 The::s_SvgHandler_instance = 0; 0054 } 0055 0056 0057 bool SvgHandler::loadSvg( const QString& name ) 0058 { 0059 const QString &svgFilename = 0060 QStandardPaths::locate( QStandardPaths::GenericDataLocation, name ); 0061 QSvgRenderer *renderer = new QSvgRenderer( svgFilename, this ); 0062 0063 if ( !renderer->isValid() ) 0064 { 0065 delete renderer; 0066 return false; 0067 } 0068 QWriteLocker writeLocker( &m_lock ); 0069 0070 if( m_renderer ) 0071 delete m_renderer; 0072 0073 m_renderer = renderer; 0074 return true; 0075 } 0076 0077 QSvgRenderer * SvgHandler::getRenderer() 0078 { 0079 QReadLocker readLocker( &m_lock ); 0080 if( ! m_renderer ) 0081 { 0082 readLocker.unlock(); 0083 if( !loadSvg( m_themeFile ) ) 0084 { 0085 QWriteLocker writeLocker( &m_lock ); 0086 m_renderer = new QSvgRenderer( this ); 0087 } 0088 readLocker.relock(); 0089 } 0090 return m_renderer; 0091 } 0092 0093 QPixmap SvgHandler::renderSvg( const QString& keyname, 0094 int width, 0095 int height, 0096 const QString& element ) 0097 { 0098 QString key = keyname % QChar( ':' ) % QString::number( width ) % 0099 QChar( 'x' ) % QString::number( height ); 0100 0101 QPixmap pixmap; 0102 QMap<QString, QPixmap>::const_iterator it = m_cache.constFind( key ); 0103 if( it != m_cache.constEnd() ) 0104 { 0105 pixmap = *it; 0106 } 0107 else 0108 { 0109 pixmap = QPixmap( width * dpr, height * dpr ); 0110 pixmap.setDevicePixelRatio(dpr); 0111 pixmap.fill( Qt::transparent ); 0112 0113 QReadLocker readLocker( &m_lock ); 0114 if( ! m_renderer ) 0115 { 0116 readLocker.unlock(); 0117 if( !loadSvg( m_themeFile ) ) 0118 { 0119 return pixmap; 0120 } 0121 readLocker.relock(); 0122 } 0123 0124 QPainter pt( &pixmap ); 0125 if ( element.isEmpty() ) 0126 m_renderer->render( &pt, QRectF( 0, 0, width, height ) ); 0127 else { 0128 m_renderer->render( &pt, element, QRectF( 0, 0, width, height ) ); 0129 } 0130 0131 m_cache.insert( key, pixmap ); 0132 } 0133 0134 return pixmap; 0135 } 0136 0137 void SvgHandler::reTint() 0138 { 0139 // The::svgTinter()->init(); 0140 if ( !loadSvg( m_themeFile )) 0141 qCDebug(JUK_LOG) << "Unable to load theme file: " << m_themeFile; 0142 emit retinted(); 0143 } 0144 0145 QString SvgHandler::themeFile() 0146 { 0147 return m_themeFile; 0148 } 0149 0150 QRectF SvgHandler::sliderKnobRect( const QRectF &slider, qreal percent, bool inverse ) const 0151 { 0152 if ( inverse ) 0153 percent = 1.0 - percent; 0154 const int knobSize = slider.height() - 4; 0155 QRectF ret( 0, 0, knobSize, knobSize ); 0156 ret.moveTo( slider.x() + qRound( ( slider.width() - knobSize ) * percent ), slider.y() + 1 ); 0157 return ret; 0158 } 0159 0160 // Experimental, using a mockup from Nuno Pinheiro (new_slider_nuno) 0161 void SvgHandler::paintCustomSlider( QPainter *p, QStyleOptionSlider *slider, qreal percentage ) 0162 { 0163 qreal sliderHeight = slider->rect.height() - 6; 0164 const bool inverse = ( slider->orientation == Qt::Vertical ) ? slider->upsideDown : 0165 ( (slider->direction == Qt::RightToLeft) != slider->upsideDown ); 0166 QRectF knob = sliderKnobRect( slider->rect, percentage, inverse ); 0167 QPointF pt = slider->rect.topLeft() + QPointF( 0, 2 ); 0168 0169 //debug() << "rel: " << knobRelPos << ", width: " << width << ", height:" << height << ", %: " << percentage; 0170 0171 // Draw the slider background in 3 parts 0172 0173 p->drawPixmap( pt, renderSvg( "progress_slider_left", sliderHeight, sliderHeight, "progress_slider_left" ) ); 0174 0175 pt.rx() += sliderHeight; 0176 QRectF midRect(pt, QSize(slider->rect.width() - sliderHeight * 2, sliderHeight) ); 0177 p->drawTiledPixmap( midRect, renderSvg( "progress_slider_mid", 32, sliderHeight, "progress_slider_mid" ) ); 0178 0179 pt = midRect.topRight() + QPoint( 1, 0 ); 0180 p->drawPixmap( pt, renderSvg( "progress_slider_right", sliderHeight, sliderHeight, "progress_slider_right" ) ); 0181 0182 //draw the played background. 0183 0184 qreal playedBarHeight = sliderHeight - 6; 0185 qreal min = 0; 0186 0187 qreal sizeOfLeftPlayed = qBound( min, inverse ? slider->rect.right() - knob.right() + 2 : 0188 knob.x() - 2, playedBarHeight ); 0189 0190 if( sizeOfLeftPlayed > 0 ) 0191 { 0192 QPointF tl, br; 0193 if ( inverse ) 0194 { 0195 tl = knob.topRight() + QPointF( -5, 5 ); // 5px x padding to avoid a "gap" between it and the top and bottom of the round knob. 0196 br = slider->rect.topRight() + QPointF( -3, 5 + playedBarHeight - 1 ); 0197 QPixmap rightEnd = renderSvg( "progress_slider_played_right", playedBarHeight, playedBarHeight, "progress_slider_played_right" ); 0198 p->drawPixmap( br.x() - rightEnd.width() + 1, tl.y(), rightEnd, qMax(qreal(0), rightEnd.width() - (sizeOfLeftPlayed + 3)), 0, sizeOfLeftPlayed + 3, playedBarHeight ); 0199 br.rx() -= playedBarHeight; 0200 } 0201 else 0202 { 0203 tl = slider->rect.topLeft() + QPointF( 3, 5 ); 0204 br = QPointF( knob.x() + 5, tl.y() + playedBarHeight - 1 ); 0205 QPixmap leftEnd = renderSvg( "progress_slider_played_left", playedBarHeight, playedBarHeight, "progress_slider_played_left" ); 0206 p->drawPixmap( tl.x(), tl.y(), leftEnd, 0, 0, sizeOfLeftPlayed + 3, playedBarHeight ); 0207 tl.rx() += playedBarHeight; 0208 } 0209 if ( sizeOfLeftPlayed == playedBarHeight ) 0210 p->drawTiledPixmap( QRectF(tl, br), renderSvg( "progress_slider_played_mid", 32, playedBarHeight, "progress_slider_played_mid" ) ); 0211 0212 } 0213 0214 if ( slider->state & QStyle::State_Enabled ) 0215 { // Draw the knob (handle) 0216 const char *string = ( slider->activeSubControls & QStyle::SC_SliderHandle ) ? 0217 "slider_knob_200911_active" : "slider_knob_200911"; 0218 p->drawPixmap( knob.topLeft(), renderSvg( string, knob.width(), knob.height(), string ) ); 0219 } 0220 } 0221 0222 void SvgHandler::setDevicePixelRatioF(qreal dpr) 0223 { 0224 this->dpr = dpr; 0225 }