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 "QskGridBox.h"
|
|
|
|
#include "QskLayoutEngine.h"
|
2018-08-03 08:15:28 +02:00
|
|
|
#include "QskLayoutItem.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
class QskGridBox::PrivateData
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
public:
|
|
|
|
PrivateData()
|
|
|
|
: isExpanding( false )
|
|
|
|
, unlimitedSpanned( 0 )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isExpanding;
|
|
|
|
unsigned int unlimitedSpanned;
|
|
|
|
};
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskGridBox::QskGridBox( QQuickItem* parent )
|
|
|
|
: QskLayout( parent )
|
|
|
|
, m_data( new PrivateData() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QskGridBox::~QskGridBox()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::addItem( QQuickItem* item,
|
|
|
|
int row, int column, int rowSpan, int columnSpan,
|
|
|
|
Qt::Alignment alignment )
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
auto layoutItem = new QskLayoutItem( item, row, column, rowSpan, columnSpan );
|
2017-07-21 18:21:34 +02:00
|
|
|
layoutItem->setAlignment( alignment );
|
|
|
|
|
|
|
|
const int index = itemCount(); // position and index doesn't match
|
|
|
|
|
|
|
|
setupLayoutItem( layoutItem, index );
|
|
|
|
insertItemInternal( layoutItem, -1 );
|
|
|
|
layoutItemInserted( layoutItem, index );
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskGridBox::rowCount() const
|
|
|
|
{
|
|
|
|
return engine().effectiveLastRow( Qt::Vertical ) + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskGridBox::columnCount() const
|
|
|
|
{
|
|
|
|
return engine().effectiveLastRow( Qt::Horizontal ) + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
QQuickItem* QskGridBox::itemAt( int row, int column ) const
|
|
|
|
{
|
|
|
|
QskLayoutItem* layoutItem = engine().layoutItemAt( row, column );
|
|
|
|
if ( layoutItem )
|
|
|
|
return layoutItem->item();
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskGridBox::indexAt( int row, int column ) const
|
|
|
|
{
|
|
|
|
return engine().indexAt( row, column );
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskGridBox::rowOfIndex( int index ) const
|
|
|
|
{
|
|
|
|
QskLayoutItem* layoutItem = engine().layoutItemAt( index );
|
|
|
|
if ( layoutItem == nullptr )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return layoutItem->firstRow();
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskGridBox::rowSpanOfIndex( int index ) const
|
|
|
|
{
|
|
|
|
QskLayoutItem* layoutItem = engine().layoutItemAt( index );
|
|
|
|
if ( layoutItem == nullptr )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return layoutItem->rowSpan();
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskGridBox::columnOfIndex( int index ) const
|
|
|
|
{
|
|
|
|
QskLayoutItem* layoutItem = engine().layoutItemAt( index );
|
|
|
|
if ( layoutItem == nullptr )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return layoutItem->firstColumn();
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskGridBox::columnSpanOfIndex( int index ) const
|
|
|
|
{
|
|
|
|
QskLayoutItem* layoutItem = engine().layoutItemAt( index );
|
|
|
|
if ( layoutItem == nullptr )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return layoutItem->columnSpan();
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setupLayoutItem( QskLayoutItem* layoutItem, int index )
|
|
|
|
{
|
|
|
|
Q_UNUSED( index )
|
|
|
|
|
|
|
|
QskLayoutEngine& engine = this->engine();
|
|
|
|
|
|
|
|
m_data->isExpanding = ( layoutItem->lastColumn() >= engine.columnCount() ) ||
|
|
|
|
( layoutItem->lastRow() >= engine.rowCount() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::layoutItemInserted( QskLayoutItem* layoutItem, int index )
|
|
|
|
{
|
|
|
|
Q_UNUSED( index )
|
|
|
|
|
|
|
|
if ( m_data->isExpanding )
|
|
|
|
{
|
|
|
|
// the new item has extended the number of rows/columns and
|
|
|
|
// we need to adjust all items without fixed spanning
|
|
|
|
|
|
|
|
if ( m_data->unlimitedSpanned > 0 )
|
|
|
|
engine().adjustSpans( columnCount(), rowCount() );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( layoutItem->hasUnlimitedSpan() )
|
|
|
|
{
|
|
|
|
// the item itself might need to be adjusted
|
|
|
|
|
|
|
|
if ( layoutItem->hasUnlimitedSpan( Qt::Horizontal ) )
|
|
|
|
{
|
|
|
|
const int span = columnCount() - layoutItem->firstColumn();
|
|
|
|
layoutItem->setRowSpan( span, Qt::Horizontal );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( layoutItem->hasUnlimitedSpan( Qt::Vertical ) )
|
|
|
|
{
|
|
|
|
const int span = rowCount() - layoutItem->firstRow();
|
|
|
|
layoutItem->setRowSpan( span, Qt::Vertical );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_data->unlimitedSpanned++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::layoutItemRemoved( QskLayoutItem* layoutItem, int index )
|
|
|
|
{
|
|
|
|
Q_UNUSED( index )
|
|
|
|
|
|
|
|
if ( layoutItem->hasUnlimitedSpan() )
|
|
|
|
m_data->unlimitedSpanned--;
|
|
|
|
|
|
|
|
QskLayoutEngine& engine = this->engine();
|
|
|
|
|
|
|
|
// cleanup rows/columns
|
|
|
|
|
|
|
|
const QSize cells = engine.requiredCells();
|
|
|
|
|
|
|
|
const int numPendingColumns = engine.columnCount() - cells.width();
|
|
|
|
const int numPendingRows = engine.rowCount() - cells.height();
|
|
|
|
|
|
|
|
if ( numPendingColumns > 0 || numPendingRows > 0 )
|
|
|
|
{
|
|
|
|
if ( m_data->unlimitedSpanned > 0 )
|
|
|
|
engine.adjustSpans( cells.height(), cells.width() );
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
engine.removeRows( cells.width(), numPendingColumns, Qt::Horizontal );
|
|
|
|
engine.removeRows( cells.height(), numPendingRows, Qt::Vertical );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setSpacing( qreal spacing )
|
|
|
|
{
|
|
|
|
setHorizontalSpacing( spacing );
|
|
|
|
setVerticalSpacing( spacing );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setHorizontalSpacing( qreal spacing )
|
|
|
|
{
|
|
|
|
spacing = qMax( spacing, 0.0 );
|
|
|
|
|
|
|
|
if ( spacing != engine().spacing( Qt::Horizontal ) )
|
|
|
|
{
|
|
|
|
engine().setSpacing( spacing, Qt::Horizontal );
|
|
|
|
activate();
|
|
|
|
|
|
|
|
Q_EMIT horizontalSpacingChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-07 17:04:05 +01:00
|
|
|
qreal QskGridBox::horizontalSpacing() const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
return engine().spacing( Qt::Horizontal );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::resetHorizontalSpacing()
|
|
|
|
{
|
|
|
|
const qreal spacing = QskLayoutEngine::defaultSpacing( Qt::Horizontal );
|
|
|
|
setHorizontalSpacing( spacing );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setVerticalSpacing( qreal spacing )
|
|
|
|
{
|
|
|
|
spacing = qMax( spacing, 0.0 );
|
|
|
|
|
|
|
|
if ( spacing != engine().spacing( Qt::Vertical ) )
|
|
|
|
{
|
|
|
|
engine().setSpacing( spacing, Qt::Vertical );
|
|
|
|
activate();
|
|
|
|
|
|
|
|
Q_EMIT verticalSpacingChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-07 17:04:05 +01:00
|
|
|
qreal QskGridBox::verticalSpacing() const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
return engine().spacing( Qt::Vertical );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::resetVerticalSpacing()
|
|
|
|
{
|
|
|
|
const qreal spacing = QskLayoutEngine::defaultSpacing( Qt::Vertical );
|
|
|
|
setVerticalSpacing( spacing );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setRowSpacing( int row, qreal spacing )
|
|
|
|
{
|
|
|
|
spacing = qMax( spacing, 0.0 );
|
|
|
|
|
|
|
|
if ( spacing != engine().rowSpacing( row, Qt::Vertical ) )
|
|
|
|
{
|
|
|
|
engine().setRowSpacing( row, spacing, Qt::Vertical );
|
|
|
|
activate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskGridBox::rowSpacing( int row ) const
|
|
|
|
{
|
|
|
|
return engine().rowSpacing( row, Qt::Vertical );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setColumnSpacing( int column, qreal spacing )
|
|
|
|
{
|
|
|
|
spacing = qMax( spacing, 0.0 );
|
|
|
|
|
|
|
|
if ( spacing != engine().rowSpacing( column, Qt::Horizontal ) )
|
|
|
|
{
|
|
|
|
engine().setRowSpacing( column, spacing, Qt::Horizontal );
|
|
|
|
activate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskGridBox::columnSpacing( int column ) const
|
|
|
|
{
|
|
|
|
return engine().rowSpacing( column, Qt::Horizontal );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setRowStretchFactor( int row, int stretch )
|
|
|
|
{
|
|
|
|
if ( stretch != engine().rowStretchFactor( row, Qt::Vertical ) )
|
|
|
|
{
|
|
|
|
engine().setRowStretchFactor( row, stretch, Qt::Vertical );
|
|
|
|
activate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskGridBox::rowStretchFactor( int row ) const
|
|
|
|
{
|
|
|
|
return engine().rowStretchFactor( row, Qt::Vertical );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setColumnStretchFactor( int column, int stretch )
|
|
|
|
{
|
|
|
|
if ( stretch != engine().rowStretchFactor( column, Qt::Horizontal ) )
|
|
|
|
{
|
|
|
|
engine().setRowStretchFactor( column, stretch, Qt::Horizontal );
|
|
|
|
activate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskGridBox::columnStretchFactor( int column ) const
|
|
|
|
{
|
|
|
|
return engine().rowStretchFactor( column, Qt::Horizontal );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setRowMinimumHeight( int row, qreal height )
|
|
|
|
{
|
|
|
|
setRowSizeHint( Qt::MinimumSize, row, height, Qt::Vertical );
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskGridBox::rowMinimumHeight( int row ) const
|
|
|
|
{
|
|
|
|
return engine().rowSizeHint( Qt::MinimumSize, row, Qt::Vertical );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setRowPreferredHeight( int row, qreal height )
|
|
|
|
{
|
|
|
|
setRowSizeHint( Qt::PreferredSize, row, height, Qt::Vertical );
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskGridBox::rowPreferredHeight( int row ) const
|
|
|
|
{
|
|
|
|
return engine().rowSizeHint( Qt::PreferredSize, row, Qt::Vertical );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setRowMaximumHeight( int row, qreal height )
|
|
|
|
{
|
|
|
|
setRowSizeHint( Qt::MaximumSize, row, height, Qt::Vertical );
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskGridBox::rowMaximumHeight( int row ) const
|
|
|
|
{
|
|
|
|
return engine().rowSizeHint( Qt::MaximumSize, row, Qt::Vertical );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setRowFixedHeight( int row, qreal height )
|
|
|
|
{
|
|
|
|
setRowMinimumHeight( row, height );
|
|
|
|
setRowMaximumHeight( row, height );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setColumnMinimumWidth( int column, qreal width )
|
|
|
|
{
|
|
|
|
setRowSizeHint( Qt::MinimumSize, column, width, Qt::Horizontal );
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskGridBox::columnMinimumWidth( int column ) const
|
|
|
|
{
|
|
|
|
return engine().rowSizeHint( Qt::MinimumSize, column, Qt::Horizontal );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setColumnPreferredWidth( int column, qreal width )
|
|
|
|
{
|
|
|
|
setRowSizeHint( Qt::PreferredSize, column, width, Qt::Horizontal );
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskGridBox::columnPreferredWidth( int column ) const
|
|
|
|
{
|
|
|
|
return engine().rowSizeHint( Qt::PreferredSize, column, Qt::Horizontal );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setColumnMaximumWidth( int column, qreal width )
|
|
|
|
{
|
|
|
|
setRowSizeHint( Qt::MaximumSize, column, width, Qt::Horizontal );
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskGridBox::columnMaximumWidth( int column ) const
|
|
|
|
{
|
|
|
|
return engine().rowSizeHint( Qt::MaximumSize, column, Qt::Horizontal );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setColumnFixedWidth( int column, qreal width )
|
|
|
|
{
|
|
|
|
setColumnMinimumWidth( column, width );
|
|
|
|
setColumnMaximumWidth( column, width );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setRowAlignment( int row, Qt::Alignment alignment )
|
|
|
|
{
|
|
|
|
if ( engine().rowAlignment( row, Qt::Vertical ) != alignment )
|
|
|
|
{
|
|
|
|
engine().setRowAlignment( row, alignment, Qt::Vertical );
|
|
|
|
activate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt::Alignment QskGridBox::rowAlignment( int row ) const
|
|
|
|
{
|
|
|
|
return engine().rowAlignment( row, Qt::Vertical );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setColumnAlignment( int column, Qt::Alignment alignment )
|
|
|
|
{
|
|
|
|
if ( alignment != engine().rowAlignment( column, Qt::Horizontal ) )
|
|
|
|
{
|
|
|
|
engine().setRowAlignment( column, alignment, Qt::Horizontal );
|
|
|
|
activate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt::Alignment QskGridBox::columnAlignment( int column ) const
|
|
|
|
{
|
|
|
|
return engine().rowAlignment( column, Qt::Horizontal );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setAlignment( QQuickItem* item, Qt::Alignment alignment )
|
|
|
|
{
|
|
|
|
QskLayoutItem* layoutItem = engine().layoutItemOf( item );
|
|
|
|
if ( layoutItem && layoutItem->alignment() != alignment )
|
|
|
|
{
|
|
|
|
layoutItem->setAlignment( alignment );
|
|
|
|
activate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt::Alignment QskGridBox::alignment( QQuickItem* item ) const
|
|
|
|
{
|
|
|
|
QskLayoutItem* layoutItem = engine().layoutItemOf( item );
|
|
|
|
if ( layoutItem )
|
|
|
|
return layoutItem->alignment();
|
|
|
|
|
|
|
|
return Qt::Alignment();
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setRetainSizeWhenHidden( QQuickItem* item, bool on )
|
|
|
|
{
|
|
|
|
QskLayoutItem* layoutItem = engine().layoutItemOf( item );
|
|
|
|
if ( layoutItem && on != layoutItem->retainSizeWhenHidden() )
|
|
|
|
{
|
|
|
|
layoutItem->setRetainSizeWhenHidden( on );
|
|
|
|
invalidate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskGridBox::retainSizeWhenHidden( QQuickItem* item ) const
|
|
|
|
{
|
|
|
|
QskLayoutItem* layoutItem = engine().layoutItemOf( item );
|
|
|
|
if ( layoutItem )
|
|
|
|
return layoutItem->retainSizeWhenHidden();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
QSizeF QskGridBox::contentsSizeHint() const
|
|
|
|
{
|
|
|
|
if ( !isActive() )
|
|
|
|
return QSizeF( -1, -1 );
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( itemCount() == 0 )
|
2017-07-21 18:21:34 +02:00
|
|
|
return QSizeF( 0, 0 );
|
2018-08-03 08:15:28 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
return engine().sizeHint( Qt::PreferredSize );
|
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
qreal QskGridBox::heightForWidth( qreal width ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-10-23 19:19:09 +02:00
|
|
|
const auto m = margins();
|
|
|
|
width -= m.left() + m.right();
|
|
|
|
|
2018-11-08 09:02:03 +01:00
|
|
|
qreal height = engine().heightForWidth( width );
|
2018-10-23 19:19:09 +02:00
|
|
|
|
|
|
|
height += m.top() + m.bottom();
|
|
|
|
return height;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskGridBox::widthForHeight( qreal height ) const
|
|
|
|
{
|
2018-10-23 19:19:09 +02:00
|
|
|
const auto m = margins();
|
|
|
|
height -= m.top() + m.bottom();
|
|
|
|
|
2018-11-08 09:02:03 +01:00
|
|
|
qreal width = engine().widthForHeight( height );
|
2018-10-23 19:19:09 +02:00
|
|
|
|
|
|
|
width += m.left() + m.right();
|
|
|
|
return width;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskGridBox::setRowSizeHint(
|
|
|
|
Qt::SizeHint which, int row, qreal size, Qt::Orientation orientation )
|
|
|
|
{
|
|
|
|
if ( size != engine().rowSizeHint( which, row, orientation ) )
|
|
|
|
{
|
|
|
|
engine().setRowSizeHint( which, row, size, orientation );
|
|
|
|
activate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "moc_QskGridBox.cpp"
|