tools/designer/src/lib/shared/formlayoutmenu.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 "formlayoutmenu_p.h"
       
    43 #include "layoutinfo_p.h"
       
    44 #include "qdesigner_command_p.h"
       
    45 #include "qdesigner_utils_p.h"
       
    46 #include "qdesigner_propertycommand_p.h"
       
    47 #include "ui_formlayoutrowdialog.h"
       
    48 
       
    49 #include <QtDesigner/QDesignerFormWindowInterface>
       
    50 #include <QtDesigner/QDesignerFormEditorInterface>
       
    51 #include <QtDesigner/QDesignerWidgetFactoryInterface>
       
    52 #include <QtDesigner/QDesignerPropertySheetExtension>
       
    53 #include <QtDesigner/QExtensionManager>
       
    54 #include <QtDesigner/QDesignerWidgetDataBaseInterface>
       
    55 #include <QtDesigner/QDesignerLanguageExtension>
       
    56 
       
    57 #include <QtGui/QAction>
       
    58 #include <QtGui/QWidget>
       
    59 #include <QtGui/QFormLayout>
       
    60 #include <QtGui/QUndoStack>
       
    61 #include <QtGui/QDialog>
       
    62 #include <QtGui/QPushButton>
       
    63 #include <QtGui/QRegExpValidator>
       
    64 
       
    65 #include <QtCore/QPair>
       
    66 #include <QtCore/QCoreApplication>
       
    67 #include <QtCore/QRegExp>
       
    68 #include <QtCore/QMultiHash>
       
    69 #include <QtCore/QDebug>
       
    70 
       
    71 static const char *buddyPropertyC = "buddy";
       
    72 static const char *fieldWidgetBaseClasses[] = {
       
    73     "QLineEdit", "QComboBox", "QSpinBox", "QDoubleSpinBox", "QCheckBox",
       
    74     "QDateEdit", "QTimeEdit", "QDateTimeEdit", "QDial", "QWidget"
       
    75 };
       
    76 
       
    77 QT_BEGIN_NAMESPACE
       
    78 
       
    79 namespace qdesigner_internal {
       
    80 
       
    81 // Struct that describes a row of controls (descriptive label and control) to
       
    82 // be added to a form layout.
       
    83 struct FormLayoutRow {
       
    84     FormLayoutRow() : buddy(false) {}
       
    85 
       
    86     QString labelName;
       
    87     QString labelText;
       
    88     QString fieldClassName;
       
    89     QString fieldName;
       
    90     bool buddy;
       
    91 };
       
    92 
       
    93 // A Dialog to edit a FormLayoutRow. Lets the user input a label text, label
       
    94 // name, field widget type, field object name and buddy setting. As the
       
    95 // user types the label text; the object names to be used for label and field
       
    96 // are updated. It also checks the buddy setting depending on whether  the
       
    97 // label text contains a buddy marker.
       
    98 class FormLayoutRowDialog : public QDialog {
       
    99     Q_DISABLE_COPY(FormLayoutRowDialog)
       
   100     Q_OBJECT
       
   101 public:
       
   102     explicit FormLayoutRowDialog(QDesignerFormEditorInterface *core,
       
   103                                  QWidget *parent);
       
   104 
       
   105     FormLayoutRow formLayoutRow() const;
       
   106 
       
   107     bool buddy() const;
       
   108     void setBuddy(bool);
       
   109 
       
   110     // Accessors for form layout row numbers using 0..[n-1] convention
       
   111     int row() const;
       
   112     void setRow(int);
       
   113     void setRowRange(int, int);
       
   114 
       
   115     QString fieldClass() const;
       
   116     QString labelText() const;
       
   117 
       
   118     static QStringList fieldWidgetClasses(QDesignerFormEditorInterface *core);
       
   119 
       
   120 private slots:
       
   121     void labelTextEdited(const QString &text);
       
   122     void labelNameEdited(const QString &text);
       
   123     void fieldNameEdited(const QString &text);
       
   124     void buddyClicked();
       
   125     void fieldClassChanged(int);
       
   126 
       
   127 private:
       
   128     bool isValid() const;
       
   129     void updateObjectNames(bool updateLabel, bool updateField);
       
   130     void updateOkButton();
       
   131 
       
   132     // Check for buddy marker in string
       
   133     const QRegExp m_buddyMarkerRegexp;
       
   134 
       
   135     Ui::FormLayoutRowDialog m_ui;
       
   136     bool m_labelNameEdited;
       
   137     bool m_fieldNameEdited;
       
   138     bool m_buddyClicked;
       
   139 };
       
   140 
       
   141 FormLayoutRowDialog::FormLayoutRowDialog(QDesignerFormEditorInterface *core,
       
   142                                          QWidget *parent) :
       
   143     QDialog(parent),
       
   144     m_buddyMarkerRegexp(QLatin1String("\\&[^&]")),
       
   145     m_labelNameEdited(false),
       
   146     m_fieldNameEdited(false),
       
   147     m_buddyClicked(false)
       
   148 {
       
   149     Q_ASSERT(m_buddyMarkerRegexp.isValid());
       
   150 
       
   151     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
       
   152     setModal(true);
       
   153     m_ui.setupUi(this);
       
   154     connect(m_ui.labelTextLineEdit, SIGNAL(textEdited(QString)), this, SLOT(labelTextEdited(QString)));
       
   155 
       
   156     QRegExpValidator *nameValidator = new QRegExpValidator(QRegExp(QLatin1String("^[a-zA-Z0-9_]+$")), this);
       
   157     Q_ASSERT(nameValidator->regExp().isValid());
       
   158 
       
   159     m_ui.labelNameLineEdit->setValidator(nameValidator);
       
   160     connect(m_ui.labelNameLineEdit, SIGNAL(textEdited(QString)),
       
   161             this, SLOT(labelNameEdited(QString)));
       
   162 
       
   163     m_ui.fieldNameLineEdit->setValidator(nameValidator);
       
   164     connect(m_ui.fieldNameLineEdit, SIGNAL(textEdited(QString)),
       
   165             this, SLOT(fieldNameEdited(QString)));
       
   166 
       
   167     connect(m_ui.buddyCheckBox, SIGNAL(clicked()), this, SLOT(buddyClicked()));
       
   168 
       
   169     m_ui.fieldClassComboBox->addItems(fieldWidgetClasses(core));
       
   170     m_ui.fieldClassComboBox->setCurrentIndex(0);
       
   171     connect(m_ui.fieldClassComboBox, SIGNAL(currentIndexChanged(int)),
       
   172             this, SLOT(fieldClassChanged(int)));
       
   173 
       
   174     updateOkButton();
       
   175 }
       
   176 
       
   177 FormLayoutRow FormLayoutRowDialog::formLayoutRow() const
       
   178 {
       
   179     FormLayoutRow rc;
       
   180     rc.labelText = labelText();
       
   181     rc.labelName = m_ui.labelNameLineEdit->text();
       
   182     rc.fieldClassName = fieldClass();
       
   183     rc.fieldName = m_ui.fieldNameLineEdit->text();
       
   184     rc.buddy = buddy();
       
   185     return rc;
       
   186 }
       
   187 
       
   188 bool FormLayoutRowDialog::buddy() const
       
   189 {
       
   190     return m_ui.buddyCheckBox->checkState() == Qt::Checked;
       
   191 }
       
   192 
       
   193 void FormLayoutRowDialog::setBuddy(bool b)
       
   194 {
       
   195     m_ui.buddyCheckBox->setCheckState(b ? Qt::Checked : Qt::Unchecked);
       
   196 }
       
   197 
       
   198 // Convert rows to 1..n convention for users
       
   199 int FormLayoutRowDialog::row() const
       
   200 {
       
   201     return m_ui.rowSpinBox->value()  - 1;
       
   202 }
       
   203 
       
   204 void FormLayoutRowDialog::setRow(int row)
       
   205 {
       
   206     m_ui.rowSpinBox->setValue(row + 1);
       
   207 }
       
   208 
       
   209 void FormLayoutRowDialog::setRowRange(int from, int to)
       
   210 {
       
   211     m_ui.rowSpinBox->setMinimum(from + 1);
       
   212     m_ui.rowSpinBox->setMaximum(to + 1);
       
   213     m_ui.rowSpinBox->setEnabled(to - from > 0);
       
   214 }
       
   215 
       
   216 QString FormLayoutRowDialog::fieldClass() const
       
   217 {
       
   218     return m_ui.fieldClassComboBox->itemText(m_ui.fieldClassComboBox->currentIndex());
       
   219 }
       
   220 
       
   221 QString FormLayoutRowDialog::labelText() const
       
   222 {
       
   223     return m_ui.labelTextLineEdit->text();
       
   224 }
       
   225 
       
   226 bool FormLayoutRowDialog::isValid() const
       
   227 {
       
   228     // Check for non-empty names and presence of buddy marker if checked
       
   229     const QString name = labelText();
       
   230     if (name.isEmpty() || m_ui.labelNameLineEdit->text().isEmpty() || m_ui.fieldNameLineEdit->text().isEmpty())
       
   231         return false;
       
   232     if (buddy() && !name.contains(m_buddyMarkerRegexp))
       
   233         return false;
       
   234     return true;
       
   235 }
       
   236 
       
   237 void FormLayoutRowDialog::updateOkButton()
       
   238 {
       
   239     m_ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(isValid());
       
   240 }
       
   241 
       
   242 void FormLayoutRowDialog::labelTextEdited(const QString &text)
       
   243 {
       
   244     updateObjectNames(true, true);
       
   245     // Set buddy if '&' is present unless the user changed it
       
   246     if (!m_buddyClicked)
       
   247         setBuddy(text.contains(m_buddyMarkerRegexp));
       
   248 
       
   249     updateOkButton();
       
   250 }
       
   251 
       
   252 // Get a suitable object name postfix from a class name:
       
   253 // "namespace::QLineEdit"->"LineEdit"
       
   254 static inline QString postFixFromClassName(QString className)
       
   255 {
       
   256     const int index = className.lastIndexOf(QLatin1String("::"));
       
   257     if (index != -1)
       
   258         className.remove(0, index + 2);
       
   259     if (className.size() > 2)
       
   260         if (className.at(0) == QLatin1Char('Q') || className.at(0) == QLatin1Char('K'))
       
   261             if (className.at(1).isUpper())
       
   262                 className.remove(0, 1);
       
   263     return className;
       
   264 }
       
   265 
       
   266 // Helper routines to filter out characters for converting texts into
       
   267 // class name prefixes. Only accepts ASCII characters/digits and underscores.
       
   268 
       
   269 enum PrefixCharacterKind { PC_Digit, PC_UpperCaseLetter, PC_LowerCaseLetter,
       
   270                            PC_Other, PC_Invalid };
       
   271 
       
   272 static inline PrefixCharacterKind prefixCharacterKind(const QChar &c)
       
   273 {
       
   274     switch (c.category()) {
       
   275     case QChar::Number_DecimalDigit:
       
   276         return PC_Digit;
       
   277     case QChar::Letter_Lowercase: {
       
   278             const char a = c.toAscii();
       
   279             if (a >= 'a' && a <= 'z')
       
   280                 return PC_LowerCaseLetter;
       
   281         }
       
   282         break;
       
   283     case QChar::Letter_Uppercase: {
       
   284             const char a = c.toAscii();
       
   285             if (a >= 'A' && a <= 'Z')
       
   286                 return PC_UpperCaseLetter;
       
   287         }
       
   288         break;
       
   289     case QChar::Punctuation_Connector:
       
   290         if (c.toAscii() == '_')
       
   291             return PC_Other;
       
   292         break;
       
   293     default:
       
   294         break;
       
   295     }
       
   296     return PC_Invalid;
       
   297 }
       
   298 
       
   299 // Convert the text the user types into a usable class name prefix by filtering
       
   300 // characters, lower-casing the first character and camel-casing subsequent
       
   301 // words. ("zip code:") --> ("zipCode").
       
   302 
       
   303 static QString prefixFromLabel(const QString &prefix)
       
   304 {
       
   305     QString rc;
       
   306     const int length = prefix.size();
       
   307     bool lastWasAcceptable = false;
       
   308     for (int i = 0 ; i < length; i++) {
       
   309         const QChar c = prefix.at(i);
       
   310         const PrefixCharacterKind kind = prefixCharacterKind(c);
       
   311         const bool acceptable = kind != PC_Invalid;
       
   312         if (acceptable) {
       
   313             if (rc.isEmpty()) {
       
   314                 // Lower-case first character
       
   315                 rc += kind == PC_UpperCaseLetter ? c.toLower() : c;
       
   316             } else {
       
   317                 // Camel-case words
       
   318                 rc += !lastWasAcceptable && kind == PC_LowerCaseLetter ? c.toUpper() : c;
       
   319             }
       
   320         }
       
   321         lastWasAcceptable = acceptable;
       
   322     }
       
   323     return rc;
       
   324 }
       
   325 
       
   326 void FormLayoutRowDialog::updateObjectNames(bool updateLabel, bool updateField)
       
   327 {
       
   328     // Generate label + field object names from the label text, that is,
       
   329     // "&Zip code:" -> "zipcodeLabel", "zipcodeLineEdit" unless the user
       
   330     // edited it.
       
   331     const bool doUpdateLabel = !m_labelNameEdited && updateLabel;
       
   332     const bool doUpdateField = !m_fieldNameEdited && updateField;
       
   333     if (!doUpdateLabel && !doUpdateField)
       
   334         return;
       
   335 
       
   336     const QString prefix = prefixFromLabel(labelText());
       
   337     // Set names
       
   338     if (doUpdateLabel)
       
   339         m_ui.labelNameLineEdit->setText(prefix + QLatin1String("Label"));
       
   340     if (doUpdateField)
       
   341         m_ui.fieldNameLineEdit->setText(prefix + postFixFromClassName(fieldClass()));
       
   342 }
       
   343 
       
   344 void FormLayoutRowDialog::fieldClassChanged(int)
       
   345 {
       
   346     updateObjectNames(false, true);
       
   347 }
       
   348 
       
   349 void FormLayoutRowDialog::labelNameEdited(const QString & /*text*/)
       
   350 {
       
   351     m_labelNameEdited = true; // stop auto-updating after user change
       
   352     updateOkButton();
       
   353 }
       
   354 
       
   355 void FormLayoutRowDialog::fieldNameEdited(const QString & /*text*/)
       
   356 {
       
   357     m_fieldNameEdited = true; // stop auto-updating after user change
       
   358     updateOkButton();
       
   359 }
       
   360 
       
   361 void FormLayoutRowDialog::buddyClicked()
       
   362 {
       
   363     m_buddyClicked = true; // stop auto-updating after user change
       
   364     updateOkButton();
       
   365 }
       
   366 
       
   367 /* Create a list of classes suitable for field widgets. Take the fixed base
       
   368  * classes provided and look in the widget database for custom widgets derived
       
   369  * from them ("QLineEdit", "CustomLineEdit", "QComboBox"...). */
       
   370 QStringList FormLayoutRowDialog::fieldWidgetClasses(QDesignerFormEditorInterface *core)
       
   371 {
       
   372     // Base class -> custom widgets map
       
   373     typedef QMultiHash<QString, QString> ClassMap;
       
   374 
       
   375     static QStringList rc;
       
   376     if (rc.empty()) {
       
   377         const int fwCount = sizeof(fieldWidgetBaseClasses)/sizeof(const char*);
       
   378         // Turn known base classes into list
       
   379         QStringList baseClasses;
       
   380         for (int i = 0; i < fwCount; i++)
       
   381             baseClasses.push_back(QLatin1String(fieldWidgetBaseClasses[i]));
       
   382         // Scan for custom widgets that inherit them and store them in a
       
   383         // multimap of base class->custom widgets unless we have a language
       
   384         // extension installed which might do funny things with custom widgets.
       
   385         ClassMap customClassMap;
       
   386         if (qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core) == 0) {
       
   387             const QDesignerWidgetDataBaseInterface *wdb = core->widgetDataBase();
       
   388             const int wdbCount = wdb->count();
       
   389             for (int w = 0; w < wdbCount; ++w) {
       
   390                 // Check for non-container custom types that extend the
       
   391                 // respective base class.
       
   392                 const QDesignerWidgetDataBaseItemInterface *dbItem = wdb->item(w);
       
   393                 if (!dbItem->isPromoted() && !dbItem->isContainer() && dbItem->isCustom()) {
       
   394                     const int index = baseClasses.indexOf(dbItem->extends());
       
   395                     if (index != -1)
       
   396                     customClassMap.insert(baseClasses.at(index), dbItem->name());
       
   397                 }
       
   398             }
       
   399         }
       
   400         // Compile final list, taking each base class and append custom widgets
       
   401         // based on it.
       
   402         for (int i = 0; i < fwCount; i++) {
       
   403             rc.push_back(baseClasses.at(i));
       
   404             rc += customClassMap.values(baseClasses.at(i));
       
   405         }
       
   406     }
       
   407     return rc;
       
   408 }
       
   409 
       
   410 // ------------------ Utilities
       
   411 
       
   412 static QFormLayout *managedFormLayout(const QDesignerFormEditorInterface *core, const QWidget *w)
       
   413 {
       
   414     QLayout *l = 0;
       
   415     if (LayoutInfo::managedLayoutType(core, w, &l) == LayoutInfo::Form)
       
   416         return qobject_cast<QFormLayout *>(l);
       
   417     return 0;
       
   418 }
       
   419 
       
   420 // Create the widgets of a control row and apply text properties contained
       
   421 // in the struct, called by addFormLayoutRow()
       
   422 static QPair<QWidget *,QWidget *>
       
   423         createWidgets(const FormLayoutRow &row, QWidget *parent,
       
   424                       QDesignerFormWindowInterface *formWindow)
       
   425 {
       
   426     QDesignerFormEditorInterface *core = formWindow->core();
       
   427     QDesignerWidgetFactoryInterface *wf = core->widgetFactory();
       
   428 
       
   429     QPair<QWidget *,QWidget *> rc = QPair<QWidget *,QWidget *>(wf->createWidget(QLatin1String("QLabel"), parent),
       
   430                                                                wf->createWidget(row.fieldClassName, parent));
       
   431     // Set up properties of the label
       
   432     const QString objectNameProperty = QLatin1String("objectName");
       
   433     QDesignerPropertySheetExtension *labelSheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), rc.first);
       
   434     int nameIndex = labelSheet->indexOf(objectNameProperty);
       
   435     labelSheet->setProperty(nameIndex, qVariantFromValue(PropertySheetStringValue(row.labelName)));
       
   436     labelSheet->setChanged(nameIndex, true);
       
   437     formWindow->ensureUniqueObjectName(rc.first);
       
   438     const int textIndex = labelSheet->indexOf(QLatin1String("text"));
       
   439     labelSheet->setProperty(textIndex, qVariantFromValue(PropertySheetStringValue(row.labelText)));
       
   440     labelSheet->setChanged(textIndex, true);
       
   441     // Set up properties of the control
       
   442     QDesignerPropertySheetExtension *controlSheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), rc.second);
       
   443     nameIndex = controlSheet->indexOf(objectNameProperty);
       
   444     controlSheet->setProperty(nameIndex, qVariantFromValue(PropertySheetStringValue(row.fieldName)));
       
   445     controlSheet->setChanged(nameIndex, true);
       
   446     formWindow->ensureUniqueObjectName(rc.second);
       
   447     return rc;
       
   448 }
       
   449 
       
   450 // Create a command sequence on the undo stack of the form window that creates
       
   451 // the widgets of the row and inserts them into the form layout.
       
   452 static void addFormLayoutRow(const FormLayoutRow &formLayoutRow, int row, QWidget *w,
       
   453                                QDesignerFormWindowInterface *formWindow)
       
   454 {
       
   455     QFormLayout *formLayout = managedFormLayout(formWindow->core(), w);
       
   456     Q_ASSERT(formLayout);
       
   457     QUndoStack *undoStack = formWindow->commandHistory();
       
   458     const QString macroName = QCoreApplication::translate("Command", "Add '%1' to '%2'").arg(formLayoutRow.labelText, formLayout->objectName());
       
   459     undoStack->beginMacro(macroName);
       
   460 
       
   461     // Create a list of widget insertion commands and pass them a cell position
       
   462     const QPair<QWidget *,QWidget *> widgetPair = createWidgets(formLayoutRow, w, formWindow);
       
   463 
       
   464     InsertWidgetCommand *labelCmd = new InsertWidgetCommand(formWindow);
       
   465     labelCmd->init(widgetPair.first, false, row, 0);
       
   466     undoStack->push(labelCmd);
       
   467     InsertWidgetCommand *controlCmd = new InsertWidgetCommand(formWindow);
       
   468     controlCmd->init(widgetPair.second, false, row, 1);
       
   469     undoStack->push(controlCmd);
       
   470     if (formLayoutRow.buddy) {
       
   471         SetPropertyCommand *buddyCommand = new SetPropertyCommand(formWindow);
       
   472         buddyCommand->init(widgetPair.first, QLatin1String(buddyPropertyC), widgetPair.second->objectName());
       
   473         undoStack->push(buddyCommand);
       
   474     }
       
   475     undoStack->endMacro();
       
   476 }
       
   477 
       
   478 // ---------------- FormLayoutMenu
       
   479 FormLayoutMenu::FormLayoutMenu(QObject *parent) :
       
   480     QObject(parent),
       
   481     m_separator1(new QAction(this)),
       
   482     m_populateFormAction(new QAction(tr("Add form layout row..."), this)),
       
   483     m_separator2(new QAction(this))
       
   484 {
       
   485     m_separator1->setSeparator(true);
       
   486     connect(m_populateFormAction, SIGNAL(triggered()), this, SLOT(slotAddRow()));
       
   487     m_separator2->setSeparator(true);
       
   488 }
       
   489 
       
   490 void FormLayoutMenu::populate(QWidget *w, QDesignerFormWindowInterface *fw, ActionList &actions)
       
   491 {
       
   492     switch (LayoutInfo::managedLayoutType(fw->core(), w)) {
       
   493     case LayoutInfo::Form:
       
   494         if (!actions.empty() && !actions.back()->isSeparator())
       
   495             actions.push_back(m_separator1);
       
   496         actions.push_back(m_populateFormAction);
       
   497         actions.push_back(m_separator2);
       
   498         m_widget = w;
       
   499         break;
       
   500     default:
       
   501         m_widget = 0;
       
   502         break;
       
   503     }
       
   504 }
       
   505 
       
   506 void FormLayoutMenu::slotAddRow()
       
   507 {
       
   508     QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_widget);
       
   509     Q_ASSERT(m_widget && fw);
       
   510     const int rowCount = managedFormLayout(fw->core(), m_widget)->rowCount();
       
   511 
       
   512     FormLayoutRowDialog dialog(fw->core(), fw);
       
   513     dialog.setRowRange(0, rowCount);
       
   514     dialog.setRow(rowCount);
       
   515 
       
   516     if (dialog.exec() != QDialog::Accepted)
       
   517         return;
       
   518     addFormLayoutRow(dialog.formLayoutRow(), dialog.row(), m_widget, fw);
       
   519 }
       
   520 
       
   521 QAction *FormLayoutMenu::preferredEditAction(QWidget *w, QDesignerFormWindowInterface *fw)
       
   522 {
       
   523     if (LayoutInfo::managedLayoutType(fw->core(), w) == LayoutInfo::Form) {
       
   524         m_widget = w;
       
   525         return m_populateFormAction;
       
   526     }
       
   527     return 0;
       
   528 }
       
   529 }
       
   530 
       
   531 QT_END_NAMESPACE
       
   532 
       
   533 #include "formlayoutmenu.moc"
       
   534