kde-extraapps/juk/svghandler.cpp
2014-11-28 15:08:46 +00:00

226 lines
7.1 KiB
C++

/**
* Copyright (c) 2008 Nikolaj Hald Nielsen <nhn@kde.org>
* Copyright (c) 2008 Jeff Mitchell <kde-dev@emailgoeshere.com>
* Copyright (c) 2009 Mark Kretschmann <kretschmann@kde.org>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "svghandler.h"
#include <KColorScheme>
#include <KColorUtils>
#include <KStandardDirs>
#include <KDebug>
#include <QHash>
#include <QPainter>
#include <QPalette>
#include <QReadLocker>
#include <QStringBuilder>
#include <QStyleOptionSlider>
#include <QSvgRenderer>
#include <QWriteLocker>
namespace The {
static SvgHandler* s_SvgHandler_instance = 0;
SvgHandler* svgHandler()
{
if( !s_SvgHandler_instance )
s_SvgHandler_instance = new SvgHandler();
return s_SvgHandler_instance;
}
}
SvgHandler::SvgHandler( QObject* parent )
: QObject( parent )
, m_renderer( 0 )
, m_themeFile( "juk/pics/theme.svg" )
{
}
SvgHandler::~SvgHandler()
{
delete m_renderer;
The::s_SvgHandler_instance = 0;
}
bool SvgHandler::loadSvg( const QString& name )
{
const QString &svgFilename = KStandardDirs::locate( "data", name );
QSvgRenderer *renderer = new QSvgRenderer( svgFilename, this );
if ( !renderer->isValid() )
{
delete renderer;
return false;
}
QWriteLocker writeLocker( &m_lock );
if( m_renderer )
delete m_renderer;
m_renderer = renderer;
return true;
}
QSvgRenderer * SvgHandler::getRenderer()
{
QReadLocker readLocker( &m_lock );
if( ! m_renderer )
{
readLocker.unlock();
if( !loadSvg( m_themeFile ) )
{
QWriteLocker writeLocker( &m_lock );
m_renderer = new QSvgRenderer( this );
}
readLocker.relock();
}
return m_renderer;
}
QPixmap SvgHandler::renderSvg( const QString& keyname,
int width,
int height,
const QString& element )
{
QString key = keyname % QChar( ':' ) % QString::number( width ) %
QChar( 'x' ) % QString::number( height );
QPixmap pixmap;
QMap<QString, QPixmap>::const_iterator it = m_cache.constFind( key );
if( it != m_cache.constEnd() )
{
pixmap = *it;
}
else
{
pixmap = QPixmap( width, height );
pixmap.fill( Qt::transparent );
QReadLocker readLocker( &m_lock );
if( ! m_renderer )
{
readLocker.unlock();
if( !loadSvg( m_themeFile ) )
{
return pixmap;
}
readLocker.relock();
}
QPainter pt( &pixmap );
if ( element.isEmpty() )
m_renderer->render( &pt, QRectF( 0, 0, width, height ) );
else {
m_renderer->render( &pt, element, QRectF( 0, 0, width, height ) );
}
m_cache.insert( key, pixmap );
}
return pixmap;
}
void SvgHandler::reTint()
{
// The::svgTinter()->init();
if ( !loadSvg( m_themeFile ))
kDebug() << "Unable to load theme file: " << m_themeFile;
emit retinted();
}
QString SvgHandler::themeFile()
{
return m_themeFile;
}
QRect SvgHandler::sliderKnobRect( const QRect &slider, qreal percent, bool inverse ) const
{
if ( inverse )
percent = 1.0 - percent;
const int knobSize = slider.height() - 4;
QRect ret( 0, 0, knobSize, knobSize );
ret.moveTo( slider.x() + qRound( ( slider.width() - knobSize ) * percent ), slider.y() + 1 );
return ret;
}
// Experimental, using a mockup from Nuno Pinheiro (new_slider_nuno)
void SvgHandler::paintCustomSlider( QPainter *p, QStyleOptionSlider *slider, qreal percentage )
{
int sliderHeight = slider->rect.height() - 6;
const bool inverse = ( slider->orientation == Qt::Vertical ) ? slider->upsideDown :
( (slider->direction == Qt::RightToLeft) != slider->upsideDown );
QRect knob = sliderKnobRect( slider->rect, percentage, inverse );
QPoint pt = slider->rect.topLeft() + QPoint( 0, 2 );
//debug() << "rel: " << knobRelPos << ", width: " << width << ", height:" << height << ", %: " << percentage;
// Draw the slider background in 3 parts
p->drawPixmap( pt, renderSvg( "progress_slider_left", sliderHeight, sliderHeight, "progress_slider_left" ) );
pt.rx() += sliderHeight;
QRect midRect(pt, QSize(slider->rect.width() - sliderHeight * 2, sliderHeight) );
p->drawTiledPixmap( midRect, renderSvg( "progress_slider_mid", 32, sliderHeight, "progress_slider_mid" ) );
pt = midRect.topRight() + QPoint( 1, 0 );
p->drawPixmap( pt, renderSvg( "progress_slider_right", sliderHeight, sliderHeight, "progress_slider_right" ) );
//draw the played background.
int playedBarHeight = sliderHeight - 6;
int sizeOfLeftPlayed = qBound( 0, inverse ? slider->rect.right() - knob.right() + 2 :
knob.x() - 2, playedBarHeight );
if( sizeOfLeftPlayed > 0 )
{
QPoint tl, br;
if ( inverse )
{
tl = knob.topRight() + QPoint( -5, 5 ); // 5px x padding to avoid a "gap" between it and the top and bottom of the round knob.
br = slider->rect.topRight() + QPoint( -3, 5 + playedBarHeight - 1 );
QPixmap rightEnd = renderSvg( "progress_slider_played_right", playedBarHeight, playedBarHeight, "progress_slider_played_right" );
p->drawPixmap( br.x() - rightEnd.width() + 1, tl.y(), rightEnd, qMax(0, rightEnd.width() - (sizeOfLeftPlayed + 3)), 0, sizeOfLeftPlayed + 3, playedBarHeight );
br.rx() -= playedBarHeight;
}
else
{
tl = slider->rect.topLeft() + QPoint( 3, 5 );
br = QPoint( knob.x() + 5, tl.y() + playedBarHeight - 1 );
QPixmap leftEnd = renderSvg( "progress_slider_played_left", playedBarHeight, playedBarHeight, "progress_slider_played_left" );
p->drawPixmap( tl.x(), tl.y(), leftEnd, 0, 0, sizeOfLeftPlayed + 3, playedBarHeight );
tl.rx() += playedBarHeight;
}
if ( sizeOfLeftPlayed == playedBarHeight )
p->drawTiledPixmap( QRect(tl, br), renderSvg( "progress_slider_played_mid", 32, playedBarHeight, "progress_slider_played_mid" ) );
}
if ( slider->state & QStyle::State_Enabled )
{ // Draw the knob (handle)
const char *string = ( slider->activeSubControls & QStyle::SC_SliderHandle ) ?
"slider_knob_200911_active" : "slider_knob_200911";
p->drawPixmap( knob.topLeft(), renderSvg( string, knob.width(), knob.height(), string ) );
}
}
#include "svghandler.moc"