tools/designer/src/lib/shared/layoutinfo.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Designer of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "layoutinfo_p.h"
       
    43 
       
    44 #include <QtDesigner/QDesignerFormEditorInterface>
       
    45 #include <QtDesigner/QDesignerContainerExtension>
       
    46 #include <QtDesigner/QDesignerMetaDataBaseInterface>
       
    47 #include <QtDesigner/QExtensionManager>
       
    48 
       
    49 #include <QtGui/QHBoxLayout>
       
    50 #include <QtGui/QFormLayout>
       
    51 #include <QtGui/QSplitter>
       
    52 #include <QtCore/QDebug>
       
    53 #include <QtCore/QHash>
       
    54 #include <QtCore/QRect>
       
    55 
       
    56 QT_BEGIN_NAMESPACE
       
    57 
       
    58 namespace qdesigner_internal {
       
    59 /*!
       
    60   \overload
       
    61 */
       
    62 LayoutInfo::Type LayoutInfo::layoutType(const QDesignerFormEditorInterface *core, const QLayout *layout)
       
    63 {
       
    64     Q_UNUSED(core)
       
    65     if (!layout)
       
    66         return NoLayout;
       
    67     else if (qobject_cast<const QHBoxLayout*>(layout))
       
    68         return HBox;
       
    69     else if (qobject_cast<const QVBoxLayout*>(layout))
       
    70         return VBox;
       
    71     else if (qobject_cast<const QGridLayout*>(layout))
       
    72         return Grid;
       
    73     else if (qobject_cast<const QFormLayout*>(layout))
       
    74        return Form;
       
    75     return UnknownLayout;
       
    76 }
       
    77 
       
    78 static const QHash<QString, LayoutInfo::Type> &layoutNameTypeMap()
       
    79 {
       
    80     static QHash<QString, LayoutInfo::Type> nameTypeMap;
       
    81     if (nameTypeMap.empty()) {
       
    82         nameTypeMap.insert(QLatin1String("QVBoxLayout"), LayoutInfo::VBox);
       
    83         nameTypeMap.insert(QLatin1String("QHBoxLayout"), LayoutInfo::HBox);
       
    84         nameTypeMap.insert(QLatin1String("QGridLayout"), LayoutInfo::Grid);
       
    85         nameTypeMap.insert(QLatin1String("QFormLayout"), LayoutInfo::Form);
       
    86     }
       
    87     return nameTypeMap;
       
    88 }
       
    89 
       
    90 LayoutInfo::Type LayoutInfo::layoutType(const QString &typeName)
       
    91 {
       
    92     return layoutNameTypeMap().value(typeName, NoLayout);
       
    93 }
       
    94 
       
    95 QString LayoutInfo::layoutName(Type t)
       
    96 {
       
    97     return layoutNameTypeMap().key(t);
       
    98 }
       
    99 
       
   100 /*!
       
   101   \overload
       
   102 */
       
   103 LayoutInfo::Type LayoutInfo::layoutType(const QDesignerFormEditorInterface *core, const QWidget *w)
       
   104 {
       
   105     if (const QSplitter *splitter = qobject_cast<const QSplitter *>(w))
       
   106         return  splitter->orientation() == Qt::Horizontal ? HSplitter : VSplitter;
       
   107     return layoutType(core, w->layout());
       
   108 }
       
   109 
       
   110 LayoutInfo::Type LayoutInfo::managedLayoutType(const QDesignerFormEditorInterface *core,
       
   111                                                const QWidget *w,
       
   112                                                QLayout **ptrToLayout)
       
   113 {
       
   114     if (ptrToLayout)
       
   115         *ptrToLayout = 0;
       
   116     if (const QSplitter *splitter = qobject_cast<const QSplitter *>(w))
       
   117         return  splitter->orientation() == Qt::Horizontal ? HSplitter : VSplitter;
       
   118     QLayout *layout = managedLayout(core, w);
       
   119     if (!layout)
       
   120         return NoLayout;
       
   121     if (ptrToLayout)
       
   122         *ptrToLayout = layout;
       
   123     return layoutType(core, layout);
       
   124 }
       
   125 
       
   126 QWidget *LayoutInfo::layoutParent(const QDesignerFormEditorInterface *core, QLayout *layout)
       
   127 {
       
   128     Q_UNUSED(core)
       
   129 
       
   130     QObject *o = layout;
       
   131     while (o) {
       
   132         if (QWidget *widget = qobject_cast<QWidget*>(o))
       
   133             return widget;
       
   134 
       
   135         o = o->parent();
       
   136     }
       
   137     return 0;
       
   138 }
       
   139 
       
   140 void LayoutInfo::deleteLayout(const QDesignerFormEditorInterface *core, QWidget *widget)
       
   141 {
       
   142     if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), widget))
       
   143         widget = container->widget(container->currentIndex());
       
   144 
       
   145     Q_ASSERT(widget != 0);
       
   146 
       
   147     QLayout *layout = managedLayout(core, widget);
       
   148 
       
   149     if (layout == 0 || core->metaDataBase()->item(layout) != 0) {
       
   150         delete layout;
       
   151         widget->updateGeometry();
       
   152         return;
       
   153     }
       
   154 
       
   155     qDebug() << "trying to delete an unmanaged layout:" << "widget:" << widget << "layout:" << layout;
       
   156 }
       
   157 
       
   158 LayoutInfo::Type LayoutInfo::laidoutWidgetType(const QDesignerFormEditorInterface *core,
       
   159                                                QWidget *widget,
       
   160                                                bool *isManaged,
       
   161                                                QLayout **ptrToLayout)
       
   162 {
       
   163     if (isManaged)
       
   164         *isManaged = false;
       
   165     if (ptrToLayout)
       
   166         *ptrToLayout = 0;
       
   167 
       
   168     QWidget *parent = widget->parentWidget();
       
   169     if (!parent)
       
   170         return NoLayout;
       
   171 
       
   172     // 1) Splitter
       
   173     if (QSplitter *splitter  = qobject_cast<QSplitter*>(parent)) {
       
   174         if (isManaged)
       
   175             *isManaged = core->metaDataBase()->item(splitter);
       
   176         return  splitter->orientation() == Qt::Horizontal ? HSplitter : VSplitter;
       
   177     }
       
   178 
       
   179     // 2) Layout of parent
       
   180     QLayout *parentLayout = parent->layout();
       
   181     if (!parentLayout)
       
   182         return NoLayout;
       
   183 
       
   184     if (parentLayout->indexOf(widget) != -1) {
       
   185         if (isManaged)
       
   186             *isManaged = core->metaDataBase()->item(parentLayout);
       
   187         if (ptrToLayout)
       
   188             *ptrToLayout = parentLayout;
       
   189         return layoutType(core, parentLayout);
       
   190     }
       
   191 
       
   192     // 3) Some child layout (see below comment about Q3GroupBox)
       
   193     const QList<QLayout*> childLayouts = qFindChildren<QLayout*>(parentLayout);
       
   194     if (childLayouts.empty())
       
   195         return NoLayout;
       
   196     const QList<QLayout*>::const_iterator lcend = childLayouts.constEnd();
       
   197     for (QList<QLayout*>::const_iterator it = childLayouts.constBegin(); it != lcend; ++it) {
       
   198         QLayout *layout = *it;
       
   199         if (layout->indexOf(widget) != -1) {
       
   200             if (isManaged)
       
   201                 *isManaged = core->metaDataBase()->item(layout);
       
   202             if (ptrToLayout)
       
   203                 *ptrToLayout = layout;
       
   204             return layoutType(core, layout);
       
   205         }
       
   206     }
       
   207 
       
   208     return NoLayout;
       
   209 }
       
   210 
       
   211 QLayout *LayoutInfo::internalLayout(const QWidget *widget)
       
   212 {
       
   213     QLayout *widgetLayout = widget->layout();
       
   214     if (widgetLayout && widget->inherits("Q3GroupBox")) {
       
   215         if (widgetLayout->count()) {
       
   216             widgetLayout = widgetLayout->itemAt(0)->layout();
       
   217         } else {
       
   218             widgetLayout = 0;
       
   219         }
       
   220     }
       
   221     return widgetLayout;
       
   222 }
       
   223 
       
   224 
       
   225 QLayout *LayoutInfo::managedLayout(const QDesignerFormEditorInterface *core, const QWidget *widget)
       
   226 {
       
   227     if (widget == 0)
       
   228         return 0;
       
   229 
       
   230     QLayout *layout = widget->layout();
       
   231     if (!layout)
       
   232         return 0;
       
   233 
       
   234     return managedLayout(core, layout);
       
   235 }
       
   236 
       
   237 QLayout *LayoutInfo::managedLayout(const QDesignerFormEditorInterface *core, QLayout *layout)
       
   238 {
       
   239     QDesignerMetaDataBaseInterface *metaDataBase = core->metaDataBase();
       
   240 
       
   241     if (!metaDataBase)
       
   242         return layout;
       
   243     /* This code exists mainly for the Q3GroupBox class, for which
       
   244      * widget->layout() returns an internal VBoxLayout. */
       
   245     const QDesignerMetaDataBaseItemInterface *item = metaDataBase->item(layout);
       
   246     if (item == 0) {
       
   247         layout = qFindChild<QLayout*>(layout);
       
   248         item = metaDataBase->item(layout);
       
   249     }
       
   250     if (!item)
       
   251         return 0;
       
   252     return layout;
       
   253 }
       
   254 
       
   255 // Is it a a dummy grid placeholder created by Designer?
       
   256 bool LayoutInfo::isEmptyItem(QLayoutItem *item)
       
   257 {
       
   258     if (item == 0) {
       
   259         qDebug() << "** WARNING Zero-item passed on to isEmptyItem(). This indicates a layout inconsistency.";
       
   260         return true;
       
   261     }
       
   262     return item->spacerItem() != 0;
       
   263 }
       
   264 
       
   265 QDESIGNER_SHARED_EXPORT void getFormLayoutItemPosition(const QFormLayout *formLayout, int index, int *rowPtr, int *columnPtr, int *rowspanPtr, int *colspanPtr)
       
   266 {
       
   267     int row;
       
   268     QFormLayout::ItemRole role;
       
   269     formLayout->getItemPosition(index, &row, &role);
       
   270     const int columnspan = role == QFormLayout::SpanningRole ? 2 : 1;
       
   271     const int column = (columnspan > 1 || role == QFormLayout::LabelRole) ? 0 : 1;
       
   272     if (rowPtr)
       
   273         *rowPtr = row;
       
   274     if (columnPtr)
       
   275         *columnPtr = column;
       
   276     if (rowspanPtr)
       
   277         *rowspanPtr = 1;
       
   278     if (colspanPtr)
       
   279         *colspanPtr = columnspan;
       
   280 }
       
   281 
       
   282 static inline QFormLayout::ItemRole formLayoutRole(int column, int colspan)
       
   283 {
       
   284     if (colspan > 1)
       
   285         return QFormLayout::SpanningRole;
       
   286     return column == 0 ? QFormLayout::LabelRole : QFormLayout::FieldRole;
       
   287 }
       
   288 
       
   289 QDESIGNER_SHARED_EXPORT void formLayoutAddWidget(QFormLayout *formLayout, QWidget *w, const QRect &r, bool insert)
       
   290 {
       
   291     // Consistent API galore...
       
   292     if (insert) {
       
   293         const bool spanning = r.width() > 1;
       
   294         if (spanning) {
       
   295             formLayout->insertRow(r.y(), w);
       
   296         } else {
       
   297             QWidget *label = 0, *field = 0;
       
   298             if (r.x() == 0) {
       
   299                 label = w;
       
   300             } else {
       
   301                 field = w;
       
   302             }
       
   303             formLayout->insertRow(r.y(), label, field);
       
   304         }
       
   305     } else {
       
   306         formLayout->setWidget(r.y(), formLayoutRole(r.x(), r.width()), w);
       
   307     }
       
   308 }
       
   309 
       
   310 } // namespace qdesigner_internal
       
   311 
       
   312 QT_END_NAMESPACE