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 "QskControl.h"
|
2019-09-04 06:59:43 +02:00
|
|
|
#include "QskControlPrivate.h"
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
#include "QskAspect.h"
|
2019-04-24 08:39:13 +02:00
|
|
|
#include "QskFunctions.h"
|
2018-08-03 08:15:28 +02:00
|
|
|
#include "QskEvent.h"
|
|
|
|
#include "QskQuick.h"
|
|
|
|
#include "QskSetup.h"
|
2018-07-19 14:10:48 +02:00
|
|
|
#include "QskSkin.h"
|
2019-04-25 14:23:39 +02:00
|
|
|
#include "QskSkinlet.h"
|
2018-08-03 08:15:28 +02:00
|
|
|
#include "QskSkinHintTable.h"
|
2020-10-28 19:35:51 +01:00
|
|
|
#include "QskMargins.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-07-19 14:10:48 +02:00
|
|
|
#include <qlocale.h>
|
|
|
|
#include <qvector.h>
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2019-04-02 17:50:08 +02:00
|
|
|
QSK_SYSTEM_STATE( QskControl, Disabled, QskAspect::FirstSystemState )
|
|
|
|
QSK_SYSTEM_STATE( QskControl, Hovered, QskAspect::LastSystemState >> 1 )
|
|
|
|
QSK_SYSTEM_STATE( QskControl, Focused, QskAspect::LastSystemState )
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-12-12 20:02:48 +01:00
|
|
|
static inline void qskSendEventTo( QObject* object, QEvent::Type type )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
QEvent event( type );
|
|
|
|
QCoreApplication::sendEvent( object, &event );
|
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskControl::QskControl( QQuickItem* parent )
|
2019-09-04 06:59:43 +02:00
|
|
|
: QskQuickItem( *( new QskControlPrivate() ), parent )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2019-09-04 06:59:43 +02:00
|
|
|
Inherited::setActiveFocusOnTab( false );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
if ( parent )
|
|
|
|
{
|
|
|
|
// inheriting attributes from parent
|
2019-09-04 06:59:43 +02:00
|
|
|
QskControlPrivate::resolveLocale( this );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
2017-12-14 09:41:10 +01:00
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
QskControl::~QskControl()
|
|
|
|
{
|
2019-04-18 16:12:33 +02:00
|
|
|
#if defined( QT_DEBUG )
|
|
|
|
if ( auto w = window() )
|
|
|
|
{
|
2020-03-10 10:28:39 +01:00
|
|
|
if( this == w->mouseGrabberItem() )
|
|
|
|
{
|
|
|
|
// to catch suicide situations as a result of mouse clicks
|
|
|
|
qWarning() << "QskControl::~QskControl: probably suicide situation detected, control is the mouse grabber item" << this;
|
|
|
|
}
|
|
|
|
|
2019-04-18 16:12:33 +02:00
|
|
|
}
|
|
|
|
#endif
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setAutoFillBackground( bool on )
|
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
Q_D( QskControl );
|
|
|
|
if ( on != d->autoFillBackground )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
d->autoFillBackground = on;
|
2017-07-21 18:21:34 +02:00
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskControl::autoFillBackground() const
|
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
return d_func()->autoFillBackground;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setAutoLayoutChildren( bool on )
|
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
Q_D( QskControl );
|
|
|
|
if ( on != d->autoLayoutChildren )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
d->autoLayoutChildren = on;
|
2017-07-21 18:21:34 +02:00
|
|
|
if ( on )
|
|
|
|
polish();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskControl::autoLayoutChildren() const
|
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
return d_func()->autoLayoutChildren;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2017-10-24 19:32:54 +02:00
|
|
|
void QskControl::setWheelEnabled( bool on )
|
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
Q_D( QskControl );
|
|
|
|
if ( on != d->isWheelEnabled )
|
2017-10-24 19:32:54 +02:00
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
d->isWheelEnabled = on;
|
|
|
|
Q_EMIT wheelEnabledChanged();
|
2017-10-24 19:32:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskControl::isWheelEnabled() const
|
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
return d_func()->isWheelEnabled;
|
2017-10-24 19:32:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setFocusPolicy( Qt::FocusPolicy policy )
|
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
Q_D( QskControl );
|
|
|
|
if ( policy != d->focusPolicy )
|
2017-10-24 19:32:54 +02:00
|
|
|
{
|
2019-09-04 06:59:43 +02:00
|
|
|
d->focusPolicy = ( policy & ~Qt::TabFocus );
|
2020-07-25 18:53:43 +02:00
|
|
|
|
|
|
|
const bool tabFocus = policy & Qt::TabFocus;
|
|
|
|
|
|
|
|
if ( !tabFocus && window() )
|
|
|
|
{
|
|
|
|
// Removing the activeFocusItem from the focus tab chain is not possible
|
|
|
|
if ( window()->activeFocusItem() == this )
|
|
|
|
{
|
|
|
|
if ( auto focusItem = nextItemInFocusChain( true ) )
|
|
|
|
focusItem->setFocus( true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Inherited::setActiveFocusOnTab( tabFocus );
|
2017-10-24 19:32:54 +02:00
|
|
|
|
2017-10-30 08:33:43 +01:00
|
|
|
Q_EMIT focusPolicyChanged();
|
2017-10-24 19:32:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt::FocusPolicy QskControl::focusPolicy() const
|
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
uint policy = d_func()->focusPolicy;
|
2019-09-04 06:59:43 +02:00
|
|
|
if ( Inherited::activeFocusOnTab() )
|
2017-10-24 19:32:54 +02:00
|
|
|
policy |= Qt::TabFocus;
|
|
|
|
|
|
|
|
return static_cast< Qt::FocusPolicy >( policy );
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
void QskControl::setBackgroundColor( const QColor& color )
|
|
|
|
{
|
|
|
|
setAutoFillBackground( true );
|
2017-10-17 17:34:00 +02:00
|
|
|
setBackground( QskGradient( color ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setBackground( const QskGradient& gradient )
|
|
|
|
{
|
2020-12-15 07:21:12 +01:00
|
|
|
const auto aspect = QskAspect::Control | QskAspect::Color;
|
2017-10-17 17:34:00 +02:00
|
|
|
|
2017-10-30 12:06:19 +01:00
|
|
|
if ( hintTable().gradient( aspect ) != gradient )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
|
|
|
setGradientHint( aspect, gradient );
|
2017-10-30 12:06:19 +01:00
|
|
|
if ( autoFillBackground() )
|
|
|
|
update();
|
|
|
|
|
|
|
|
Q_EMIT backgroundChanged();
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::resetBackground()
|
|
|
|
{
|
2020-12-15 07:21:12 +01:00
|
|
|
if ( resetHint( QskAspect::Control | QskAspect::Color ) )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2017-10-30 12:06:19 +01:00
|
|
|
update();
|
|
|
|
Q_EMIT backgroundChanged();
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QskGradient QskControl::background() const
|
|
|
|
{
|
2020-12-15 07:21:12 +01:00
|
|
|
return gradientHint( QskAspect::Control );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setMargins( qreal margin )
|
|
|
|
{
|
|
|
|
setMargins( QMarginsF( margin, margin, margin, margin ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setMargins( const QMarginsF& margins )
|
|
|
|
{
|
|
|
|
const QMarginsF m(
|
|
|
|
qMax( qreal( margins.left() ), qreal( 0.0 ) ),
|
|
|
|
qMax( qreal( margins.top() ), qreal( 0.0 ) ),
|
|
|
|
qMax( qreal( margins.right() ), qreal( 0.0 ) ),
|
|
|
|
qMax( qreal( margins.bottom() ), qreal( 0.0 ) ) );
|
|
|
|
|
|
|
|
if ( m != this->margins() )
|
|
|
|
{
|
2019-09-20 07:08:08 +02:00
|
|
|
const auto subControl = effectiveSubcontrol( QskAspect::Control );
|
|
|
|
|
2020-12-15 07:21:12 +01:00
|
|
|
setMarginHint( subControl, m );
|
2017-07-21 18:21:34 +02:00
|
|
|
resetImplicitSize();
|
|
|
|
|
2017-10-25 14:53:49 +02:00
|
|
|
Q_D( const QskControl );
|
2019-09-04 06:59:43 +02:00
|
|
|
if ( polishOnResize() || d->autoLayoutChildren )
|
2017-07-21 18:21:34 +02:00
|
|
|
polish();
|
|
|
|
|
|
|
|
qskSendEventTo( this, QEvent::ContentsRectChange );
|
2017-10-30 08:48:49 +01:00
|
|
|
Q_EMIT marginsChanged();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::resetMargins()
|
|
|
|
{
|
2017-10-17 17:34:00 +02:00
|
|
|
using namespace QskAspect;
|
|
|
|
|
2019-12-14 16:40:18 +01:00
|
|
|
if ( resetHint( Control | Metric | Margin ) )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2019-12-14 16:40:18 +01:00
|
|
|
resetImplicitSize();
|
|
|
|
|
|
|
|
Q_D( const QskControl );
|
|
|
|
if ( polishOnResize() || d->autoLayoutChildren )
|
|
|
|
polish();
|
|
|
|
|
|
|
|
qskSendEventTo( this, QEvent::ContentsRectChange );
|
|
|
|
Q_EMIT marginsChanged();
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QMarginsF QskControl::margins() const
|
|
|
|
{
|
2020-12-15 07:21:12 +01:00
|
|
|
return marginHint( QskAspect::Control );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QRectF QskControl::contentsRect() const
|
|
|
|
{
|
2019-09-04 06:59:43 +02:00
|
|
|
return qskValidOrEmptyInnerRect( rect(), margins() );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
QRectF QskControl::subControlRect( QskAspect::Subcontrol subControl ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2019-09-04 06:59:43 +02:00
|
|
|
return effectiveSkinlet()->subControlRect( this, contentsRect(), subControl );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
QRectF QskControl::subControlRect(
|
|
|
|
const QSizeF& size, QskAspect::Subcontrol subControl ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2019-09-04 06:59:43 +02:00
|
|
|
QRectF rect( 0.0, 0.0, size.width(), size.height() );
|
|
|
|
rect = qskValidOrEmptyInnerRect( rect, margins() );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
return effectiveSkinlet()->subControlRect( this, rect, subControl );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QLocale QskControl::locale() const
|
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
return d_func()->locale;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setLocale( const QLocale& locale )
|
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
Q_D( QskControl );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-25 14:53:49 +02:00
|
|
|
d->explicitLocale = true;
|
|
|
|
|
|
|
|
if ( d->locale != locale )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
d->locale = locale;
|
2017-07-21 18:21:34 +02:00
|
|
|
qskSendEventTo( this, QEvent::LocaleChange );
|
|
|
|
qskSetup->inheritLocale( this, locale );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::resetLocale()
|
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
Q_D( QskControl );
|
|
|
|
|
|
|
|
if ( d->explicitLocale )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
d->explicitLocale = false;
|
2019-09-04 06:59:43 +02:00
|
|
|
QskControlPrivate::resolveLocale( this );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-08 10:34:00 +02:00
|
|
|
void QskControl::initSizePolicy(
|
|
|
|
QskSizePolicy::Policy horizontalPolicy,
|
|
|
|
QskSizePolicy::Policy verticalPolicy )
|
|
|
|
{
|
|
|
|
Q_D( QskControl );
|
|
|
|
|
|
|
|
/*
|
|
|
|
In constructors of derived classes you don't need
|
|
|
|
to propagate changes by layoutConstraintChanged.
|
|
|
|
Sometimes it is even worse as the parent might not be
|
|
|
|
even prepared to handle the LayouRequest event.
|
|
|
|
*/
|
2018-08-03 08:15:28 +02:00
|
|
|
|
2018-05-08 10:34:00 +02:00
|
|
|
d->sizePolicy.setHorizontalPolicy( horizontalPolicy );
|
|
|
|
d->sizePolicy.setVerticalPolicy( verticalPolicy );
|
2019-06-19 13:25:29 +02:00
|
|
|
|
|
|
|
if ( horizontalPolicy == QskSizePolicy::Constrained
|
|
|
|
&& verticalPolicy == QskSizePolicy::Constrained )
|
|
|
|
{
|
2020-01-02 17:48:16 +01:00
|
|
|
qWarning( "QskControl::initSizePolicy: conflicting constraints" );
|
2019-06-19 13:25:29 +02:00
|
|
|
}
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
|
2019-06-20 11:45:32 +02:00
|
|
|
void QskControl::setSizePolicy( QskSizePolicy policy )
|
2018-05-08 10:34:00 +02:00
|
|
|
{
|
|
|
|
Q_D( QskControl );
|
|
|
|
|
|
|
|
if ( policy != d->sizePolicy )
|
|
|
|
{
|
|
|
|
d->sizePolicy = policy;
|
2019-09-04 06:59:43 +02:00
|
|
|
d->layoutConstraintChanged();
|
2019-06-19 13:25:29 +02:00
|
|
|
|
|
|
|
if ( policy.policy( Qt::Horizontal ) == QskSizePolicy::Constrained
|
|
|
|
&& policy.policy( Qt::Vertical ) == QskSizePolicy::Constrained )
|
|
|
|
{
|
2020-01-02 17:48:16 +01:00
|
|
|
qWarning( "QskControl::setSizePolicy: conflicting constraints" );
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setSizePolicy(
|
|
|
|
QskSizePolicy::Policy horizontalPolicy,
|
|
|
|
QskSizePolicy::Policy verticalPolicy )
|
|
|
|
{
|
|
|
|
setSizePolicy( QskSizePolicy( horizontalPolicy, verticalPolicy ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setSizePolicy(
|
|
|
|
Qt::Orientation orientation, QskSizePolicy::Policy policy )
|
|
|
|
{
|
|
|
|
Q_D( QskControl );
|
|
|
|
|
|
|
|
if ( d->sizePolicy.policy( orientation ) != policy )
|
|
|
|
{
|
|
|
|
d->sizePolicy.setPolicy( orientation, policy );
|
2019-09-04 06:59:43 +02:00
|
|
|
d->layoutConstraintChanged();
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-20 11:45:32 +02:00
|
|
|
QskSizePolicy QskControl::sizePolicy() const
|
2018-05-08 10:34:00 +02:00
|
|
|
{
|
|
|
|
return d_func()->sizePolicy;
|
|
|
|
}
|
|
|
|
|
|
|
|
QskSizePolicy::Policy QskControl::sizePolicy( Qt::Orientation orientation ) const
|
|
|
|
{
|
|
|
|
return d_func()->sizePolicy.policy( orientation );
|
|
|
|
}
|
|
|
|
|
2019-09-05 10:46:42 +02:00
|
|
|
/*
|
|
|
|
Layout attributes belong more to the layout code, than
|
|
|
|
being parameters of the control. So storing them here is kind of a
|
|
|
|
design flaw ( similar to QWidget/QSizePolicy ).
|
|
|
|
But this way we don't need to add the attributes to all type of
|
|
|
|
layout engines + we can make use of them when doing layouts
|
|
|
|
manually ( f.e autoLayoutChildren ).
|
|
|
|
*/
|
|
|
|
void QskControl::setLayoutAlignmentHint( Qt::Alignment alignment )
|
|
|
|
{
|
|
|
|
Q_D( QskControl );
|
|
|
|
|
2019-09-13 06:55:28 +02:00
|
|
|
if ( layoutAlignmentHint() != alignment )
|
2019-09-05 10:46:42 +02:00
|
|
|
{
|
|
|
|
d->layoutAlignmentHint = alignment;
|
|
|
|
d->layoutConstraintChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt::Alignment QskControl::layoutAlignmentHint() const
|
|
|
|
{
|
|
|
|
return static_cast< Qt::Alignment >( d_func()->layoutAlignmentHint );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setLayoutHint( LayoutHint flag, bool on )
|
|
|
|
{
|
|
|
|
Q_D( QskControl );
|
|
|
|
if ( ( d->layoutHints & flag ) != on )
|
|
|
|
{
|
|
|
|
if ( on )
|
|
|
|
d->layoutHints |= flag;
|
|
|
|
else
|
|
|
|
d->layoutHints &= ~flag;
|
2019-09-10 17:01:47 +02:00
|
|
|
|
2019-09-05 10:46:42 +02:00
|
|
|
d->layoutConstraintChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskControl::testLayoutHint( LayoutHint hint ) const
|
|
|
|
{
|
|
|
|
return d_func()->layoutHints & hint;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setLayoutHints( LayoutHints hints )
|
|
|
|
{
|
|
|
|
Q_D( QskControl );
|
|
|
|
if ( hints != layoutHints() )
|
|
|
|
{
|
|
|
|
d->layoutHints = hints;
|
|
|
|
d->layoutConstraintChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QskControl::LayoutHints QskControl::layoutHints() const
|
|
|
|
{
|
|
|
|
return static_cast< LayoutHints >( d_func()->layoutHints );
|
|
|
|
}
|
|
|
|
|
2019-09-06 19:57:25 +02:00
|
|
|
bool QskControl::isVisibleToLayout() const
|
|
|
|
{
|
|
|
|
return !isTransparentForPositioner()
|
|
|
|
&& ( isVisibleToParent() || ( layoutHints() & RetainSizeWhenHidden ) );
|
|
|
|
}
|
|
|
|
|
2018-05-08 10:34:00 +02:00
|
|
|
void QskControl::setPreferredSize( const QSizeF& size )
|
|
|
|
{
|
|
|
|
setExplicitSizeHint( Qt::PreferredSize, size );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setPreferredSize( qreal width, qreal height )
|
|
|
|
{
|
2019-09-13 06:57:48 +02:00
|
|
|
setExplicitSizeHint( Qt::PreferredSize, QSizeF( width, height ) );
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setPreferredWidth( qreal width )
|
|
|
|
{
|
2019-09-13 06:57:48 +02:00
|
|
|
const qreal height = explicitSizeHint( Qt::PreferredSize ).height();
|
|
|
|
setExplicitSizeHint( Qt::PreferredSize, QSizeF( width, height ) );
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setPreferredHeight( qreal height )
|
|
|
|
{
|
2019-09-13 06:57:48 +02:00
|
|
|
const qreal width = explicitSizeHint( Qt::PreferredSize ).width();
|
|
|
|
setExplicitSizeHint( Qt::PreferredSize, QSizeF( width, height ) );
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setMinimumSize( const QSizeF& size )
|
|
|
|
{
|
|
|
|
setExplicitSizeHint( Qt::MinimumSize, size );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setMinimumSize( qreal width, qreal height )
|
|
|
|
{
|
2019-09-13 06:57:48 +02:00
|
|
|
setExplicitSizeHint( Qt::MinimumSize, QSizeF( width, height ) );
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setMinimumWidth( qreal width )
|
|
|
|
{
|
2019-09-13 06:57:48 +02:00
|
|
|
const qreal height = explicitSizeHint( Qt::MinimumSize ).height();
|
|
|
|
setExplicitSizeHint( Qt::MinimumSize, QSizeF( width, height ) );
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setMinimumHeight( qreal height )
|
|
|
|
{
|
2019-09-13 06:57:48 +02:00
|
|
|
const qreal width = explicitSizeHint( Qt::MinimumSize ).width();
|
|
|
|
setExplicitSizeHint( Qt::MinimumSize, QSizeF( width, height ) );
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setMaximumSize( const QSizeF& size )
|
|
|
|
{
|
|
|
|
setExplicitSizeHint( Qt::MaximumSize, size );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setMaximumSize( qreal width, qreal height )
|
|
|
|
{
|
2019-09-13 06:57:48 +02:00
|
|
|
setExplicitSizeHint( Qt::MaximumSize, QSizeF( width, height ) );
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setMaximumWidth( qreal width )
|
|
|
|
{
|
2019-09-13 06:57:48 +02:00
|
|
|
const qreal height = explicitSizeHint( Qt::MaximumSize ).height();
|
|
|
|
setExplicitSizeHint( Qt::MaximumSize, QSizeF( width, height ) );
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setMaximumHeight( qreal height )
|
|
|
|
{
|
2019-09-13 06:57:48 +02:00
|
|
|
const qreal width = explicitSizeHint( Qt::MaximumSize ).width();
|
|
|
|
setExplicitSizeHint( Qt::MaximumSize, QSizeF( width, height ) );
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setFixedSize( const QSizeF& size )
|
|
|
|
{
|
|
|
|
const QSizeF newSize = size.expandedTo( QSizeF( 0, 0 ) );
|
|
|
|
|
|
|
|
const QskSizePolicy policy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
|
|
|
|
|
|
|
Q_D( QskControl );
|
|
|
|
|
|
|
|
if ( policy != d->sizePolicy ||
|
|
|
|
d->explicitSizeHint( Qt::PreferredSize ) != newSize )
|
|
|
|
{
|
|
|
|
d->sizePolicy = policy;
|
|
|
|
d->setExplicitSizeHint( Qt::PreferredSize, newSize );
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
d->layoutConstraintChanged();
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setFixedSize( qreal width, qreal height )
|
|
|
|
{
|
|
|
|
setFixedSize( QSizeF( width, height ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setFixedWidth( qreal width )
|
|
|
|
{
|
|
|
|
if ( width < 0 )
|
|
|
|
width = 0;
|
|
|
|
|
|
|
|
Q_D( QskControl );
|
|
|
|
|
|
|
|
auto size = d->explicitSizeHint( Qt::PreferredSize );
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( ( d->sizePolicy.horizontalPolicy() != QskSizePolicy::Fixed ) ||
|
2019-01-04 13:42:16 +01:00
|
|
|
( size.width() != width ) )
|
2018-05-08 10:34:00 +02:00
|
|
|
{
|
|
|
|
size.setWidth( width );
|
|
|
|
|
|
|
|
d->sizePolicy.setHorizontalPolicy( QskSizePolicy::Fixed );
|
|
|
|
d->setExplicitSizeHint( Qt::PreferredSize, size );
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
d->layoutConstraintChanged();
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setFixedHeight( qreal height )
|
|
|
|
{
|
|
|
|
if ( height < 0 )
|
|
|
|
height = 0;
|
|
|
|
|
|
|
|
Q_D( QskControl );
|
|
|
|
|
|
|
|
auto size = d->explicitSizeHint( Qt::PreferredSize );
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( ( d->sizePolicy.verticalPolicy() != QskSizePolicy::Fixed ) ||
|
2019-01-04 13:42:16 +01:00
|
|
|
( size.height() != height ) )
|
2018-05-08 10:34:00 +02:00
|
|
|
{
|
|
|
|
size.setHeight( height );
|
|
|
|
|
|
|
|
d->sizePolicy.setVerticalPolicy( QskSizePolicy::Fixed );
|
|
|
|
d->setExplicitSizeHint( Qt::PreferredSize, size );
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
d->layoutConstraintChanged();
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::resetExplicitSizeHint( Qt::SizeHint whichHint )
|
|
|
|
{
|
|
|
|
if ( whichHint >= Qt::MinimumSize && whichHint <= Qt::MaximumSize )
|
2019-09-01 15:33:36 +02:00
|
|
|
{
|
|
|
|
Q_D( QskControl );
|
|
|
|
|
|
|
|
const auto oldHint = d->explicitSizeHint( whichHint );
|
|
|
|
d->resetExplicitSizeHint( whichHint );
|
|
|
|
|
|
|
|
if ( oldHint != d->explicitSizeHint( whichHint ) )
|
2019-09-04 06:59:43 +02:00
|
|
|
d->layoutConstraintChanged();
|
2019-09-01 15:33:36 +02:00
|
|
|
}
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::setExplicitSizeHint( Qt::SizeHint whichHint, const QSizeF& size )
|
|
|
|
{
|
|
|
|
if ( whichHint >= Qt::MinimumSize && whichHint <= Qt::MaximumSize )
|
|
|
|
{
|
|
|
|
const QSizeF newSize( ( size.width() < 0 ) ? -1.0 : size.width(),
|
2018-05-09 14:13:26 +02:00
|
|
|
( size.height() < 0 ) ? -1.0 : size.height() );
|
2018-05-08 10:34:00 +02:00
|
|
|
|
|
|
|
Q_D( QskControl );
|
|
|
|
|
|
|
|
if ( newSize != d->explicitSizeHint( whichHint ) )
|
|
|
|
{
|
|
|
|
d->setExplicitSizeHint( whichHint, newSize );
|
2019-09-04 06:59:43 +02:00
|
|
|
d->layoutConstraintChanged();
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-17 17:52:15 +02:00
|
|
|
void QskControl::setExplicitSizeHint(
|
|
|
|
Qt::SizeHint whichHint, qreal width, qreal height )
|
2018-05-08 10:34:00 +02:00
|
|
|
{
|
|
|
|
setExplicitSizeHint( whichHint, QSizeF( width, height ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
QSizeF QskControl::explicitSizeHint( Qt::SizeHint whichHint ) const
|
|
|
|
{
|
2019-09-10 17:01:47 +02:00
|
|
|
if ( whichHint < Qt::MinimumSize || whichHint > Qt::MaximumSize )
|
|
|
|
return QSizeF();
|
2018-05-08 10:34:00 +02:00
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
return d_func()->explicitSizeHint( whichHint );
|
2018-05-08 10:34:00 +02:00
|
|
|
}
|
|
|
|
|
2019-07-17 17:52:15 +02:00
|
|
|
QSizeF QskControl::implicitSizeHint(
|
|
|
|
Qt::SizeHint whichHint, const QSizeF& constraint ) const
|
|
|
|
{
|
|
|
|
if ( whichHint < Qt::MinimumSize || whichHint > Qt::MaximumSize )
|
2019-09-10 17:01:47 +02:00
|
|
|
return QSizeF();
|
2019-07-17 17:52:15 +02:00
|
|
|
|
|
|
|
if ( constraint.isValid() )
|
|
|
|
{
|
|
|
|
// having constraints in both directions does not make sense
|
|
|
|
return constraint;
|
|
|
|
}
|
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
QSizeF hint;
|
2019-07-17 17:52:15 +02:00
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
if ( whichHint == Qt::PreferredSize
|
|
|
|
&& constraint.width() < 0.0 && constraint.height() < 0.0 )
|
2019-07-17 17:52:15 +02:00
|
|
|
{
|
2019-09-10 17:01:47 +02:00
|
|
|
// this one might be cached
|
|
|
|
hint = implicitSize();
|
2019-07-17 17:52:15 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-09-10 17:01:47 +02:00
|
|
|
hint = d_func()->implicitSizeHint( whichHint, constraint );
|
2019-07-17 17:52:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return hint;
|
|
|
|
}
|
|
|
|
|
|
|
|
QSizeF QskControl::effectiveSizeHint(
|
2019-09-10 17:01:47 +02:00
|
|
|
Qt::SizeHint which, const QSizeF& constraint ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2019-09-10 17:01:47 +02:00
|
|
|
if ( which < Qt::MinimumSize || which > Qt::MaximumSize )
|
2017-07-21 18:21:34 +02:00
|
|
|
return QSizeF( 0, 0 );
|
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
if ( constraint.isValid() )
|
|
|
|
return constraint;
|
|
|
|
|
|
|
|
const bool isConstrained =
|
|
|
|
constraint.width() >= 0 || constraint.height() >= 0;
|
|
|
|
|
2019-07-25 18:38:09 +02:00
|
|
|
Q_D( const QskControl );
|
|
|
|
|
|
|
|
d->blockLayoutRequestEvents = false;
|
2019-06-22 16:17:12 +02:00
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
QSizeF hint;
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
/*
|
|
|
|
The explicit size has always precedence over the implicit size,
|
|
|
|
and will kill the effect of the constraint
|
2019-07-25 18:38:09 +02:00
|
|
|
*/
|
2018-05-01 13:55:26 +02:00
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
hint = d->explicitSizeHint( which );
|
2019-07-25 18:38:09 +02:00
|
|
|
|
|
|
|
if ( !hint.isValid() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2019-09-10 17:01:47 +02:00
|
|
|
const auto implicitHint = implicitSizeHint( which, constraint );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2019-07-25 18:38:09 +02:00
|
|
|
if ( hint.width() < 0 )
|
2019-09-10 17:01:47 +02:00
|
|
|
hint.setWidth( implicitHint.width() );
|
2019-07-25 18:38:09 +02:00
|
|
|
|
|
|
|
if ( hint.height() < 0 )
|
2019-09-10 17:01:47 +02:00
|
|
|
hint.setHeight( implicitHint.height() );
|
2019-07-17 17:52:15 +02:00
|
|
|
}
|
2019-07-25 18:38:09 +02:00
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
if ( !isConstrained && ( hint.width() >= 0 || hint.height() >= 0 ) )
|
2019-07-17 17:52:15 +02:00
|
|
|
{
|
2019-07-25 18:38:09 +02:00
|
|
|
/*
|
2019-09-10 17:01:47 +02:00
|
|
|
We normalize the unconstrained hints by the explicit hints, so that
|
2019-07-25 18:38:09 +02:00
|
|
|
we always have: minimum <= preferred <= maximum.
|
|
|
|
*/
|
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
if ( which == Qt::MaximumSize )
|
2019-07-25 18:38:09 +02:00
|
|
|
{
|
|
|
|
const auto minimumHint = d->explicitSizeHint( Qt::MinimumSize );
|
|
|
|
|
|
|
|
if ( hint.width() >= 0 )
|
2019-09-10 17:01:47 +02:00
|
|
|
hint.rwidth() = qMax( hint.width(), minimumHint.width() );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2019-07-25 18:38:09 +02:00
|
|
|
if ( hint.height() >= 0 )
|
2019-09-10 17:01:47 +02:00
|
|
|
hint.rheight() = qMax( hint.height(), minimumHint.height() );
|
2019-07-25 18:38:09 +02:00
|
|
|
}
|
2019-09-10 17:01:47 +02:00
|
|
|
else if ( which == Qt::PreferredSize )
|
2019-07-25 18:38:09 +02:00
|
|
|
{
|
|
|
|
const auto minimumHint = d->explicitSizeHint( Qt::MinimumSize );
|
|
|
|
const auto maximumHint = d->explicitSizeHint( Qt::MaximumSize );
|
|
|
|
|
|
|
|
if ( hint.width() >= 0 )
|
|
|
|
{
|
2019-09-10 17:01:47 +02:00
|
|
|
if ( maximumHint.width() >= 0 )
|
|
|
|
hint.rwidth() = qMin( hint.width(), maximumHint.width() );
|
2019-07-25 18:38:09 +02:00
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
hint.rwidth() = qMax( hint.width(), minimumHint.width() );
|
2019-07-25 18:38:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( hint.height() >= 0 )
|
|
|
|
{
|
2019-09-10 17:01:47 +02:00
|
|
|
if ( maximumHint.height() >= 0 )
|
|
|
|
hint.rheight() = qMin( hint.height(), maximumHint.height() );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
hint.rheight() = qMax( hint.height(), minimumHint.height() );
|
2019-07-25 18:38:09 +02:00
|
|
|
}
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2019-07-17 17:52:15 +02:00
|
|
|
return hint;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-05-01 13:55:26 +02:00
|
|
|
qreal QskControl::heightForWidth( qreal width ) const
|
|
|
|
{
|
2019-09-10 17:01:47 +02:00
|
|
|
const auto hint = effectiveSizeHint(
|
|
|
|
Qt::PreferredSize, QSizeF( width, -1.0 ) );
|
2019-06-22 16:17:12 +02:00
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
return hint.height();
|
2018-05-01 13:55:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskControl::widthForHeight( qreal height ) const
|
|
|
|
{
|
2019-09-10 17:01:47 +02:00
|
|
|
const auto hint = effectiveSizeHint(
|
|
|
|
Qt::PreferredSize, QSizeF( -1.0, height ) );
|
2018-08-03 08:15:28 +02:00
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
return hint.width();
|
2018-05-01 13:55:26 +02:00
|
|
|
}
|
|
|
|
|
2019-09-13 06:54:55 +02:00
|
|
|
QSizeF QskControl::sizeConstraint(
|
|
|
|
Qt::SizeHint which, const QSizeF& constraint ) const
|
|
|
|
{
|
|
|
|
return qskSizeConstraint( this, which, constraint );
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
bool QskControl::event( QEvent* event )
|
|
|
|
{
|
2019-09-04 06:59:43 +02:00
|
|
|
switch ( static_cast< int >( event->type() ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
case QEvent::EnabledChange:
|
|
|
|
{
|
|
|
|
setSkinStateFlag( Disabled, !isEnabled() );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QEvent::LocaleChange:
|
|
|
|
{
|
|
|
|
Q_EMIT localeChanged( locale() );
|
|
|
|
break;
|
|
|
|
}
|
2019-09-20 07:43:16 +02:00
|
|
|
case QEvent::ContentsRectChange:
|
|
|
|
{
|
|
|
|
resetImplicitSize();
|
|
|
|
if ( d_func()->autoLayoutChildren )
|
|
|
|
polish();
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
case QEvent::LayoutRequest:
|
|
|
|
{
|
2017-10-25 14:53:49 +02:00
|
|
|
if ( d_func()->autoLayoutChildren )
|
2020-09-04 07:37:16 +02:00
|
|
|
{
|
2017-07-21 18:21:34 +02:00
|
|
|
resetImplicitSize();
|
2020-09-04 07:37:16 +02:00
|
|
|
polish();
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2017-12-14 09:41:10 +01:00
|
|
|
case QEvent::StyleChange:
|
|
|
|
{
|
|
|
|
// The skin has changed
|
|
|
|
|
|
|
|
if ( skinlet() == nullptr )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
When we don't have a local skinlet, the skinlet
|
2018-04-05 14:18:15 +02:00
|
|
|
from the previous skin might be cached.
|
2017-12-14 09:41:10 +01:00
|
|
|
*/
|
2018-04-05 14:18:15 +02:00
|
|
|
|
2017-12-14 09:41:10 +01:00
|
|
|
setSkinlet( nullptr );
|
|
|
|
}
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
break;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
case QskEvent::Gesture:
|
|
|
|
{
|
|
|
|
gestureEvent( static_cast< QskGestureEvent* >( event ) );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
if ( d_func()->maybeGesture( this, event ) )
|
|
|
|
return true;
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
return Inherited::event( event );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskControl::childMouseEventFilter( QQuickItem* item, QEvent* event )
|
|
|
|
{
|
2019-03-07 13:20:48 +01:00
|
|
|
#if QT_VERSION < QT_VERSION_CHECK( 5, 10, 0 )
|
|
|
|
|
|
|
|
if ( event->type() == QEvent::MouseButtonPress )
|
|
|
|
{
|
2019-04-04 17:59:17 +02:00
|
|
|
auto me = static_cast< QMouseEvent* >( event );
|
2019-03-07 13:20:48 +01:00
|
|
|
|
|
|
|
if ( me->source() == Qt::MouseEventSynthesizedByQt )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Unhandled touch events result in creating synthetic
|
|
|
|
mouse events. For all versions < 5.10 those events are
|
|
|
|
passed through childMouseEventFilter without doing the
|
|
|
|
extra checks, that are done for real mouse events.
|
2019-04-04 17:59:17 +02:00
|
|
|
Furthermore the coordinates are relative
|
|
|
|
to this - not to item.
|
|
|
|
|
2019-03-07 13:20:48 +01:00
|
|
|
To avoid having a different behavior between using
|
|
|
|
mouse and touch, we do those checks here.
|
|
|
|
*/
|
|
|
|
|
2019-04-04 17:59:17 +02:00
|
|
|
auto itm = item;
|
|
|
|
auto pos = item->mapFromScene( me->windowPos() );
|
|
|
|
|
|
|
|
for ( itm = item; itm != this; itm = itm->parentItem() )
|
|
|
|
{
|
|
|
|
if ( itm->acceptedMouseButtons() & me->button() )
|
|
|
|
{
|
|
|
|
if ( itm->contains( pos ) )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos += QPointF( itm->x(), itm->y() );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( itm != item )
|
|
|
|
{
|
|
|
|
if ( itm == this )
|
|
|
|
return false;
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
QScopedPointer< QMouseEvent > clonedEvent(
|
2019-04-04 17:59:17 +02:00
|
|
|
QQuickWindowPrivate::cloneMouseEvent( me, &pos ) );
|
|
|
|
|
|
|
|
return d_func()->maybeGesture( itm, clonedEvent.data() );
|
|
|
|
}
|
2019-03-07 13:20:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
return d_func()->maybeGesture( item, event );
|
|
|
|
}
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
bool QskControl::gestureFilter( QQuickItem*, QEvent* )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
void QskControl::gestureEvent( QskGestureEvent* )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::hoverEnterEvent( QHoverEvent* event )
|
|
|
|
{
|
|
|
|
Inherited::hoverEnterEvent( event );
|
|
|
|
setSkinStateFlag( Hovered );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::hoverLeaveEvent( QHoverEvent* event )
|
|
|
|
{
|
|
|
|
Inherited::hoverLeaveEvent( event );
|
|
|
|
setSkinStateFlag( Hovered, false );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskControl::itemChange( QQuickItem::ItemChange change,
|
|
|
|
const QQuickItem::ItemChangeData& value )
|
|
|
|
{
|
2019-09-04 06:59:43 +02:00
|
|
|
switch ( static_cast< int >( change ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
case QQuickItem::ItemParentHasChanged:
|
|
|
|
{
|
2017-12-08 13:56:35 +01:00
|
|
|
if ( value.item )
|
|
|
|
{
|
2019-09-04 06:59:43 +02:00
|
|
|
if ( !d_func()->explicitLocale )
|
|
|
|
QskControlPrivate::resolveLocale( this );
|
2017-12-08 13:56:35 +01:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
#if 1
|
2017-07-21 18:21:34 +02:00
|
|
|
// not necessarily correct, when parent != parentItem ???
|
|
|
|
qskSendEventTo( this, QEvent::ParentChange );
|
2019-09-04 06:59:43 +02:00
|
|
|
#endif
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2017-11-18 13:52:48 +01:00
|
|
|
case QQuickItem::ItemChildAddedChange:
|
|
|
|
{
|
2019-09-04 06:59:43 +02:00
|
|
|
if ( autoLayoutChildren() && !qskIsTransparentForPositioner( value.item ) )
|
2017-11-18 13:52:48 +01:00
|
|
|
polish();
|
2017-12-05 13:10:17 +01:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QQuickItem::ItemActiveFocusHasChanged:
|
|
|
|
{
|
|
|
|
setSkinStateFlag( Focused, hasActiveFocus() );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-09-04 06:59:43 +02:00
|
|
|
|
|
|
|
Inherited::itemChange( change, value );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-10-26 17:59:19 +01:00
|
|
|
void QskControl::geometryChange(
|
2017-07-21 18:21:34 +02:00
|
|
|
const QRectF& newGeometry, const QRectF& oldGeometry )
|
|
|
|
{
|
2019-09-04 06:59:43 +02:00
|
|
|
if ( d_func()->autoLayoutChildren )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2019-09-04 06:59:43 +02:00
|
|
|
if ( newGeometry.size() != oldGeometry.size() )
|
2017-07-21 18:21:34 +02:00
|
|
|
polish();
|
|
|
|
}
|
|
|
|
|
2020-10-26 17:59:19 +01:00
|
|
|
Inherited::geometryChange( newGeometry, oldGeometry );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
void QskControl::updateItemPolish()
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2019-09-20 07:08:08 +02:00
|
|
|
updateResources(); // an extra dirty bit for this ???
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2019-09-20 07:08:08 +02:00
|
|
|
if ( width() >= 0.0 || height() >= 0.0 )
|
|
|
|
{
|
|
|
|
if ( d_func()->autoLayoutChildren && !maybeUnresized() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2019-09-20 07:08:08 +02:00
|
|
|
const auto rect = layoutRect();
|
|
|
|
|
|
|
|
const auto children = childItems();
|
|
|
|
for ( auto child : children )
|
2019-06-20 11:45:32 +02:00
|
|
|
{
|
2019-09-20 07:08:08 +02:00
|
|
|
/*
|
|
|
|
We don't want to resize invisible children, but then
|
|
|
|
we would need to set up connections to know when a child
|
|
|
|
becomes visible. So we don't use qskIsVisibleToLayout here.
|
2020-03-10 10:28:39 +01:00
|
|
|
And what about using QskControl::LayoutOutWhenHidden ?
|
2019-09-20 07:08:08 +02:00
|
|
|
*/
|
|
|
|
if ( !qskIsTransparentForPositioner( child ) )
|
|
|
|
{
|
|
|
|
const auto r = qskConstrainedItemRect( child, rect );
|
|
|
|
qskSetItemGeometry( child, r );
|
|
|
|
}
|
2019-06-20 11:45:32 +02:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2019-09-20 07:08:08 +02:00
|
|
|
updateLayout();
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
QSGNode* QskControl::updateItemPaintNode( QSGNode* node )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
if ( node == nullptr )
|
|
|
|
node = new QSGNode;
|
|
|
|
|
2019-09-05 07:05:28 +02:00
|
|
|
updateNode( node );
|
2017-07-21 18:21:34 +02:00
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
QskControl* QskControl::owningControl() const
|
|
|
|
{
|
|
|
|
return const_cast< QskControl* >( this );
|
|
|
|
}
|
|
|
|
|
2019-06-23 12:53:38 +02:00
|
|
|
QRectF QskControl::layoutRect() const
|
|
|
|
{
|
|
|
|
Q_D( const QskControl );
|
|
|
|
|
|
|
|
if ( d->width <= 0.0 && d->height <= 0.0 )
|
|
|
|
return QRectF();
|
|
|
|
|
|
|
|
return layoutRectForSize( size() );
|
|
|
|
}
|
|
|
|
|
2019-04-26 18:09:59 +02:00
|
|
|
QRectF QskControl::layoutRectForSize( const QSizeF& size ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2019-04-26 18:09:59 +02:00
|
|
|
const QRectF r( 0.0, 0.0, size.width(), size.height() );
|
|
|
|
return qskValidOrEmptyInnerRect( r, margins() );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QRectF QskControl::gestureRect() const
|
|
|
|
{
|
2018-02-07 19:30:34 +01:00
|
|
|
return rect();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-01-19 10:15:29 +01:00
|
|
|
QRectF QskControl::focusIndicatorRect() const
|
|
|
|
{
|
2018-02-01 09:28:47 +01:00
|
|
|
return contentsRect();
|
2018-01-19 10:15:29 +01:00
|
|
|
}
|
|
|
|
|
2020-03-16 13:17:51 +01:00
|
|
|
QRectF QskControl::focusIndicatorClipRect() const
|
2020-03-13 07:39:31 +01:00
|
|
|
{
|
2020-03-16 13:17:51 +01:00
|
|
|
return clipRect();
|
2020-03-13 07:39:31 +01:00
|
|
|
}
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
void QskControl::updateLayout()
|
2018-06-26 11:10:44 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
void QskControl::updateResources()
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-09-11 06:51:40 +02:00
|
|
|
QSizeF QskControl::contentsSizeHint( Qt::SizeHint, const QSizeF& ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2019-09-11 06:51:40 +02:00
|
|
|
return QSizeF();
|
2019-09-10 17:01:47 +02:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
QSizeF QskControl::layoutSizeHint(
|
|
|
|
Qt::SizeHint which, const QSizeF& constraint ) const
|
|
|
|
{
|
2019-09-11 06:51:40 +02:00
|
|
|
if ( which == Qt::MaximumSize || !d_func()->autoLayoutChildren )
|
2019-09-10 17:01:47 +02:00
|
|
|
return QSizeF();
|
|
|
|
|
2019-09-18 08:57:08 +02:00
|
|
|
qreal w = -1.0;
|
|
|
|
qreal h = -1.0;
|
2019-09-10 17:01:47 +02:00
|
|
|
|
|
|
|
const auto children = childItems();
|
2019-09-20 07:08:08 +02:00
|
|
|
|
2019-09-10 17:01:47 +02:00
|
|
|
for ( const auto child : children )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2019-09-20 07:08:08 +02:00
|
|
|
if ( !qskIsVisibleToLayout( child ) )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const auto policy = qskSizePolicy( child );
|
|
|
|
|
|
|
|
if ( constraint.width() >= 0.0 && policy.isConstrained( Qt::Vertical ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2019-09-18 08:57:08 +02:00
|
|
|
const auto hint = qskSizeConstraint( child, which, constraint );
|
2019-09-20 07:43:16 +02:00
|
|
|
h = qMax( h, hint.height() );
|
2019-09-20 07:08:08 +02:00
|
|
|
}
|
|
|
|
else if ( constraint.height() >= 0.0 && policy.isConstrained( Qt::Horizontal ) )
|
|
|
|
{
|
|
|
|
const auto hint = qskSizeConstraint( child, which, constraint );
|
2019-09-20 07:43:16 +02:00
|
|
|
w = qMax( w, hint.width() );
|
2019-09-20 07:08:08 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const auto hint = qskSizeConstraint( child, which, QSizeF() );
|
2019-09-18 08:57:08 +02:00
|
|
|
|
2019-09-20 07:43:16 +02:00
|
|
|
w = qMax( w, hint.width() );
|
|
|
|
h = qMax( h, hint.height() );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return QSizeF( w, h );
|
|
|
|
}
|
|
|
|
|
|
|
|
QVector< QskAspect::Subcontrol > QskControl::subControls() const
|
|
|
|
{
|
2020-12-15 07:21:12 +01:00
|
|
|
QVector< QskAspect::Subcontrol > subControls;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
for ( auto mo = metaObject(); mo != nullptr; mo = mo->superClass() )
|
|
|
|
{
|
|
|
|
const auto moSubControls = QskAspect::subControls( mo );
|
|
|
|
|
|
|
|
for ( auto subControl : moSubControls )
|
|
|
|
{
|
|
|
|
const auto subControlEffective = effectiveSubcontrol( subControl );
|
|
|
|
|
|
|
|
if ( subControlEffective == subControl )
|
|
|
|
{
|
|
|
|
subControls += subControlEffective;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// when subControlEffective differs it usually has
|
|
|
|
// been mapped to a subcontrol of an inherited class
|
|
|
|
// that is already in the list.
|
|
|
|
|
|
|
|
if ( !subControls.contains( subControlEffective ) )
|
|
|
|
{
|
|
|
|
subControls += subControlEffective;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return subControls;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "moc_QskControl.cpp"
|