qskinny/src/controls/QskTextLabel.cpp

296 lines
6.8 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 "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
{
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;
}
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 );
2019-01-04 13:42:16 +01:00
setTextOptions( options );
}
Qt::TextElideMode QskTextLabel::elideMode() const
{
return m_data->textOptions.elideMode();
}
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 );
}
}
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(
Qt::SizeHint which, const QSizeF& constraint ) const
2017-07-21 18:21:34 +02:00
{
if ( which != Qt::PreferredSize )
return QSizeF();
2017-07-21 18:21:34 +02:00
2017-10-20 20:26:39 +02:00
const auto font = effectiveFont( Text );
2017-07-21 18:21:34 +02:00
QSizeF hint;
2018-12-13 11:29:40 +01:00
const qreal lineHeight = QFontMetricsF( font ).height();
2018-12-13 11:29:40 +01:00
if ( m_data->text.isEmpty() )
2017-07-21 18:21:34 +02:00
{
if ( constraint.height() < 0.0 )
hint.setHeight( qCeil( lineHeight ) );
2017-07-21 18:21:34 +02:00
}
else if ( constraint.width() >= 0.0 )
2017-07-21 18:21:34 +02:00
{
if ( m_data->textOptions.effectiveElideMode() != Qt::ElideNone )
2018-12-13 11:29:40 +01:00
{
hint.setHeight( qCeil( lineHeight ) );
2018-12-13 11:29:40 +01:00
}
else
{
/*
In case of QskTextOptions::NoWrap we could count
the line numbers and calculate the height from
lineHeight. TODO ...
*/
qreal maxHeight = std::numeric_limits< qreal >::max();
if ( maxHeight / lineHeight > m_data->textOptions.maximumLineCount() )
{
// be careful with overflows
maxHeight = m_data->textOptions.maximumLineCount() * lineHeight;
}
2018-12-13 11:29:40 +01:00
QSizeF size( constraint.width(), maxHeight );
size = QskTextRenderer::textSize(
m_data->text, font, m_data->effectiveOptions(), size );
2018-12-13 11:29:40 +01:00
hint.setHeight( qCeil( size.height() ) );
}
2018-12-13 11:29:40 +01:00
}
else if ( constraint.height() >= 0.0 )
{
const qreal maxWidth = std::numeric_limits< qreal >::max();
2017-07-21 18:21:34 +02:00
QSizeF size( maxWidth, constraint.height() );
size = QskTextRenderer::textSize( m_data->text, font,
m_data->effectiveOptions(), size );
2017-07-21 18:21:34 +02:00
hint.setWidth( qCeil( size.width() ) );
}
else
2017-07-21 18:21:34 +02:00
{
hint = QskTextRenderer::textSize(
m_data->text, font, m_data->effectiveOptions() );
2017-07-21 18:21:34 +02:00
}
return hint;
2017-07-21 18:21:34 +02:00
}
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"