2019-09-04 06:59:43 +02:00
|
|
|
/******************************************************************************
|
2024-01-17 14:31:45 +01:00
|
|
|
* QSkinny - Copyright (C) The authors
|
2023-04-06 09:23:37 +02:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2019-09-04 06:59:43 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
#include "QskItem.h"
|
|
|
|
#include "QskItemPrivate.h"
|
2019-09-04 06:59:43 +02:00
|
|
|
#include "QskQuick.h"
|
|
|
|
#include "QskEvent.h"
|
|
|
|
#include "QskSetup.h"
|
2024-01-30 10:43:27 +01:00
|
|
|
#include "QskSkinManager.h"
|
2019-09-04 06:59:43 +02:00
|
|
|
#include "QskSkin.h"
|
|
|
|
#include "QskDirtyItemFilter.h"
|
|
|
|
|
|
|
|
#include <qglobalstatic.h>
|
|
|
|
#include <qquickwindow.h>
|
|
|
|
|
|
|
|
#if defined( QT_DEBUG )
|
2022-03-20 13:14:06 +01:00
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
QSK_QT_PRIVATE_BEGIN
|
2022-03-20 13:14:06 +01:00
|
|
|
|
2021-09-21 10:28:13 +02:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK( 6, 2, 0 )
|
|
|
|
#ifndef emit
|
|
|
|
#define emit
|
2022-03-20 13:14:06 +01:00
|
|
|
#include <private/qabstractanimation_p.h>
|
|
|
|
#undef emit
|
2021-09-21 10:28:13 +02:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2023-04-05 09:56:28 +02:00
|
|
|
#if defined( QT_DEBUG )
|
2019-09-04 06:59:43 +02:00
|
|
|
#include <private/qquickpositioners_p.h>
|
2023-04-05 09:56:28 +02:00
|
|
|
#endif
|
2022-03-20 13:14:06 +01:00
|
|
|
|
2024-02-08 11:33:42 +01:00
|
|
|
#include <private/qquickitemchangelistener_p.h>
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
QSK_QT_PRIVATE_END
|
2022-03-20 13:14:06 +01:00
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <unordered_set>
|
|
|
|
|
|
|
|
static inline void qskSendEventTo( QObject* object, QEvent::Type type )
|
|
|
|
{
|
|
|
|
QEvent event( type );
|
|
|
|
QCoreApplication::sendEvent( object, &event );
|
|
|
|
}
|
|
|
|
|
2021-02-09 08:13:20 +01:00
|
|
|
static inline void qskApplyUpdateFlags(
|
2024-02-02 14:13:33 +01:00
|
|
|
QskItem::UpdateFlags flags, QskItem* item )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
auto d = static_cast< QskItemPrivate* >( QskItemPrivate::get( item ) );
|
2021-02-09 08:13:20 +01:00
|
|
|
d->applyUpdateFlags( flags );
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void qskFilterWindow( QQuickWindow* window )
|
|
|
|
{
|
|
|
|
if ( window == nullptr )
|
|
|
|
return;
|
|
|
|
|
|
|
|
static QskDirtyItemFilter itemFilter;
|
|
|
|
itemFilter.addWindow( window );
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
class QskItemRegistry
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
public:
|
2024-02-02 14:13:33 +01:00
|
|
|
QskItemRegistry()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
Its faster and saves some memory to have this registry instead
|
|
|
|
of setting up direct connections between qskSetup and each control
|
|
|
|
|
2022-03-08 12:08:15 +01:00
|
|
|
We would also need to send QEvent::StyleChange, when
|
|
|
|
a window has a new skin. TODO ...
|
|
|
|
*/
|
2024-01-30 10:43:27 +01:00
|
|
|
QObject::connect( qskSkinManager, &QskSkinManager::skinChanged,
|
|
|
|
qskSkinManager, [ this ] { updateSkin(); } );
|
2024-01-30 16:46:01 +01:00
|
|
|
|
|
|
|
QObject::connect( qskSkinManager, &QskSkinManager::colorSchemeChanged,
|
|
|
|
qskSkinManager, [ this ] { updateSkin(); } );
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
inline void insert( QskItem* item )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
m_items.insert( item );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
inline void remove( QskItem* item )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
m_items.erase( item );
|
|
|
|
}
|
|
|
|
|
2024-02-02 15:01:43 +01:00
|
|
|
void updateItemFlags()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 15:01:43 +01:00
|
|
|
const auto flags = QskSetup::updateFlags();
|
2019-09-04 06:59:43 +02:00
|
|
|
|
|
|
|
for ( auto item : m_items )
|
2021-02-09 08:13:20 +01:00
|
|
|
qskApplyUpdateFlags( flags, item );
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void updateSkin()
|
|
|
|
{
|
|
|
|
QEvent event( QEvent::StyleChange );
|
|
|
|
|
|
|
|
for ( auto item : m_items )
|
|
|
|
{
|
|
|
|
event.setAccepted( true );
|
|
|
|
QCoreApplication::sendEvent( item, &event );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2024-02-02 14:13:33 +01:00
|
|
|
std::unordered_set< QskItem* > m_items;
|
2019-09-04 06:59:43 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
A helper class to store the released window to be able to
|
|
|
|
put it later into the WindowChange event.
|
|
|
|
*/
|
|
|
|
class QskWindowStore
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
QskWindowStore()
|
|
|
|
: m_refCount( 0 )
|
|
|
|
, m_window( nullptr )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void setWindow( QQuickWindow* window )
|
|
|
|
{
|
|
|
|
if ( m_window != window )
|
|
|
|
{
|
|
|
|
m_window = window;
|
|
|
|
m_refCount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( m_window )
|
|
|
|
m_refCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
QQuickWindow* window()
|
|
|
|
{
|
|
|
|
QQuickWindow* w = m_window;
|
|
|
|
|
|
|
|
if ( m_window )
|
|
|
|
{
|
|
|
|
if ( --m_refCount == 0 )
|
|
|
|
m_window = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
int m_refCount;
|
|
|
|
QQuickWindow* m_window;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2024-02-08 11:33:42 +01:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
// A helper class for the polishOnParentResize feature
|
|
|
|
|
|
|
|
class QskParentListener final : public QQuickItemChangeListener
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
void update( QQuickItem* parentItem )
|
|
|
|
{
|
|
|
|
if ( parentItem == nullptr )
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto changeTypes =
|
|
|
|
QQuickItemPrivate::Geometry | QQuickItemPrivate::Children;
|
|
|
|
|
|
|
|
auto d = QQuickItemPrivate::get( parentItem );
|
|
|
|
|
|
|
|
if ( needListening( parentItem ) )
|
|
|
|
d->updateOrAddItemChangeListener( this, changeTypes );
|
|
|
|
else
|
|
|
|
d->removeItemChangeListener( this, changeTypes );
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
inline bool needListening( const QQuickItem* parentItem ) const
|
|
|
|
{
|
|
|
|
const auto children = parentItem->childItems();
|
|
|
|
for ( auto child : children )
|
|
|
|
{
|
|
|
|
if ( auto item = qobject_cast< const QskItem* >( child ) )
|
|
|
|
{
|
|
|
|
if ( item->polishOnParentResize() )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void itemGeometryChanged( QQuickItem* parentItem,
|
|
|
|
QQuickGeometryChange, const QRectF& ) override
|
|
|
|
{
|
|
|
|
const auto children = parentItem->childItems();
|
|
|
|
for ( auto child : children )
|
|
|
|
{
|
|
|
|
if ( auto item = qobject_cast< QskItem* >( child ) )
|
|
|
|
{
|
|
|
|
if ( item->polishOnParentResize() )
|
|
|
|
{
|
|
|
|
item->resetImplicitSize();
|
|
|
|
item->polish();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void itemChildRemoved( QQuickItem* parentItem, QQuickItem* )
|
|
|
|
{
|
|
|
|
update( parentItem );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_GLOBAL_STATIC( QskItemRegistry, qskRegistry )
|
2019-09-04 06:59:43 +02:00
|
|
|
Q_GLOBAL_STATIC( QskWindowStore, qskReleasedWindowCounter )
|
2024-02-08 11:33:42 +01:00
|
|
|
Q_GLOBAL_STATIC( QskParentListener, qskParentListener )
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
QskItem::QskItem( QskItemPrivate& dd, QQuickItem* parent )
|
2019-09-04 06:59:43 +02:00
|
|
|
: QQuickItem( dd, parent )
|
|
|
|
{
|
|
|
|
setFlag( QQuickItem::ItemHasContents, true );
|
2024-02-02 09:48:26 +01:00
|
|
|
Inherited::setActiveFocusOnTab( false );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
if ( dd.updateFlags & QskItem::DeferredUpdate )
|
2019-09-04 06:59:43 +02:00
|
|
|
qskFilterWindow( window() );
|
|
|
|
|
|
|
|
qskRegistry->insert( this );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
QskItem::~QskItem()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
We set componentComplete to false, so that operations
|
|
|
|
that are triggered by detaching the item from its parent
|
|
|
|
can be aware of the about-to-delete state.
|
2023-10-23 18:32:08 +02:00
|
|
|
|
|
|
|
Note, that since Qt >= 6.5 this information is stored
|
|
|
|
in QQuickItemPrivate::inDestructor.
|
|
|
|
|
|
|
|
s.a: qskIsItemInDestructor
|
2019-09-04 06:59:43 +02:00
|
|
|
*/
|
|
|
|
d_func()->componentComplete = false;
|
|
|
|
|
|
|
|
if ( qskRegistry )
|
|
|
|
qskRegistry->remove( this );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
const char* QskItem::className() const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
return metaObject()->className();
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::classBegin()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
Inherited::classBegin();
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::componentComplete()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
#if defined( QT_DEBUG )
|
2024-02-02 14:13:33 +01:00
|
|
|
if ( d_func()->updateFlags & QskItem::DeferredLayout )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2022-03-20 13:14:06 +01:00
|
|
|
if ( qobject_cast< const QQuickBasePositioner* >( parent() ) )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
qWarning( "QskItem in DeferredLayout mode under control of a positioner" );
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Inherited::componentComplete();
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::releaseResources()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
Inherited::releaseResources();
|
|
|
|
|
|
|
|
// QQuickItem::derefWindow runs over the children between
|
|
|
|
// calling releaseResources and itemChange. So we need to have
|
|
|
|
// a reference count to know, when we have processed all
|
|
|
|
// sequences to be able to provide the correct "oldWindow"
|
|
|
|
// in the WindowChange event.
|
|
|
|
|
|
|
|
qskReleasedWindowCounter->setWindow( window() );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::setDisabled( bool on )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2021-02-15 09:17:29 +01:00
|
|
|
Inherited::setEnabled( !on );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::setHidden( bool on )
|
2021-02-15 09:17:29 +01:00
|
|
|
{
|
|
|
|
Inherited::setVisible( !on );
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::show()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
Inherited::setVisible( true );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::hide()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
Inherited::setVisible( false );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
bool QskItem::isVisibleTo( const QQuickItem* ancestor ) const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
return qskIsVisibleTo( this, ancestor );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
bool QskItem::isVisibleToParent() const
|
2019-09-06 19:56:03 +02:00
|
|
|
{
|
|
|
|
return d_func()->explicitVisible;
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::setGeometry( qreal x, qreal y, qreal width, qreal height )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
// QQuickItem does not even offer changing the geometry
|
|
|
|
// in one call - what leads to 2 calls of the updateGeometry
|
|
|
|
// hook. Grmpf ...
|
|
|
|
|
|
|
|
Q_D( QQuickItem );
|
|
|
|
|
2021-09-21 08:51:01 +02:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK( 6, 2, 0 )
|
|
|
|
d->heightValidFlag = true;
|
|
|
|
d->widthValidFlag = true;
|
|
|
|
#else
|
2019-09-04 06:59:43 +02:00
|
|
|
d->heightValid = true;
|
|
|
|
d->widthValid = true;
|
2021-09-21 08:51:01 +02:00
|
|
|
#endif
|
2019-09-04 06:59:43 +02:00
|
|
|
|
|
|
|
const QRectF oldRect( d->x, d->y, d->width, d->height );
|
|
|
|
|
|
|
|
int dirtyType = 0;
|
|
|
|
|
|
|
|
if ( d->x != x || d->y != y )
|
|
|
|
{
|
|
|
|
d->x = x;
|
|
|
|
d->y = y;
|
|
|
|
|
|
|
|
dirtyType |= QQuickItemPrivate::Position;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( d->width != width || d->height != height )
|
|
|
|
{
|
|
|
|
d->height = height;
|
|
|
|
d->width = width;
|
|
|
|
|
|
|
|
dirtyType |= QQuickItemPrivate::Size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( dirtyType )
|
|
|
|
{
|
|
|
|
if ( dirtyType & QQuickItemPrivate::Position )
|
|
|
|
d->dirty( QQuickItemPrivate::Position );
|
|
|
|
|
|
|
|
if ( dirtyType & QQuickItemPrivate::Size )
|
|
|
|
d->dirty( QQuickItemPrivate::Size );
|
|
|
|
|
|
|
|
/*
|
2020-10-26 17:59:19 +01:00
|
|
|
Unfortunately geometryChange(d) is protected and we can't implement
|
2019-09-04 06:59:43 +02:00
|
|
|
this code as qskSetItemGeometry - further hacking required: TODO ...
|
|
|
|
*/
|
|
|
|
|
2020-10-26 17:59:19 +01:00
|
|
|
const QRectF newRect( d->x, d->y, d->width, d->height );
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
|
|
|
geometryChange( newRect, oldRect );
|
|
|
|
#else
|
|
|
|
geometryChanged( newRect, oldRect );
|
|
|
|
#endif
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
QRectF QskItem::rect() const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
Q_D( const QQuickItem );
|
|
|
|
return QRectF( 0, 0, d->width, d->height );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
QRectF QskItem::geometry() const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
Q_D( const QQuickItem );
|
|
|
|
return QRectF( d->x, d->y, d->width, d->height );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::setTabFence( bool on )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
Q_D( QQuickItem );
|
|
|
|
if ( on != d->isTabFence )
|
|
|
|
{
|
|
|
|
d->isTabFence = on;
|
|
|
|
Q_EMIT itemFlagsChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
bool QskItem::isTabFence() const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
return d_func()->isTabFence;
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::setFocusPolicy( Qt::FocusPolicy policy )
|
2024-02-02 09:48:26 +01:00
|
|
|
{
|
2024-02-02 12:38:03 +01:00
|
|
|
/*
|
|
|
|
Qt::FocusPolicy has always been there with widgets, got lost with
|
|
|
|
Qt/Quick and has been reintroduced with Qt/Quick Controls 2 ( QC2 ).
|
|
|
|
Unfortunately this was done by adding code on top instead of fixing
|
|
|
|
the foundation.
|
|
|
|
*/
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( QskItem );
|
2024-02-02 09:48:26 +01:00
|
|
|
if ( policy != d->focusPolicy )
|
|
|
|
{
|
|
|
|
d->focusPolicy = ( policy & ~Qt::TabFocus );
|
|
|
|
|
|
|
|
const bool tabFocus = policy & Qt::TabFocus;
|
|
|
|
|
|
|
|
if ( !tabFocus && window() )
|
|
|
|
{
|
2024-02-02 12:38:03 +01:00
|
|
|
// removing the activeFocusItem from the focus tab chain is not possible
|
2024-02-02 09:48:26 +01:00
|
|
|
if ( window()->activeFocusItem() == this )
|
|
|
|
{
|
|
|
|
if ( auto focusItem = nextItemInFocusChain( true ) )
|
|
|
|
focusItem->setFocus( true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Inherited::setActiveFocusOnTab( tabFocus );
|
|
|
|
|
|
|
|
Q_EMIT focusPolicyChanged( focusPolicy() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
Qt::FocusPolicy QskItem::focusPolicy() const
|
2024-02-02 09:48:26 +01:00
|
|
|
{
|
|
|
|
uint policy = d_func()->focusPolicy;
|
|
|
|
if ( Inherited::activeFocusOnTab() )
|
|
|
|
policy |= Qt::TabFocus;
|
|
|
|
|
|
|
|
return static_cast< Qt::FocusPolicy >( policy );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::setWheelEnabled( bool on )
|
2024-02-02 09:48:26 +01:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( QskItem );
|
2024-02-02 09:48:26 +01:00
|
|
|
if ( on != d->wheelEnabled )
|
|
|
|
{
|
|
|
|
d->wheelEnabled = on;
|
|
|
|
Q_EMIT wheelEnabledChanged( on );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
bool QskItem::isWheelEnabled() const
|
2024-02-02 09:48:26 +01:00
|
|
|
{
|
|
|
|
return d_func()->wheelEnabled;
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::setPolishOnResize( bool on )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( QskItem );
|
2019-09-04 06:59:43 +02:00
|
|
|
if ( on != d->polishOnResize )
|
|
|
|
{
|
|
|
|
d->polishOnResize = on;
|
|
|
|
polish();
|
|
|
|
|
|
|
|
Q_EMIT itemFlagsChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
bool QskItem::polishOnResize() const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
return d_func()->polishOnResize;
|
|
|
|
}
|
|
|
|
|
2024-02-08 11:33:42 +01:00
|
|
|
void QskItem::setPolishOnParentResize( bool on )
|
|
|
|
{
|
|
|
|
Q_D( QskItem );
|
|
|
|
if ( on != d->polishOnParentResize )
|
|
|
|
{
|
|
|
|
d->polishOnParentResize = on;
|
|
|
|
|
|
|
|
if ( parentItem() && qskParentListener )
|
|
|
|
{
|
|
|
|
qskParentListener->update( parentItem() );
|
|
|
|
|
|
|
|
resetImplicitSize();
|
|
|
|
polish();
|
|
|
|
}
|
|
|
|
|
|
|
|
Q_EMIT itemFlagsChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskItem::polishOnParentResize() const
|
|
|
|
{
|
|
|
|
return d_func()->polishOnParentResize;
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
bool QskItem::layoutMirroring() const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2021-02-03 13:20:23 +01:00
|
|
|
#if 1
|
|
|
|
/*
|
|
|
|
What about using Qt::LayoutDirection instead. It sounds
|
|
|
|
like a more expressive API and we do not run into conflicts
|
|
|
|
with the layoutMirroring() attached property for QML.
|
|
|
|
But what is the situation with locales, where the default direction
|
|
|
|
is RightToLeft ?
|
|
|
|
*/
|
2019-09-04 06:59:43 +02:00
|
|
|
return d_func()->effectiveLayoutMirror;
|
2021-02-03 13:20:23 +01:00
|
|
|
#endif
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::setLayoutMirroring( bool on, bool childrenInherit )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
// Again we have to deal with an existing API made for QML,
|
|
|
|
// that is weired for C++: LayoutMirroring/QQuickLayoutMirroringAttached
|
|
|
|
// Internally it is managed by 5(!) different flags - condolences
|
|
|
|
// to the poor guy who has been sentenced to maintain this.
|
|
|
|
|
|
|
|
// Anyway, the code below might achieve the desired behavior without
|
|
|
|
// breaking the QML path.
|
|
|
|
|
|
|
|
Q_D( QQuickItem );
|
|
|
|
|
2021-02-03 13:20:23 +01:00
|
|
|
if ( childrenInherit != d->inheritMirrorFromItem )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2021-02-03 13:20:23 +01:00
|
|
|
d->inheritMirrorFromItem = childrenInherit;
|
2019-09-04 06:59:43 +02:00
|
|
|
d->resolveLayoutMirror();
|
|
|
|
}
|
|
|
|
|
|
|
|
d->isMirrorImplicit = false;
|
|
|
|
|
|
|
|
if ( on != d->effectiveLayoutMirror )
|
|
|
|
{
|
|
|
|
d->setLayoutMirror( on );
|
2021-02-03 13:20:23 +01:00
|
|
|
if ( childrenInherit )
|
2019-09-04 06:59:43 +02:00
|
|
|
d->resolveLayoutMirror();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::resetLayoutMirroring()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
Q_D( QQuickItem );
|
|
|
|
|
|
|
|
if ( d && !d->isMirrorImplicit )
|
|
|
|
{
|
|
|
|
d->isMirrorImplicit = true;
|
|
|
|
// d->inheritMirrorFromItem = false;
|
|
|
|
d->resolveLayoutMirror();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
bool QskItem::isPolishScheduled() const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
return d_func()->polishScheduled;
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
bool QskItem::isUpdateNodeScheduled() const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( const QskItem );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
|
|
|
return ( d->dirtyAttributes & QQuickItemPrivate::ContentUpdateMask ) &&
|
|
|
|
( d->flags & QQuickItem::ItemHasContents );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
bool QskItem::isInitiallyPainted() const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2021-02-01 10:09:37 +01:00
|
|
|
return d_func()->initiallyPainted;
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
bool QskItem::maybeUnresized() const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( const QskItem );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
|
|
|
if ( d->width <= 0.0 && d->height <= 0.0 )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Unfortunately the list of items to-be-polished is not processed
|
|
|
|
in top/down order and we might run into updatePolish() before
|
|
|
|
having a proper size. But when the parentItem() is waiting
|
|
|
|
for to-be-polished, we assume, that we will be resized then
|
|
|
|
and run into another updatePolish() then.
|
|
|
|
*/
|
|
|
|
if ( d->polishOnResize && qskIsPolishScheduled( parentItem() ) )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
QskItem::UpdateFlags QskItem::updateFlags() const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2021-02-09 08:13:20 +01:00
|
|
|
return UpdateFlags( d_func()->updateFlags );
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::resetUpdateFlags()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( QskItem );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
|
|
|
// clear all bits in the mask
|
2021-02-09 08:13:20 +01:00
|
|
|
d->updateFlagsMask = 0;
|
2024-02-02 15:01:43 +01:00
|
|
|
d->applyUpdateFlags( QskSetup::updateFlags() );
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::setUpdateFlag( UpdateFlag flag, bool on )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( QskItem );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2021-02-09 08:13:20 +01:00
|
|
|
d->updateFlagsMask |= flag;
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2021-02-09 08:13:20 +01:00
|
|
|
if ( testUpdateFlag( flag ) != on )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2021-02-09 08:13:20 +01:00
|
|
|
applyUpdateFlag( flag, on );
|
|
|
|
Q_EMIT updateFlagsChanged( updateFlags() );
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::resetUpdateFlag( UpdateFlag flag )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( QskItem );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2021-02-09 08:13:20 +01:00
|
|
|
d->updateFlagsMask &= ~flag;
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2024-02-02 15:01:43 +01:00
|
|
|
const bool on = QskSetup::testUpdateFlag( flag );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2021-02-09 08:13:20 +01:00
|
|
|
if ( testUpdateFlag( flag ) != on )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2021-02-09 08:13:20 +01:00
|
|
|
applyUpdateFlag( flag, on );
|
|
|
|
Q_EMIT updateFlagsChanged( updateFlags() );
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
bool QskItem::testUpdateFlag( UpdateFlag flag ) const
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2021-02-09 08:13:20 +01:00
|
|
|
return d_func()->updateFlags & flag;
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::applyUpdateFlag( UpdateFlag flag, bool on )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( QskItem );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2021-02-09 08:13:20 +01:00
|
|
|
if ( testUpdateFlag( flag ) == on )
|
2019-09-04 06:59:43 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
if ( on )
|
2021-02-09 08:13:20 +01:00
|
|
|
d->updateFlags |= flag;
|
2019-09-04 06:59:43 +02:00
|
|
|
else
|
2021-02-09 08:13:20 +01:00
|
|
|
d->updateFlags &= ~flag;
|
2019-09-04 06:59:43 +02:00
|
|
|
|
|
|
|
switch ( flag )
|
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
case QskItem::DeferredUpdate:
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
if ( on )
|
|
|
|
{
|
|
|
|
qskFilterWindow( window() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( !isVisible() )
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2024-02-02 14:13:33 +01:00
|
|
|
case QskItem::DeferredPolish:
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
if ( !on && d->blockedPolish )
|
|
|
|
polish();
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2024-02-02 14:13:33 +01:00
|
|
|
case QskItem::DeferredLayout:
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
if ( !on )
|
|
|
|
{
|
|
|
|
// Update the implicitSize and rebind the size to it.
|
|
|
|
// Having set the size explicitly gets lost.
|
|
|
|
|
2021-09-21 08:51:01 +02:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK( 6, 2, 0 )
|
|
|
|
d->widthValidFlag = d->heightValidFlag = false;
|
|
|
|
#else
|
2019-09-04 06:59:43 +02:00
|
|
|
d->widthValid = d->heightValid = false;
|
2021-09-21 08:51:01 +02:00
|
|
|
#endif
|
2019-09-04 06:59:43 +02:00
|
|
|
d->updateImplicitSize( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2024-02-02 14:13:33 +01:00
|
|
|
case QskItem::CleanupOnVisibility:
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
if ( on && !isVisible() )
|
|
|
|
d->cleanupNodes();
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2024-02-02 14:13:33 +01:00
|
|
|
case QskItem::DebugForceBackground:
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
// no need to mark it dirty
|
|
|
|
if ( flags() & QQuickItem::ItemHasContents )
|
|
|
|
update();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::resetImplicitSize()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( QskItem );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
if ( d->updateFlags & QskItem::DeferredLayout )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
d->blockedImplicitSize = true;
|
|
|
|
d->layoutConstraintChanged();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d->updateImplicitSize( true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
bool QskItem::event( QEvent* event )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
const int eventType = event->type();
|
2021-03-03 08:25:39 +01:00
|
|
|
const bool hasContents = flags() & QQuickItem::ItemHasContents;
|
2019-09-04 06:59:43 +02:00
|
|
|
|
|
|
|
switch( eventType )
|
|
|
|
{
|
|
|
|
case QEvent::StyleChange:
|
|
|
|
{
|
|
|
|
d_func()->clearPreviousNodes = true;
|
|
|
|
|
|
|
|
resetImplicitSize();
|
|
|
|
polish();
|
|
|
|
|
2021-03-03 08:25:39 +01:00
|
|
|
if ( hasContents )
|
2019-09-04 06:59:43 +02:00
|
|
|
update();
|
|
|
|
|
|
|
|
changeEvent( event );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case QEvent::ContentsRectChange:
|
|
|
|
{
|
2021-02-11 12:45:17 +01:00
|
|
|
resetImplicitSize();
|
|
|
|
|
2021-03-03 08:25:39 +01:00
|
|
|
if ( d_func()->polishOnResize )
|
2019-09-04 06:59:43 +02:00
|
|
|
polish();
|
|
|
|
|
2021-03-03 08:25:39 +01:00
|
|
|
if ( hasContents )
|
2021-02-11 12:45:17 +01:00
|
|
|
update();
|
|
|
|
|
2019-09-04 06:59:43 +02:00
|
|
|
changeEvent( event );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case QEvent::ReadOnlyChange:
|
2021-02-09 12:26:58 +01:00
|
|
|
case QEvent::EnabledChange:
|
|
|
|
case QEvent::LocaleChange:
|
2019-09-04 06:59:43 +02:00
|
|
|
case QEvent::ParentChange:
|
2021-03-03 08:25:39 +01:00
|
|
|
case QEvent::LayoutDirectionChange:
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
changeEvent( event );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case QskEvent::GeometryChange:
|
|
|
|
{
|
|
|
|
geometryChangeEvent( static_cast< QskGeometryChangeEvent* >( event ) );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case QskEvent::WindowChange:
|
|
|
|
{
|
|
|
|
windowChangeEvent( static_cast< QskWindowChangeEvent* >( event ) );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case QEvent::LayoutRequest:
|
|
|
|
{
|
|
|
|
if ( d_func()->polishOnResize )
|
|
|
|
polish();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2021-02-23 12:04:55 +01:00
|
|
|
case QEvent::FocusIn:
|
|
|
|
{
|
|
|
|
if ( window() == nullptr )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
During deconstruction of the window we run into
|
|
|
|
focus changes when the items in the tree get destroyed.
|
|
|
|
Calling focusInEvent() in this state does not make sense
|
|
|
|
and often results in crashes in overloaded event handlers.
|
|
|
|
*/
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-02-02 12:38:03 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QEvent::MouseButtonPress:
|
|
|
|
case QEvent::MouseButtonRelease:
|
|
|
|
{
|
|
|
|
if ( ( focusPolicy() & Qt::ClickFocus ) == Qt::ClickFocus )
|
|
|
|
{
|
|
|
|
if ( QGuiApplication::styleHints()->setFocusOnTouchRelease() )
|
|
|
|
{
|
|
|
|
if ( event->type() == QEvent::MouseButtonRelease )
|
|
|
|
forceActiveFocus( Qt::MouseFocusReason );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( event->type() == QEvent::MouseButtonPress )
|
|
|
|
forceActiveFocus( Qt::MouseFocusReason );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QEvent::Wheel:
|
|
|
|
{
|
|
|
|
if ( !isWheelEnabled() )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
We block further processing of the event. This is in line
|
|
|
|
with not receiving any mouse event that have not been
|
|
|
|
explicitly enabled with setAcceptedMouseButtons().
|
|
|
|
*/
|
|
|
|
event->ignore();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ( focusPolicy() & Qt::WheelFocus ) == Qt::WheelFocus )
|
|
|
|
forceActiveFocus( Qt::MouseFocusReason );
|
|
|
|
|
2021-02-23 12:04:55 +01:00
|
|
|
break;
|
|
|
|
}
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return Inherited::event( event );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::windowChangeEvent( QskWindowChangeEvent* )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::geometryChangeEvent( QskGeometryChangeEvent* )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::changeEvent( QEvent* )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::itemChange( QQuickItem::ItemChange change,
|
2021-02-09 12:26:58 +01:00
|
|
|
const QQuickItem::ItemChangeData& changeData )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
switch ( change )
|
|
|
|
{
|
|
|
|
case QQuickItem::ItemSceneChange:
|
|
|
|
{
|
2021-02-09 12:26:58 +01:00
|
|
|
if ( changeData.window )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( const QskItem );
|
|
|
|
if ( d->updateFlags & QskItem::DeferredUpdate )
|
2021-02-09 12:26:58 +01:00
|
|
|
qskFilterWindow( changeData.window );
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
auto oldWindow = qskReleasedWindowCounter->window();
|
2021-04-26 15:11:19 +02:00
|
|
|
|
|
|
|
if ( oldWindow && oldWindow->contentItem()
|
|
|
|
&& ( oldWindow->activeFocusItem() == this ) )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
Removing an item from the scene might result in
|
|
|
|
changes of the active focus item. Unfortunately the corresponding
|
|
|
|
FocusIn/Out events are sent, while the item tree is in an
|
|
|
|
invalid state.
|
|
|
|
When having event handlers, that do modifications of the focus
|
|
|
|
( f.e. assigning the local focus, inside of a focus scope )
|
|
|
|
we might end up with having a dangling pointer for
|
|
|
|
oldWindow->activeFocusItem().
|
|
|
|
*/
|
2021-03-11 17:32:59 +01:00
|
|
|
|
2021-04-26 11:44:25 +02:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK( 6, 1, 0 )
|
|
|
|
auto wd = QQuickWindowPrivate::get( oldWindow )->deliveryAgentPrivate();
|
2021-08-04 09:31:16 +02:00
|
|
|
#else
|
2021-03-11 17:32:59 +01:00
|
|
|
auto wd = QQuickWindowPrivate::get( oldWindow );
|
2021-04-26 11:44:25 +02:00
|
|
|
#endif
|
2021-03-11 17:32:59 +01:00
|
|
|
if ( auto scope = qskNearestFocusScope( this ) )
|
|
|
|
{
|
|
|
|
wd->clearFocusInScope( scope, this, Qt::OtherFocusReason );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wd->activeFocusItem = nullptr;
|
|
|
|
}
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-03-06 10:51:14 +01:00
|
|
|
#if 1
|
2021-02-09 12:26:58 +01:00
|
|
|
if ( changeData.window == nullptr )
|
2020-03-06 10:51:14 +01:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( QskItem );
|
2020-03-06 10:51:14 +01:00
|
|
|
|
|
|
|
if( d->focus )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
The focus flag is not cleared, when removing an
|
|
|
|
item from the window. In situations where the item gets
|
|
|
|
reinserted into the window - or transferred to another one -
|
|
|
|
we might run into situations, where 2 items in the same scope
|
|
|
|
have the "focus" flag being set.
|
|
|
|
A better solution might be to check the flag when reinserting
|
|
|
|
into a window ...
|
|
|
|
*/
|
|
|
|
d->focus = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-02-09 12:26:58 +01:00
|
|
|
QskWindowChangeEvent event( oldWindow, changeData.window );
|
2019-09-04 06:59:43 +02:00
|
|
|
QCoreApplication::sendEvent( this, &event );
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QQuickItem::ItemEnabledHasChanged:
|
|
|
|
{
|
2022-03-08 11:53:46 +01:00
|
|
|
qskSendEventTo( this, QEvent::EnabledChange );
|
2019-09-04 06:59:43 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QQuickItem::ItemVisibleHasChanged:
|
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( QskItem );
|
2019-09-04 06:59:43 +02:00
|
|
|
#if 1
|
|
|
|
/*
|
|
|
|
~QQuickItem sends QQuickItem::ItemVisibleHasChanged recursively
|
|
|
|
to all childItems. When being a child ( not only a childItem() )
|
|
|
|
we are short before being destructed too and any updates
|
|
|
|
done here are totally pointless. TODO ...
|
|
|
|
*/
|
|
|
|
#endif
|
2021-02-09 12:26:58 +01:00
|
|
|
if ( changeData.boolValue )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
if ( d->blockedPolish )
|
|
|
|
polish();
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
if ( d->updateFlags & QskItem::DeferredUpdate )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
if ( d->dirtyAttributes && ( d->flags & QQuickItem::ItemHasContents ) )
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
if ( d->updateFlags & QskItem::CleanupOnVisibility )
|
2019-09-04 06:59:43 +02:00
|
|
|
d->cleanupNodes();
|
|
|
|
|
2021-02-01 10:09:37 +01:00
|
|
|
d->initiallyPainted = false;
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( parentItem() && parentItem()->isVisible() )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Layout code might consider the visiblility of the children
|
|
|
|
and therefore needs to be updated. Posting a statement about
|
|
|
|
changed layout constraints has this effect, but is not correct.
|
|
|
|
The right way to go would be to create show/hide events and to
|
|
|
|
handle them, where visibility of the children matters.
|
|
|
|
TODO ...
|
|
|
|
*/
|
|
|
|
|
|
|
|
d->layoutConstraintChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QQuickItem::ItemParentHasChanged:
|
2024-02-08 11:33:42 +01:00
|
|
|
{
|
|
|
|
if( polishOnParentResize() && qskParentListener )
|
|
|
|
qskParentListener->update( parentItem() );
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2019-09-04 06:59:43 +02:00
|
|
|
case QQuickItem::ItemChildAddedChange:
|
|
|
|
case QQuickItem::ItemChildRemovedChange:
|
2021-02-09 12:26:58 +01:00
|
|
|
{
|
2021-02-11 12:45:17 +01:00
|
|
|
// do we want to have events for those ???
|
2021-02-09 12:26:58 +01:00
|
|
|
break;
|
|
|
|
}
|
2021-02-11 12:45:17 +01:00
|
|
|
|
2021-02-09 12:26:58 +01:00
|
|
|
case QQuickItem::ItemOpacityHasChanged:
|
|
|
|
case QQuickItem::ItemActiveFocusHasChanged:
|
|
|
|
case QQuickItem::ItemRotationHasChanged:
|
|
|
|
case QQuickItem::ItemAntialiasingHasChanged:
|
|
|
|
case QQuickItem::ItemDevicePixelRatioHasChanged:
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-09 12:26:58 +01:00
|
|
|
Inherited::itemChange( change, changeData );
|
2019-09-04 06:59:43 +02:00
|
|
|
}
|
|
|
|
|
2020-10-26 17:59:19 +01:00
|
|
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::geometryChanged(
|
2019-09-04 06:59:43 +02:00
|
|
|
const QRectF& newGeometry, const QRectF& oldGeometry )
|
|
|
|
{
|
2020-10-26 17:59:19 +01:00
|
|
|
geometryChange( newGeometry, oldGeometry );
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::geometryChange(
|
2020-10-26 17:59:19 +01:00
|
|
|
const QRectF& newGeometry, const QRectF& oldGeometry )
|
|
|
|
{
|
|
|
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
2019-09-04 06:59:43 +02:00
|
|
|
Inherited::geometryChanged( newGeometry, oldGeometry );
|
2020-10-26 17:59:19 +01:00
|
|
|
#else
|
|
|
|
Inherited::geometryChange( newGeometry, oldGeometry );
|
|
|
|
#endif
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( const QskItem );
|
2019-09-04 06:59:43 +02:00
|
|
|
if ( !d->polishScheduled && d->polishOnResize )
|
|
|
|
{
|
|
|
|
if ( newGeometry.size() != oldGeometry.size() )
|
|
|
|
polish();
|
|
|
|
}
|
|
|
|
|
|
|
|
QskGeometryChangeEvent event( newGeometry, oldGeometry );
|
|
|
|
QCoreApplication::sendEvent( this, &event );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::mouseUngrabEvent()
|
2021-02-26 12:42:49 +01:00
|
|
|
{
|
|
|
|
Inherited::mouseUngrabEvent();
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::touchUngrabEvent()
|
2021-02-26 12:42:49 +01:00
|
|
|
{
|
|
|
|
Inherited::touchUngrabEvent();
|
|
|
|
}
|
|
|
|
|
2021-03-02 17:09:38 +01:00
|
|
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::windowDeactivateEvent()
|
2021-02-26 12:42:49 +01:00
|
|
|
{
|
|
|
|
Inherited::windowDeactivateEvent();
|
|
|
|
}
|
|
|
|
|
2021-03-02 17:09:38 +01:00
|
|
|
#endif
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::updatePolish()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( QskItem );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
if ( d->updateFlags & QskItem::DeferredPolish )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
if ( !isVisible() )
|
|
|
|
{
|
|
|
|
d->blockedPolish = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
d->blockedPolish = false;
|
|
|
|
|
2021-02-01 10:09:37 +01:00
|
|
|
if ( !d->initiallyPainted )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
We should find a better way for identifying, when
|
|
|
|
an item is about to be shown, than making it dependend
|
|
|
|
from polishing and the existence of scene graph nodes. TODO ...
|
|
|
|
*/
|
|
|
|
aboutToShow();
|
|
|
|
}
|
|
|
|
|
|
|
|
updateItemPolish();
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::aboutToShow()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
void QskItem::updateItemPolish()
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
QSGNode* QskItem::updatePaintNode( QSGNode* node, UpdatePaintNodeData* data )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
2021-12-27 10:21:03 +01:00
|
|
|
Q_UNUSED( data )
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_D( QskItem );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
Q_ASSERT( isVisible() || !( d->updateFlags & QskItem::DeferredUpdate ) );
|
2019-09-04 06:59:43 +02:00
|
|
|
|
2021-02-01 10:09:37 +01:00
|
|
|
d->initiallyPainted = true;
|
2019-09-04 06:59:43 +02:00
|
|
|
|
|
|
|
if ( d->clearPreviousNodes )
|
|
|
|
{
|
|
|
|
delete node;
|
|
|
|
node = nullptr;
|
2024-01-24 17:34:58 +01:00
|
|
|
#if 1
|
|
|
|
/*
|
|
|
|
controls might find subnodes using qskPaintNode - not good
|
|
|
|
as d->paintNode is not updated before leaving here. TODO ...
|
|
|
|
|
|
|
|
In the initial call we will always have a nullptr - even if
|
|
|
|
it has already been allocated. When deleting it we have a dangling pointer.
|
|
|
|
instead of the new one.
|
|
|
|
|
2024-02-02 09:48:26 +01:00
|
|
|
To avoid creashes for the second situation we manually clear d->paintNode.
|
2024-01-24 17:34:58 +01:00
|
|
|
*/
|
|
|
|
d->paintNode = nullptr;
|
|
|
|
#endif
|
2019-09-04 06:59:43 +02:00
|
|
|
|
|
|
|
d->clearPreviousNodes = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return updateItemPaintNode( node );
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
QSGNode* QskItem::updateItemPaintNode( QSGNode* node )
|
2019-09-04 06:59:43 +02:00
|
|
|
{
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2024-02-02 15:01:43 +01:00
|
|
|
void qskUpdateItemFlags()
|
|
|
|
{
|
|
|
|
if ( qskRegistry )
|
|
|
|
qskRegistry->updateItemFlags();
|
|
|
|
}
|
|
|
|
|
2024-02-02 14:13:33 +01:00
|
|
|
#include "moc_QskItem.cpp"
|