1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
board_init_f(ulong flag)21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include "qdesigner_taskmenu_p.h"
30 #include "qdesigner_command_p.h"
31 #include "qdesigner_command2_p.h"
32 #include "richtexteditor_p.h"
33 #include "plaintexteditor_p.h"
34 #include "stylesheeteditor_p.h"
35 #include "qlayout_widget_p.h"
36 #include "layout_p.h"
37 #include "selectsignaldialog_p.h"
38 #include "spacer_widget_p.h"
39 #include "textpropertyeditor_p.h"
40 #include "promotiontaskmenu_p.h"
41 #include "metadatabase_p.h"
42 #include "signalslotdialog_p.h"
43 #include "qdesigner_membersheet_p.h"
44 #include "qdesigner_propertycommand_p.h"
45 #include "qdesigner_utils_p.h"
46 #include "qdesigner_objectinspector_p.h"
47 #include "morphmenu_p.h"
48 #include "formlayoutmenu_p.h"
49 #include "widgetfactory_p.h"
50 #include "abstractintrospection_p.h"
51 #include "widgetdatabase_p.h"
52 
53 #include <shared_enums_p.h>
54 
55 #include <QtDesigner/abstractformwindow.h>
56 #include <QtDesigner/abstractformwindowcursor.h>
57 #include <QtDesigner/propertysheet.h>
58 #include <QtDesigner/abstractformeditor.h>
59 #include <QtDesigner/abstractlanguage.h>
60 #include <QtDesigner/abstractintegration.h>
61 #include <QtDesigner/qextensionmanager.h>
62 
63 #include <QtWidgets/qaction.h>
64 #include <QtWidgets/qactiongroup.h>
65 #include <QtWidgets/qwidget.h>
66 #include <QtWidgets/qmenubar.h>
67 #include <QtWidgets/qmainwindow.h>
68 #include <QtWidgets/qstatusbar.h>
69 #include <QtWidgets/qdialogbuttonbox.h>
70 #include <QtWidgets/qboxlayout.h>
71 #include <QtWidgets/qpushbutton.h>
72 #include <QtWidgets/qundostack.h>
73 #include <QtCore/qdebug.h>
74 #include <QtCore/qcoreapplication.h>
75 
76 QT_BEGIN_NAMESPACE
77 
78 static inline QAction *createSeparatorHelper(QObject *parent) {
79     QAction *rc = new QAction(parent);
80     rc->setSeparator(true);
81     return rc;
82 }
83 
84 static QString objName(const QDesignerFormEditorInterface *core, QObject *object) {
85     QDesignerPropertySheetExtension *sheet
86             = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), object);
87     Q_ASSERT(sheet != nullptr);
88 
handoff_arch_save(struct spl_handoff * ho)89     const QString objectNameProperty = QStringLiteral("objectName");
90     const int index = sheet->indexOf(objectNameProperty);
91     const QVariant v = sheet->property(index);
92     if (v.canConvert<qdesigner_internal::PropertySheetStringValue>())
93         return v.value<qdesigner_internal::PropertySheetStringValue>().value();
94     return v.toString();
95 }
96 
97 enum { ApplyMinimumWidth = 0x1, ApplyMinimumHeight = 0x2, ApplyMaximumWidth = 0x4, ApplyMaximumHeight = 0x8 };
98 
99 namespace  {
100 // --------------- ObjectNameDialog
101 class ObjectNameDialog : public QDialog
102 {
103      public:
104          ObjectNameDialog(QWidget *parent, const QString &oldName);
105          QString newObjectName() const;
106 
107      private:
108          qdesigner_internal::TextPropertyEditor *m_editor;
109 };
110 
111 ObjectNameDialog::ObjectNameDialog(QWidget *parent, const QString &oldName)
112     : QDialog(parent),
113       m_editor( new qdesigner_internal::TextPropertyEditor(this, qdesigner_internal::TextPropertyEditor::EmbeddingNone,
114                                                            qdesigner_internal::ValidationObjectName))
115 {
116     setWindowTitle(QCoreApplication::translate("ObjectNameDialog", "Change Object Name"));
117     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
118 
119     QVBoxLayout *vboxLayout = new QVBoxLayout(this);
120     vboxLayout->addWidget(new QLabel(QCoreApplication::translate("ObjectNameDialog", "Object Name")));
121 
122     m_editor->setText(oldName);
123     m_editor->selectAll();
124     m_editor->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
125     vboxLayout->addWidget(m_editor);
126 
127     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
128                                                        Qt::Horizontal, this);
129     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
130     okButton->setDefault(true);
131     vboxLayout->addWidget(buttonBox);
132 
133     connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
134     connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
135 }
136 
137 QString ObjectNameDialog::newObjectName() const
138 {
139     return m_editor->text();
140 }
141 } // namespace
142 
143 namespace qdesigner_internal {
144 
145 // Sub menu displaying the alignment options of a widget in a managed
146 // grid/box layout cell.
147 class LayoutAlignmentMenu {
148 public:
149     explicit LayoutAlignmentMenu(QObject *parent);
150 
151     QAction *subMenuAction() const { return m_subMenuAction; }
152 
153     void connect(QObject *receiver, const char *aSlot);
154 
155     // Set up enabled state and checked actions according to widget (managed box/grid)
156     bool setAlignment(const QDesignerFormEditorInterface *core, QWidget *w);
157 
158     // Return the currently checked alignment
159     Qt::Alignment alignment() const;
160 
161 private:
162     enum Actions { HorizNone, Left, HorizCenter, Right, VerticalNone, Top, VerticalCenter, Bottom };
163     static QAction *createAction(const QString &text, int data, QMenu *menu, QActionGroup *ag);
164 
165     QAction *m_subMenuAction;
166     QActionGroup *m_horizGroup;
167     QActionGroup *m_verticalGroup;
168     QAction *m_actions[Bottom + 1];
169 };
170 
171 QAction *LayoutAlignmentMenu::createAction(const QString &text, int data, QMenu *menu, QActionGroup *ag)
172 {
173     QAction * a = new QAction(text, nullptr);
174     a->setCheckable(true);
175     a->setData(QVariant(data));
176     menu->addAction(a);
177     ag->addAction(a);
178     return a;
179 }
180 
181 LayoutAlignmentMenu::LayoutAlignmentMenu(QObject *parent) :
182     m_subMenuAction(new QAction(QDesignerTaskMenu::tr("Layout Alignment"), parent)),
183     m_horizGroup(new QActionGroup(parent)),
184     m_verticalGroup(new QActionGroup(parent))
185 {
186     m_horizGroup->setExclusive(true);
187     m_verticalGroup->setExclusive(true);
188 
189     QMenu *menu = new QMenu;
190     m_subMenuAction->setMenu(menu);
191 
192     m_actions[HorizNone] = createAction(QDesignerTaskMenu::tr("No Horizontal Alignment"), 0, menu, m_horizGroup);
193     m_actions[Left] = createAction(QDesignerTaskMenu::tr("Left"), Qt::AlignLeft, menu, m_horizGroup);
194     m_actions[HorizCenter] = createAction(QDesignerTaskMenu::tr("Center Horizontally"), Qt::AlignHCenter, menu, m_horizGroup);
195     m_actions[Right] = createAction(QDesignerTaskMenu::tr("Right"), Qt::AlignRight, menu, m_horizGroup);
196     menu->addSeparator();
197     m_actions[VerticalNone] = createAction(QDesignerTaskMenu::tr("No Vertical Alignment"), 0, menu, m_verticalGroup);
198     m_actions[Top] = createAction(QDesignerTaskMenu::tr("Top"), Qt::AlignTop, menu, m_verticalGroup);
199     m_actions[VerticalCenter] = createAction(QDesignerTaskMenu::tr("Center Vertically"), Qt::AlignVCenter, menu, m_verticalGroup);
200     m_actions[Bottom] = createAction(QDesignerTaskMenu::tr("Bottom"), Qt::AlignBottom, menu, m_verticalGroup);
201 }
202 
203 void LayoutAlignmentMenu::connect(QObject *receiver, const char *aSlot)
204 {
205     QObject::connect(m_horizGroup, SIGNAL(triggered(QAction*)), receiver, aSlot);
206     QObject::connect(m_verticalGroup, SIGNAL(triggered(QAction*)), receiver, aSlot);
207 }
208 
209 bool LayoutAlignmentMenu::setAlignment(const QDesignerFormEditorInterface *core, QWidget *w)
210 {
211     bool enabled;
212     const Qt::Alignment alignment = LayoutAlignmentCommand::alignmentOf(core, w, &enabled);
213     if (!enabled) {
214         m_subMenuAction->setEnabled(false);
215         m_actions[HorizNone]->setChecked(true);
216         m_actions[VerticalNone]->setChecked(true);
217         return false;
218     }
219     // Get alignment
220     switch (alignment & Qt::AlignHorizontal_Mask) {
221     case Qt::AlignLeft:
222         m_actions[Left]->setChecked(true);
223         break;
224     case Qt::AlignHCenter:
225         m_actions[HorizCenter]->setChecked(true);
226         break;
227     case Qt::AlignRight:
228         m_actions[Right]->setChecked(true);
229         break;
230     default:
231         m_actions[HorizNone]->setChecked(true);
232         break;
233     }
234     switch (alignment & Qt::AlignVertical_Mask) {
235     case Qt::AlignTop:
236         m_actions[Top]->setChecked(true);
237         break;
238     case Qt::AlignVCenter:
239         m_actions[VerticalCenter]->setChecked(true);
240         break;
241     case Qt::AlignBottom:
242         m_actions[Bottom]->setChecked(true);
243         break;
244     default:
245         m_actions[VerticalNone]->setChecked(true);
246         break;
247     }
248     return true;
249 }
250 
251 Qt::Alignment LayoutAlignmentMenu::alignment() const
252 {
253     Qt::Alignment alignment;
254     if (const QAction *horizAction = m_horizGroup->checkedAction())
255         if (const int horizAlign = horizAction->data().toInt())
256             alignment |= static_cast<Qt::Alignment>(horizAlign);
257     if (const QAction *vertAction = m_verticalGroup->checkedAction())
258         if (const int vertAlign = vertAction->data().toInt())
259             alignment |= static_cast<Qt::Alignment>(vertAlign);
260     return alignment;
261 }
262 
263 // -------------- QDesignerTaskMenuPrivate
264 class QDesignerTaskMenuPrivate {
265 public:
266     QDesignerTaskMenuPrivate(QWidget *widget, QObject *parent);
267 
268     QDesignerTaskMenu *m_q;
269     QPointer<QWidget> m_widget;
270     QAction *m_separator;
271     QAction *m_separator2;
272     QAction *m_separator3;
273     QAction *m_separator4;
274     QAction *m_separator5;
275     QAction *m_separator6;
276     QAction *m_separator7;
277     QAction *m_changeObjectNameAction;
278     QAction *m_changeToolTip;
279     QAction *m_changeWhatsThis;
280     QAction *m_changeStyleSheet;
281     MorphMenu *m_morphMenu;
282     FormLayoutMenu *m_formLayoutMenu;
283 
284     QAction *m_addMenuBar;
285     QAction *m_addToolBar;
286     QAction *m_addAreaSubMenu;
287     QAction *m_addStatusBar;
288     QAction *m_removeStatusBar;
289     QAction *m_containerFakeMethods;
290     QAction *m_navigateToSlot;
291     PromotionTaskMenu* m_promotionTaskMenu;
292     QActionGroup *m_sizeActionGroup;
293     LayoutAlignmentMenu m_layoutAlignmentMenu;
294     QAction *m_sizeActionsSubMenu;
295 };
296 
297 QDesignerTaskMenuPrivate::QDesignerTaskMenuPrivate(QWidget *widget, QObject *parent) :
298     m_q(nullptr),
299     m_widget(widget),
300     m_separator(createSeparatorHelper(parent)),
301     m_separator2(createSeparatorHelper(parent)),
302     m_separator3(createSeparatorHelper(parent)),
303     m_separator4(createSeparatorHelper(parent)),
304     m_separator5(createSeparatorHelper(parent)),
305     m_separator6(createSeparatorHelper(parent)),
306     m_separator7(createSeparatorHelper(parent)),
307     m_changeObjectNameAction(new QAction(QDesignerTaskMenu::tr("Change objectName..."), parent)),
308     m_changeToolTip(new QAction(QDesignerTaskMenu::tr("Change toolTip..."), parent)),
309     m_changeWhatsThis(new QAction(QDesignerTaskMenu::tr("Change whatsThis..."), parent)),
310     m_changeStyleSheet(new QAction(QDesignerTaskMenu::tr("Change styleSheet..."), parent)),
311     m_morphMenu(new MorphMenu(parent)),
312     m_formLayoutMenu(new FormLayoutMenu(parent)),
313     m_addMenuBar(new QAction(QDesignerTaskMenu::tr("Create Menu Bar"), parent)),
314     m_addToolBar(new QAction(QDesignerTaskMenu::tr("Add Tool Bar"), parent)),
315     m_addAreaSubMenu(new QAction(QDesignerTaskMenu::tr("Add Tool Bar to Other Area"), parent)),
316     m_addStatusBar(new QAction(QDesignerTaskMenu::tr("Create Status Bar"), parent)),
317     m_removeStatusBar(new QAction(QDesignerTaskMenu::tr("Remove Status Bar"), parent)),
318     m_containerFakeMethods(new QAction(QDesignerTaskMenu::tr("Change signals/slots..."), parent)),
319     m_navigateToSlot(new QAction(QDesignerTaskMenu::tr("Go to slot..."), parent)),
320     m_promotionTaskMenu(new PromotionTaskMenu(widget, PromotionTaskMenu::ModeManagedMultiSelection, parent)),
321     m_sizeActionGroup(new QActionGroup(parent)),
322     m_layoutAlignmentMenu(parent),
323     m_sizeActionsSubMenu(new QAction(QDesignerTaskMenu::tr("Size Constraints"), parent))
324 {
325     QMenu *sizeMenu = new QMenu;
326     m_sizeActionsSubMenu->setMenu(sizeMenu);
327     QAction *sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Minimum Width"));
328     sizeAction->setData(ApplyMinimumWidth);
329     sizeMenu->addAction(sizeAction);
330 
331     sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Minimum Height"));
332     sizeAction->setData(ApplyMinimumHeight);
333     sizeMenu->addAction(sizeAction);
334 
335     sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Minimum Size"));
336     sizeAction->setData(ApplyMinimumWidth|ApplyMinimumHeight);
337     sizeMenu->addAction(sizeAction);
338 
339     sizeMenu->addSeparator();
340 
341     sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Maximum Width"));
342     sizeAction->setData(ApplyMaximumWidth);
343     sizeMenu->addAction(sizeAction);
344 
345     sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Maximum Height"));
346     sizeAction->setData(ApplyMaximumHeight);
347     sizeMenu->addAction(sizeAction);
348 
349     sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Maximum Size"));
350     sizeAction->setData(ApplyMaximumWidth|ApplyMaximumHeight);
351     sizeMenu->addAction(sizeAction);
352 }
353 
354 // --------- QDesignerTaskMenu
355 QDesignerTaskMenu::QDesignerTaskMenu(QWidget *widget, QObject *parent) :
356     QObject(parent),
357     d(new QDesignerTaskMenuPrivate(widget, parent))
358 {
359     d->m_q = this;
360     Q_ASSERT(qobject_cast<QDesignerFormWindowInterface*>(widget) == 0);
361 
362     connect(d->m_changeObjectNameAction, &QAction::triggered, this, &QDesignerTaskMenu::changeObjectName);
363     connect(d->m_changeToolTip, &QAction::triggered, this, &QDesignerTaskMenu::changeToolTip);
364     connect(d->m_changeWhatsThis, &QAction::triggered, this, &QDesignerTaskMenu::changeWhatsThis);
365     connect(d->m_changeStyleSheet, &QAction::triggered, this, &QDesignerTaskMenu::changeStyleSheet);
366     connect(d->m_addMenuBar, &QAction::triggered, this, &QDesignerTaskMenu::createMenuBar);
367     connect(d->m_addToolBar, &QAction::triggered, this,
368             [this] () { this->addToolBar(Qt::TopToolBarArea); });
369     auto areaMenu = new QMenu;
370     d->m_addAreaSubMenu->setMenu(areaMenu);
371     areaMenu->addAction(QDesignerTaskMenu::tr("Left"),
372                         [this] () { this->addToolBar(Qt::LeftToolBarArea); });
373     areaMenu->addAction(QDesignerTaskMenu::tr("Right"),
374                         [this] () { this->addToolBar(Qt::RightToolBarArea); });
375     areaMenu->addAction(QDesignerTaskMenu::tr("Bottom"),
376                         [this] () { this->addToolBar(Qt::BottomToolBarArea); });
377     connect(d->m_addStatusBar, &QAction::triggered, this, &QDesignerTaskMenu::createStatusBar);
378     connect(d->m_removeStatusBar, &QAction::triggered, this, &QDesignerTaskMenu::removeStatusBar);
379     connect(d->m_containerFakeMethods, &QAction::triggered, this, &QDesignerTaskMenu::containerFakeMethods);
380     connect(d->m_navigateToSlot, &QAction::triggered, this, &QDesignerTaskMenu::slotNavigateToSlot);
381     connect(d->m_sizeActionGroup, &QActionGroup::triggered, this, &QDesignerTaskMenu::applySize);
382     d->m_layoutAlignmentMenu.connect(this, SLOT(slotLayoutAlignment()));
383 }
384 
385 QDesignerTaskMenu::~QDesignerTaskMenu()
386 {
387     delete d;
388 }
389 
390 QAction *QDesignerTaskMenu::createSeparator()
391 {
392     return createSeparatorHelper(this);
393 }
394 
395 QWidget *QDesignerTaskMenu::widget() const
396 {
397     return d->m_widget;
398 }
399 
400 QDesignerFormWindowInterface *QDesignerTaskMenu::formWindow() const
401 {
402     QDesignerFormWindowInterface *result = QDesignerFormWindowInterface::findFormWindow(widget());
403     Q_ASSERT(result != nullptr);
404     return result;
405 }
406 
407 void QDesignerTaskMenu::createMenuBar()
408 {
409     if (QDesignerFormWindowInterface *fw = formWindow()) {
410         QMainWindow *mw = qobject_cast<QMainWindow*>(fw->mainContainer());
411         if (!mw) {
412             // ### warning message
413             return;
414         }
415 
416         CreateMenuBarCommand *cmd = new CreateMenuBarCommand(fw);
417         cmd->init(mw);
418         fw->commandHistory()->push(cmd);
419     }
420 }
421 
422 void QDesignerTaskMenu::addToolBar(Qt::ToolBarArea area)
423 {
424     if (QDesignerFormWindowInterface *fw = formWindow()) {
425         QMainWindow *mw = qobject_cast<QMainWindow*>(fw->mainContainer());
426         if (!mw) {
427             // ### warning message
428             return;
429         }
430 
431         AddToolBarCommand *cmd = new AddToolBarCommand(fw);
432         cmd->init(mw, area);
433         fw->commandHistory()->push(cmd);
434     }
435 }
436 
437 void QDesignerTaskMenu::createStatusBar()
438 {
439     if (QDesignerFormWindowInterface *fw = formWindow()) {
440         QMainWindow *mw = qobject_cast<QMainWindow*>(fw->mainContainer());
441         if (!mw) {
442             // ### warning message
443             return;
444         }
445 
446         CreateStatusBarCommand *cmd = new CreateStatusBarCommand(fw);
447         cmd->init(mw);
448         fw->commandHistory()->push(cmd);
449     }
450 }
451 
452 void QDesignerTaskMenu::removeStatusBar()
453 {
454     if (QDesignerFormWindowInterface *fw = formWindow()) {
455         QMainWindow *mw = qobject_cast<QMainWindow*>(fw->mainContainer());
456         if (!mw) {
457             // ### warning message
458             return;
459         }
460 
461         DeleteStatusBarCommand *cmd = new DeleteStatusBarCommand(fw);
462         cmd->init(mw->findChild<QStatusBar *>(QString(), Qt::FindDirectChildrenOnly));
463         fw->commandHistory()->push(cmd);
464     }
465 }
466 
467 QList<QAction*> QDesignerTaskMenu::taskActions() const
468 {
469     QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(widget());
470     Q_ASSERT(formWindow);
471 
472     const bool isMainContainer = formWindow->mainContainer() == widget();
473 
474     QList<QAction*> actions;
475 
476     if (const QMainWindow *mw = qobject_cast<const QMainWindow*>(formWindow->mainContainer()))  {
477         if (isMainContainer || mw->centralWidget() == widget()) {
478             if (mw->findChild<QMenuBar *>(QString(), Qt::FindDirectChildrenOnly) == nullptr)
479                 actions.append(d->m_addMenuBar);
480 
481             actions.append(d->m_addToolBar);
482             actions.append(d->m_addAreaSubMenu);
483             // ### create the status bar
484             if (mw->findChild<QStatusBar *>(QString(), Qt::FindDirectChildrenOnly))
485                 actions.append(d->m_removeStatusBar);
486             else
487                 actions.append(d->m_addStatusBar);
488 
489             actions.append(d->m_separator);
490         }
491     }
492     actions.append(d->m_changeObjectNameAction);
493     d->m_morphMenu->populate(d->m_widget, formWindow, actions);
494     d->m_formLayoutMenu->populate(d->m_widget, formWindow, actions);
495     actions.append(d->m_separator2);
496     actions.append(d->m_changeToolTip);
497     actions.append(d->m_changeWhatsThis);
498     actions.append(d->m_changeStyleSheet);
499     actions.append(d->m_separator6);
500     actions.append(d->m_sizeActionsSubMenu);
501     if (d->m_layoutAlignmentMenu.setAlignment(formWindow->core(), d->m_widget))
502         actions.append(d->m_layoutAlignmentMenu.subMenuAction());
503 
504     d->m_promotionTaskMenu->setMode(formWindow->isManaged(d->m_widget) ?
505                                     PromotionTaskMenu::ModeManagedMultiSelection : PromotionTaskMenu::ModeUnmanagedMultiSelection);
506     d->m_promotionTaskMenu->addActions(formWindow, PromotionTaskMenu::LeadingSeparator, actions);
507 
508     if (isMainContainer && !qt_extension<QDesignerLanguageExtension*>(formWindow->core()->extensionManager(), formWindow->core())) {
509         actions.append(d->m_separator5);
510         actions.append(d->m_containerFakeMethods);
511     }
512 
513     if (isSlotNavigationEnabled(formWindow->core())) {
514         actions.append(d->m_separator7);
515         actions.append(d->m_navigateToSlot);
516     }
517 
518     return actions;
519 }
520 
521 void QDesignerTaskMenu::changeObjectName()
522 {
523     QDesignerFormWindowInterface *fw = formWindow();
524     Q_ASSERT(fw != nullptr);
525 
526     const QString oldObjectName = objName(fw->core(), widget());
527 
528     ObjectNameDialog dialog(fw, oldObjectName);
529     if (dialog.exec() == QDialog::Accepted) {
530         const QString newObjectName = dialog.newObjectName();
531         if (!newObjectName.isEmpty() && newObjectName  != oldObjectName ) {
532             const QString objectNameProperty = QStringLiteral("objectName");
533             PropertySheetStringValue objectNameValue;
534             objectNameValue.setValue(newObjectName);
535             setProperty(fw, CurrentWidgetMode, objectNameProperty, QVariant::fromValue(objectNameValue));
536         }
537     }
538 }
539 
540 void QDesignerTaskMenu::changeTextProperty(const QString &propertyName, const QString &windowTitle, PropertyMode pm, Qt::TextFormat desiredFormat)
541 {
542     QDesignerFormWindowInterface *fw = formWindow();
543     if (!fw)
544         return;
545     Q_ASSERT(d->m_widget->parentWidget() != nullptr);
546 
547     const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(fw->core()->extensionManager(), d->m_widget);
548     const int index = sheet->indexOf(propertyName);
549     if (index == -1) {
550         qDebug() << "** WARNING Invalid property" << propertyName << " passed to changeTextProperty!";
551         return;
552     }
553     PropertySheetStringValue textValue = qvariant_cast<PropertySheetStringValue>(sheet->property(index));
554     const QString oldText = textValue.value();
555     // Pop up respective dialog
556     bool accepted = false;
557     QString newText;
558     switch (desiredFormat) {
559     case Qt::PlainText: {
560         PlainTextEditorDialog dlg(fw->core(), fw);
561         if (!windowTitle.isEmpty())
562             dlg.setWindowTitle(windowTitle);
563         dlg.setDefaultFont(d->m_widget->font());
564         dlg.setText(oldText);
565         accepted = dlg.showDialog() == QDialog::Accepted;
566         newText = dlg.text();
567     }
568         break;
569     default: {
570         RichTextEditorDialog dlg(fw->core(), fw);
571         if (!windowTitle.isEmpty())
572             dlg.setWindowTitle(windowTitle);
573         dlg.setDefaultFont(d->m_widget->font());
574         dlg.setText(oldText);
575         accepted = dlg.showDialog() == QDialog::Accepted;
576         newText = dlg.text(desiredFormat);
577     }
578         break;
579     }
580     // change property
581     if (!accepted || oldText == newText)
582           return;
583 
584 
585     textValue.setValue(newText);
586     setProperty(fw, pm, propertyName, QVariant::fromValue(textValue));
587 }
588 
589 void QDesignerTaskMenu::changeToolTip()
590 {
591     changeTextProperty(QStringLiteral("toolTip"), tr("Edit ToolTip"), MultiSelectionMode, Qt::AutoText);
592 }
593 
594 void QDesignerTaskMenu::changeWhatsThis()
595 {
596     changeTextProperty(QStringLiteral("whatsThis"), tr("Edit WhatsThis"), MultiSelectionMode, Qt::AutoText);
597 }
598 
599 void QDesignerTaskMenu::changeStyleSheet()
600 {
601     if (QDesignerFormWindowInterface *fw = formWindow()) {
602         StyleSheetPropertyEditorDialog dlg(fw, fw, d->m_widget);
603         dlg.exec();
604     }
605 }
606 
607 void QDesignerTaskMenu::containerFakeMethods()
608 {
609     QDesignerFormWindowInterface *fw = formWindow();
610     if (!fw)
611         return;
612     SignalSlotDialog::editMetaDataBase(fw, d->m_widget, fw);
613 }
614 
615 bool QDesignerTaskMenu::isSlotNavigationEnabled(const QDesignerFormEditorInterface *core)
616 {
617     return core->integration()->hasFeature(QDesignerIntegration::SlotNavigationFeature);
618 }
619 
620 void QDesignerTaskMenu::slotNavigateToSlot()
621 {
622     QDesignerFormEditorInterface *core = formWindow()->core();
623     Q_ASSERT(core);
624     navigateToSlot(core, widget());
625 }
626 
627 void QDesignerTaskMenu::navigateToSlot(QDesignerFormEditorInterface *core,
628                                        QObject *object,
629                                        const QString &defaultSignal)
630 {
631     SelectSignalDialog dialog;
632     dialog.populate(core, object, defaultSignal);
633     if (dialog.exec() != QDialog::Accepted)
634         return;
635     // TODO: Check whether signal is connected to slot
636     const SelectSignalDialog::Method method = dialog.selectedMethod();
637     if (method.isValid()) {
638         core->integration()->emitNavigateToSlot(objName(core, object),
639                                                 method.signature,
640                                                 method.parameterNames);
641     }
642 }
643 
644 // Add a command that takes over the value of the current geometry as
645 // minimum/maximum size according to the flags.
646 static void createSizeCommand(QDesignerFormWindowInterface *fw, QWidget *w, int flags)
647 {
648     const QSize size = w->size();
649     if (flags & (ApplyMinimumWidth|ApplyMinimumHeight)) {
650         QSize minimumSize = w-> minimumSize();
651         if (flags & ApplyMinimumWidth)
652             minimumSize.setWidth(size.width());
653         if (flags & ApplyMinimumHeight)
654              minimumSize.setHeight(size.height());
655         SetPropertyCommand* cmd = new SetPropertyCommand(fw);
656         cmd->init(w, QStringLiteral("minimumSize"), minimumSize);
657         fw->commandHistory()->push(cmd);
658     }
659     if (flags & (ApplyMaximumWidth|ApplyMaximumHeight)) {
660         QSize maximumSize = w-> maximumSize();
661         if (flags & ApplyMaximumWidth)
662             maximumSize.setWidth(size.width());
663         if (flags & ApplyMaximumHeight)
664              maximumSize.setHeight(size.height());
665         SetPropertyCommand* cmd = new SetPropertyCommand(fw);
666         cmd->init(w, QStringLiteral("maximumSize"), maximumSize);
667         fw->commandHistory()->push(cmd);
668     }
669 }
670 
671 void QDesignerTaskMenu::applySize(QAction *a)
672 {
673     QDesignerFormWindowInterface *fw = formWindow();
674     if (!fw)
675         return;
676 
677     const QWidgetList selection = applicableWidgets(fw, MultiSelectionMode);
678     if (selection.isEmpty())
679         return;
680 
681     const int mask = a->data().toInt();
682     const int size = selection.size();
683     fw->commandHistory()->beginMacro(tr("Set size constraint on %n widget(s)", nullptr, size));
684     for (int i = 0; i < size; i++)
685         createSizeCommand(fw, selection.at(i), mask);
686     fw->commandHistory()->endMacro();
687 }
688 
689 template <class Container>
690     static void getApplicableObjects(const QDesignerFormWindowInterface *fw, QWidget *current,
691                                      QDesignerTaskMenu::PropertyMode pm, Container *c)
692 {
693     // Current is always first
694     c->push_back(current);
695     if (pm == QDesignerTaskMenu::CurrentWidgetMode)
696         return;
697     QDesignerObjectInspector *designerObjectInspector = qobject_cast<QDesignerObjectInspector *>(fw->core()->objectInspector());
698     if (!designerObjectInspector)
699         return; // Ooops, someone plugged an old-style Object Inspector
700     // Add managed or unmanaged selection according to current type, make current first
701     Selection s;
702     designerObjectInspector->getSelection(s);
703     const QWidgetList &source = fw->isManaged(current) ? s.managed : s.unmanaged;
704     const QWidgetList::const_iterator cend = source.constEnd();
705     for ( QWidgetList::const_iterator it = source.constBegin(); it != cend; ++it)
706         if (*it != current) // was first
707             c->push_back(*it);
708 }
709 
710 QObjectList QDesignerTaskMenu::applicableObjects(const QDesignerFormWindowInterface *fw, PropertyMode pm) const
711 {
712     QObjectList rc;
713     getApplicableObjects(fw, d->m_widget, pm, &rc);
714     return rc;
715 }
716 
717 QWidgetList QDesignerTaskMenu::applicableWidgets(const QDesignerFormWindowInterface *fw, PropertyMode pm) const
718 {
719     QWidgetList rc;
720     getApplicableObjects(fw, d->m_widget, pm, &rc);
721     return rc;
722 }
723 
724 void QDesignerTaskMenu::setProperty(QDesignerFormWindowInterface *fw,  PropertyMode pm, const QString &name, const QVariant &newValue)
725 {
726     SetPropertyCommand* setPropertyCommand = new SetPropertyCommand(fw);
727     if (setPropertyCommand->init(applicableObjects(fw, pm), name, newValue, d->m_widget)) {
728         fw->commandHistory()->push(setPropertyCommand);
729     } else {
730         delete setPropertyCommand;
731         qDebug() << "Unable to set property " << name << '.';
732     }
733 }
734 
735 void QDesignerTaskMenu::slotLayoutAlignment()
736 {
737     QDesignerFormWindowInterface *fw = formWindow();
738     const Qt::Alignment newAlignment = d->m_layoutAlignmentMenu.alignment();
739     LayoutAlignmentCommand *cmd = new LayoutAlignmentCommand(fw);
740     if (cmd->init(d->m_widget, newAlignment)) {
741         fw->commandHistory()->push(cmd);
742     } else {
743         delete cmd;
744     }
745 }
746 } // namespace qdesigner_internal
747 
748 QT_END_NAMESPACE
749