qskinny/src/controls/QskGraphicLabel.cpp

332 lines
7.2 KiB
C++
Raw Normal View History

2017-07-21 18:21:34 +02:00
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskGraphicLabel.h"
#include "QskGraphic.h"
#include "QskGraphicProvider.h"
#include "QskGraphicTextureFactory.h"
#include "QskAspect.h"
#include "QskSetup.h"
#include "QskSkin.h"
#include <QtMath>
QSK_SUBCONTROL( QskGraphicLabel, Graphic )
class QskGraphicLabel::PrivateData
{
public:
PrivateData( const QUrl& sourceUrl ):
source( sourceUrl ),
sourceSize( -1, -1 ),
alignment( Qt::AlignLeft | Qt::AlignVCenter ),
fillMode( QskGraphicLabel::PreserveAspectFit ),
mirror( false ),
isSourceDirty( !sourceUrl.isEmpty() )
{
}
QUrl source;
QSize sourceSize;
QskGraphic graphic;
Qt::Alignment alignment;
uint fillMode : 2;
bool mirror : 1;
bool isSourceDirty : 1;
};
QskGraphicLabel::QskGraphicLabel( const QUrl& source, QQuickItem* parent ):
Inherited( parent ),
m_data( new PrivateData( source ) )
{
setSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Expanding );
if ( !m_data->source.isEmpty() )
polish();
}
QskGraphicLabel::QskGraphicLabel( QQuickItem* parent ):
QskGraphicLabel( QUrl(), parent )
{
}
QskGraphicLabel::QskGraphicLabel( const QString& source, QQuickItem* parent ):
QskGraphicLabel( QUrl( source ), parent )
{
}
QskGraphicLabel::QskGraphicLabel( const QskGraphic& graphic, QQuickItem* parent ):
QskGraphicLabel( parent )
{
m_data->graphic = graphic;
}
QskGraphicLabel::~QskGraphicLabel()
{
}
bool QskGraphicLabel::isEmpty() const
{
return m_data->graphic.isNull() && m_data->source.isEmpty();
}
QUrl QskGraphicLabel::source() const
{
return m_data->source;
}
void QskGraphicLabel::setSource( const QUrl& url )
{
if ( url == m_data->source )
return;
m_data->graphic.reset();
m_data->isSourceDirty = true;
m_data->source = url;
resetImplicitSize();
polish();
update();
Q_EMIT sourceChanged();
}
QskGraphic QskGraphicLabel::graphic() const
{
return m_data->graphic;
}
void QskGraphicLabel::setGraphic( const QskGraphic& graphic )
{
if ( m_data->graphic != graphic )
{
m_data->graphic = graphic;
resetImplicitSize();
update();
}
// in case we have a sequence setting a source and a graphic later
m_data->isSourceDirty = false;
if ( !m_data->source.isEmpty() )
{
m_data->source.clear();
Q_EMIT sourceChanged();
}
}
void QskGraphicLabel::setGraphicRole( int role )
{
const int oldRole = graphicRole();
QskSkinnable::setGraphicRole( effectiveSubcontrol( Graphic ), role );
if ( role != oldRole )
{
update();
Q_EMIT graphicRoleChanged();
}
}
int QskGraphicLabel::graphicRole() const
{
return QskSkinnable::graphicRole( Graphic );
}
2017-07-21 18:21:34 +02:00
QskColorFilter QskGraphicLabel::graphicFilter() const
{
// can be removed once we can store a filter inidividually
// for a skinnable
return effectiveGraphicFilter( QskGraphicLabel::Graphic );
}
void QskGraphicLabel::setMirror( bool on )
{
if ( on != m_data->mirror )
{
m_data->mirror = on;
if ( !( m_data->sourceSize.isEmpty() || m_data->graphic.isEmpty() ) )
update();
Q_EMIT mirrorChanged();
}
}
bool QskGraphicLabel::mirror() const
{
return m_data->mirror;
}
void QskGraphicLabel::setSourceSize( const QSize& size )
{
QSize sz = size;
if ( sz.width() < 0 )
sz.setWidth( -1 );
if ( sz.height() < 0 )
sz.setHeight( -1 );
if ( m_data->sourceSize != sz )
{
m_data->sourceSize = sz;
resetImplicitSize();
update();
Q_EMIT sourceSizeChanged();
}
}
QSize QskGraphicLabel::sourceSize() const
{
return m_data->sourceSize;
}
void QskGraphicLabel::resetSourceSize()
{
setSourceSize( QSize( -1, -1 ) );
}
void QskGraphicLabel::setFillMode( FillMode mode )
{
if ( mode != m_data->fillMode )
{
m_data->fillMode = mode;
if ( !m_data->graphic.isEmpty() )
update();
Q_EMIT fillModeChanged();
}
}
QskGraphicLabel::FillMode QskGraphicLabel::fillMode() const
{
return static_cast< QskGraphicLabel::FillMode >( m_data->fillMode );
}
Qt::Alignment QskGraphicLabel::alignment() const
{
return m_data->alignment;
}
void QskGraphicLabel::setAlignment( Qt::Alignment alignment )
{
if ( alignment != m_data->alignment )
{
m_data->alignment = alignment;
if ( !( m_data->sourceSize.isEmpty() || m_data->graphic.isEmpty() ) )
update();
Q_EMIT alignmentChanged();
}
}
QskGraphic QskGraphicLabel::loadSource( const QUrl& url ) const
{
return Qsk::loadGraphic( url );
}
void QskGraphicLabel::updateLayout()
{
if ( !m_data->source.isEmpty() && m_data->isSourceDirty )
m_data->graphic = loadSource( m_data->source );
m_data->isSourceDirty = false;
}
qreal QskGraphicLabel::heightForWidth( qreal width ) const
{
const QSizeF sz = effectiveSourceSize();
if ( sz.isEmpty() )
return 0;
return sz.height() * width / sz.width();
}
qreal QskGraphicLabel::widthForHeight( qreal height ) const
{
const QSizeF sz = effectiveSourceSize();
if ( sz.isEmpty() )
return 0;
return sz.width() * height / sz.height();
}
QSizeF QskGraphicLabel::contentsSizeHint() const
{
return effectiveSourceSize();
}
QSizeF QskGraphicLabel::effectiveSourceSize() const
{
const QSizeF& sourceSize = m_data->sourceSize;
if ( sourceSize.width() >= 0 && sourceSize.height() >= 0 )
{
// the size has been explicitly set
return sourceSize;
}
if ( !m_data->source.isEmpty() && m_data->isSourceDirty )
{
// we have to load to know about the geometry
m_data->graphic = loadSource( m_data->source );
m_data->isSourceDirty = false;
}
QSizeF sz( 0, 0 );
if ( !m_data->graphic.isEmpty() )
{
const QSizeF defaultSize = m_data->graphic.defaultSize();
if ( sourceSize.width() <= 0 && sourceSize.height() <= 0 )
{
// size is derived from the default size
sz = defaultSize;
}
else if ( sourceSize.width() <= 0 )
{
// only the height has been given
const qreal f = sourceSize.height() / defaultSize.height();
sz.setWidth( f * defaultSize.width() );
sz.setHeight( sourceSize.height() );
}
else
{
// only the width has been given
const qreal f = sourceSize.width() / defaultSize.width();
sz.setWidth( sourceSize.width() );
sz.setHeight( f * defaultSize.height() );
}
}
return sz;
}
void QskGraphicLabel::changeEvent( QEvent* event )
{
if ( event->type() == QEvent::StyleChange )
{
if ( !m_data->source.isEmpty() && qskSetup->skin()->hasGraphicProvider() )
{
// we might need to reload from a different skin
m_data->isSourceDirty = true;
}
}
Inherited::changeEvent( event );
}
#include "moc_QskGraphicLabel.cpp"