tools/designer/src/lib/shared/widgetfactory.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
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 "widgetfactory_p.h"
       
    43 #include "widgetdatabase_p.h"
       
    44 #include "metadatabase_p.h"
       
    45 #include "qlayout_widget_p.h"
       
    46 #include "qdesigner_widget_p.h"
       
    47 #include "qdesigner_tabwidget_p.h"
       
    48 #include "qdesigner_toolbox_p.h"
       
    49 #include "qdesigner_stackedbox_p.h"
       
    50 #include "qdesigner_toolbar_p.h"
       
    51 #include "qdesigner_menubar_p.h"
       
    52 #include "qdesigner_menu_p.h"
       
    53 #include "qdesigner_dockwidget_p.h"
       
    54 #include "qdesigner_utils_p.h"
       
    55 #include "formwindowbase_p.h"
       
    56 
       
    57 // shared
       
    58 #include "layoutinfo_p.h"
       
    59 #include "spacer_widget_p.h"
       
    60 #include "layout_p.h"
       
    61 #include "abstractintrospection_p.h"
       
    62 
       
    63 // sdk
       
    64 #include <QtDesigner/QDesignerFormEditorInterface>
       
    65 #include <QtDesigner/QDesignerContainerExtension>
       
    66 #include <QtDesigner/QDesignerCustomWidgetInterface>
       
    67 #include <QtDesigner/QExtensionManager>
       
    68 #include <QtDesigner/QDesignerPropertySheetExtension>
       
    69 #include <QtDesigner/QDesignerLanguageExtension>
       
    70 #include <QtDesigner/QDesignerFormWindowManagerInterface>
       
    71 #include <QtDesigner/QDesignerFormWindowCursorInterface>
       
    72 
       
    73 #include <QtGui/QtGui>
       
    74 #include <QtGui/QScrollBar>
       
    75 #include <QtGui/QFontComboBox>
       
    76 #include <QtGui/QAbstractSpinBox>
       
    77 #include <QtGui/QLineEdit>
       
    78 #include <QtGui/QButtonGroup>
       
    79 #include <QtGui/QStyle>
       
    80 #include <QtGui/QStyleFactory>
       
    81 #include <QtGui/QWizard>
       
    82 #include <QtCore/qdebug.h>
       
    83 #include <QtCore/QMetaObject>
       
    84 
       
    85 QT_BEGIN_NAMESPACE
       
    86 
       
    87 #ifdef Q_OS_WIN
       
    88 static inline bool isAxWidget(const QObject *o)
       
    89 {
       
    90     // Is it one of  QDesignerAxWidget/QDesignerAxPluginWidget?
       
    91     static const char *axWidgetName = "QDesignerAx";
       
    92     static const unsigned axWidgetNameLen = qstrlen(axWidgetName);
       
    93     return qstrncmp(o->metaObject()->className(), axWidgetName, axWidgetNameLen) == 0;
       
    94 }
       
    95 #endif
       
    96 
       
    97 /* Dynamic boolean property indicating object was created by the factory
       
    98  * for the form editor. */
       
    99 
       
   100 static const char *formEditorDynamicProperty = "_q_formEditorObject";
       
   101 
       
   102 namespace qdesigner_internal {
       
   103 
       
   104 // A friendly SpinBox that grants access to its QLineEdit
       
   105 class FriendlySpinBox : public QAbstractSpinBox {
       
   106 public:
       
   107     friend class WidgetFactory;
       
   108 };
       
   109 
       
   110 // An event filter for form-combo boxes that prevents the embedded line edit
       
   111 // from getting edit focus (and drawing blue artifacts/lines). It catches the
       
   112 // ChildPolished event when the "editable" property flips to true and the
       
   113 // QLineEdit is created and turns off the LineEdit's focus policy.
       
   114 
       
   115 class ComboEventFilter : public QObject {
       
   116 public:
       
   117     explicit ComboEventFilter(QComboBox *parent) : QObject(parent) {}
       
   118     virtual bool eventFilter(QObject *watched, QEvent *event);
       
   119 };
       
   120 
       
   121 bool ComboEventFilter::eventFilter(QObject *watched, QEvent *event)
       
   122 {
       
   123     if (event->type() == QEvent::ChildPolished) {
       
   124         QComboBox *cb = static_cast<QComboBox*>(watched);
       
   125         if (QLineEdit *le = cb->lineEdit())
       
   126             le->setFocusPolicy(Qt::NoFocus);
       
   127     }
       
   128     return QObject::eventFilter(watched, event);
       
   129 }
       
   130 
       
   131 /* Watch out for QWizards changing their pages and make sure that not some
       
   132  * selected widget becomes invisible on a hidden page (causing the selection
       
   133  * handles to shine through). Select the wizard in that case  in analogy to
       
   134  * the QTabWidget event filters, etc. */
       
   135 
       
   136 class WizardPageChangeWatcher : public QObject {
       
   137     Q_OBJECT
       
   138 public:
       
   139     explicit WizardPageChangeWatcher(QWizard *parent);
       
   140 
       
   141 public slots:
       
   142     void pageChanged();
       
   143 };
       
   144 
       
   145 WizardPageChangeWatcher::WizardPageChangeWatcher(QWizard *parent) :
       
   146     QObject(parent)
       
   147 {
       
   148     connect(parent, SIGNAL(currentIdChanged(int)), this, SLOT(pageChanged()));
       
   149 }
       
   150 
       
   151 void WizardPageChangeWatcher::pageChanged()
       
   152 {
       
   153     /* Use a bit more conservative approach than that for the QTabWidget,
       
   154      * change the selection only if a selected child becomes invisible by
       
   155      * changing the page. */
       
   156     QWizard *wizard = static_cast<QWizard *>(parent());
       
   157     QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(wizard);
       
   158     if (!fw)
       
   159         return;
       
   160     QDesignerFormWindowCursorInterface *cursor = fw->cursor();
       
   161     const int selCount = cursor->selectedWidgetCount();
       
   162     for (int i = 0; i <  selCount; i++) {
       
   163         if (!cursor->selectedWidget(i)->isVisible()) {
       
   164             fw->clearSelection(false);
       
   165             fw->selectWidget(wizard, true);
       
   166             break;
       
   167         }
       
   168     }
       
   169 }
       
   170 
       
   171 // ---------------- WidgetFactory::Strings
       
   172 WidgetFactory::Strings::Strings() :
       
   173     m_alignment(QLatin1String("alignment")),
       
   174     m_bottomMargin(QLatin1String("bottomMargin")),
       
   175     m_geometry(QLatin1String("geometry")),
       
   176     m_leftMargin(QLatin1String("leftMargin")),
       
   177     m_line(QLatin1String("Line")),
       
   178     m_objectName(QLatin1String("objectName")),
       
   179     m_spacerName(QLatin1String("spacerName")),
       
   180     m_orientation(QLatin1String("orientation")),
       
   181     m_q3WidgetStack(QLatin1String("Q3WidgetStack")),
       
   182     m_qAction(QLatin1String("QAction")),
       
   183     m_qButtonGroup(QLatin1String("QButtonGroup")),
       
   184     m_qAxWidget(QLatin1String("QAxWidget")),
       
   185     m_qDialog(QLatin1String("QDialog")),
       
   186     m_qDockWidget(QLatin1String("QDockWidget")),
       
   187     m_qLayoutWidget(QLatin1String("QLayoutWidget")),
       
   188     m_qMenu(QLatin1String("QMenu")),
       
   189     m_qMenuBar(QLatin1String("QMenuBar")),
       
   190     m_qWidget(QLatin1String("QWidget")),
       
   191     m_rightMargin(QLatin1String("rightMargin")),
       
   192     m_sizeHint(QLatin1String("sizeHint")),
       
   193     m_spacer(QLatin1String("Spacer")),
       
   194     m_text(QLatin1String("text")),
       
   195     m_title(QLatin1String("title")),
       
   196     m_topMargin(QLatin1String("topMargin")),
       
   197     m_windowIcon(QLatin1String("windowIcon")),
       
   198     m_windowTitle(QLatin1String("windowTitle"))
       
   199 {
       
   200 }
       
   201 // ---------------- WidgetFactory
       
   202 QPointer<QWidget> *WidgetFactory::m_lastPassiveInteractor = new QPointer<QWidget>();
       
   203 bool WidgetFactory::m_lastWasAPassiveInteractor = false;
       
   204 const char *WidgetFactory::disableStyleCustomPaintingPropertyC = "_q_custom_style_disabled";
       
   205 
       
   206 WidgetFactory::WidgetFactory(QDesignerFormEditorInterface *core, QObject *parent)
       
   207     : QDesignerWidgetFactoryInterface(parent),
       
   208       m_core(core),
       
   209       m_formWindow(0),
       
   210       m_currentStyle(0)
       
   211 {
       
   212 }
       
   213 
       
   214 WidgetFactory::~WidgetFactory()
       
   215 {
       
   216 }
       
   217 
       
   218 QDesignerFormWindowInterface *WidgetFactory::currentFormWindow(QDesignerFormWindowInterface *fw)
       
   219 {
       
   220     QDesignerFormWindowInterface *was = m_formWindow;
       
   221     m_formWindow = fw;
       
   222     return was;
       
   223 }
       
   224 
       
   225 void WidgetFactory::loadPlugins()
       
   226 {
       
   227     m_customFactory.clear();
       
   228 
       
   229     QDesignerPluginManager *pluginManager = m_core->pluginManager();
       
   230 
       
   231     QList<QDesignerCustomWidgetInterface*> lst = pluginManager->registeredCustomWidgets();
       
   232     foreach (QDesignerCustomWidgetInterface *c, lst) {
       
   233         m_customFactory.insert(c->name(), c);
       
   234     }
       
   235 }
       
   236 
       
   237 // Convencience to create non-widget objects. Returns 0 if unknown
       
   238 QObject* WidgetFactory::createObject(const QString &className, QObject* parent) const
       
   239 {
       
   240     if (className.isEmpty()) {
       
   241         qWarning("** WARNING %s called with an empty class name", Q_FUNC_INFO);
       
   242         return 0;
       
   243     }
       
   244     if (className == m_strings.m_qAction)
       
   245         return new QAction(parent);
       
   246     if (className == m_strings.m_qButtonGroup)
       
   247         return new QButtonGroup(parent);
       
   248     return 0;
       
   249 }
       
   250 
       
   251 QWidget*  WidgetFactory::createCustomWidget(const QString &className, QWidget *parentWidget, bool *creationError) const
       
   252 {
       
   253     *creationError = false;
       
   254     CustomWidgetFactoryMap::const_iterator it = m_customFactory.constFind(className);
       
   255     if (it == m_customFactory.constEnd())
       
   256         return 0;
       
   257 
       
   258     QDesignerCustomWidgetInterface *factory = it.value();
       
   259     QWidget *rc = factory->createWidget(parentWidget);
       
   260     // shouldn't happen
       
   261     if (!rc) {
       
   262         *creationError = true;
       
   263         designerWarning(tr("The custom widget factory registered for widgets of class %1 returned 0.").arg(className));
       
   264         return 0;
       
   265     }
       
   266     // Figure out the base class unless it is known
       
   267     static QSet<QString> knownCustomClasses;
       
   268     if (!knownCustomClasses.contains(className)) {
       
   269         QDesignerWidgetDataBaseInterface *wdb = m_core->widgetDataBase();
       
   270         const int widgetInfoIndex = wdb->indexOfObject(rc, false);
       
   271         if (widgetInfoIndex != -1) {
       
   272             if (wdb->item(widgetInfoIndex)->extends().isEmpty()) {
       
   273                 const QDesignerMetaObjectInterface *mo = core()->introspection()->metaObject(rc)->superClass();
       
   274                 // If we hit on a 'Q3DesignerXXWidget' that claims to be a 'Q3XXWidget', step
       
   275                 // over.
       
   276                 if (mo && mo->className() == className)
       
   277                     mo = mo->superClass();
       
   278                 while (mo != 0) {
       
   279                     if (core()->widgetDataBase()->indexOfClassName(mo->className()) != -1) {
       
   280                         wdb->item(widgetInfoIndex)->setExtends(mo->className());
       
   281                         break;
       
   282                     }
       
   283                     mo = mo->superClass();
       
   284                 }
       
   285             }
       
   286             knownCustomClasses.insert(className);
       
   287         }
       
   288     }
       
   289     // Since a language plugin may lie about its names, like Qt Jambi
       
   290     // does, return immediately here...
       
   291     QDesignerLanguageExtension *lang =
       
   292         qt_extension<QDesignerLanguageExtension *>(m_core->extensionManager(), m_core);
       
   293     if (lang)
       
   294         return rc;
       
   295 
       
   296 #ifdef Q_OS_WIN
       
   297     if (isAxWidget(rc))
       
   298        return rc;
       
   299 #endif
       
   300     // Check for mismatched class names which is hard to track.
       
   301     // Perform literal comparison first for QAxWidget, for which a meta object hack is in effect.
       
   302     const char *createdClassNameC = rc->metaObject()->className();
       
   303     const QByteArray classNameB = className.toUtf8();
       
   304     const char *classNameC = classNameB.constData();
       
   305 
       
   306     if (qstrcmp(createdClassNameC, classNameC) && !rc->inherits(classNameC))
       
   307         designerWarning(tr("A class name mismatch occurred when creating a widget using the custom widget factory registered for widgets of class %1."
       
   308                            " It returned a widget of class %2.").arg(className).arg(QString::fromUtf8(createdClassNameC)));
       
   309     return rc;
       
   310 }
       
   311 
       
   312 
       
   313 QWidget *WidgetFactory::createWidget(const QString &widgetName, QWidget *parentWidget) const
       
   314 {
       
   315     if (widgetName.isEmpty()) {
       
   316         qWarning("** WARNING %s called with an empty class name", Q_FUNC_INFO);
       
   317         return 0;
       
   318     }
       
   319     // Preview or for form window?
       
   320     QDesignerFormWindowInterface *fw = m_formWindow;
       
   321     if (! fw)
       
   322         fw = QDesignerFormWindowInterface::findFormWindow(parentWidget);
       
   323 
       
   324     QWidget *w = 0;
       
   325     do {
       
   326         // 1) custom. If there is an explicit failure(factory wants to indicate something is wrong),
       
   327         //    return 0, do not try to find fallback, which might be worse in the case of Q3 widget.
       
   328         bool customWidgetCreationError;
       
   329         w = createCustomWidget(widgetName, parentWidget, &customWidgetCreationError);
       
   330         if (w) {
       
   331             break;
       
   332         } else {
       
   333             if (customWidgetCreationError)
       
   334                 return 0;
       
   335         }
       
   336 
       
   337         // 2) Special widgets
       
   338         if (widgetName == m_strings.m_line) {
       
   339             w = new Line(parentWidget);
       
   340         } else if (widgetName == m_strings.m_qDockWidget) {
       
   341             w = new QDesignerDockWidget(parentWidget);
       
   342         } else if (widgetName == m_strings.m_qMenuBar) {
       
   343             w = new QDesignerMenuBar(parentWidget);
       
   344         } else if (widgetName == m_strings.m_qMenu) {
       
   345             w = new QDesignerMenu(parentWidget);
       
   346         } else if (widgetName == m_strings.m_spacer) {
       
   347             w = new Spacer(parentWidget);
       
   348         } else if (widgetName == m_strings.m_qDockWidget) {
       
   349             w = new QDesignerDockWidget(parentWidget);
       
   350         } else if (widgetName == m_strings.m_qLayoutWidget) {
       
   351             w = fw ? new QLayoutWidget(fw, parentWidget) : new QWidget(parentWidget);
       
   352         } else if (widgetName == m_strings.m_qDialog) {
       
   353             if (fw) {
       
   354                 w = new QDesignerDialog(fw, parentWidget);
       
   355             } else {
       
   356                 w = new QDialog(parentWidget);
       
   357             }
       
   358         } else if (widgetName == m_strings.m_qWidget) {
       
   359             /* We want a 'QDesignerWidget' that draws a grid only for widget
       
   360              * forms and container extension pages (not for preview and not
       
   361              * for normal QWidget children on forms (legacy) */
       
   362             if (fw && parentWidget) {
       
   363                 if (qt_extension<QDesignerContainerExtension*>(m_core->extensionManager(), parentWidget)) {
       
   364                     w = new QDesignerWidget(fw, parentWidget);
       
   365                 } else {
       
   366                     if (const FormWindowBase *fwb = qobject_cast<FormWindowBase *>(fw))
       
   367                         if (parentWidget == fwb->formContainer())
       
   368                             w = new QDesignerWidget(fw, parentWidget);
       
   369                 }
       
   370             }
       
   371             if (!w)
       
   372                 w = new QWidget(parentWidget);
       
   373         }
       
   374         if (w)
       
   375             break;
       
   376 
       
   377         // 3) table
       
   378         const QByteArray widgetNameBA = widgetName.toUtf8();
       
   379         const char *widgetNameC = widgetNameBA.constData();
       
   380 
       
   381         if (w) { // symmetry for macro
       
   382         }
       
   383 
       
   384 #define DECLARE_LAYOUT(L, C)
       
   385 #define DECLARE_COMPAT_WIDGET(W, C) /*DECLARE_WIDGET(W, C)*/
       
   386 #define DECLARE_WIDGET(W, C) else if (!qstrcmp(widgetNameC, #W)) { Q_ASSERT(w == 0); w = new W(parentWidget); }
       
   387 #define DECLARE_WIDGET_1(W, C) else if (!qstrcmp(widgetNameC, #W)) { Q_ASSERT(w == 0); w = new W(0, parentWidget); }
       
   388 
       
   389 #include "widgets.table"
       
   390 
       
   391 #undef DECLARE_COMPAT_WIDGET
       
   392 #undef DECLARE_LAYOUT
       
   393 #undef DECLARE_WIDGET
       
   394 #undef DECLARE_WIDGET_1
       
   395 
       
   396         if (w)
       
   397             break;
       
   398         // 4) fallBack
       
   399         const QString fallBackBaseClass = m_strings.m_qWidget;
       
   400         QDesignerWidgetDataBaseInterface *db = core()->widgetDataBase();
       
   401         QDesignerWidgetDataBaseItemInterface *item = db->item(db->indexOfClassName(widgetName));
       
   402         if (item == 0) {
       
   403             // Emergency: Create, derived from QWidget
       
   404             QString includeFile = widgetName.toLower();
       
   405             includeFile +=  QLatin1String(".h");
       
   406             item = appendDerived(db,widgetName, tr("%1 Widget").arg(widgetName),fallBackBaseClass,
       
   407                                  includeFile, true, true);
       
   408             Q_ASSERT(item);
       
   409         }
       
   410         QString baseClass = item->extends();
       
   411         if (baseClass.isEmpty()) {
       
   412             // Currently happens in the case of Q3-Support widgets
       
   413             baseClass =fallBackBaseClass;
       
   414         }
       
   415         w = createWidget(baseClass, parentWidget);
       
   416         promoteWidget(core(),w,widgetName);
       
   417     } while (false);
       
   418 
       
   419     Q_ASSERT(w != 0);
       
   420     if (m_currentStyle)
       
   421         w->setStyle(m_currentStyle);
       
   422      initializeCommon(w);
       
   423     if (fw) { // form editor  initialization
       
   424         initialize(w);
       
   425     } else { // preview-only initialization
       
   426         initializePreview(w);
       
   427     }
       
   428     return w;
       
   429 }
       
   430 
       
   431 QString WidgetFactory::classNameOf(QDesignerFormEditorInterface *c, const QObject* o)
       
   432 {
       
   433     if (o == 0)
       
   434         return QString();
       
   435 
       
   436     const char *className = o->metaObject()->className();
       
   437     if (!o->isWidgetType())
       
   438         return QLatin1String(className);
       
   439     const QWidget *w = static_cast<const QWidget*>(o);
       
   440     // check promoted before designer special
       
   441     const QString customClassName = promotedCustomClassName(c, const_cast<QWidget*>(w));
       
   442     if (!customClassName.isEmpty())
       
   443         return customClassName;
       
   444     if (qobject_cast<const QDesignerMenuBar*>(w))
       
   445         return QLatin1String("QMenuBar");
       
   446     else if (qobject_cast<const QDesignerMenu*>(w))
       
   447         return QLatin1String("QMenu");
       
   448      else if (qobject_cast<const QDesignerDockWidget*>(w))
       
   449         return QLatin1String("QDockWidget");
       
   450     else if (qobject_cast<const QDesignerDialog*>(w))
       
   451         return QLatin1String("QDialog");
       
   452     else if (qobject_cast<const QDesignerWidget*>(w))
       
   453         return QLatin1String("QWidget");
       
   454 #ifdef Q_OS_WIN
       
   455     else if (isAxWidget(w))
       
   456         return QLatin1String("QAxWidget");
       
   457 #endif
       
   458     else if (qstrcmp(className, "QDesignerQ3WidgetStack") == 0)
       
   459         return QLatin1String("Q3WidgetStack");
       
   460 
       
   461     return QLatin1String(className);
       
   462 }
       
   463 
       
   464 QLayout *WidgetFactory::createUnmanagedLayout(QWidget *parentWidget, int type)
       
   465 {
       
   466     switch (type) {
       
   467     case LayoutInfo::HBox:
       
   468         return new QHBoxLayout(parentWidget);
       
   469     case LayoutInfo::VBox:
       
   470         return new QVBoxLayout(parentWidget);
       
   471     case LayoutInfo::Grid:
       
   472         return new QGridLayout(parentWidget);
       
   473     case LayoutInfo::Form:
       
   474         return new QFormLayout(parentWidget);
       
   475     default:
       
   476         Q_ASSERT(0);
       
   477         break;
       
   478     }
       
   479     return 0;
       
   480 }
       
   481 
       
   482 
       
   483 /*!  Creates a layout on the widget \a widget of the type \a type
       
   484   which can be \c HBox, \c VBox or \c Grid.
       
   485 */
       
   486 
       
   487 QLayout *WidgetFactory::createLayout(QWidget *widget, QLayout *parentLayout, int type) const // ### (sizepolicy)
       
   488 {
       
   489     QDesignerMetaDataBaseInterface *metaDataBase = core()->metaDataBase();
       
   490 
       
   491     if (parentLayout == 0) {
       
   492         QWidget *page = containerOfWidget(widget);
       
   493         if (page) {
       
   494             widget = page;
       
   495         } else {
       
   496             const QString msg = tr("The current page of the container '%1' (%2) could not be determined while creating a layout."
       
   497 "This indicates an inconsistency in the ui-file, probably a layout being constructed on a container widget.").arg(widget->objectName()).arg(classNameOf(core(), widget));
       
   498             designerWarning(msg);
       
   499         }
       
   500     }
       
   501 
       
   502     Q_ASSERT(metaDataBase->item(widget) != 0); // ensure the widget is managed
       
   503 
       
   504     if (parentLayout == 0 && metaDataBase->item(widget->layout()) == 0) {
       
   505         parentLayout = widget->layout();
       
   506     }
       
   507 
       
   508     QWidget *parentWidget = parentLayout != 0 ? 0 : widget;
       
   509 
       
   510     QLayout *layout = createUnmanagedLayout(parentWidget, type);
       
   511     metaDataBase->add(layout); // add the layout in the MetaDataBase
       
   512 
       
   513     QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), layout);
       
   514 
       
   515     sheet->setChanged(sheet->indexOf(m_strings.m_objectName), true);
       
   516     if (widget->inherits("Q3GroupBox")) {
       
   517         layout->setContentsMargins(widget->style()->pixelMetric(QStyle::PM_LayoutLeftMargin),
       
   518                                     widget->style()->pixelMetric(QStyle::PM_LayoutTopMargin),
       
   519                                     widget->style()->pixelMetric(QStyle::PM_LayoutRightMargin),
       
   520                                     widget->style()->pixelMetric(QStyle::PM_LayoutBottomMargin));
       
   521         QGridLayout *grid = qobject_cast<QGridLayout *>(layout);
       
   522         if (grid) {
       
   523             grid->setHorizontalSpacing(-1);
       
   524             grid->setVerticalSpacing(-1);
       
   525         } else {
       
   526             layout->setSpacing(-1);
       
   527         }
       
   528         layout->setAlignment(Qt::AlignTop);
       
   529         // Just to ensure; before 4.3 orientation property was always set (now only for QSplitter class).
       
   530         // Calling Q3GroupBox::setOrientation() invoked in turn setSpacing(0). Below fixes that
       
   531         widget->layout()->setSpacing(-1);
       
   532     } else if (widget->inherits("QLayoutWidget")) {
       
   533         sheet->setProperty(sheet->indexOf(m_strings.m_leftMargin), 0);
       
   534         sheet->setProperty(sheet->indexOf(m_strings.m_topMargin), 0);
       
   535         sheet->setProperty(sheet->indexOf(m_strings.m_rightMargin), 0);
       
   536         sheet->setProperty(sheet->indexOf(m_strings.m_bottomMargin), 0);
       
   537     }
       
   538 
       
   539     if (sheet) {
       
   540         const int index = sheet->indexOf(m_strings.m_alignment);
       
   541         if (index != -1)
       
   542             sheet->setChanged(index, true);
       
   543     }
       
   544 
       
   545     if (metaDataBase->item(widget->layout()) == 0) {
       
   546         Q_ASSERT(layout->parent() == 0);
       
   547         QBoxLayout *box = qobject_cast<QBoxLayout*>(widget->layout());
       
   548         if (!box) {  // we support only unmanaged box layouts
       
   549             const QString msg = tr("Attempt to add a layout to a widget '%1' (%2) which already has an unmanaged layout of type %3.\n"
       
   550                                             "This indicates an inconsistency in the ui-file.").
       
   551                                  arg(widget->objectName()).arg(classNameOf(core(), widget)).arg(classNameOf(core(), widget->layout()));
       
   552             designerWarning(msg);
       
   553             return 0;
       
   554         }
       
   555         box->addLayout(layout);
       
   556     }
       
   557 
       
   558     return layout;
       
   559 }
       
   560 
       
   561 /*!  Returns the widget into which children should be inserted when \a
       
   562   w is a container known to designer.
       
   563 
       
   564   Usually, it is \a w itself, but there are exceptions (for example, a
       
   565   tabwidget is known to designer as a container, but the child
       
   566   widgets should be inserted into the current page of the
       
   567   tabwidget. In this case, the current page of
       
   568   the tabwidget  would be returned.)
       
   569  */
       
   570 QWidget* WidgetFactory::containerOfWidget(QWidget *w) const
       
   571 {
       
   572     if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), w))
       
   573         return container->widget(container->currentIndex());
       
   574 
       
   575     return w;
       
   576 }
       
   577 
       
   578 /*!  Returns the actual designer widget of the container \a w. This is
       
   579   normally \a w itself, but it might be a parent or grand parent of \a w
       
   580   (for example, when working with a tabwidget and \a w is the container which
       
   581   contains and layouts children, but the actual widget known to
       
   582   designer is the tabwidget which is the parent of \a w. In this case,
       
   583   the tabwidget would be returned.)
       
   584 */
       
   585 
       
   586 QWidget* WidgetFactory::widgetOfContainer(QWidget *w) const
       
   587 {
       
   588     // ### cleanup
       
   589     if (!w)
       
   590         return 0;
       
   591     if (w->parentWidget() && w->parentWidget()->parentWidget() &&
       
   592          w->parentWidget()->parentWidget()->parentWidget() &&
       
   593          qobject_cast<QToolBox*>(w->parentWidget()->parentWidget()->parentWidget()))
       
   594         return w->parentWidget()->parentWidget()->parentWidget();
       
   595 
       
   596     while (w != 0) {
       
   597         if (core()->widgetDataBase()->isContainer(w) ||
       
   598              (w && qobject_cast<QDesignerFormWindowInterface*>(w->parentWidget())))
       
   599             return w;
       
   600 
       
   601         w = w->parentWidget();
       
   602     }
       
   603 
       
   604     return w;
       
   605 }
       
   606 
       
   607 QDesignerFormEditorInterface *WidgetFactory::core() const
       
   608 {
       
   609     return m_core;
       
   610 }
       
   611 
       
   612 // Necessary initializations for form editor/preview objects
       
   613 void WidgetFactory::initializeCommon(QWidget *widget) const
       
   614 {
       
   615     // Apply style
       
   616     if (m_currentStyle)
       
   617         widget->setStyle(m_currentStyle);
       
   618     // Prevent the wizard from emulating the Windows Vista Theme.
       
   619     // This theme (in both Aero and Basic mode) is tricky to
       
   620     // emulate properly in designer due to 1) the manipulation of the non-client area of
       
   621     // the top-level window, and 2) the upper-right location of the Back button.
       
   622     // The wizard falls back to QWizard::ModernStyle whenever the Vista theme
       
   623     // would normally apply.
       
   624     if (QWizard *wizard = qobject_cast<QWizard *>(widget)) {
       
   625         wizard->setProperty("_q_wizard_vista_off", QVariant(true));
       
   626         return;
       
   627     }
       
   628 }
       
   629 
       
   630 // Necessary initializations for preview objects
       
   631 void WidgetFactory::initializePreview(QWidget *widget) const
       
   632 {
       
   633 
       
   634     if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(widget)) {
       
   635         QStackedWidgetPreviewEventFilter::install(stackedWidget); // Add browse button only.
       
   636         return;
       
   637     }
       
   638 }
       
   639 
       
   640 // Necessary initializations for form editor objects
       
   641 void WidgetFactory::initialize(QObject *object) const
       
   642 {
       
   643     // Indicate that this is a form object (for QDesignerFormWindowInterface::findFormWindow)
       
   644     object->setProperty(formEditorDynamicProperty, QVariant(true));
       
   645     QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(m_core->extensionManager(), object);
       
   646     if (!sheet)
       
   647         return;
       
   648 
       
   649     sheet->setChanged(sheet->indexOf(m_strings.m_objectName), true);
       
   650 
       
   651     if (!object->isWidgetType()) {
       
   652         if (qobject_cast<QAction*>(object))
       
   653             sheet->setChanged(sheet->indexOf(m_strings.m_text), true);
       
   654         return;
       
   655     }
       
   656 
       
   657     QWidget *widget = static_cast<QWidget*>(object);
       
   658     const bool isMenu = qobject_cast<QMenu*>(widget);
       
   659     const bool isMenuBar = !isMenu && qobject_cast<QMenuBar*>(widget);
       
   660 
       
   661     widget->setAttribute(Qt::WA_TransparentForMouseEvents, false);
       
   662     widget->setFocusPolicy((isMenu || isMenuBar) ? Qt::StrongFocus : Qt::NoFocus);
       
   663 
       
   664     if (!isMenu)
       
   665         sheet->setChanged(sheet->indexOf(m_strings.m_geometry), true);
       
   666 
       
   667     if (qobject_cast<Spacer*>(widget)) {
       
   668         sheet->setChanged(sheet->indexOf(m_strings.m_spacerName), true);
       
   669         return;
       
   670     }
       
   671 
       
   672     const int o = sheet->indexOf(m_strings.m_orientation);
       
   673     if (o != -1 && widget->inherits("QSplitter"))
       
   674         sheet->setChanged(o, true);
       
   675 
       
   676     if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
       
   677         ToolBarEventFilter::install(toolBar);
       
   678         sheet->setVisible(sheet->indexOf(m_strings.m_windowTitle), true);
       
   679         toolBar->setFloatable(false);  // prevent toolbars from being dragged off
       
   680         return;
       
   681     }
       
   682 
       
   683     if (qobject_cast<QDockWidget*>(widget)) {
       
   684         sheet->setVisible(sheet->indexOf(m_strings.m_windowTitle), true);
       
   685         sheet->setVisible(sheet->indexOf(m_strings.m_windowIcon), true);
       
   686         return;
       
   687     }
       
   688 
       
   689     if (isMenu) {
       
   690         sheet->setChanged(sheet->indexOf(m_strings.m_title), true);
       
   691         return;
       
   692     }
       
   693     // helpers
       
   694     if (QToolBox *toolBox = qobject_cast<QToolBox*>(widget)) {
       
   695         QToolBoxHelper::install(toolBox);
       
   696         return;
       
   697     }
       
   698     if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(widget)) {
       
   699         QStackedWidgetEventFilter::install(stackedWidget);
       
   700         return;
       
   701     }
       
   702     if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(widget)) {
       
   703         QTabWidgetEventFilter::install(tabWidget);
       
   704         return;
       
   705     }
       
   706     // Prevent embedded line edits from getting focus
       
   707     if (QAbstractSpinBox *asb = qobject_cast<QAbstractSpinBox *>(widget)) {
       
   708         if (QLineEdit *lineEdit = static_cast<FriendlySpinBox*>(asb)->lineEdit())
       
   709             lineEdit->setFocusPolicy(Qt::NoFocus);
       
   710         return;
       
   711     }
       
   712     if (QComboBox *cb =  qobject_cast<QComboBox *>(widget)) {
       
   713         if (QFontComboBox *fcb =  qobject_cast<QFontComboBox *>(widget)) {
       
   714             fcb->lineEdit()->setFocusPolicy(Qt::NoFocus); // Always present
       
   715             return;
       
   716         }
       
   717         cb->installEventFilter(new ComboEventFilter(cb));
       
   718         return;
       
   719     }
       
   720     if (QWizard *wz = qobject_cast<QWizard *>(widget)) {
       
   721         WizardPageChangeWatcher *pw = new WizardPageChangeWatcher(wz);
       
   722         Q_UNUSED(pw);
       
   723     }
       
   724 }
       
   725 
       
   726 static inline QString classNameOfStyle(const QStyle *s)
       
   727 {
       
   728     return QLatin1String(s->metaObject()->className());
       
   729 }
       
   730 
       
   731 QString WidgetFactory::styleName() const
       
   732 {
       
   733     return classNameOfStyle(style());
       
   734 }
       
   735 
       
   736 static inline bool isApplicationStyle(const QString &styleName)
       
   737 {
       
   738     return styleName.isEmpty() || styleName == classNameOfStyle(qApp->style());
       
   739 }
       
   740 
       
   741 void WidgetFactory::setStyleName(const QString &styleName)
       
   742 {
       
   743     m_currentStyle = isApplicationStyle(styleName) ? static_cast<QStyle*>(0) : getStyle(styleName);
       
   744 }
       
   745 
       
   746 QStyle *WidgetFactory::style() const
       
   747 {
       
   748     return m_currentStyle ? m_currentStyle : qApp->style();
       
   749 }
       
   750 
       
   751 QStyle *WidgetFactory::getStyle(const QString &styleName)
       
   752 {
       
   753     if (isApplicationStyle(styleName))
       
   754         return qApp->style();
       
   755 
       
   756     StyleCache::iterator it = m_styleCache.find(styleName);
       
   757     if (it == m_styleCache.end()) {
       
   758         QStyle *style = QStyleFactory::create(styleName);
       
   759         if (!style) {
       
   760             const QString msg = tr("Cannot create style '%1'.").arg(styleName);
       
   761             designerWarning(msg);
       
   762             return 0;
       
   763         }
       
   764         it = m_styleCache.insert(styleName, style);
       
   765     }
       
   766     return it.value();
       
   767 }
       
   768 
       
   769 void WidgetFactory::applyStyleTopLevel(const QString &styleName, QWidget *w)
       
   770 {
       
   771     if (QStyle *style = getStyle(styleName))
       
   772         applyStyleToTopLevel(style, w);
       
   773 }
       
   774 
       
   775 void WidgetFactory::applyStyleToTopLevel(QStyle *style, QWidget *widget)
       
   776 {
       
   777     const QPalette standardPalette = style->standardPalette();
       
   778     if (widget->style() == style && widget->palette() == standardPalette)
       
   779         return;
       
   780 
       
   781     widget->setStyle(style);
       
   782     widget->setPalette(standardPalette);
       
   783     const QWidgetList lst = qFindChildren<QWidget*>(widget);
       
   784     const QWidgetList::const_iterator cend = lst.constEnd();
       
   785     for (QWidgetList::const_iterator it = lst.constBegin(); it != cend; ++it)
       
   786         (*it)->setStyle(style);
       
   787 }
       
   788 
       
   789 // Check for 'interactor' click on a tab bar,
       
   790 // which can appear within a QTabWidget or as a standalone widget.
       
   791 
       
   792 static bool isTabBarInteractor(const QTabBar *tabBar)
       
   793 {
       
   794     // Tabbar embedded in Q(Designer)TabWidget, ie, normal tab widget case
       
   795     if (qobject_cast<const QTabWidget*>(tabBar->parentWidget()))
       
   796         return true;
       
   797 
       
   798     // Standalone tab bar on the form. Return true for tab rect areas
       
   799     // only to allow the user to select the tab bar by clicking outside the actual tabs.
       
   800     const int count = tabBar->count();
       
   801     if (count == 0)
       
   802         return false;
       
   803 
       
   804     // click into current tab: No Interaction
       
   805     const int currentIndex = tabBar->currentIndex();
       
   806     const QPoint pos = tabBar->mapFromGlobal(QCursor::pos());
       
   807     if (tabBar->tabRect(currentIndex).contains(pos))
       
   808         return false;
       
   809 
       
   810     // click outside: No Interaction
       
   811     const QRect geometry = QRect(QPoint(0, 0), tabBar->size());
       
   812     if (!geometry.contains(pos))
       
   813         return false;
       
   814     // click into another tab: Let's interact, switch tabs.
       
   815     for (int i = 0; i < count; i++)
       
   816         if (tabBar->tabRect(i).contains(pos))
       
   817             return true;
       
   818     return false;
       
   819 }
       
   820 
       
   821 bool WidgetFactory::isPassiveInteractor(QWidget *widget)
       
   822 {
       
   823     static const QString qtPassive = QLatin1String("__qt__passive_");
       
   824     if (m_lastPassiveInteractor != 0 && (QWidget*)(*m_lastPassiveInteractor) == widget)
       
   825         return m_lastWasAPassiveInteractor;
       
   826 
       
   827     if (QApplication::activePopupWidget() || widget == 0) // if a popup is open, we have to make sure that this one is closed, else X might do funny things
       
   828         return true;
       
   829 
       
   830     m_lastWasAPassiveInteractor = false;
       
   831     (*m_lastPassiveInteractor) = widget;
       
   832 
       
   833     if (const QTabBar *tabBar = qobject_cast<const QTabBar*>(widget)) {
       
   834         if (isTabBarInteractor(tabBar))
       
   835             m_lastWasAPassiveInteractor = true;
       
   836         return m_lastWasAPassiveInteractor;
       
   837 #ifndef QT_NO_SIZEGRIP
       
   838     }  else if (qobject_cast<QSizeGrip*>(widget)) {
       
   839         return (m_lastWasAPassiveInteractor = true);
       
   840 #endif
       
   841     }  else if (qobject_cast<QMdiSubWindow*>(widget))
       
   842         return (m_lastWasAPassiveInteractor = true);
       
   843     else if (qobject_cast<QAbstractButton*>(widget) && (qobject_cast<QTabBar*>(widget->parent()) || qobject_cast<QToolBox*>(widget->parent())))
       
   844         return (m_lastWasAPassiveInteractor = true);
       
   845     else if (qobject_cast<QMenuBar*>(widget))
       
   846         return (m_lastWasAPassiveInteractor = true);
       
   847     else if (qobject_cast<QToolBar*>(widget))
       
   848         return (m_lastWasAPassiveInteractor = true);
       
   849     else if (qobject_cast<QScrollBar*>(widget)) {
       
   850         // A scroll bar is an interactor on a QAbstractScrollArea only.
       
   851         if (const QWidget *parent = widget->parentWidget()) {
       
   852             const QString objectName = parent->objectName();
       
   853             static const QString scrollAreaVContainer = QLatin1String("qt_scrollarea_vcontainer");
       
   854     void activeFormWindowChanged(QDesignerFormWindowInterface *formWindow);
       
   855     void formWindowAdded(QDesignerFormWindowInterface *formWindow);
       
   856             static const QString scrollAreaHContainer = QLatin1String("qt_scrollarea_hcontainer");
       
   857             if (objectName == scrollAreaVContainer || objectName == scrollAreaHContainer) {
       
   858                 m_lastWasAPassiveInteractor = true;
       
   859                 return m_lastWasAPassiveInteractor;
       
   860             }
       
   861         }
       
   862     } else if (qstrcmp(widget->metaObject()->className(), "QDockWidgetTitle") == 0)
       
   863         return (m_lastWasAPassiveInteractor = true);
       
   864     else if (qstrcmp(widget->metaObject()->className(), "QWorkspaceTitleBar") == 0)
       
   865         return (m_lastWasAPassiveInteractor = true);
       
   866     else if (widget->objectName().startsWith(qtPassive))
       
   867         return (m_lastWasAPassiveInteractor = true);
       
   868     return m_lastWasAPassiveInteractor;
       
   869 }
       
   870 
       
   871 void WidgetFactory::formWindowAdded(QDesignerFormWindowInterface *formWindow)
       
   872 {
       
   873     setFormWindowStyle(formWindow);
       
   874 }
       
   875 
       
   876 void WidgetFactory::activeFormWindowChanged(QDesignerFormWindowInterface *formWindow)
       
   877 {
       
   878     setFormWindowStyle(formWindow);
       
   879 }
       
   880 
       
   881 void WidgetFactory::setFormWindowStyle(QDesignerFormWindowInterface *formWindow)
       
   882 {
       
   883     if (FormWindowBase *fwb = qobject_cast<FormWindowBase *>(formWindow))
       
   884         setStyleName(fwb->styleName());
       
   885 }
       
   886 
       
   887 bool WidgetFactory::isFormEditorObject(const QObject *object)
       
   888 {
       
   889     return object->property(formEditorDynamicProperty).isValid();
       
   890 }
       
   891 } // namespace qdesigner_internal
       
   892 
       
   893 QT_END_NAMESPACE
       
   894 
       
   895 #include "widgetfactory.moc"