221 lines
5.5 KiB
C++
221 lines
5.5 KiB
C++
/******************************************************************************
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
*****************************************************************************/
|
|
|
|
#include "QskLayoutEngine.h"
|
|
#include "QskLayoutItem.h"
|
|
#include <QDebug>
|
|
|
|
static inline bool qskIsColliding(
|
|
const QskLayoutEngine* engine, QskLayoutItem* item )
|
|
{
|
|
for ( int row = item->firstRow(); row <= item->lastRow(); row++ )
|
|
{
|
|
for ( int col = item->firstColumn(); col <= item->lastColumn(); col++ )
|
|
{
|
|
if ( engine->itemAt(row, col) )
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
class MessageHandler
|
|
{
|
|
public:
|
|
MessageHandler()
|
|
{
|
|
m_defaultHandler = qInstallMessageHandler( suppressWarning );
|
|
}
|
|
|
|
~MessageHandler()
|
|
{
|
|
qInstallMessageHandler( m_defaultHandler );
|
|
}
|
|
|
|
private:
|
|
static void suppressWarning( QtMsgType type,
|
|
const QMessageLogContext& context, const QString& message )
|
|
{
|
|
if ( type == QtWarningMsg )
|
|
return;
|
|
|
|
if ( m_defaultHandler )
|
|
( *m_defaultHandler )( type, context, message );
|
|
}
|
|
|
|
static QtMessageHandler m_defaultHandler;
|
|
};
|
|
|
|
QtMessageHandler MessageHandler::m_defaultHandler;
|
|
|
|
class LayoutStyleInfo final : public QAbstractLayoutStyleInfo
|
|
{
|
|
public:
|
|
virtual qreal spacing( Qt::Orientation ) const override
|
|
{
|
|
// later from the theme !!
|
|
return 5.0;
|
|
}
|
|
|
|
virtual qreal windowMargin( Qt::Orientation ) const override
|
|
{
|
|
// later from the theme !!
|
|
return 0;
|
|
}
|
|
|
|
virtual bool hasChangedCore() const override
|
|
{
|
|
return false; // never changes
|
|
}
|
|
};
|
|
}
|
|
|
|
QskLayoutEngine::QskLayoutEngine():
|
|
QGridLayoutEngine( Qt::AlignVCenter, true /*snapToPixelGrid*/ )
|
|
{
|
|
}
|
|
|
|
QskLayoutEngine::~QskLayoutEngine()
|
|
{
|
|
}
|
|
|
|
void QskLayoutEngine::setGeometries( const QRectF rect )
|
|
{
|
|
const LayoutStyleInfo styleInfo;
|
|
QGridLayoutEngine::setGeometries( rect, &styleInfo );
|
|
}
|
|
|
|
void QskLayoutEngine::insertLayoutItem( QskLayoutItem* item, int index )
|
|
{
|
|
if ( qskIsColliding( this, item ) )
|
|
{
|
|
// It is totally valid to have more than one item in the same cell
|
|
// and we make use of it f.e in QskStackLayout. So we better
|
|
// suppress the corresponding warning to avoid confusion.
|
|
|
|
MessageHandler suppressWarning;
|
|
insertItem( item, index );
|
|
}
|
|
else
|
|
{
|
|
insertItem( item, index );
|
|
}
|
|
}
|
|
|
|
int QskLayoutEngine::indexAt( int row, int column ) const
|
|
{
|
|
const auto item = layoutItemAt( row, column );
|
|
if ( item )
|
|
return q_items.indexOf( item );
|
|
|
|
return -1;
|
|
}
|
|
|
|
QskLayoutItem* QskLayoutEngine::layoutItemAt( int index ) const
|
|
{
|
|
if ( index < 0 || index >= q_items.count() )
|
|
return nullptr;
|
|
|
|
return static_cast< QskLayoutItem* >( q_items[index] );
|
|
}
|
|
|
|
QskLayoutItem* QskLayoutEngine::layoutItemAt( int row, int column ) const
|
|
{
|
|
if ( row < 0 || row >= rowCount() || column < 0 || column >= columnCount() )
|
|
return nullptr;
|
|
|
|
return static_cast< QskLayoutItem* >( itemAt( row, column ) );
|
|
}
|
|
|
|
QskLayoutItem* QskLayoutEngine::layoutItemAt(
|
|
int row, int column, Qt::Orientation orientation ) const
|
|
{
|
|
if ( orientation == Qt::Horizontal )
|
|
return layoutItemAt( row, column );
|
|
else
|
|
return layoutItemAt( column, row );
|
|
}
|
|
|
|
int QskLayoutEngine::indexOf( const QQuickItem* item ) const
|
|
{
|
|
// linear search might become slow for many items,
|
|
// better introduce some sort of hash table TODO ...
|
|
|
|
for ( int i = q_items.count() - 1; i >= 0; --i )
|
|
{
|
|
const auto layoutItem = static_cast< const QskLayoutItem* >( q_items[i] );
|
|
if ( layoutItem->item() == item )
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
QSizeF QskLayoutEngine::sizeHint( Qt::SizeHint which, const QSizeF& constraint ) const
|
|
{
|
|
const LayoutStyleInfo styleInfo;
|
|
return QGridLayoutEngine::sizeHint( which, constraint, &styleInfo );
|
|
}
|
|
|
|
qreal QskLayoutEngine::spacing( Qt::Orientation orientation ) const
|
|
{
|
|
const LayoutStyleInfo styleInfo;
|
|
return QGridLayoutEngine::spacing( orientation, &styleInfo );
|
|
}
|
|
|
|
qreal QskLayoutEngine::defaultSpacing( Qt::Orientation orientation )
|
|
{
|
|
return LayoutStyleInfo().spacing( orientation );
|
|
}
|
|
|
|
#if 1
|
|
// QGridLayout or here ???
|
|
QSize QskLayoutEngine::requiredCells() const
|
|
{
|
|
int lastRow = -1;
|
|
int lastColumn = -1;
|
|
|
|
for ( int i = 0; i < itemCount(); i++ )
|
|
{
|
|
const QskLayoutItem* l = layoutItemAt( i );
|
|
if ( l->isIgnored() )
|
|
continue;
|
|
|
|
const int col = l->hasUnlimitedSpan( Qt::Horizontal )
|
|
? l->firstColumn() + 1 : l->lastColumn();
|
|
|
|
if ( col > lastColumn )
|
|
lastColumn = col;
|
|
|
|
const int row = l->hasUnlimitedSpan( Qt::Vertical )
|
|
? l->firstRow() + 1 : l->lastRow();
|
|
|
|
if ( row > lastRow )
|
|
lastRow = row;
|
|
}
|
|
|
|
return QSize( lastColumn + 1, lastRow + 1 );
|
|
}
|
|
|
|
void QskLayoutEngine::adjustSpans( int numRows, int numColumns )
|
|
{
|
|
for ( int i = 0; i < itemCount(); i++ )
|
|
{
|
|
QskLayoutItem* l = layoutItemAt( i );
|
|
|
|
if ( l->hasUnlimitedSpan( Qt::Horizontal ) )
|
|
l->setRowSpan( numColumns - l->firstColumn(), Qt::Horizontal );
|
|
|
|
if ( l->hasUnlimitedSpan( Qt::Vertical ) )
|
|
l->setRowSpan( numRows - l->firstRow(), Qt::Vertical );
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|