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 "QskTextLabel.h"
|
|
|
|
#include "QskAspect.h"
|
|
|
|
#include "QskTextOptions.h"
|
2017-10-23 07:46:46 +02:00
|
|
|
#include "QskTextRenderer.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-07-19 14:10:48 +02:00
|
|
|
#include <qfontmetrics.h>
|
|
|
|
#include <qmath.h>
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
QSK_SUBCONTROL( QskTextLabel, Text )
|
|
|
|
|
|
|
|
class QskTextLabel::PrivateData
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
public:
|
|
|
|
PrivateData( const QString& txt )
|
|
|
|
: text( txt )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-10-20 13:09:30 +02:00
|
|
|
effectiveTextFormat = textOptions.format();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2017-10-20 13:09:30 +02:00
|
|
|
QskTextOptions effectiveOptions() const
|
|
|
|
{
|
|
|
|
if ( textOptions.format() != QskTextOptions::AutoText )
|
|
|
|
return textOptions;
|
|
|
|
|
|
|
|
if ( effectiveTextFormat == QskTextOptions::AutoText )
|
2017-10-20 13:31:55 +02:00
|
|
|
effectiveTextFormat = textOptions.effectiveFormat( text );
|
2017-10-20 13:09:30 +02:00
|
|
|
|
|
|
|
QskTextOptions options = textOptions;
|
|
|
|
options.setFormat( effectiveTextFormat );
|
|
|
|
|
|
|
|
return options;
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
QString text;
|
2017-10-20 13:09:30 +02:00
|
|
|
|
|
|
|
QskTextOptions textOptions;
|
|
|
|
mutable QskTextOptions::TextFormat effectiveTextFormat;
|
2017-07-21 18:21:34 +02:00
|
|
|
};
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskTextLabel::QskTextLabel( QQuickItem* parent )
|
|
|
|
: QskTextLabel( QString(), parent )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskTextLabel::QskTextLabel( const QString& text, QQuickItem* parent )
|
|
|
|
: Inherited( parent )
|
|
|
|
, m_data( new PrivateData( text ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-08-31 09:09:05 +02:00
|
|
|
initSizePolicy( QskSizePolicy::Minimum, QskSizePolicy::Fixed );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QskTextLabel::~QskTextLabel()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskTextLabel::setText( const QString& text )
|
|
|
|
{
|
|
|
|
if ( text == m_data->text )
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_data->text = text;
|
2017-10-20 13:09:30 +02:00
|
|
|
m_data->effectiveTextFormat = m_data->textOptions.format();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
resetImplicitSize();
|
|
|
|
update();
|
|
|
|
|
|
|
|
Q_EMIT textChanged( text );
|
|
|
|
}
|
|
|
|
|
|
|
|
QString QskTextLabel::text() const
|
|
|
|
{
|
|
|
|
return m_data->text;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskTextLabel::setTextOptions( const QskTextOptions& options )
|
|
|
|
{
|
|
|
|
if ( options == m_data->textOptions )
|
|
|
|
return;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
// we are killing user settings of the policy this way ??
|
|
|
|
|
|
|
|
const QskSizePolicy::Policy policy = ( options.wrapMode() == QTextOption::NoWrap )
|
|
|
|
? QskSizePolicy::Minimum : QskSizePolicy::Preferred;
|
|
|
|
|
|
|
|
setSizePolicy( policy, sizePolicy().verticalPolicy() );
|
|
|
|
#endif
|
|
|
|
|
2017-10-20 13:09:30 +02:00
|
|
|
m_data->effectiveTextFormat = options.format();
|
2017-07-21 18:21:34 +02:00
|
|
|
m_data->textOptions = options;
|
|
|
|
|
|
|
|
resetImplicitSize();
|
|
|
|
update();
|
|
|
|
|
2018-11-06 18:47:30 +01:00
|
|
|
Q_EMIT textOptionsChanged( options );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QskTextOptions QskTextLabel::textOptions() const
|
|
|
|
{
|
|
|
|
return m_data->textOptions;
|
|
|
|
}
|
|
|
|
|
2018-10-19 12:53:45 +02:00
|
|
|
void QskTextLabel::setTextFormat( QskTextOptions::TextFormat format )
|
|
|
|
{
|
|
|
|
auto options = m_data->textOptions;
|
|
|
|
options.setFormat( format );
|
|
|
|
|
|
|
|
setTextOptions( options );
|
|
|
|
}
|
|
|
|
|
|
|
|
QskTextOptions::TextFormat QskTextLabel::textFormat() const
|
|
|
|
{
|
|
|
|
return m_data->textOptions.format();
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskTextLabel::setWrapMode( QskTextOptions::WrapMode wrapMode )
|
|
|
|
{
|
|
|
|
auto options = m_data->textOptions;
|
|
|
|
options.setWrapMode( wrapMode );
|
|
|
|
|
|
|
|
setTextOptions( options );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
QskTextOptions::WrapMode QskTextLabel::wrapMode() const
|
|
|
|
{
|
|
|
|
return m_data->textOptions.wrapMode();
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskTextLabel::setElideMode( Qt::TextElideMode elideMode )
|
|
|
|
{
|
|
|
|
auto options = m_data->textOptions;
|
|
|
|
options.setElideMode( elideMode );
|
|
|
|
|
|
|
|
setTextOptions( options );
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt::TextElideMode QskTextLabel::elideMode() const
|
|
|
|
{
|
|
|
|
return m_data->textOptions.elideMode();
|
|
|
|
}
|
|
|
|
|
2017-08-22 20:15:11 +02:00
|
|
|
void QskTextLabel::setFontRole( int role )
|
|
|
|
{
|
|
|
|
const int oldRole = fontRole();
|
|
|
|
|
|
|
|
QskSkinnable::setFontRole( effectiveSubcontrol( Text ), role );
|
|
|
|
|
|
|
|
if ( oldRole != role )
|
|
|
|
{
|
|
|
|
resetImplicitSize();
|
|
|
|
update();
|
|
|
|
|
|
|
|
Q_EMIT fontRoleChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskTextLabel::fontRole() const
|
|
|
|
{
|
|
|
|
return QskSkinnable::fontRole( Text );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskTextLabel::setTextColor( const QColor& color )
|
|
|
|
{
|
|
|
|
const QColor oldColor = textColor();
|
|
|
|
|
|
|
|
QskSkinnable::setColor( effectiveSubcontrol( Text ), color );
|
|
|
|
|
|
|
|
if ( oldColor != color )
|
|
|
|
{
|
|
|
|
update();
|
2018-11-06 18:47:30 +01:00
|
|
|
Q_EMIT textColorChanged( color );
|
2017-08-22 20:15:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QColor QskTextLabel::textColor() const
|
|
|
|
{
|
|
|
|
return QskSkinnable::color( Text );
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
Qt::Alignment QskTextLabel::alignment() const
|
|
|
|
{
|
|
|
|
return flagHint< Qt::Alignment >(
|
|
|
|
Text | QskAspect::Alignment, Qt::AlignLeft | Qt::AlignTop );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskTextLabel::setAlignment( Qt::Alignment alignment )
|
|
|
|
{
|
|
|
|
if ( alignment == this->alignment() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto subControl = effectiveSubcontrol( Text );
|
|
|
|
setFlagHint( subControl | QskAspect::Alignment, alignment );
|
|
|
|
|
|
|
|
if ( m_data->text.isEmpty() )
|
|
|
|
update();
|
|
|
|
|
|
|
|
Q_EMIT alignmentChanged();
|
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QFont QskTextLabel::font() const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
return effectiveFont( QskTextLabel::Text );
|
|
|
|
}
|
|
|
|
|
|
|
|
QSizeF QskTextLabel::contentsSizeHint() const
|
|
|
|
{
|
|
|
|
if ( !m_data->text.isEmpty() )
|
|
|
|
{
|
2017-10-20 20:26:39 +02:00
|
|
|
const auto font = effectiveFont( Text );
|
2017-10-23 07:46:46 +02:00
|
|
|
return QskTextRenderer::textSize(
|
2017-10-20 20:26:39 +02:00
|
|
|
m_data->text, font, m_data->effectiveOptions() );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return QSizeF( 0, 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskTextLabel::heightForWidth( qreal width ) const
|
|
|
|
{
|
2017-10-20 20:26:39 +02:00
|
|
|
const auto font = effectiveFont( Text );
|
|
|
|
const qreal lineHeight = QFontMetricsF( font ).height();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
if ( m_data->text.isEmpty() ||
|
|
|
|
( m_data->textOptions.wrapMode() == QskTextOptions::NoWrap ) )
|
|
|
|
{
|
|
|
|
return lineHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal maxHeight = std::numeric_limits< qreal >::max();
|
|
|
|
if ( maxHeight / lineHeight > m_data->textOptions.maximumLineCount() )
|
|
|
|
{
|
|
|
|
// be careful with overflows
|
|
|
|
maxHeight = m_data->textOptions.maximumLineCount() * lineHeight;
|
|
|
|
}
|
|
|
|
|
2017-10-20 20:26:39 +02:00
|
|
|
QSizeF size( width, maxHeight );
|
2018-08-03 08:15:28 +02:00
|
|
|
size = QskTextRenderer::textSize(
|
|
|
|
m_data->text, font, m_data->effectiveOptions(), size );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
return qCeil( size.height() );
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskTextLabel::widthForHeight( qreal height ) const
|
|
|
|
{
|
|
|
|
if ( m_data->text.isEmpty() ||
|
|
|
|
( m_data->textOptions.wrapMode() == QskTextOptions::NoWrap ) )
|
|
|
|
{
|
|
|
|
return Inherited::widthForHeight( height );
|
|
|
|
}
|
|
|
|
|
2017-10-20 20:26:39 +02:00
|
|
|
const auto font = effectiveFont( Text );
|
2017-07-21 18:21:34 +02:00
|
|
|
const qreal maxWidth = std::numeric_limits< qreal >::max();
|
|
|
|
|
2017-10-20 20:26:39 +02:00
|
|
|
QSizeF size( maxWidth, height );
|
2017-10-23 07:46:46 +02:00
|
|
|
size = QskTextRenderer::textSize( m_data->text, font,
|
|
|
|
m_data->effectiveOptions(), size );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
return qCeil( size.width() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskTextLabel::changeEvent( QEvent* event )
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
switch ( event->type() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
case QEvent::LocaleChange:
|
|
|
|
{
|
|
|
|
if ( !m_data->text.isEmpty() )
|
|
|
|
{
|
|
|
|
// maybe Qt::LayoutDirection has changed
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Inherited::changeEvent( event );
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "moc_QskTextLabel.cpp"
|