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 }