void MFreestyleLayoutPolicy::relayout()
{
    Q_D(MFreestyleLayoutPolicy);

    QPointF topLeft = contentsArea().topLeft();

    QList<QRectF> new_geometries;
    const int size = count();
    for (int i = 0; i < size; ++i) {
        new_geometries << itemGeometry(i);
        d->placeItem(i, new_geometries, topLeft, contentsArea().width());
    }

    QRectF area = contentsArea();
    for (int i = 0; i < size; ++i) {
        area = area.united(new_geometries.at(i));
        setItemGeometry(i, new_geometries.at(i));
    }

    //if we have moved items outside of the bounding box, we need to invalidate the layout
    //causing another relayout, but we have to be careful that we don't end up in an
    //infinite loop because of this.
    if (area.isValid() && !contentsArea().adjusted(-0.0000001, -0.0000001, 0.0000001, 0.0000001).contains(area)) //adjust for rounding errors
        updateGeometry();
}
void MFreestyleLayoutPolicy::addItemAtGeometry(QGraphicsLayoutItem *item, const QRectF &geom)
{
    Q_D(MFreestyleLayoutPolicy);

    MAbstractLayoutPolicy::addItem(item);

    QPointF topLeft = contentsArea().topLeft();

    //set the item's geometry to geom, bounded by the item's minimum and maximum
    //size.
    QSizeF maximum = item->effectiveSizeHint(Qt::MaximumSize);
    QSizeF minimum = item->effectiveSizeHint(Qt::MinimumSize);
    QRectF new_geometry = QRectF(geom.topLeft(), geom.size().boundedTo(maximum).expandedTo(minimum));

    QList<QRectF> new_geometries;
    const int size = count();
    for (int i = 0; i < size - 1; ++i)
        new_geometries << itemGeometry(i);

    //Add the new item to the list of geometries and place it
    new_geometries << new_geometry;
    d->placeItem(size - 1, new_geometries, topLeft, contentsArea().width());

    for (int i = 0; i < size; ++i)
        setItemGeometry(i, new_geometries.at(i));

    updateGeometry();
}
QSizeF MFreestyleLayoutPolicy::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
    Q_D(const MFreestyleLayoutPolicy);

    if (which == Qt::MaximumSize) {
        // maximum size is the QWIDGETSIZE_MAX
        QSizeF new_size = constraint;
        if (new_size.width() < 0)
            new_size.setWidth(QWIDGETSIZE_MAX);
        if (new_size.height() < 0)
            new_size.setHeight(QWIDGETSIZE_MAX);
        return new_size;
    }

    // minimum and preferred size of a layout is the bounding box of the children
    int i = count();
    QRectF boundingBox;
    while (--i >= 0) {
        // iterate through children
        boundingBox = boundingBox.united(itemGeometry(i));
    }

    qreal right, bottom;
    d->layout->getContentsMargins(NULL, NULL, &right, &bottom);
    return QSizeF(boundingBox.right() + right - d->layout->geometry().left(), boundingBox.bottom() + bottom - d->layout->geometry().top());
}
QList<QRect> QwtDynGridLayout::layoutItems( const QRect &rect,
    uint numCols ) const
{
    QList<QRect> itemGeometries;
    if ( numCols == 0 || isEmpty() )
        return itemGeometries;

    uint numRows = itemCount() / numCols;
    if ( numRows % itemCount() )
        numRows++;

    QVector<int> rowHeight( numRows );
    QVector<int> colWidth( numCols );

    layoutGrid( numCols, rowHeight, colWidth );

    bool expandH, expandV;
    expandH = expandingDirections() & Qt::Horizontal;
    expandV = expandingDirections() & Qt::Vertical;

    if ( expandH || expandV )
        stretchGrid( rect, numCols, rowHeight, colWidth );

    const int maxCols = d_data->maxCols;
    d_data->maxCols = numCols;
    const QRect alignedRect = alignmentRect( rect );
    d_data->maxCols = maxCols;

    const int xOffset = expandH ? 0 : alignedRect.x();
    const int yOffset = expandV ? 0 : alignedRect.y();

    QVector<int> colX( numCols );
    QVector<int> rowY( numRows );

    const int xySpace = spacing();

    rowY[0] = yOffset + margin();
    for ( int r = 1; r < ( int )numRows; r++ )
        rowY[r] = rowY[r-1] + rowHeight[r-1] + xySpace;

    colX[0] = xOffset + margin();
    for ( int c = 1; c < ( int )numCols; c++ )
        colX[c] = colX[c-1] + colWidth[c-1] + xySpace;

    const int itemCount = d_data->itemList.size();
    for ( int i = 0; i < itemCount; i++ )
    {
        const int row = i / numCols;
        const int col = i % numCols;

        QRect itemGeometry( colX[col], rowY[row],
            colWidth[col], rowHeight[row] );
        itemGeometries.append( itemGeometry );
    }

    return itemGeometries;
}
void MFreestyleLayoutPolicy::moveItemTo(QGraphicsLayoutItem *item, const QRectF &geom)
{
    Q_D(MFreestyleLayoutPolicy);

    int index = indexOf(item);
    if (index < 0)
        return; //Item not found

    QPointF topLeft = contentsArea().topLeft();
    QList<QRectF> new_geometries;

    const int size = count();
    for (int i = 0; i < size; ++i)
        new_geometries << itemGeometry(i);

    new_geometries[index] = geom;

    d->placeItem(index, new_geometries, topLeft, contentsArea().width());

    for (int i = 0; i < size; ++i)
        setItemGeometry(i, new_geometries.at(i));
    updateGeometry();
}