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 "QskPushButton.h"
|
|
|
|
#include "QskAspect.h"
|
2017-10-17 17:34:00 +02:00
|
|
|
#include "QskBoxShapeMetrics.h"
|
2018-08-03 08:15:28 +02:00
|
|
|
#include "QskCorner.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
#include "QskGraphic.h"
|
|
|
|
#include "QskGraphicProvider.h"
|
|
|
|
#include "QskSetup.h"
|
2018-08-03 08:15:28 +02:00
|
|
|
#include "QskSkin.h"
|
2017-11-17 08:03:38 +01:00
|
|
|
#include "QskSkinlet.h"
|
2018-08-03 08:15:28 +02:00
|
|
|
#include "QskTextOptions.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-07-19 14:10:48 +02:00
|
|
|
#include <qfontmetrics.h>
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
QSK_SUBCONTROL( QskPushButton, Panel )
|
|
|
|
QSK_SUBCONTROL( QskPushButton, Text )
|
|
|
|
QSK_SUBCONTROL( QskPushButton, Graphic )
|
|
|
|
|
|
|
|
class QskPushButton::PrivateData
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
public:
|
|
|
|
PrivateData( const QString& txt )
|
|
|
|
: text( txt )
|
2018-11-26 17:52:16 +01:00
|
|
|
, graphicSourceSize( -1, -1 )
|
2018-08-03 08:15:28 +02:00
|
|
|
, isGraphicSourceDirty( false )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
textOptions.setElideMode( Qt::ElideMiddle );
|
|
|
|
}
|
|
|
|
|
|
|
|
QString text;
|
|
|
|
QskTextOptions textOptions;
|
|
|
|
|
|
|
|
QUrl graphicSource;
|
|
|
|
QskGraphic graphic;
|
|
|
|
|
2018-11-26 17:52:16 +01:00
|
|
|
QSizeF graphicSourceSize;
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
bool isGraphicSourceDirty : 1;
|
|
|
|
};
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskPushButton::QskPushButton( QQuickItem* parent )
|
|
|
|
: QskPushButton( QString(), parent )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskPushButton::QskPushButton( 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
|
|
|
}
|
|
|
|
|
|
|
|
QskPushButton::~QskPushButton()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskPushButton::setCorner( const QskCorner& corner )
|
|
|
|
{
|
|
|
|
using namespace QskAspect;
|
2017-10-17 17:34:00 +02:00
|
|
|
const Aspect aspect = Panel | Shape;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
if ( corner.metrics() != boxShapeHint( aspect ) )
|
|
|
|
{
|
|
|
|
setBoxShapeHint( aspect, corner.metrics() );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
update();
|
|
|
|
Q_EMIT cornerChanged();
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QskCorner QskPushButton::corner() const
|
|
|
|
{
|
|
|
|
using namespace QskAspect;
|
2017-10-17 17:34:00 +02:00
|
|
|
const Aspect aspect = Panel | Shape;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
const auto shape = boxShapeHint( aspect );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
#if 1
|
|
|
|
QskCorner corner;
|
|
|
|
corner.setRadius( shape.radius( Qt::TopLeftCorner ).width() );
|
|
|
|
corner.setSizeMode( shape.sizeMode() );
|
|
|
|
corner.setAspectRatioMode( shape.aspectRatioMode() );
|
|
|
|
#endif
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
return corner;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskPushButton::setFlat( bool on )
|
|
|
|
{
|
|
|
|
if ( on != isFlat() )
|
|
|
|
{
|
|
|
|
setSkinStateFlag( Flat, on );
|
|
|
|
Q_EMIT flatChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskPushButton::isFlat() const
|
|
|
|
{
|
|
|
|
return skinState() & Flat;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskPushButton::setText( const QString& text )
|
|
|
|
{
|
|
|
|
if ( text != m_data->text )
|
|
|
|
{
|
|
|
|
m_data->text = text;
|
|
|
|
|
|
|
|
resetImplicitSize();
|
|
|
|
update();
|
|
|
|
|
|
|
|
Q_EMIT textChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QString QskPushButton::text() const
|
|
|
|
{
|
|
|
|
return m_data->text;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskPushButton::setTextOptions( const QskTextOptions& options )
|
|
|
|
{
|
|
|
|
if ( options != m_data->textOptions )
|
|
|
|
{
|
|
|
|
m_data->textOptions = options;
|
|
|
|
|
|
|
|
resetImplicitSize();
|
|
|
|
update();
|
|
|
|
|
|
|
|
Q_EMIT textOptionsChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QskTextOptions QskPushButton::textOptions() const
|
|
|
|
{
|
|
|
|
return m_data->textOptions;
|
|
|
|
}
|
|
|
|
|
|
|
|
QFont QskPushButton::font() const
|
|
|
|
{
|
|
|
|
return effectiveFont( QskPushButton::Text );
|
|
|
|
}
|
|
|
|
|
2018-11-26 17:52:16 +01:00
|
|
|
void QskPushButton::resetGraphicSourceSize()
|
|
|
|
{
|
|
|
|
setGraphicSourceSize( QSizeF( -1.0, -1.0 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskPushButton::setGraphicSourceSize( const QSizeF& size )
|
|
|
|
{
|
|
|
|
auto newSize = size;
|
|
|
|
if ( newSize.width() < 0.0 )
|
|
|
|
newSize.setWidth( -1.0 );
|
|
|
|
|
|
|
|
if ( newSize.height() < 0.0 )
|
|
|
|
newSize.setHeight( -1.0 );
|
|
|
|
|
|
|
|
if ( size != m_data->graphicSourceSize )
|
|
|
|
{
|
|
|
|
m_data->graphicSourceSize = size;
|
|
|
|
|
|
|
|
resetImplicitSize();
|
|
|
|
polish();
|
|
|
|
update();
|
|
|
|
|
|
|
|
Q_EMIT graphicSourceSizeChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QSizeF QskPushButton::graphicSourceSize() const
|
|
|
|
{
|
|
|
|
return m_data->graphicSourceSize;
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
void QskPushButton::setGraphicSource( const QUrl& url )
|
|
|
|
{
|
|
|
|
if ( m_data->graphicSource == url )
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_data->graphicSource = url;
|
|
|
|
m_data->graphic.reset();
|
|
|
|
|
|
|
|
m_data->isGraphicSourceDirty = true;
|
|
|
|
|
|
|
|
resetImplicitSize();
|
|
|
|
polish();
|
|
|
|
update();
|
|
|
|
|
|
|
|
Q_EMIT graphicSourceChanged();
|
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
void QskPushButton::setGraphicSource( const QString& source )
|
2018-06-07 07:24:34 +02:00
|
|
|
{
|
|
|
|
setGraphicSource( QUrl( source ) );
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
QUrl QskPushButton::graphicSource() const
|
|
|
|
{
|
|
|
|
return m_data->graphicSource;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskPushButton::setGraphic( const QskGraphic& graphic )
|
|
|
|
{
|
|
|
|
if ( graphic != m_data->graphic )
|
|
|
|
{
|
|
|
|
m_data->graphic = graphic;
|
|
|
|
|
|
|
|
if ( !m_data->graphicSource.isEmpty() )
|
|
|
|
{
|
2018-01-16 20:34:54 +01:00
|
|
|
m_data->graphicSource = QString();
|
2017-07-21 18:21:34 +02:00
|
|
|
m_data->isGraphicSourceDirty = false;
|
|
|
|
|
|
|
|
Q_EMIT graphicSourceChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
Q_EMIT graphicChanged();
|
|
|
|
|
|
|
|
resetImplicitSize();
|
|
|
|
polish();
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QskGraphic QskPushButton::graphic() const
|
|
|
|
{
|
|
|
|
return m_data->graphic;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskPushButton::hasGraphic() const
|
|
|
|
{
|
|
|
|
return !( graphic().isEmpty() && graphicSource().isEmpty() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskPushButton::updateLayout()
|
|
|
|
{
|
|
|
|
if ( m_data->isGraphicSourceDirty )
|
|
|
|
{
|
|
|
|
if ( !m_data->graphicSource.isEmpty() )
|
|
|
|
m_data->graphic = loadGraphic( m_data->graphicSource );
|
|
|
|
|
|
|
|
m_data->isGraphicSourceDirty = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-17 08:03:38 +01:00
|
|
|
QRectF QskPushButton::layoutRect() const
|
|
|
|
{
|
|
|
|
return innerBox( Panel, effectiveSkinlet()->subControlRect( this, Panel ) );
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
QSizeF QskPushButton::contentsSizeHint() const
|
|
|
|
{
|
|
|
|
QSizeF size( 0, 0 );
|
|
|
|
|
2018-11-26 17:52:16 +01:00
|
|
|
const QFontMetricsF fm( font() );
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
if ( !m_data->text.isEmpty() )
|
|
|
|
{
|
|
|
|
// in elide mode we might want to ignore the text width ???
|
|
|
|
|
|
|
|
size += fm.size( Qt::TextShowMnemonic, m_data->text );
|
|
|
|
}
|
|
|
|
|
2018-11-26 17:52:16 +01:00
|
|
|
if ( m_data->isGraphicSourceDirty )
|
|
|
|
{
|
|
|
|
if ( !m_data->graphicSource.isEmpty() )
|
|
|
|
m_data->graphic = loadGraphic( m_data->graphicSource );
|
2019-01-04 13:42:16 +01:00
|
|
|
|
2018-11-26 17:52:16 +01:00
|
|
|
m_data->isGraphicSourceDirty = false;
|
2019-01-04 13:42:16 +01:00
|
|
|
}
|
2018-11-26 17:52:16 +01:00
|
|
|
|
|
|
|
if ( !m_data->graphic.isEmpty() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-11-26 17:52:16 +01:00
|
|
|
qreal w = m_data->graphicSourceSize.width();
|
|
|
|
qreal h = m_data->graphicSourceSize.height();
|
|
|
|
|
|
|
|
if ( ( w < 0.0 ) && ( h < 0.0 ) )
|
|
|
|
h = 1.5 * fm.height();
|
|
|
|
|
|
|
|
if ( w < 0 )
|
|
|
|
w = m_data->graphic.widthForHeight( h );
|
|
|
|
else if ( h < 0 )
|
|
|
|
h = m_data->graphic.heightForWidth( w );
|
|
|
|
|
|
|
|
const qreal padding = 2.0; // Graphic::Padding ???
|
|
|
|
|
|
|
|
size.rheight() += 2 * padding + h;
|
|
|
|
size.rwidth() = qMax( size.width(), w );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const QSizeF minSize( metric( Panel | QskAspect::MinimumWidth ),
|
|
|
|
metric( Panel | QskAspect::MinimumHeight ) );
|
|
|
|
|
|
|
|
size = size.expandedTo( minSize );
|
|
|
|
size = outerBoxSize( Panel, size );
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskPushButton::changeEvent( QEvent* event )
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
switch ( event->type() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
case QEvent::StyleChange:
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( !m_data->graphicSource.isEmpty() &&
|
|
|
|
qskSetup->skin()->hasGraphicProvider() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
// we might need to reload from a different skin
|
|
|
|
m_data->isGraphicSourceDirty = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QEvent::LocaleChange:
|
|
|
|
{
|
|
|
|
if ( !m_data->text.isEmpty() )
|
|
|
|
{
|
|
|
|
// maybe QLocale::textDirection() has changed
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Inherited::changeEvent( event );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskPushButton::hoverEnterEvent( QHoverEvent* event )
|
|
|
|
{
|
|
|
|
Inherited::hoverEnterEvent( event );
|
|
|
|
Q_EMIT hovered( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskPushButton::hoverLeaveEvent( QHoverEvent* event )
|
|
|
|
{
|
|
|
|
Inherited::hoverLeaveEvent( event );
|
|
|
|
Q_EMIT hovered( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
QskGraphic QskPushButton::loadGraphic( const QUrl& url ) const
|
|
|
|
{
|
|
|
|
return Qsk::loadGraphic( url );
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "moc_QskPushButton.cpp"
|