6#include "QskLinearBox.h"
7#include "QskLinearLayoutEngine.h"
11static void qskSetItemActive( QObject* receiver,
const QQuickItem* item,
bool on )
20 auto sendLayoutRequest =
23 QEvent event( QEvent::LayoutRequest );
24 QCoreApplication::sendEvent( receiver, &event );
27 QObject::connect( item, &QQuickItem::implicitWidthChanged,
28 receiver, sendLayoutRequest );
30 QObject::connect( item, &QQuickItem::implicitHeightChanged,
31 receiver, sendLayoutRequest );
35 QObject::disconnect( item, &QQuickItem::implicitWidthChanged, receiver,
nullptr );
36 QObject::disconnect( item, &QQuickItem::implicitHeightChanged, receiver,
nullptr );
40class QskLinearBox::PrivateData
52 :
QskLinearBox( Qt::Horizontal, std::numeric_limits< uint >::max(), parent )
57 :
QskLinearBox( orientation, std::numeric_limits< uint >::max(), parent )
63 , m_data( new PrivateData( orientation, dimension ) )
69 auto& engine = m_data->engine;
71 for (
int i = 0; i < engine.count(); i++ )
73 if (
auto item = engine.itemAt( i ) )
80 setItemActive( item,
false );
85int QskLinearBox::elementCount()
const
87 return m_data->engine.count();
90qreal QskLinearBox::spacingAtIndex(
int index )
const
92 return m_data->engine.spacerAt( index );
95QQuickItem* QskLinearBox::itemAtIndex(
int index )
const
97 return m_data->engine.itemAt( index );
100int QskLinearBox::indexOf(
const QQuickItem* item )
const
102 return m_data->engine.indexOf( item );
105void QskLinearBox::removeAt(
int index )
107 removeItemInternal( index,
true );
110void QskLinearBox::removeItemInternal(
int index,
bool unparent )
112 auto& engine = m_data->engine;
114 if ( index < 0 || index >= engine.count() )
117 auto item = engine.itemAt( index );
118 engine.removeAt( index );
122 setItemActive( item,
false );
125 unparentItem( item );
132void QskLinearBox::removeItem(
const QQuickItem* item )
134 removeAt( indexOf( item ) );
137void QskLinearBox::clear(
bool autoDelete )
139 auto& engine = m_data->engine;
142 const bool hasVisibleElements = engine.rowCount() > 0;
144 for (
int i = engine.count() - 1; i >= 0; i-- )
146 auto item = engine.itemAt( i );
147 engine.removeAt( i );
151 setItemActive( item,
false );
153 if( autoDelete && ( item->parent() ==
this ) )
156 unparentItem( item );
160 if ( hasVisibleElements )
164void QskLinearBox::autoAddItem( QQuickItem* item )
166 insertItem( -1, item );
169void QskLinearBox::autoRemoveItem( QQuickItem* item )
171 removeItemInternal( indexOf( item ),
false );
174void QskLinearBox::activate()
179void QskLinearBox::invalidate()
181 m_data->engine.invalidate();
187void QskLinearBox::setItemActive( QQuickItem* item,
bool on )
191 QObject::connect( item, &QQuickItem::visibleChanged,
192 this, &QskLinearBox::invalidate );
196 QObject::disconnect( item, &QQuickItem::visibleChanged,
197 this, &QskLinearBox::invalidate );
200 if ( qskControlCast( item ) ==
nullptr )
201 qskSetItemActive(
this, item, on );
204void QskLinearBox::updateLayout()
210QSizeF QskLinearBox::layoutSizeHint(
211 Qt::SizeHint which,
const QSizeF& constraint )
const
213 if ( which == Qt::MaximumSize )
219 return m_data->engine.sizeHint( which, constraint );
226 if ( event->isResized() )
231void QskLinearBox::itemChange( ItemChange change,
const ItemChangeData& value )
236 if ( change == QQuickItem::ItemVisibleHasChanged )
239 if ( value.boolValue )
245bool QskLinearBox::event( QEvent* event )
247 switch (
static_cast< int >( event->type() ) )
249 case QEvent::LayoutRequest:
254 case QEvent::LayoutDirectionChange:
256 m_data->engine.setVisualDirection(
262 case QEvent::ContentsRectChange:
269 return Inherited::event( event );
274 if ( m_data->engine.setDimension(
dimension ) )
285 return m_data->engine.dimension();
290 if ( m_data->engine.setOrientation(
orientation ) )
301 return m_data->engine.orientation();
306 auto& engine = m_data->engine;
311 for (
int i = 0; i < engine.itemCount(); i++ )
313 auto alignment = engine.alignmentAt( i );
314 qbswap(
static_cast< quint16
>( alignment ) );
315 engine.setAlignmentAt( i, alignment );
321 if ( engine.orientation() == Qt::Horizontal )
327void QskLinearBox::setDefaultAlignment( Qt::Alignment alignment )
329 if ( m_data->engine.setDefaultAlignment( alignment ) )
330 Q_EMIT defaultAlignmentChanged();
333Qt::Alignment QskLinearBox::defaultAlignment()
const
335 return m_data->engine.defaultAlignment();
346 if ( m_data->engine.setSpacing(
347 spacing, Qt::Horizontal | Qt::Vertical ) )
356 const qreal
spacing = m_data->engine.defaultSpacing( Qt::Horizontal );
363 return m_data->engine.spacing( Qt::Horizontal );
366void QskLinearBox::setExtraSpacingAt( Qt::Edges edges )
368 if ( edges != m_data->engine.extraSpacingAt() )
370 m_data->engine.setExtraSpacingAt( edges );
373 Q_EMIT extraSpacingAtChanged();
377Qt::Edges QskLinearBox::extraSpacingAt()
const
379 return m_data->engine.extraSpacingAt();
382int QskLinearBox::addItem( QQuickItem* item, Qt::Alignment alignment )
384 return insertItem( -1, item, alignment );
387int QskLinearBox::addItem( QQuickItem* item )
389 return insertItem( -1, item );
392int QskLinearBox::insertItem(
393 int index, QQuickItem* item, Qt::Alignment alignment )
395 if (
auto control = qskControlCast( item ) )
396 control->setLayoutAlignmentHint( alignment );
398 return insertItem( index, item );
401int QskLinearBox::insertItem(
int index, QQuickItem* item )
403 if ( item ==
nullptr || item ==
this )
406 if ( !qskPlacementPolicy( item ).isEffective() )
408 qWarning() <<
"Inserting an item that is to be ignored for layouting:"
409 << item->metaObject()->className();
414 auto& engine = m_data->engine;
416 if ( item->parentItem() ==
this )
418 const int oldIndex = indexOf( item );
423 const bool doAppend = index < 0 || index >= engine.count();
425 if ( ( index == oldIndex ) ||
426 ( doAppend && oldIndex == engine.count() - 1 ) )
432 removeAt( oldIndex );
436 reparentItem( item );
438 index = engine.insertItem( item, index );
442 bool reordered =
false;
444 if ( index < engine.count() - 1 )
446 for (
int i = index + 1; i < engine.count(); i++ )
448 if (
auto nextItem = engine.itemAt( i ) )
450 item->stackBefore( nextItem );
460 const auto children = childItems();
461 if ( item != children.last() )
462 item->stackAfter( children.last() );
465 setItemActive( item,
true );
483 auto& engine = m_data->engine;
485 const int numItems = engine.count();
486 if ( index < 0 || index > numItems )
489 index = engine.insertSpacerAt( index,
spacing );
515 auto& engine = m_data->engine;
526 return m_data->engine.stretchFactorAt( index );
539void QskLinearBox::dump()
const
541 const auto& engine = m_data->engine;
543 auto debug = qDebug();
545 QDebugStateSaver saver(
debug );
550 debug <<
"QskLinearBox" << engine.orientation()
551 <<
" w:" << constraint.width() <<
" h:" << constraint.height() <<
'\n';
553 for (
int i = 0; i < engine.count(); i++ )
555 debug <<
" " << i <<
": ";
557 if (
auto item = engine.itemAt( i ) )
559 const auto size = qskSizeConstraint( item, Qt::PreferredSize );
560 debug << item->metaObject()->className()
561 <<
" w:" << size.width() <<
" h:" << size.height();
565 debug <<
"spacer: " << engine.spacerAt( i );
572#include "moc_QskLinearBox.cpp"
QRectF layoutRect() const
Base class of layouts with index ordered elements.
void itemChange(ItemChange, const ItemChangeData &) override
virtual void geometryChangeEvent(QskGeometryChangeEvent *)
bool maybeUnresized() const
bool layoutMirroring() const
Layout stringing items in rows and columns.
Q_INVOKABLE int stretchFactor(int index) const
void resetSpacing()
Reset the global spacing to its initial value.
Q_INVOKABLE int insertSpacer(int index, qreal spacing, int stretchFactor=0)
Insert a spacer at a specific position.
void orientationChanged()
uint dimension
Upper limit for the number of elements in a row or column.
QskLinearBox(QQuickItem *parent=nullptr)
Create a row layout.
void setSpacing(qreal spacing)
Set the global spacing of the layout.
void setDimension(uint)
Set the dimension of the layout.
qreal spacing
Global layout spacing.
void setOrientation(Qt::Orientation)
Set the orientation of the layout.
Q_INVOKABLE void setStretchFactor(int index, int stretchFactor)
Modify the stretch factor of a layout element.
void transpose()
Invert the orientation of the layout.
Q_INVOKABLE int addStretch(int stretchFactor=0)
Append a stretch to the layout.
Qt::Orientation orientation
Direction of flow for laying out the items.
Q_INVOKABLE int insertStretch(int index, int stretchFactor=0)
Insert a stretch at a specific position.
void geometryChangeEvent(QskGeometryChangeEvent *) override
Q_INVOKABLE int addSpacer(qreal spacing, int stretchFactor=0)
Append a spacer to the layout.
void debug(QskAspect) const