/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Designer of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qlayout_widget_p.h"
#include "qdesigner_utils_p.h"
#include "layout_p.h"
#include "layoutinfo_p.h"
#include "invisible_widget_p.h"
#include "qdesigner_widgetitem_p.h"

#include <QtDesigner/QDesignerFormWindowInterface>
#include <QtDesigner/QExtensionManager>
#include <QtDesigner/QDesignerFormEditorInterface>
#include <QtDesigner/QDesignerPropertySheetExtension>
#include <QtDesigner/QDesignerWidgetFactoryInterface>

#include <QtGui/QPainter>
#include <QtGui/QHBoxLayout>
#include <QtGui/QVBoxLayout>
#include <QtGui/QGridLayout>
#include <QtGui/QFormLayout>
#include <QtGui/qevent.h>

#include <QtCore/qdebug.h>
#include <QtCore/QtAlgorithms>
#include <QtCore/QMap>
#include <QtCore/QStack>
#include <QtCore/QPair>
#include <QtCore/QSet>

enum { ShiftValue = 1 };
enum { debugLayout = 0 };
enum { FormLayoutColumns = 2 };
enum { indicatorSize = 2 };
// Grid/form Helpers: get info (overloads to make templates work)

namespace { // Do not use static, will break HP-UX due to templates

QT_USE_NAMESPACE

// overloads to make templates over QGridLayout/QFormLayout work
inline int gridRowCount(const QGridLayout *gridLayout)
{
    return  gridLayout->rowCount();
}

inline int gridColumnCount(const QGridLayout *gridLayout)
{
    return  gridLayout->columnCount();
}

// QGridLayout/QFormLayout Helpers: get item position (overloads to make templates work)
inline void getGridItemPosition(QGridLayout *gridLayout, int index,
    int *row, int *column, int *rowspan, int *colspan)
{
    gridLayout->getItemPosition(index, row, column, rowspan, colspan);
}

QRect gridItemInfo(QGridLayout *grid, int index)
{
    int row, column, rowSpan, columnSpan;
    // getItemPosition is not const, grmbl..
    grid->getItemPosition(index, &row, &column, &rowSpan, &columnSpan);
    return QRect(column, row, columnSpan, rowSpan);
}

inline int gridRowCount(const QFormLayout *formLayout)    { return  formLayout->rowCount(); }
inline int gridColumnCount(const QFormLayout *) { return FormLayoutColumns; }

inline void getGridItemPosition(QFormLayout *formLayout, int index, int *row, int *column, int *rowspan, int *colspan)
{
    qdesigner_internal::getFormLayoutItemPosition(formLayout, index, row, column, rowspan, colspan);
}

QRect gridItemInfo(const QFormLayout *form, int index)
{
    int row;
    int column;
    int colspan;
    qdesigner_internal::getFormLayoutItemPosition(form, index, &row, &column, 0, &colspan);
    return QRect(column, row, colspan, 1);
}
} // namespace anonymous

QT_BEGIN_NAMESPACE

static const char *objectNameC = "objectName";
static const char *sizeConstraintC = "sizeConstraint";

/* A padding spacer element that is used to represent an empty form layout cell. It should grow with its cell.
 * Should not be used on a grid as it causes resizing inconsistencies */
namespace qdesigner_internal {
    class PaddingSpacerItem : public QSpacerItem {
    public:
        PaddingSpacerItem() : QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding) {}
        virtual Qt::Orientations expandingDirections () const { return Qt::Vertical | Qt::Horizontal; }
    };
}

static inline QSpacerItem *createGridSpacer()
{
    return new QSpacerItem(0, 0);
}

static inline QSpacerItem *createFormSpacer()
{
    return new qdesigner_internal::PaddingSpacerItem;
}

// QGridLayout/QFormLayout Helpers: Debug items of GridLikeLayout
template <class GridLikeLayout>
static QDebug debugGridLikeLayout(QDebug str, const GridLikeLayout &gl)
{
    const int count = gl.count();
    str << "Grid: " << gl.objectName() <<   gridRowCount(&gl) << " rows x " <<  gridColumnCount(&gl)
        << " cols " << count << " items\n";
    for (int i = 0; i < count; i++) {
        QLayoutItem *item = gl.itemAt(i);
        str << "Item " << i << item << item->widget() << gridItemInfo(const_cast<GridLikeLayout *>(&gl), i) << " empty=" << qdesigner_internal::LayoutInfo::isEmptyItem(item) << "\n";
    }
    return str;
}

static inline QDebug operator<<(QDebug str, const QGridLayout &gl) { return debugGridLikeLayout(str, gl); }
static inline QDebug operator<<(QDebug str, const QFormLayout &fl) { return debugGridLikeLayout(str, fl); }

static inline bool isEmptyFormLayoutRow(const QFormLayout *fl, int row)
{
    // Spanning can never be empty
    if (fl->itemAt(row, QFormLayout::SpanningRole))
        return false;
    return qdesigner_internal::LayoutInfo::isEmptyItem(fl->itemAt(row, QFormLayout::LabelRole)) && qdesigner_internal::LayoutInfo::isEmptyItem(fl->itemAt(row, QFormLayout::FieldRole));
}

static inline bool canSimplifyFormLayout(const QFormLayout *formLayout, const QRect &restrictionArea)
{
    if (restrictionArea.x() >= FormLayoutColumns)
        return false;
    // Try to find empty rows
    const int bottomCheckRow = qMin(formLayout->rowCount(), restrictionArea.top() + restrictionArea.height());
    for (int r = restrictionArea.y(); r < bottomCheckRow; r++)
        if (isEmptyFormLayoutRow(formLayout, r))
            return true;
    return false;
}

// recreate a managed layout (which does not automagically remove
// empty rows/columns like grid or form layout) in case it needs to shrink

static QLayout *recreateManagedLayout(const QDesignerFormEditorInterface *core, QWidget *w, QLayout *lt)
{
    const qdesigner_internal::LayoutInfo::Type t = qdesigner_internal::LayoutInfo::layoutType(core, lt);
    qdesigner_internal::LayoutProperties properties;
    const int mask = properties.fromPropertySheet(core, lt, qdesigner_internal::LayoutProperties::AllProperties);
    qdesigner_internal::LayoutInfo::deleteLayout(core, w);
    QLayout *rc = core->widgetFactory()->createLayout(w, 0, t);
    properties.toPropertySheet(core, rc, mask, true);
    return rc;
}

// QGridLayout/QFormLayout Helpers: find an item on a form/grid. Return index
template <class GridLikeLayout>
int findGridItemAt(GridLikeLayout *gridLayout, int at_row, int at_column)
{
    Q_ASSERT(gridLayout);
    const int count = gridLayout->count();
    for (int index = 0; index <  count; index++) {
        int row, column, rowspan, colspan;
        getGridItemPosition(gridLayout, index, &row, &column, &rowspan, &colspan);
        if (at_row >= row && at_row < (row + rowspan)
            && at_column >= column && at_column < (column + colspan)) {
            return index;
        }
    }
    return -1;
}
// QGridLayout/QFormLayout  Helpers: remove dummy spacers on form/grid
template <class GridLikeLayout>
static bool removeEmptyCellsOnGrid(GridLikeLayout *grid, const QRect &area)
{
    // check if there are any items in the way. Should be only spacers
    // Unique out items that span rows/columns.
    QVector<int> indexesToBeRemoved;
    indexesToBeRemoved.reserve(grid->count());
    const int rightColumn = area.x() + area.width();
    const int bottomRow = area.y() + area.height();
    for (int c = area.x(); c < rightColumn; c++)
        for (int r = area.y(); r < bottomRow; r++) {
            const int index = findGridItemAt(grid, r ,c);
            if (index != -1)
                if (QLayoutItem *item = grid->itemAt(index)) {
                    if (qdesigner_internal::LayoutInfo::isEmptyItem(item)) {
                        if (indexesToBeRemoved.indexOf(index) == -1)
                            indexesToBeRemoved.push_back(index);
                    } else {
                        return false;
                    }
                }
        }
    // remove, starting from last
    if (!indexesToBeRemoved.empty()) {
        qStableSort(indexesToBeRemoved.begin(), indexesToBeRemoved.end());
        for (int i = indexesToBeRemoved.size() - 1; i >= 0; i--)
            delete grid->takeAt(indexesToBeRemoved[i]);
    }
    return true;
}

namespace qdesigner_internal {
// --------- LayoutProperties

LayoutProperties::LayoutProperties()
{
    clear();
}

void LayoutProperties::clear()
{
    qFill(m_margins, m_margins + MarginCount, 0);
    qFill(m_marginsChanged, m_marginsChanged + MarginCount, false);
    qFill(m_spacings, m_spacings + SpacingsCount, 0);
    qFill(m_spacingsChanged, m_spacingsChanged + SpacingsCount, false);

    m_objectName = QVariant();
    m_objectNameChanged = false;
    m_sizeConstraint = QVariant(QLayout::SetDefaultConstraint);
    m_sizeConstraintChanged = false;

    m_fieldGrowthPolicyChanged = m_rowWrapPolicyChanged =  m_labelAlignmentChanged = m_formAlignmentChanged = false;
    m_fieldGrowthPolicy =  m_rowWrapPolicy =  m_formAlignment = QVariant();

    m_boxStretchChanged = m_gridRowStretchChanged = m_gridColumnStretchChanged = m_gridRowMinimumHeightChanged = false;
    m_boxStretch = m_gridRowStretch =  m_gridColumnStretch =  m_gridRowMinimumHeight = QVariant();
}

int LayoutProperties::visibleProperties(const  QLayout *layout)
{
    // Grid like layout have 2 spacings.
    const bool isFormLayout = qobject_cast<const QFormLayout*>(layout);
    const bool isGridLike = qobject_cast<const QGridLayout*>(layout) || isFormLayout;
    int rc = ObjectNameProperty|LeftMarginProperty|TopMarginProperty|RightMarginProperty|BottomMarginProperty|
             SizeConstraintProperty;

    rc |= isGridLike ? (HorizSpacingProperty|VertSpacingProperty) : SpacingProperty;
    if (isFormLayout) {
        rc |= FieldGrowthPolicyProperty|RowWrapPolicyProperty|LabelAlignmentProperty|FormAlignmentProperty;
    } else {
        if (isGridLike) {
            rc |=  GridRowStretchProperty|GridColumnStretchProperty|GridRowMinimumHeightProperty|GridColumnMinimumWidthProperty;
        } else {
            rc |=  BoxStretchProperty;
        }
    }
    return rc;
}

static const char *marginPropertyNamesC[] = {"leftMargin", "topMargin", "rightMargin", "bottomMargin"};
static const char *spacingPropertyNamesC[] = {"spacing", "horizontalSpacing", "verticalSpacing" };
static const char *fieldGrowthPolicyPropertyC = "fieldGrowthPolicy";
static const char *rowWrapPolicyPropertyC = "rowWrapPolicy";
static const char *labelAlignmentPropertyC = "labelAlignment";
static const char *formAlignmentPropertyC = "formAlignment";
static const char *boxStretchPropertyC = "stretch";
static const char *gridRowStretchPropertyC = "rowStretch";
static const char *gridColumnStretchPropertyC = "columnStretch";
static const char *gridRowMinimumHeightPropertyC = "rowMinimumHeight";
static const char *gridColumnMinimumWidthPropertyC = "columnMinimumWidth";

static bool intValueFromSheet(const QDesignerPropertySheetExtension *sheet, const QString &name, int *value, bool *changed)
{
    const int sheetIndex = sheet->indexOf(name);
    if (sheetIndex == -1)
        return false;
    *value = sheet->property(sheetIndex).toInt();
    *changed = sheet->isChanged(sheetIndex);
    return true;
}

static void variantPropertyFromSheet(int mask, int flag, const QDesignerPropertySheetExtension *sheet, const QString &name,
                                     QVariant *value, bool *changed, int *returnMask)
{
    if (mask & flag) {
        const int sIndex = sheet->indexOf(name);
        if (sIndex != -1) {
            *value = sheet->property(sIndex);
            *changed = sheet->isChanged(sIndex);
            *returnMask |= flag;
        }
    }
}

int LayoutProperties::fromPropertySheet(const QDesignerFormEditorInterface *core, QLayout *l, int mask)
{
    int rc = 0;
    const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), l);
    Q_ASSERT(sheet);
    // name
    if (mask & ObjectNameProperty) {
        const int nameIndex = sheet->indexOf(QLatin1String(objectNameC));
        Q_ASSERT(nameIndex != -1);
        m_objectName = sheet->property(nameIndex);
        m_objectNameChanged =  sheet->isChanged(nameIndex);
        rc |= ObjectNameProperty;
    }
    // -- Margins
    const int marginFlags[MarginCount] = { LeftMarginProperty, TopMarginProperty, RightMarginProperty, BottomMarginProperty};
    for (int i = 0; i < MarginCount; i++)
        if (mask & marginFlags[i])
            if (intValueFromSheet(sheet, QLatin1String(marginPropertyNamesC[i]), m_margins + i, m_marginsChanged + i))
                rc |= marginFlags[i];

    const int spacingFlags[] = { SpacingProperty, HorizSpacingProperty, VertSpacingProperty};
    for (int i = 0; i < SpacingsCount; i++)
        if (mask & spacingFlags[i])
            if (intValueFromSheet(sheet, QLatin1String(spacingPropertyNamesC[i]), m_spacings + i, m_spacingsChanged + i))
                rc |= spacingFlags[i];
    // sizeConstraint, flags
    variantPropertyFromSheet(mask, SizeConstraintProperty, sheet, QLatin1String(sizeConstraintC), &m_sizeConstraint, &m_sizeConstraintChanged, &rc);
    variantPropertyFromSheet(mask, FieldGrowthPolicyProperty, sheet, QLatin1String(fieldGrowthPolicyPropertyC), &m_fieldGrowthPolicy, &m_fieldGrowthPolicyChanged, &rc);
    variantPropertyFromSheet(mask, RowWrapPolicyProperty, sheet, QLatin1String(rowWrapPolicyPropertyC), &m_rowWrapPolicy, &m_rowWrapPolicyChanged, &rc);
    variantPropertyFromSheet(mask, LabelAlignmentProperty, sheet, QLatin1String(labelAlignmentPropertyC), &m_labelAlignment, &m_labelAlignmentChanged, &rc);
    variantPropertyFromSheet(mask, FormAlignmentProperty, sheet, QLatin1String(formAlignmentPropertyC), &m_formAlignment, &m_formAlignmentChanged, &rc);
    variantPropertyFromSheet(mask, BoxStretchProperty, sheet, QLatin1String(boxStretchPropertyC), &m_boxStretch, & m_boxStretchChanged, &rc);
    variantPropertyFromSheet(mask, GridRowStretchProperty, sheet, QLatin1String(gridRowStretchPropertyC), &m_gridRowStretch, &m_gridRowStretchChanged, &rc);
    variantPropertyFromSheet(mask, GridColumnStretchProperty, sheet, QLatin1String(gridColumnStretchPropertyC), &m_gridColumnStretch, &m_gridColumnStretchChanged, &rc);
    variantPropertyFromSheet(mask, GridRowMinimumHeightProperty, sheet, QLatin1String(gridRowMinimumHeightPropertyC), &m_gridRowMinimumHeight, &m_gridRowMinimumHeightChanged, &rc);
    variantPropertyFromSheet(mask, GridColumnMinimumWidthProperty, sheet, QLatin1String(gridColumnMinimumWidthPropertyC), &m_gridColumnMinimumWidth, &m_gridColumnMinimumWidthChanged, &rc);
    return rc;
}

static bool intValueToSheet(QDesignerPropertySheetExtension *sheet, const QString &name, int value, bool changed, bool applyChanged)

{

    const int sheetIndex = sheet->indexOf(name);
    if (sheetIndex == -1) {
        qWarning() << " LayoutProperties: Attempt to set property " << name << " that does not exist for the layout.";
        return false;
    }
    sheet->setProperty(sheetIndex, QVariant(value));
    if (applyChanged)
        sheet->setChanged(sheetIndex, changed);
    return true;
}

static void variantPropertyToSheet(int mask, int flag, bool applyChanged, QDesignerPropertySheetExtension *sheet, const QString &name,
                                   const QVariant &value, bool changed, int *returnMask)
{
    if (mask & flag) {
        const int sIndex = sheet->indexOf(name);
        if (sIndex != -1) {
            sheet->setProperty(sIndex, value);
            if (applyChanged)
                sheet->setChanged(sIndex, changed);
            *returnMask |= flag;
        }
    }
}

int LayoutProperties::toPropertySheet(const QDesignerFormEditorInterface *core, QLayout *l, int mask, bool applyChanged) const
{
    int rc = 0;
    QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), l);
    Q_ASSERT(sheet);
    // name
    if (mask & ObjectNameProperty) {
        const int nameIndex = sheet->indexOf(QLatin1String(objectNameC));
        Q_ASSERT(nameIndex != -1);
        sheet->setProperty(nameIndex, m_objectName);
        if (applyChanged)
           sheet->setChanged(nameIndex, m_objectNameChanged);
        rc |= ObjectNameProperty;
    }
    // margins
    const int marginFlags[MarginCount] = { LeftMarginProperty, TopMarginProperty, RightMarginProperty, BottomMarginProperty};
    for (int i = 0; i < MarginCount; i++)
        if (mask & marginFlags[i])
            if (intValueToSheet(sheet, QLatin1String(marginPropertyNamesC[i]), m_margins[i], m_marginsChanged[i], applyChanged))
                rc |= marginFlags[i];

    const int spacingFlags[] = { SpacingProperty, HorizSpacingProperty, VertSpacingProperty};
    for (int i = 0; i < SpacingsCount; i++)
        if (mask & spacingFlags[i])
            if (intValueToSheet(sheet, QLatin1String(spacingPropertyNamesC[i]), m_spacings[i], m_spacingsChanged[i], applyChanged))
                rc |= spacingFlags[i];
    // sizeConstraint
    variantPropertyToSheet(mask, SizeConstraintProperty, applyChanged, sheet, QLatin1String(sizeConstraintC), m_sizeConstraint, m_sizeConstraintChanged, &rc);
    variantPropertyToSheet(mask, FieldGrowthPolicyProperty, applyChanged, sheet, QLatin1String(fieldGrowthPolicyPropertyC), m_fieldGrowthPolicy, &m_fieldGrowthPolicyChanged, &rc);
    variantPropertyToSheet(mask, RowWrapPolicyProperty, applyChanged, sheet, QLatin1String(rowWrapPolicyPropertyC), m_rowWrapPolicy, m_rowWrapPolicyChanged, &rc);
    variantPropertyToSheet(mask, LabelAlignmentProperty, applyChanged, sheet, QLatin1String(labelAlignmentPropertyC), m_labelAlignment, m_labelAlignmentChanged, &rc);
    variantPropertyToSheet(mask, FormAlignmentProperty, applyChanged, sheet, QLatin1String(formAlignmentPropertyC), m_formAlignment, m_formAlignmentChanged, &rc);
    variantPropertyToSheet(mask, BoxStretchProperty, applyChanged, sheet, QLatin1String(boxStretchPropertyC), m_boxStretch, m_boxStretchChanged, &rc);
    variantPropertyToSheet(mask, GridRowStretchProperty, applyChanged, sheet, QLatin1String(gridRowStretchPropertyC), m_gridRowStretch, m_gridRowStretchChanged, &rc);
    variantPropertyToSheet(mask, GridColumnStretchProperty, applyChanged, sheet, QLatin1String(gridColumnStretchPropertyC), m_gridColumnStretch, m_gridColumnStretchChanged, &rc);
    variantPropertyToSheet(mask, GridRowMinimumHeightProperty, applyChanged, sheet, QLatin1String(gridRowMinimumHeightPropertyC), m_gridRowMinimumHeight, m_gridRowMinimumHeightChanged, &rc);
    variantPropertyToSheet(mask, GridColumnMinimumWidthProperty, applyChanged, sheet, QLatin1String(gridColumnMinimumWidthPropertyC), m_gridColumnMinimumWidth, m_gridColumnMinimumWidthChanged, &rc);
    return rc;
}

// ---------------- LayoutHelper
LayoutHelper::LayoutHelper()
{
}

LayoutHelper::~LayoutHelper()
{
}

int LayoutHelper::indexOf(const QLayout *lt, const QWidget *widget)
{
    if (!lt)
        return -1;

    const int itemCount = lt->count();
    for (int i = 0; i < itemCount; i++)
        if (lt->itemAt(i)->widget() == widget)
            return i;
    return -1;
}

QRect LayoutHelper::itemInfo(QLayout *lt, const QWidget *widget) const
{
    const int index = indexOf(lt, widget);
    if (index == -1) {
        qWarning() << "LayoutHelper::itemInfo: " << widget << " not in layout " << lt;
        return QRect(0, 0, 1, 1);
    }
    return itemInfo(lt, index);
}

    // ---------------- BoxLayoutHelper
    class BoxLayoutHelper : public  LayoutHelper {
    public:
        BoxLayoutHelper(const Qt::Orientation orientation) : m_orientation(orientation) {}

        virtual QRect itemInfo(QLayout *lt, int index) const;
        virtual void insertWidget(QLayout *lt, const QRect &info, QWidget *w);
        virtual void removeWidget(QLayout *lt, QWidget *widget);
        virtual void replaceWidget(QLayout *lt, QWidget *before, QWidget *after);

        virtual void pushState(const QDesignerFormEditorInterface *, const QWidget *);
        virtual void popState(const QDesignerFormEditorInterface *, QWidget *);

        virtual bool canSimplify(const QDesignerFormEditorInterface *, const QWidget *, const QRect &) const { return  false; }
        virtual void simplify(const QDesignerFormEditorInterface *, QWidget *, const QRect &) {}

        // Helper for restoring layout states
        typedef QVector <QLayoutItem *> LayoutItemVector;
        static LayoutItemVector disassembleLayout(QLayout *lt);
        static QLayoutItem *findItemOfWidget(const LayoutItemVector &lv, QWidget *w);

    private:
        typedef QVector<QWidget *> BoxLayoutState;

        static BoxLayoutState state(const QBoxLayout*lt);

        QStack<BoxLayoutState> m_states;
        const Qt::Orientation m_orientation;
    };

    QRect BoxLayoutHelper::itemInfo(QLayout * /*lt*/, int index) const
    {
        return m_orientation == Qt::Horizontal ?  QRect(index, 0, 1, 1) : QRect(0, index, 1, 1);
    }

    void BoxLayoutHelper::insertWidget(QLayout *lt, const QRect &info, QWidget *w)
    {
        QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
        QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(lt);
        Q_ASSERT(boxLayout);
        boxLayout->insertWidget(m_orientation == Qt::Horizontal ? info.x() : info.y(), w);
    }

    void BoxLayoutHelper::removeWidget(QLayout *lt, QWidget *widget)
    {
        QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(lt);
        Q_ASSERT(boxLayout);
        boxLayout->removeWidget(widget);
    }

    void BoxLayoutHelper::replaceWidget(QLayout *lt, QWidget *before, QWidget *after)
    {
        bool ok = false;
        QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
        if (QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(lt)) {
            const int index = boxLayout->indexOf(before);
            if (index != -1) {
                const bool visible = before->isVisible();
                delete boxLayout->takeAt(index);
                if (visible)
                    before->hide();
                before->setParent(0);
                boxLayout->insertWidget(index, after);
                ok = true;
            }
        }
        if (!ok)
            qWarning() << "BoxLayoutHelper::replaceWidget : Unable to replace " << before << " by " << after << " in " << lt;
    }

    BoxLayoutHelper::BoxLayoutState BoxLayoutHelper::state(const QBoxLayout*lt)
    {
        BoxLayoutState rc;
        if (const int count = lt->count()) {
            rc.reserve(count);
            for (int i = 0; i < count; i++)
                if (QWidget *w = lt->itemAt(i)->widget())
                    rc.push_back(w);
        }
        return rc;
    }

    void BoxLayoutHelper::pushState(const QDesignerFormEditorInterface *core, const QWidget *w)
    {
        const QBoxLayout *boxLayout = qobject_cast<const QBoxLayout *>(LayoutInfo::managedLayout(core, w));
        Q_ASSERT(boxLayout);
        m_states.push(state(boxLayout));
    }

    QLayoutItem *BoxLayoutHelper::findItemOfWidget(const LayoutItemVector &lv, QWidget *w)
    {
        const LayoutItemVector::const_iterator cend = lv.constEnd();
        for (LayoutItemVector::const_iterator it = lv.constBegin(); it != cend; ++it)
            if ( (*it)->widget() == w)
                return *it;

        return 0;
    }

    BoxLayoutHelper::LayoutItemVector BoxLayoutHelper::disassembleLayout(QLayout *lt)
    {
        // Take items
        const int count = lt->count();
        if (count == 0)
            return LayoutItemVector();
        LayoutItemVector rc;
        rc.reserve(count);
        for (int i = count - 1; i >= 0; i--)
            rc.push_back(lt->takeAt(i));
        return rc;
    }

    void BoxLayoutHelper::popState(const QDesignerFormEditorInterface *core, QWidget *w)
    {
        QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(LayoutInfo::managedLayout(core, w));
        Q_ASSERT(boxLayout);
        const BoxLayoutState savedState = m_states.pop();
        const BoxLayoutState currentState = state(boxLayout);
        // Check for equality/empty. Note that this will currently
        // always trigger as box layouts do not have a state apart from
        // the order and there is no layout order editor yet.
        if (savedState == state(boxLayout))
            return;

        const int count = savedState.size();
        Q_ASSERT(count == currentState.size());
        // Take items and reassemble in saved order
        const LayoutItemVector items = disassembleLayout(boxLayout);
        for (int i = 0; i < count; i++) {
            QLayoutItem *item = findItemOfWidget(items, savedState[i]);
            Q_ASSERT(item);
            boxLayout->addItem(item);
        }
    }

    // Grid Layout state. Datatypically store the state of a GridLayout as a map of
    // widgets to QRect(columns, rows) and size. Used to store the state for undo operations
    // that do not change the widgets within the layout; also provides some manipulation
    // functions and ability to apply the state to a layout provided its widgets haven't changed.
    struct GridLayoutState {
        GridLayoutState();

        void fromLayout(QGridLayout *l);
        void applyToLayout(const QDesignerFormEditorInterface *core, QWidget *w) const;

        void insertRow(int row);
        void insertColumn(int column);

        bool simplify(const QRect &r, bool testOnly);
        void removeFreeRow(int row);
        void removeFreeColumn(int column);


        // State of a cell in one dimension
        enum DimensionCellState {
            Free,
            Spanned,  // Item spans it
            Occupied  // Item bordering on it
        };
        // Horiontal, Vertical pair of state
        typedef QPair<DimensionCellState, DimensionCellState> CellState;
        typedef QVector<CellState> CellStates;

        // Figure out states of a cell and return as a flat vector of
        // [column1, column2,...] (address as  row * columnCount + col)
        static CellStates cellStates(const QList<QRect> &rects, int numRows, int numColumns);

        typedef QMap<QWidget *, QRect> WidgetItemMap;
        WidgetItemMap widgetItemMap;
        int rowCount;
        int colCount;
    };

    static inline bool needsSpacerItem(const GridLayoutState::CellState &cs) {
        return cs.first == GridLayoutState::Free && cs.second == GridLayoutState::Free;
    }

    static inline QDebug operator<<(QDebug str, const GridLayoutState &gs)
    {
        str << "GridLayoutState: " <<  gs.rowCount << " rows x " <<  gs.colCount
            << " cols " << gs.widgetItemMap.size() << " items\n";

        const GridLayoutState::WidgetItemMap::const_iterator wcend = gs.widgetItemMap.constEnd();
        for (GridLayoutState::WidgetItemMap::const_iterator it = gs.widgetItemMap.constBegin(); it != wcend; ++it)
            str << "Item " << it.key() << it.value() << '\n';
        return str;
    }

    GridLayoutState::GridLayoutState() :
         rowCount(0),
         colCount(0)
    {
    }

    GridLayoutState::CellStates GridLayoutState::cellStates(const QList<QRect> &rects, int numRows, int numColumns)
    {
        CellStates rc = CellStates(numRows * numColumns, CellState(Free, Free));
        const QList<QRect>::const_iterator rcend = rects.constEnd();
        for (QList<QRect>::const_iterator it = rects.constBegin(); it != rcend; ++it) {
            const int leftColumn = it->x();
            const int topRow = it->y();
            const int rightColumn = leftColumn + it->width() - 1;
            const int bottomRow = topRow + it->height() - 1;
            for (int r = topRow; r <= bottomRow; r++)
                for (int c = leftColumn; c <= rightColumn; c++) {
                    const int flatIndex = r * numColumns + c;
                    // Bordering horizontally?
                    DimensionCellState &horizState = rc[flatIndex].first;
                    if (c == leftColumn || c == rightColumn) {
                        horizState = Occupied;
                    } else {
                        if (horizState < Spanned)
                            horizState = Spanned;
                    }
                    // Bordering vertically?
                    DimensionCellState &vertState = rc[flatIndex].second;
                    if (r == topRow || r == bottomRow) {
                        vertState = Occupied;
                    } else {
                        if (vertState < Spanned)
                            vertState = Spanned;
                    }
                }
        }
        if (debugLayout) {
            qDebug() << "GridLayoutState::cellStates: " << numRows << " x " << numColumns;
            for (int r = 0; r < numRows; r++)
                for (int c = 0; c < numColumns; c++)
                    qDebug() << "  Row: " << r << " column: " << c <<  rc[r * numColumns + c];
        }
        return rc;
    }

    void GridLayoutState::fromLayout(QGridLayout *l)
    {
        rowCount = l->rowCount();
        colCount = l->columnCount();
        const int count = l->count();
        for (int i = 0; i < count; i++) {
            QLayoutItem *item = l->itemAt(i);
            if (!LayoutInfo::isEmptyItem(item))
                widgetItemMap.insert(item->widget(), gridItemInfo(l, i));
        }
    }

    void GridLayoutState::applyToLayout(const QDesignerFormEditorInterface *core, QWidget *w) const
    {
        typedef QMap<QLayoutItem *, QRect> LayoutItemRectMap;
        QGridLayout *grid = qobject_cast<QGridLayout *>(LayoutInfo::managedLayout(core, w));
        Q_ASSERT(grid);
        if (debugLayout)
            qDebug() << ">GridLayoutState::applyToLayout" <<  *this << *grid;
        const bool shrink = grid->rowCount() > rowCount || grid->columnCount() > colCount;
        // Build a map of existing items to rectangles via widget map, delete spacers
        LayoutItemRectMap itemMap;
        while (grid->count()) {
            QLayoutItem *item = grid->takeAt(0);
            if (!LayoutInfo::isEmptyItem(item)) {
                QWidget *itemWidget = item->widget();
                const WidgetItemMap::const_iterator it = widgetItemMap.constFind(itemWidget);
                if (it == widgetItemMap.constEnd())
                    qFatal("GridLayoutState::applyToLayout: Attempt to apply to a layout that has a widget '%s'/'%s' added after saving the state.",
                           itemWidget->metaObject()->className(), itemWidget->objectName().toUtf8().constData());
                itemMap.insert(item, it.value());
            } else {
                delete item;
            }
        }
        Q_ASSERT(itemMap.size() == widgetItemMap.size());
        // recreate if shrink
        if (shrink)
            grid = static_cast<QGridLayout*>(recreateManagedLayout(core, w, grid));

        // Add widgets items
        const LayoutItemRectMap::const_iterator icend = itemMap.constEnd();
        for (LayoutItemRectMap::const_iterator it = itemMap.constBegin(); it != icend; ++it) {
            const QRect info = it.value();
            grid->addItem(it.key(), info.y(), info.x(), info.height(), info.width());
        }
        // create spacers
        const CellStates cs = cellStates(itemMap.values(), rowCount, colCount);
        for (int r = 0; r < rowCount; r++)
            for (int c = 0; c < colCount; c++)
                if (needsSpacerItem(cs[r * colCount  + c]))
                    grid->addItem(createGridSpacer(), r, c);
        grid->activate();
        if (debugLayout)
            qDebug() << "<GridLayoutState::applyToLayout" <<  *grid;
    }

    void GridLayoutState::insertRow(int row)
    {
        rowCount++;
        const WidgetItemMap::iterator iend = widgetItemMap.end();
        for (WidgetItemMap::iterator it = widgetItemMap.begin(); it != iend; ++it) {
            const int topRow = it.value().y();
            if (topRow >= row) {
                it.value().translate(0, 1);
            } else {  //Over  it: Does it span it -> widen?
                const int rowSpan = it.value().height();
                if (rowSpan > 1 && topRow + rowSpan > row)
                    it.value().setHeight(rowSpan + 1);
            }
        }
    }

    void GridLayoutState::insertColumn(int column)
    {
        colCount++;
        const WidgetItemMap::iterator iend = widgetItemMap.end();
        for (WidgetItemMap::iterator it = widgetItemMap.begin(); it != iend; ++it) {
            const int leftColumn = it.value().x();
            if (leftColumn >= column) {
                it.value().translate(1, 0);
            } else { // Left of it: Does it span it -> widen?
                const int colSpan = it.value().width();
                if (colSpan  > 1 &&  leftColumn + colSpan > column)
                    it.value().setWidth(colSpan + 1);
            }
        }
    }

    // Simplify: Remove empty columns/rows and such ones that are only spanned (shrink
    // spanning items).
    // 'AB.C.'           'ABC'
    // 'DDDD.'     ==>   'DDD'
    // 'EF.G.'           'EFG'
    bool GridLayoutState::simplify(const QRect &r, bool testOnly)
    {
        // figure out free rows/columns.
        QVector<bool> occupiedRows(rowCount, false);
        QVector<bool> occupiedColumns(colCount, false);
        // Mark everything outside restriction rectangle as occupied
        const int restrictionLeftColumn = r.x();
        const int restrictionRightColumn = restrictionLeftColumn + r.width();
        const int restrictionTopRow = r.y();
        const int restrictionBottomRow = restrictionTopRow + r.height();
        if (restrictionLeftColumn > 0 || restrictionRightColumn < colCount ||
            restrictionTopRow     > 0 || restrictionBottomRow   < rowCount) {
            for (int r = 0; r <  rowCount; r++)
                if (r < restrictionTopRow || r >= restrictionBottomRow)
                    occupiedRows[r] = true;
            for (int c = 0; c < colCount; c++)
                if (c < restrictionLeftColumn ||  c >= restrictionRightColumn)
                    occupiedColumns[c] = true;
        }
        // figure out free fields and tick off occupied rows and columns
        const CellStates cs = cellStates(widgetItemMap.values(), rowCount, colCount);
        for (int r = 0; r < rowCount; r++)
            for (int c = 0; c < colCount; c++) {
                const CellState &state = cs[r * colCount  + c];
                if (state.first == Occupied)
                    occupiedColumns[c] = true;
                if (state.second == Occupied)
                    occupiedRows[r] = true;
            }
        // Any free rows/columns?
        if (occupiedRows.indexOf(false) ==  -1 && occupiedColumns.indexOf(false) == -1)
            return false;
        if (testOnly)
            return true;
        // remove rows
        for (int r = rowCount - 1; r >= 0; r--)
            if (!occupiedRows[r])
                removeFreeRow(r);
        // remove columns
        for (int c = colCount - 1; c >= 0; c--)
            if (!occupiedColumns[c])
                removeFreeColumn(c);
        return true;
    }

    void GridLayoutState::removeFreeRow(int removeRow)
    {
        const WidgetItemMap::iterator iend = widgetItemMap.end();
        for (WidgetItemMap::iterator it = widgetItemMap.begin(); it != iend; ++it) {
            const int r = it.value().y();
            Q_ASSERT(r != removeRow); // Free rows only
            if (r < removeRow) { // Does the item span it? - shrink it
                const int rowSpan = it.value().height();
                if (rowSpan > 1) {
                    const int bottomRow = r + rowSpan;
                    if (bottomRow > removeRow)
                        it.value().setHeight(rowSpan - 1);
                }
            } else
                if (r > removeRow) // Item below it? - move.
                    it.value().translate(0, -1);
        }
        rowCount--;
    }

    void GridLayoutState::removeFreeColumn(int removeColumn)
    {
        const WidgetItemMap::iterator iend = widgetItemMap.end();
        for (WidgetItemMap::iterator it = widgetItemMap.begin(); it != iend; ++it) {
            const int c = it.value().x();
            Q_ASSERT(c != removeColumn); // Free columns only
            if (c < removeColumn) { // Does the item span it? - shrink it
                const int colSpan = it.value().width();
                if (colSpan > 1) {
                    const int rightColumn = c + colSpan;
                    if (rightColumn > removeColumn)
                        it.value().setWidth(colSpan - 1);
                }
            } else
                if (c > removeColumn) // Item to the right of it?  - move.
                    it.value().translate(-1, 0);
        }
        colCount--;
    }

    // ---------------- GridLayoutHelper
    class GridLayoutHelper : public  LayoutHelper {
    public:
        GridLayoutHelper() {}

        virtual QRect itemInfo(QLayout *lt, int index) const;
        virtual void insertWidget(QLayout *lt, const QRect &info, QWidget *w);
        virtual void removeWidget(QLayout *lt, QWidget *widget);
        virtual void replaceWidget(QLayout *lt, QWidget *before, QWidget *after);

        virtual void pushState(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout);
        virtual void popState(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout);

        virtual bool canSimplify(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout, const QRect &restrictionArea) const;
        virtual void simplify(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout, const QRect &restrictionArea);

        static void insertRow(QGridLayout *grid, int row);

    private:
        QStack<GridLayoutState> m_states;
    };

    void GridLayoutHelper::insertRow(QGridLayout *grid, int row)
    {
        GridLayoutState state;
        state.fromLayout(grid);
        state.insertRow(row);
        QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(grid);
        state.applyToLayout(fw->core(), grid->parentWidget());
    }

    QRect GridLayoutHelper::itemInfo(QLayout * lt, int index) const
    {
        QGridLayout *grid = qobject_cast<QGridLayout *>(lt);
        Q_ASSERT(grid);
        return gridItemInfo(grid, index);
    }

    void GridLayoutHelper::insertWidget(QLayout *lt, const QRect &info, QWidget *w)
    {
        QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
        QGridLayout *gridLayout = qobject_cast<QGridLayout *>(lt);
        Q_ASSERT(gridLayout);
        // check if there are any items. Should be only spacers, else something is wrong
        const int row = info.y();
        int column = info.x();
        int colSpan = info.width();
        int rowSpan = info.height();
        // If not empty: A multiselection was dropped on an empty item, insert row
        // and spread items along new row
        if (!removeEmptyCellsOnGrid(gridLayout, info)) {
            int freeColumn = -1;
            colSpan = rowSpan = 1;
            // First look to the right for a free column
            const int columnCount = gridLayout->columnCount();
            for (int c = column; c <  columnCount; c++) {
                const int idx = findGridItemAt(gridLayout, row, c);
                if (idx != -1 && LayoutInfo::isEmptyItem(gridLayout->itemAt(idx))) {
                    freeColumn = c;
                    break;
                }
            }
            if (freeColumn != -1) {
                removeEmptyCellsOnGrid(gridLayout, QRect(freeColumn, row, 1, 1));
                column = freeColumn;
            } else {
                GridLayoutHelper::insertRow(gridLayout, row);
                column = 0;
            }
        }
        gridLayout->addWidget(w, row , column, rowSpan, colSpan);
    }

    void GridLayoutHelper::removeWidget(QLayout *lt, QWidget *widget)
    {
        QGridLayout *gridLayout = qobject_cast<QGridLayout *>(lt);
        Q_ASSERT(gridLayout);
        const int index = gridLayout->indexOf(widget);
        if (index == -1) {
            qWarning() << "GridLayoutHelper::removeWidget : Attempt to remove " << widget <<  " which is not in the layout.";
            return;
        }
        // delete old item and pad with  by spacer items
        int row, column, rowspan, colspan;
        gridLayout->getItemPosition(index, &row, &column, &rowspan, &colspan);
        delete gridLayout->takeAt(index);
        const int rightColumn = column + colspan;
        const int bottomRow = row +  rowspan;
        for (int c = column; c < rightColumn; c++)
            for (int r = row; r < bottomRow; r++)
                gridLayout->addItem(createGridSpacer(), r, c);
    }

    void GridLayoutHelper::replaceWidget(QLayout *lt, QWidget *before, QWidget *after)
    {
        bool ok = false;
        QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
        if (QGridLayout *gridLayout = qobject_cast<QGridLayout *>(lt)) {
            const int index = gridLayout->indexOf(before);
            if (index != -1) {
                int row, column, rowSpan, columnSpan;
                gridLayout->getItemPosition (index,  &row, &column, &rowSpan, &columnSpan);
                const bool visible = before->isVisible();
                delete gridLayout->takeAt(index);
                if (visible)
                    before->hide();
                before->setParent(0);
                gridLayout->addWidget(after, row, column, rowSpan, columnSpan);
                ok = true;
            }
        }
        if (!ok)
            qWarning() << "GridLayoutHelper::replaceWidget : Unable to replace " << before << " by " << after << " in " << lt;
    }

    void GridLayoutHelper::pushState(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout)
    {
        QGridLayout *gridLayout = qobject_cast<QGridLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
        Q_ASSERT(gridLayout);
        GridLayoutState gs;
        gs.fromLayout(gridLayout);
        m_states.push(gs);
    }

    void GridLayoutHelper::popState(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout)
    {
        Q_ASSERT(!m_states.empty());
        const GridLayoutState state = m_states.pop();
        state.applyToLayout(core, widgetWithManagedLayout);
    }

    bool GridLayoutHelper::canSimplify(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout, const QRect &restrictionArea) const
    {
        QGridLayout *gridLayout = qobject_cast<QGridLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
        Q_ASSERT(gridLayout);
        GridLayoutState gs;
        gs.fromLayout(gridLayout);
        return gs.simplify(restrictionArea, true);
    }

    void GridLayoutHelper::simplify(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout, const QRect &restrictionArea)
    {
        QGridLayout *gridLayout = qobject_cast<QGridLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
        Q_ASSERT(gridLayout);
        if (debugLayout)
            qDebug() << ">GridLayoutHelper::simplify" <<  *gridLayout;
        GridLayoutState gs;
        gs.fromLayout(gridLayout);
        if (gs.simplify(restrictionArea, false))
            gs.applyToLayout(core, widgetWithManagedLayout);
        if (debugLayout)
            qDebug() << "<GridLayoutHelper::simplify" <<  *gridLayout;
   }

    // ---------------- FormLayoutHelper
    class FormLayoutHelper : public  LayoutHelper {
    public:
        typedef QPair<QWidget *, QWidget *> WidgetPair;
        typedef QVector<WidgetPair> FormLayoutState;

        FormLayoutHelper() {}

        virtual QRect itemInfo(QLayout *lt, int index) const;
        virtual void insertWidget(QLayout *lt, const QRect &info, QWidget *w);
        virtual void removeWidget(QLayout *lt, QWidget *widget);
        virtual void replaceWidget(QLayout *lt, QWidget *before, QWidget *after);

        virtual void pushState(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout);
        virtual void popState(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout);

        virtual bool canSimplify(const QDesignerFormEditorInterface *core, const QWidget *, const QRect &) const;
        virtual void simplify(const QDesignerFormEditorInterface *, QWidget *, const QRect &);

    private:
        static FormLayoutState state(const QFormLayout *lt);

        QStack<FormLayoutState> m_states;
    };

    QRect FormLayoutHelper::itemInfo(QLayout * lt, int index) const
    {
        QFormLayout *form = qobject_cast<QFormLayout *>(lt);
        Q_ASSERT(form);
        int row, column, colspan;
        getFormLayoutItemPosition(form, index, &row, &column, 0, &colspan);
        return QRect(column, row, colspan, 1);
    }

    void FormLayoutHelper::insertWidget(QLayout *lt, const QRect &info, QWidget *w)
    {
        if (debugLayout)
            qDebug() << "FormLayoutHelper::insertWidget:" << w << info;
        QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
        QFormLayout *formLayout = qobject_cast<QFormLayout *>(lt);
        Q_ASSERT(formLayout);
        // check if there are any nonspacer items? (Drop on 3rd column or drop of a multiselection
        // on an empty item. As the Form layout does not have insert semantics; we need to manually insert a row
        const bool insert = !removeEmptyCellsOnGrid(formLayout, info);
        formLayoutAddWidget(formLayout, w, info, insert);
        QLayoutSupport::createEmptyCells(formLayout);
    }

    void FormLayoutHelper::removeWidget(QLayout *lt, QWidget *widget)
    {
        QFormLayout *formLayout = qobject_cast<QFormLayout *>(lt);
        Q_ASSERT(formLayout);
        const int index = formLayout->indexOf(widget);
        if (index == -1) {
            qWarning() << "FormLayoutHelper::removeWidget : Attempt to remove " << widget <<  " which is not in the layout.";
            return;
        }
        // delete old item and pad with  by spacer items
        int row, column, colspan;
        getFormLayoutItemPosition(formLayout, index, &row, &column, 0, &colspan);
        if (debugLayout)
            qDebug() << "FormLayoutHelper::removeWidget: #" << index << widget << " at " << row << column <<  colspan;
        delete formLayout->takeAt(index);
        if (colspan > 1 || column == 0)
            formLayout->setItem(row, QFormLayout::LabelRole, createFormSpacer());
        if (colspan > 1 || column == 1)
            formLayout->setItem(row, QFormLayout::FieldRole, createFormSpacer());
    }

    void FormLayoutHelper::replaceWidget(QLayout *lt, QWidget *before, QWidget *after)
    {
        bool ok = false;
        QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
        if (QFormLayout *formLayout = qobject_cast<QFormLayout *>(lt)) {
            const int index = formLayout->indexOf(before);
            if (index != -1) {
                int row;
                QFormLayout::ItemRole role;
                formLayout->getItemPosition (index, &row, &role);
                const bool visible = before->isVisible();
                delete formLayout->takeAt(index);
                if (visible)
                    before->hide();
                before->setParent(0);
                formLayout->setWidget(row, role, after);
                ok = true;
            }
        }
        if (!ok)
            qWarning() << "FormLayoutHelper::replaceWidget : Unable to replace " << before << " by " << after << " in " << lt;
    }

    FormLayoutHelper::FormLayoutState FormLayoutHelper::state(const QFormLayout *lt)
    {
        const int rowCount = lt->rowCount();
        if (rowCount == 0)
            return FormLayoutState();
        FormLayoutState rc(rowCount, WidgetPair(0, 0));
        const int count = lt->count();
        int row, column, colspan;
        for (int i = 0; i < count; i++) {
            QLayoutItem *item = lt->itemAt(i);
            if (!LayoutInfo::isEmptyItem(item)) {
                QWidget *w = item->widget();
                Q_ASSERT(w);
                getFormLayoutItemPosition(lt, i, &row, &column, 0, &colspan);
                if (colspan > 1 || column == 0)
                    rc[row].first = w;
                if (colspan > 1 || column == 1)
                    rc[row].second = w;
            }
        }
        if (debugLayout) {
            qDebug() << "FormLayoutHelper::state: " << rowCount;
            for (int r = 0; r < rowCount; r++)
                qDebug() << "  Row: " << r << rc[r].first << rc[r].second;
        }
        return rc;
    }

    void FormLayoutHelper::pushState(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout)
    {
        QFormLayout *formLayout = qobject_cast<QFormLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
        Q_ASSERT(formLayout);
        m_states.push(state(formLayout));
    }

    void FormLayoutHelper::popState(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout)
    {
        QFormLayout *formLayout = qobject_cast<QFormLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
        Q_ASSERT(!m_states.empty() && formLayout);

        const FormLayoutState storedState = m_states.pop();
        const FormLayoutState currentState =  state(formLayout);
        if (currentState ==  storedState)
            return;
        const int rowCount = storedState.size();
        // clear out, shrink if required, but maintain items via map, pad spacers
        const BoxLayoutHelper::LayoutItemVector items = BoxLayoutHelper::disassembleLayout(formLayout);
        if (rowCount < formLayout->rowCount())
            formLayout = static_cast<QFormLayout*>(recreateManagedLayout(core, widgetWithManagedLayout, formLayout ));
        for (int r = 0; r < rowCount; r++) {
            QWidget *widgets[FormLayoutColumns] = { storedState[r].first, storedState[r].second };
            const bool spanning = widgets[0] != 0 && widgets[0] == widgets[1];
            if (spanning) {
                formLayout->setWidget(r, QFormLayout::SpanningRole, widgets[0]);
            } else {
                for (int c = 0; c < FormLayoutColumns; c++) {
                    const QFormLayout::ItemRole role = c == 0 ? QFormLayout::LabelRole : QFormLayout::FieldRole;
                    if (widgets[c] && BoxLayoutHelper::findItemOfWidget(items, widgets[c])) {
                        formLayout->setWidget(r, role, widgets[c]);
                    } else {
                        formLayout->setItem(r, role, createFormSpacer());
                    }
                }
            }
        }
    }

    bool FormLayoutHelper::canSimplify(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout, const QRect &restrictionArea) const
    {
        const QFormLayout *formLayout = qobject_cast<QFormLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
        Q_ASSERT(formLayout);
        return canSimplifyFormLayout(formLayout, restrictionArea);
    }

    void FormLayoutHelper::simplify(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout, const QRect &restrictionArea)
    {
        typedef QPair<QLayoutItem*, QLayoutItem*> LayoutItemPair;
        typedef QVector<LayoutItemPair> LayoutItemPairs;

        QFormLayout *formLayout = qobject_cast<QFormLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
        Q_ASSERT(formLayout);
        if (debugLayout)
            qDebug() << "FormLayoutHelper::simplify";
        // Transform into vector of item pairs
        const int rowCount = formLayout->rowCount();
        LayoutItemPairs pairs(rowCount, LayoutItemPair(0, 0));
        for (int i =  formLayout->count() - 1; i >= 0; i--) {
            int row, col,colspan;
            getFormLayoutItemPosition(formLayout, i, &row, &col, 0, &colspan);
            if (colspan > 1) {
                 pairs[row].first = pairs[row].second = formLayout->takeAt(i);
            } else {
                if (col == 0)
                    pairs[row].first = formLayout->takeAt(i);
                else
                    pairs[row].second = formLayout->takeAt(i);
            }
        }
        // Weed out empty ones
        const int bottomCheckRow = qMin(rowCount, restrictionArea.y() + restrictionArea.height());
        for (int r = bottomCheckRow - 1; r >= restrictionArea.y(); r--)
            if (LayoutInfo::isEmptyItem(pairs[r].first) && LayoutInfo::isEmptyItem(pairs[r].second)) {
                delete pairs[r].first;
                delete pairs[r].second;
                pairs.remove(r);
            }
        const int simpleRowCount = pairs.size();
        if (simpleRowCount < rowCount)
            formLayout = static_cast<QFormLayout *>(recreateManagedLayout(core, widgetWithManagedLayout, formLayout));
        // repopulate
        for (int r = 0; r < simpleRowCount; r++) {
            const bool spanning = pairs[r].first == pairs[r].second;
            if (spanning) {
                formLayout->setItem(r, QFormLayout::SpanningRole, pairs[r].first);
            } else {
                formLayout->setItem(r, QFormLayout::LabelRole, pairs[r].first);
                formLayout->setItem(r, QFormLayout::FieldRole, pairs[r].second);
            }
        }
    }

LayoutHelper *LayoutHelper::createLayoutHelper(int type)
{
    LayoutHelper *rc = 0;
    switch (type) {
    case LayoutInfo::HBox:
        rc = new BoxLayoutHelper(Qt::Horizontal);
        break;
    case LayoutInfo::VBox:
        rc = new BoxLayoutHelper(Qt::Vertical);
        break;
    case LayoutInfo::Grid:
        rc = new GridLayoutHelper;
        break;
    case LayoutInfo::Form:
        return new FormLayoutHelper;
     default:
        break;
    }
    Q_ASSERT(rc);
    return rc;
}

// ---- QLayoutSupport (LayoutDecorationExtension)
QLayoutSupport::QLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, LayoutHelper *helper, QObject *parent)  :
      QObject(parent),
      m_formWindow(formWindow),
      m_helper(helper),
      m_widget(widget),
      m_currentIndex(-1),
      m_currentInsertMode(QDesignerLayoutDecorationExtension::InsertWidgetMode)
{
}

QLayout * QLayoutSupport::layout() const
{
    return LayoutInfo::managedLayout(m_formWindow->core(), m_widget);
}

void QLayoutSupport::hideIndicator(Indicator i)
{
    if (m_indicators[i])
        m_indicators[i]->hide();
}

void QLayoutSupport::showIndicator(Indicator i, const QRect &geometry, const QPalette &p)
{
    if (!m_indicators[i])
        m_indicators[i] = new qdesigner_internal::InvisibleWidget(m_widget);
    QWidget *indicator = m_indicators[i];
    indicator->setAutoFillBackground(true);
    indicator->setPalette(p);
    indicator->setGeometry(geometry);
    indicator->show();
    indicator->raise();
}

QLayoutSupport::~QLayoutSupport()
{
    delete m_helper;
    for (int i = 0; i < NumIndicators; i++)
        if (m_indicators[i])
            m_indicators[i]->deleteLater();
}

QGridLayout * QLayoutSupport::gridLayout() const
{
    return qobject_cast<QGridLayout*>(LayoutInfo::managedLayout(m_formWindow->core(), m_widget));
}

QRect QLayoutSupport::itemInfo(int index) const
{
    return m_helper->itemInfo(LayoutInfo::managedLayout(m_formWindow->core(), m_widget), index);
}

void QLayoutSupport::setInsertMode(InsertMode im)
{
    m_currentInsertMode = im;
}

void QLayoutSupport::setCurrentCell(const QPair<int, int> &cell)
{
    m_currentCell = cell;
}

void QLayoutSupport::adjustIndicator(const QPoint &pos, int index)
{
    if (index == -1) { // first item goes anywhere
        hideIndicator(LeftIndicator);
        hideIndicator(TopIndicator);
        hideIndicator(RightIndicator);
        hideIndicator(BottomIndicator);
        return;
    }
    m_currentIndex = index;
    m_currentInsertMode = QDesignerLayoutDecorationExtension::InsertWidgetMode;

    QLayoutItem *item = layout()->itemAt(index);
    const QRect g = extendedGeometry(index);
    // ### cleanup
    if (LayoutInfo::isEmptyItem(item)) {
        // Empty grid/form cell. Draw a rectangle
        QPalette redPalette;
        redPalette.setColor(QPalette::Window, Qt::red);

        showIndicator(LeftIndicator,   QRect(g.x(),     g.y(),      indicatorSize, g.height()), redPalette);
        showIndicator(TopIndicator,    QRect(g.x(),     g.y(),      g.width(),     indicatorSize), redPalette);
        showIndicator(RightIndicator,  QRect(g.right(), g.y(),      indicatorSize, g.height()), redPalette);
        showIndicator(BottomIndicator, QRect(g.x(),     g.bottom(), g.width(),     indicatorSize), redPalette);
        setCurrentCellFromIndicatorOnEmptyCell(m_currentIndex);
    } else {
        // Append/Insert. Draw a bar left/right or above/below
        QPalette bluePalette;
        bluePalette.setColor(QPalette::Window, Qt::blue);
        hideIndicator(LeftIndicator);
        hideIndicator(TopIndicator);

        const int fromRight = g.right() - pos.x();
        const int fromBottom = g.bottom() - pos.y();

        const int fromLeft = pos.x() - g.x();
        const int fromTop = pos.y() - g.y();

        const int fromLeftRight = qMin(fromRight, fromLeft );
        const int fromBottomTop = qMin(fromBottom, fromTop);

        const Qt::Orientation indicatorOrientation =  fromLeftRight < fromBottomTop ? Qt::Vertical :  Qt::Horizontal;

        if (supportsIndicatorOrientation(indicatorOrientation)) {
            const QRect r(layout()->geometry().topLeft(), layout()->parentWidget()->size());
            switch (indicatorOrientation) {
            case  Qt::Vertical: {
                hideIndicator(BottomIndicator);
                const bool closeToLeft = fromLeftRight == fromLeft;
                showIndicator(RightIndicator, QRect(closeToLeft ? g.x() : g.right() + 1 - indicatorSize, 0, indicatorSize, r.height()), bluePalette);

                const int incr = closeToLeft ? 0 : +1;
                setCurrentCellFromIndicator(indicatorOrientation, m_currentIndex, incr);
            }
            break;
            case  Qt::Horizontal: {
                hideIndicator(RightIndicator);
                const bool closeToTop = fromBottomTop == fromTop;
                showIndicator(BottomIndicator, QRect(r.x(), closeToTop ? g.y() : g.bottom() + 1 - indicatorSize, r.width(), indicatorSize), bluePalette);

                const int incr = closeToTop ? 0 : +1;
                setCurrentCellFromIndicator(indicatorOrientation, m_currentIndex, incr);
            }
                break;
            }
        } else {
            hideIndicator(RightIndicator);
            hideIndicator(BottomIndicator);
        } // can handle indicatorOrientation
    }
}

int QLayoutSupport::indexOf(QLayoutItem *i) const
{
    const QLayout *lt = layout();
    if (!lt)
        return -1;

    int index = 0;

    while (QLayoutItem *item = lt->itemAt(index)) {
        if (item == i)
            return index;

        ++index;
    }

    return -1;
}

int QLayoutSupport::indexOf(QWidget *widget) const
{
    const QLayout *lt = layout();
    if (!lt)
        return -1;

    int index = 0;
    while (QLayoutItem *item = lt->itemAt(index)) {
        if (item->widget() == widget)
            return index;

        ++index;
    }

    return -1;
}

QList<QWidget*> QLayoutSupport::widgets(QLayout *layout) const
{
    if (!layout)
        return QList<QWidget*>();

    QList<QWidget*> lst;
    int index = 0;
    while (QLayoutItem *item = layout->itemAt(index)) {
        ++index;

        QWidget *widget = item->widget();
        if (widget && formWindow()->isManaged(widget))
            lst.append(widget);
    }

    return lst;
}

int QLayoutSupport::findItemAt(QGridLayout *gridLayout, int at_row, int at_column)
{
    return findGridItemAt(gridLayout, at_row, at_column);
}

// Quick check whether simplify should be enabled for grids. May return false positives.
// Note: Calculating the occupied area does not work as spanning items may also be simplified.

bool QLayoutSupport::canSimplifyQuickCheck(const QGridLayout *gl)
{
    if (!gl)
        return false;
    const int colCount = gl->columnCount();
    const int rowCount = gl->rowCount();
    if (colCount < 2 || rowCount < 2)
        return false;
    // try to find a spacer.
    const int count = gl->count();
    for (int index = 0; index < count; index++)
        if (LayoutInfo::isEmptyItem(gl->itemAt(index)))
            return true;
    return false;
}

bool QLayoutSupport::canSimplifyQuickCheck(const QFormLayout *fl)
{
    return canSimplifyFormLayout(fl, QRect(QPoint(0, 0), QSize(32767, 32767)));
}

// remove dummy spacers
bool QLayoutSupport::removeEmptyCells(QGridLayout *grid, const QRect &area)
{
    return removeEmptyCellsOnGrid(grid, area);
}

void QLayoutSupport::createEmptyCells(QGridLayout *gridLayout)
{
    Q_ASSERT(gridLayout);
    GridLayoutState gs;
    gs.fromLayout(gridLayout);

    const GridLayoutState::CellStates cs = GridLayoutState::cellStates(gs.widgetItemMap.values(), gs.rowCount, gs.colCount);
    for (int c = 0; c < gs.colCount; c++)
        for (int r = 0; r < gs.rowCount; r++)
            if (needsSpacerItem(cs[r * gs.colCount + c])) {
                const int existingItemIndex = findItemAt(gridLayout, r, c);
                if (existingItemIndex == -1)
                    gridLayout->addItem(createGridSpacer(), r, c);
            }
}

bool QLayoutSupport::removeEmptyCells(QFormLayout *formLayout, const QRect &area)
{
    return removeEmptyCellsOnGrid(formLayout, area);
}

void QLayoutSupport::createEmptyCells(QFormLayout *formLayout)
{
    // No spanning items here..
    if (const int rowCount = formLayout->rowCount())
        for (int c = 0; c < FormLayoutColumns; c++)
            for (int r = 0; r < rowCount; r++)
                if (findGridItemAt(formLayout, r, c) == -1)
                    formLayout->setItem(r, c == 0 ? QFormLayout::LabelRole : QFormLayout::FieldRole, createFormSpacer());
}

int QLayoutSupport::findItemAt(const QPoint &pos) const
{
    if (!layout())
        return -1;

    const QLayout *lt = layout();
    const int count = lt->count();

    if (count == 0)
        return -1;

    int best = -1;
    int bestIndex = -1;

    for (int index = 0;  index < count;  index++) {
        QLayoutItem *item = lt->itemAt(index);
        bool visible = true;
        // When dragging widgets within layout, the source widget is invisible and must not be hit
        if (const QWidget *w = item->widget())
            visible = w->isVisible();
        if (visible) {
            const QRect g = item->geometry();

            const int dist = (g.center() - pos).manhattanLength();
            if (best == -1 || dist < best) {
                best = dist;
                bestIndex = index;
            }
        }
    }
    return bestIndex;
}

// ------------ QBoxLayoutSupport (LayoutDecorationExtension)
namespace {
class QBoxLayoutSupport: public QLayoutSupport
{
public:
    QBoxLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, Qt::Orientation orientation, QObject *parent = 0);

    virtual void insertWidget(QWidget *widget, const QPair<int, int> &cell);
    virtual void removeWidget(QWidget *widget);
    virtual void simplify() {}
    virtual void insertRow(int /*row*/) {}
    virtual void insertColumn(int /*column*/) {}

    virtual int findItemAt(int /*at_row*/, int /*at_column*/) const {    return -1; }

private:
    virtual void setCurrentCellFromIndicatorOnEmptyCell(int index);
    virtual void setCurrentCellFromIndicator(Qt::Orientation indicatorOrientation, int index, int increment);
    virtual bool supportsIndicatorOrientation(Qt::Orientation indicatorOrientation) const;
    virtual QRect extendedGeometry(int index) const;

    const Qt::Orientation m_orientation;
};

void QBoxLayoutSupport::removeWidget(QWidget *widget)
{
    QLayout *lt = layout();
    const int index = lt->indexOf(widget);
    // Adjust the current cell in case a widget was dragged within the same layout to a position
    // of higher index, which happens as follows:
    // Drag start: The widget is hidden
    // Drop: Current cell is stored, widget is removed and re-added, causing an index offset that needs to be compensated
    QPair<int, int> currCell = currentCell();
    switch (m_orientation) {
    case Qt::Horizontal:
        if (currCell.second > 0 && index < currCell.second ) {
            currCell.second--;
            setCurrentCell(currCell);
        }
        break;
    case Qt::Vertical:
        if (currCell.first > 0 && index < currCell.first) {
            currCell.first--;
            setCurrentCell(currCell);
        }
        break;
    }
    helper()->removeWidget(lt, widget);
}

QBoxLayoutSupport::QBoxLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, Qt::Orientation orientation, QObject *parent) :
    QLayoutSupport(formWindow, widget, new BoxLayoutHelper(orientation), parent),
    m_orientation(orientation)
{
}

void QBoxLayoutSupport::setCurrentCellFromIndicatorOnEmptyCell(int index)
{
    qDebug() << "QBoxLayoutSupport::setCurrentCellFromIndicatorOnEmptyCell(): Warning: found a fake spacer inside a vbox layout at " << index;
    setCurrentCell(qMakePair(0, 0));
}

void QBoxLayoutSupport::insertWidget(QWidget *widget, const QPair<int, int> &cell)
{
    switch (m_orientation) {
    case  Qt::Horizontal:
        helper()->insertWidget(layout(), QRect(cell.second, 0, 1, 1), widget);
        break;
    case  Qt::Vertical:
        helper()->insertWidget(layout(), QRect(0, cell.first, 1, 1), widget);
        break;
    }
}

void QBoxLayoutSupport::setCurrentCellFromIndicator(Qt::Orientation indicatorOrientation, int index, int increment)
{
    if (m_orientation == Qt::Horizontal && indicatorOrientation == Qt::Vertical) {
        setCurrentCell(qMakePair(0, index + increment));
    } else if (m_orientation == Qt::Vertical && indicatorOrientation == Qt::Horizontal) {
        setCurrentCell(qMakePair(index + increment, 0));
    }
}

bool QBoxLayoutSupport::supportsIndicatorOrientation(Qt::Orientation indicatorOrientation) const
{
    return m_orientation != indicatorOrientation;
}

QRect QBoxLayoutSupport::extendedGeometry(int index) const
{
    QLayoutItem *item = layout()->itemAt(index);
    // start off with item geometry
    QRect g = item->geometry();

    const QRect info = itemInfo(index);

    // On left border: extend to widget border
    if (info.x() == 0) {
        QPoint topLeft = g.topLeft();
        topLeft.rx() = layout()->geometry().left();
        g.setTopLeft(topLeft);
    }

    // On top border: extend to widget border
    if (info.y() == 0) {
        QPoint topLeft = g.topLeft();
        topLeft.ry() = layout()->geometry().top();
        g.setTopLeft(topLeft);
    }

    // is this the last item?
    const QBoxLayout *box = static_cast<const QBoxLayout*>(layout());
    if (index < box->count() -1)
        return g; // Nope.

    // extend to widget border
    QPoint bottomRight = g.bottomRight();
    switch (m_orientation) {
    case Qt::Vertical:
        bottomRight.ry() = layout()->geometry().bottom();
        break;
    case Qt::Horizontal:
        bottomRight.rx() = layout()->geometry().right();
        break;
    }
    g.setBottomRight(bottomRight);
    return g;
}

// --------------  Base class for QGridLayout-like support classes (LayoutDecorationExtension)
template <class GridLikeLayout>
class GridLikeLayoutSupportBase: public QLayoutSupport
{
public:

    GridLikeLayoutSupportBase(QDesignerFormWindowInterface *formWindow, QWidget *widget, LayoutHelper *helper, QObject *parent = 0) :
        QLayoutSupport(formWindow, widget, helper, parent) {}

    void insertWidget(QWidget *widget, const QPair<int, int> &cell);
    virtual void removeWidget(QWidget *widget) { helper()->removeWidget(layout(), widget); }
    virtual int findItemAt(int row, int column) const;

protected:
    GridLikeLayout *gridLikeLayout() const {
        return qobject_cast<GridLikeLayout*>(LayoutInfo::managedLayout(formWindow()->core(), widget()));
    }

private:

    virtual void setCurrentCellFromIndicatorOnEmptyCell(int index);
    virtual void setCurrentCellFromIndicator(Qt::Orientation indicatorOrientation, int index, int increment);
    virtual bool supportsIndicatorOrientation(Qt::Orientation) const { return true; }

    virtual QRect extendedGeometry(int index) const;

    // Overwrite to check the insertion position (if there are limits)
    virtual void checkCellForInsertion(int * /*row*/, int * /*col*/) const {}
};

template <class GridLikeLayout>
void GridLikeLayoutSupportBase<GridLikeLayout>::setCurrentCellFromIndicatorOnEmptyCell(int index)
{
    GridLikeLayout *grid = gridLikeLayout();
    Q_ASSERT(grid);

    setInsertMode(InsertWidgetMode);
    int row, column, rowspan, colspan;

    getGridItemPosition(grid, index, &row, &column, &rowspan, &colspan);
    setCurrentCell(qMakePair(row, column));
}

template <class GridLikeLayout>
void GridLikeLayoutSupportBase<GridLikeLayout>::setCurrentCellFromIndicator(Qt::Orientation indicatorOrientation, int index, int increment) {
    const QRect info = itemInfo(index);
    switch (indicatorOrientation) {
    case Qt::Vertical: {
        setInsertMode(InsertColumnMode);
        int row = info.top();
        int column = increment ? info.right() + 1 : info.left();
        checkCellForInsertion(&row, &column);
        setCurrentCell(qMakePair(row , column));
    }
        break;
    case Qt::Horizontal: {
        setInsertMode(InsertRowMode);
        int row = increment ? info.bottom() + 1 : info.top();
        int column = info.left();
        checkCellForInsertion(&row, &column);
        setCurrentCell(qMakePair(row, column));
    }
        break;
    }
}

template <class GridLikeLayout>
void GridLikeLayoutSupportBase<GridLikeLayout>::insertWidget(QWidget *widget, const QPair<int, int> &cell)
{
    helper()->insertWidget(layout(), QRect(cell.second, cell.first, 1, 1), widget);
}

template <class GridLikeLayout>
int GridLikeLayoutSupportBase<GridLikeLayout>::findItemAt(int at_row, int at_column) const
{
    GridLikeLayout *grid = gridLikeLayout();
    Q_ASSERT(grid);
    return findGridItemAt(grid, at_row, at_column);
}

template <class GridLikeLayout>
QRect GridLikeLayoutSupportBase<GridLikeLayout>::extendedGeometry(int index) const
{
    QLayoutItem *item = layout()->itemAt(index);
    // start off with item geometry
    QRect g = item->geometry();

    const QRect info = itemInfo(index);

    // On left border: extend to widget border
    if (info.x() == 0) {
        QPoint topLeft = g.topLeft();
        topLeft.rx() = layout()->geometry().left();
        g.setTopLeft(topLeft);
    }

    // On top border: extend to widget border
    if (info.y() == 0) {
        QPoint topLeft = g.topLeft();
        topLeft.ry() = layout()->geometry().top();
        g.setTopLeft(topLeft);
    }
    const GridLikeLayout *grid = gridLikeLayout();
    Q_ASSERT(grid);

    // extend to widget border
    QPoint bottomRight = g.bottomRight();
    if (gridRowCount(grid) == info.y())
        bottomRight.ry() = layout()->geometry().bottom();
    if (gridColumnCount(grid) == info.x())
        bottomRight.rx() = layout()->geometry().right();
    g.setBottomRight(bottomRight);
    return g;
}

// --------------  QGridLayoutSupport (LayoutDecorationExtension)
class QGridLayoutSupport: public GridLikeLayoutSupportBase<QGridLayout>
{
public:

    QGridLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, QObject *parent = 0);

    virtual void simplify();
    virtual void insertRow(int row);
    virtual void insertColumn(int column);

private:
};

QGridLayoutSupport::QGridLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, QObject *parent) :
    GridLikeLayoutSupportBase<QGridLayout>(formWindow, widget, new GridLayoutHelper, parent)
{
}

void QGridLayoutSupport::insertRow(int row)
{
    QGridLayout *grid = gridLayout();
    Q_ASSERT(grid);
    GridLayoutHelper::insertRow(grid, row);
}

void QGridLayoutSupport::insertColumn(int column)
{
    QGridLayout *grid = gridLayout();
    Q_ASSERT(grid);
    GridLayoutState state;
    state.fromLayout(grid);
    state.insertColumn(column);
    state.applyToLayout(formWindow()->core(), widget());
}

void QGridLayoutSupport::simplify()
{
    QGridLayout *grid = gridLayout();
    Q_ASSERT(grid);
    GridLayoutState state;
    state.fromLayout(grid);

    const QRect fullArea = QRect(0, 0, state.colCount, state.rowCount);
    if (state.simplify(fullArea, false))
        state.applyToLayout(formWindow()->core(), widget());
}

// --------------  QFormLayoutSupport (LayoutDecorationExtension)
class QFormLayoutSupport: public GridLikeLayoutSupportBase<QFormLayout>
{
public:
    QFormLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, QObject *parent = 0);

    virtual void simplify() {}
    virtual void insertRow(int /*row*/) {}
    virtual void insertColumn(int /*column*/) {}

private:
    virtual void checkCellForInsertion(int * row, int *col) const;
};

QFormLayoutSupport::QFormLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, QObject *parent) :
    GridLikeLayoutSupportBase<QFormLayout>(formWindow, widget, new FormLayoutHelper, parent)
{
}

void QFormLayoutSupport::checkCellForInsertion(int *row, int *col) const
{
    if (*col >= FormLayoutColumns) { // Clamp to 2 columns
        *col = 1;
        (*row)++;
    }
}
} //  anonymous namespace

QLayoutSupport *QLayoutSupport::createLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, QObject *parent)
{
    const QLayout *layout = LayoutInfo::managedLayout(formWindow->core(), widget);
    Q_ASSERT(layout);
    QLayoutSupport *rc = 0;
    switch (LayoutInfo::layoutType(formWindow->core(), layout)) {
    case LayoutInfo::HBox:
        rc = new QBoxLayoutSupport(formWindow, widget, Qt::Horizontal, parent);
        break;
    case LayoutInfo::VBox:
        rc = new QBoxLayoutSupport(formWindow, widget, Qt::Vertical, parent);
        break;
    case LayoutInfo::Grid:
        rc = new QGridLayoutSupport(formWindow, widget, parent);
        break;
    case LayoutInfo::Form:
        rc = new QFormLayoutSupport(formWindow, widget, parent);
        break;
     default:
        break;
    }
    Q_ASSERT(rc);
    return rc;
}
} // namespace qdesigner_internal

// -------------- QLayoutWidget
QLayoutWidget::QLayoutWidget(QDesignerFormWindowInterface *formWindow, QWidget *parent)
    : QWidget(parent), m_formWindow(formWindow),
      m_leftMargin(0), m_topMargin(0), m_rightMargin(0), m_bottomMargin(0)
{
}

void QLayoutWidget::paintEvent(QPaintEvent*)
{
    if (m_formWindow->currentTool() != 0)
        return;

    // only draw red borders if we're editting widgets

    QPainter p(this);

    QMap<int, QMap<int, bool> > excludedRowsForColumn;
    QMap<int, QMap<int, bool> > excludedColumnsForRow;

    QLayout *lt = layout();
    QGridLayout *grid = qobject_cast<QGridLayout *>(lt);
    if (lt) {
        if (const int count = lt->count()) {
            p.setPen(QPen(QColor(255, 0, 0, 35), 1));
            for (int i = 0; i < count; i++) {
                QLayoutItem *item = lt->itemAt(i);
                if (grid) {
                    int row, column, rowSpan, columnSpan;
                    grid->getItemPosition(i, &row, &column, &rowSpan, &columnSpan);
                    QMap<int, bool> rows;
                    QMap<int, bool> columns;
                    for (int i = rowSpan; i > 1; i--)
                        rows[row + i - 2] = true;
                    for (int i = columnSpan; i > 1; i--)
                        columns[column + i - 2] = true;

                    while (rowSpan > 0) {
                        excludedColumnsForRow[row + rowSpan - 1].unite(columns);
                        rowSpan--;
                    }
                    while (columnSpan > 0) {
                        excludedRowsForColumn[column + columnSpan - 1].unite(rows);
                        columnSpan--;
                    }
                }
                if (item->spacerItem()) {
                    const QRect geometry = item->geometry();
                    if (!geometry.isNull())
                        p.drawRect(geometry.adjusted(1, 1, -2, -2));
                }
            }
        }
    }
    if (grid) {
        p.setPen(QPen(QColor(0, 0x80, 0, 0x80), 1));
        const int rowCount = grid->rowCount();
        const int columnCount = grid->columnCount();
        for (int i = 0; i < rowCount; i++) {
            for (int j = 0; j < columnCount; j++) {
                const QRect cellRect = grid->cellRect(i, j);
                if (j < columnCount - 1 && excludedColumnsForRow.value(i).value(j, false) == false) {
                    const double y0 = (i == 0)
                            ? 0 : (grid->cellRect(i - 1, j).bottom() + cellRect.top()) / 2.0;
                    const double y1 = (i == rowCount - 1)
                            ? height() - 1 : (cellRect.bottom() + grid->cellRect(i + 1, j).top()) / 2.0;
                    const double x = (cellRect.right() + grid->cellRect(i, j + 1).left()) / 2.0;
                    p.drawLine(QPointF(x, y0), QPointF(x, y1));
                }
                if (i < rowCount - 1 && excludedRowsForColumn.value(j).value(i, false) == false) {
                    const double x0 = (j == 0)
                            ? 0 : (grid->cellRect(i, j - 1).right() + cellRect.left()) / 2.0;
                    const double x1 = (j == columnCount - 1)
                            ? width() - 1 : (cellRect.right() + grid->cellRect(i, j + 1).left()) / 2.0;
                    const double y = (cellRect.bottom() + grid->cellRect(i + 1, j).top()) / 2.0;
                    p.drawLine(QPointF(x0, y), QPointF(x1, y));
                }
            }
        }
    }
    p.setPen(QPen(QColor(255, 0, 0, 128), 1));
    p.drawRect(0, 0, width() - 1, height() - 1);
}

bool QLayoutWidget::event(QEvent *e)
{
    switch (e->type()) {
        case QEvent::LayoutRequest: {
            (void) QWidget::event(e);
            // Magic: We are layouted, but the parent is not..
            if (layout() && qdesigner_internal::LayoutInfo::layoutType(formWindow()->core(), parentWidget()) == qdesigner_internal::LayoutInfo::NoLayout) {
                resize(layout()->totalMinimumSize().expandedTo(size()));
            }

            update();

            return true;
        }

        default:
            break;
    }

    return QWidget::event(e);
}

int QLayoutWidget::layoutLeftMargin() const
{
    if (m_leftMargin < 0 && layout()) {
        int margin;
        layout()->getContentsMargins(&margin, 0, 0, 0);
        return margin;
    }
    return m_leftMargin;
}

void QLayoutWidget::setLayoutLeftMargin(int layoutMargin)
{
    m_leftMargin = layoutMargin;
    if (layout()) {
        int newMargin = m_leftMargin;
        if (newMargin >= 0 && newMargin < ShiftValue)
            newMargin = ShiftValue;
        int left, top, right, bottom;
        layout()->getContentsMargins(&left, &top, &right, &bottom);
        layout()->setContentsMargins(newMargin, top, right, bottom);
    }
}

int QLayoutWidget::layoutTopMargin() const
{
    if (m_topMargin < 0 && layout()) {
        int margin;
        layout()->getContentsMargins(0, &margin, 0, 0);
        return margin;
    }
    return m_topMargin;
}

void QLayoutWidget::setLayoutTopMargin(int layoutMargin)
{
    m_topMargin = layoutMargin;
    if (layout()) {
        int newMargin = m_topMargin;
        if (newMargin >= 0 && newMargin < ShiftValue)
            newMargin = ShiftValue;
        int left, top, right, bottom;
        layout()->getContentsMargins(&left, &top, &right, &bottom);
        layout()->setContentsMargins(left, newMargin, right, bottom);
    }
}

int QLayoutWidget::layoutRightMargin() const
{
    if (m_rightMargin < 0 && layout()) {
        int margin;
        layout()->getContentsMargins(0, 0, &margin, 0);
        return margin;
    }
    return m_rightMargin;
}

void QLayoutWidget::setLayoutRightMargin(int layoutMargin)
{
    m_rightMargin = layoutMargin;
    if (layout()) {
        int newMargin = m_rightMargin;
        if (newMargin >= 0 && newMargin < ShiftValue)
            newMargin = ShiftValue;
        int left, top, right, bottom;
        layout()->getContentsMargins(&left, &top, &right, &bottom);
        layout()->setContentsMargins(left, top, newMargin, bottom);
    }
}

int QLayoutWidget::layoutBottomMargin() const
{
    if (m_bottomMargin < 0 && layout()) {
        int margin;
        layout()->getContentsMargins(0, 0, 0, &margin);
        return margin;
    }
    return m_bottomMargin;
}

void QLayoutWidget::setLayoutBottomMargin(int layoutMargin)
{
    m_bottomMargin = layoutMargin;
    if (layout()) {
        int newMargin = m_bottomMargin;
        if (newMargin >= 0 && newMargin < ShiftValue)
            newMargin = ShiftValue;
        int left, top, right, bottom;
        layout()->getContentsMargins(&left, &top, &right, &bottom);
        layout()->setContentsMargins(left, top, right, newMargin);
    }
}

QT_END_NAMESPACE
