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
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
76QT_BEGIN_NAMESPACE
77
78static inline QAction *createSeparatorHelper(QObject *parent) {
79 QAction *rc = new QAction(parent);
80 rc->setSeparator(true);
81 return rc;
82}
83
84static QString objName(const QDesignerFormEditorInterface *core, QObject *object) {
85 QDesignerPropertySheetExtension *sheet
86 = qt_extension<QDesignerPropertySheetExtension*>(manager: core->extensionManager(), object);
87 Q_ASSERT(sheet != nullptr);
88
89 const QString objectNameProperty = QStringLiteral("objectName");
90 const int index = sheet->indexOf(name: 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
97enum { ApplyMinimumWidth = 0x1, ApplyMinimumHeight = 0x2, ApplyMaximumWidth = 0x4, ApplyMaximumHeight = 0x8 };
98
99namespace {
100// --------------- ObjectNameDialog
101class 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
111ObjectNameDialog::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(context: "ObjectNameDialog", key: "Change Object Name"));
117 setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
118
119 QVBoxLayout *vboxLayout = new QVBoxLayout(this);
120 vboxLayout->addWidget(new QLabel(QCoreApplication::translate(context: "ObjectNameDialog", key: "Object Name")));
121
122 m_editor->setText(oldName);
123 m_editor->selectAll();
124 m_editor->setSizePolicy(hor: QSizePolicy::Preferred, ver: 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(which: QDialogButtonBox::Ok);
130 okButton->setDefault(true);
131 vboxLayout->addWidget(buttonBox);
132
133 connect(sender: buttonBox, signal: &QDialogButtonBox::accepted, receiver: this, slot: &QDialog::accept);
134 connect(sender: buttonBox, signal: &QDialogButtonBox::rejected, receiver: this, slot: &QDialog::reject);
135}
136
137QString ObjectNameDialog::newObjectName() const
138{
139 return m_editor->text();
140}
141} // namespace
142
143namespace qdesigner_internal {
144
145// Sub menu displaying the alignment options of a widget in a managed
146// grid/box layout cell.
147class LayoutAlignmentMenu {
148public:
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
161private:
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
171QAction *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(action: a);
177 ag->addAction(a);
178 return a;
179}
180
181LayoutAlignmentMenu::LayoutAlignmentMenu(QObject *parent) :
182 m_subMenuAction(new QAction(QDesignerTaskMenu::tr(s: "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(text: QDesignerTaskMenu::tr(s: "No Horizontal Alignment"), data: 0, menu, ag: m_horizGroup);
193 m_actions[Left] = createAction(text: QDesignerTaskMenu::tr(s: "Left"), data: Qt::AlignLeft, menu, ag: m_horizGroup);
194 m_actions[HorizCenter] = createAction(text: QDesignerTaskMenu::tr(s: "Center Horizontally"), data: Qt::AlignHCenter, menu, ag: m_horizGroup);
195 m_actions[Right] = createAction(text: QDesignerTaskMenu::tr(s: "Right"), data: Qt::AlignRight, menu, ag: m_horizGroup);
196 menu->addSeparator();
197 m_actions[VerticalNone] = createAction(text: QDesignerTaskMenu::tr(s: "No Vertical Alignment"), data: 0, menu, ag: m_verticalGroup);
198 m_actions[Top] = createAction(text: QDesignerTaskMenu::tr(s: "Top"), data: Qt::AlignTop, menu, ag: m_verticalGroup);
199 m_actions[VerticalCenter] = createAction(text: QDesignerTaskMenu::tr(s: "Center Vertically"), data: Qt::AlignVCenter, menu, ag: m_verticalGroup);
200 m_actions[Bottom] = createAction(text: QDesignerTaskMenu::tr(s: "Bottom"), data: Qt::AlignBottom, menu, ag: m_verticalGroup);
201}
202
203void LayoutAlignmentMenu::connect(QObject *receiver, const char *aSlot)
204{
205 QObject::connect(sender: m_horizGroup, SIGNAL(triggered(QAction*)), receiver, member: aSlot);
206 QObject::connect(sender: m_verticalGroup, SIGNAL(triggered(QAction*)), receiver, member: aSlot);
207}
208
209bool LayoutAlignmentMenu::setAlignment(const QDesignerFormEditorInterface *core, QWidget *w)
210{
211 bool enabled;
212 const Qt::Alignment alignment = LayoutAlignmentCommand::alignmentOf(core, w, enabled: &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
251Qt::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
264class QDesignerTaskMenuPrivate {
265public:
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
297QDesignerTaskMenuPrivate::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(s: "Change objectName..."), parent)),
308 m_changeToolTip(new QAction(QDesignerTaskMenu::tr(s: "Change toolTip..."), parent)),
309 m_changeWhatsThis(new QAction(QDesignerTaskMenu::tr(s: "Change whatsThis..."), parent)),
310 m_changeStyleSheet(new QAction(QDesignerTaskMenu::tr(s: "Change styleSheet..."), parent)),
311 m_morphMenu(new MorphMenu(parent)),
312 m_formLayoutMenu(new FormLayoutMenu(parent)),
313 m_addMenuBar(new QAction(QDesignerTaskMenu::tr(s: "Create Menu Bar"), parent)),
314 m_addToolBar(new QAction(QDesignerTaskMenu::tr(s: "Add Tool Bar"), parent)),
315 m_addAreaSubMenu(new QAction(QDesignerTaskMenu::tr(s: "Add Tool Bar to Other Area"), parent)),
316 m_addStatusBar(new QAction(QDesignerTaskMenu::tr(s: "Create Status Bar"), parent)),
317 m_removeStatusBar(new QAction(QDesignerTaskMenu::tr(s: "Remove Status Bar"), parent)),
318 m_containerFakeMethods(new QAction(QDesignerTaskMenu::tr(s: "Change signals/slots..."), parent)),
319 m_navigateToSlot(new QAction(QDesignerTaskMenu::tr(s: "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(s: "Size Constraints"), parent))
324{
325 QMenu *sizeMenu = new QMenu;
326 m_sizeActionsSubMenu->setMenu(sizeMenu);
327 QAction *sizeAction = m_sizeActionGroup->addAction(text: QDesignerTaskMenu::tr(s: "Set Minimum Width"));
328 sizeAction->setData(ApplyMinimumWidth);
329 sizeMenu->addAction(action: sizeAction);
330
331 sizeAction = m_sizeActionGroup->addAction(text: QDesignerTaskMenu::tr(s: "Set Minimum Height"));
332 sizeAction->setData(ApplyMinimumHeight);
333 sizeMenu->addAction(action: sizeAction);
334
335 sizeAction = m_sizeActionGroup->addAction(text: QDesignerTaskMenu::tr(s: "Set Minimum Size"));
336 sizeAction->setData(ApplyMinimumWidth|ApplyMinimumHeight);
337 sizeMenu->addAction(action: sizeAction);
338
339 sizeMenu->addSeparator();
340
341 sizeAction = m_sizeActionGroup->addAction(text: QDesignerTaskMenu::tr(s: "Set Maximum Width"));
342 sizeAction->setData(ApplyMaximumWidth);
343 sizeMenu->addAction(action: sizeAction);
344
345 sizeAction = m_sizeActionGroup->addAction(text: QDesignerTaskMenu::tr(s: "Set Maximum Height"));
346 sizeAction->setData(ApplyMaximumHeight);
347 sizeMenu->addAction(action: sizeAction);
348
349 sizeAction = m_sizeActionGroup->addAction(text: QDesignerTaskMenu::tr(s: "Set Maximum Size"));
350 sizeAction->setData(ApplyMaximumWidth|ApplyMaximumHeight);
351 sizeMenu->addAction(action: sizeAction);
352}
353
354// --------- QDesignerTaskMenu
355QDesignerTaskMenu::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(sender: d->m_changeObjectNameAction, signal: &QAction::triggered, receiver: this, slot: &QDesignerTaskMenu::changeObjectName);
363 connect(sender: d->m_changeToolTip, signal: &QAction::triggered, receiver: this, slot: &QDesignerTaskMenu::changeToolTip);
364 connect(sender: d->m_changeWhatsThis, signal: &QAction::triggered, receiver: this, slot: &QDesignerTaskMenu::changeWhatsThis);
365 connect(sender: d->m_changeStyleSheet, signal: &QAction::triggered, receiver: this, slot: &QDesignerTaskMenu::changeStyleSheet);
366 connect(sender: d->m_addMenuBar, signal: &QAction::triggered, receiver: this, slot: &QDesignerTaskMenu::createMenuBar);
367 connect(sender: d->m_addToolBar, signal: &QAction::triggered, context: this,
368 slot: [this] () { this->addToolBar(area: Qt::TopToolBarArea); });
369 auto areaMenu = new QMenu;
370 d->m_addAreaSubMenu->setMenu(areaMenu);
371 areaMenu->addAction(text: QDesignerTaskMenu::tr(s: "Left"),
372 slot: [this] () { this->addToolBar(area: Qt::LeftToolBarArea); });
373 areaMenu->addAction(text: QDesignerTaskMenu::tr(s: "Right"),
374 slot: [this] () { this->addToolBar(area: Qt::RightToolBarArea); });
375 areaMenu->addAction(text: QDesignerTaskMenu::tr(s: "Bottom"),
376 slot: [this] () { this->addToolBar(area: Qt::BottomToolBarArea); });
377 connect(sender: d->m_addStatusBar, signal: &QAction::triggered, receiver: this, slot: &QDesignerTaskMenu::createStatusBar);
378 connect(sender: d->m_removeStatusBar, signal: &QAction::triggered, receiver: this, slot: &QDesignerTaskMenu::removeStatusBar);
379 connect(sender: d->m_containerFakeMethods, signal: &QAction::triggered, receiver: this, slot: &QDesignerTaskMenu::containerFakeMethods);
380 connect(sender: d->m_navigateToSlot, signal: &QAction::triggered, receiver: this, slot: &QDesignerTaskMenu::slotNavigateToSlot);
381 connect(sender: d->m_sizeActionGroup, signal: &QActionGroup::triggered, receiver: this, slot: &QDesignerTaskMenu::applySize);
382 d->m_layoutAlignmentMenu.connect(receiver: this, SLOT(slotLayoutAlignment()));
383}
384
385QDesignerTaskMenu::~QDesignerTaskMenu()
386{
387 delete d;
388}
389
390QAction *QDesignerTaskMenu::createSeparator()
391{
392 return createSeparatorHelper(parent: this);
393}
394
395QWidget *QDesignerTaskMenu::widget() const
396{
397 return d->m_widget;
398}
399
400QDesignerFormWindowInterface *QDesignerTaskMenu::formWindow() const
401{
402 QDesignerFormWindowInterface *result = QDesignerFormWindowInterface::findFormWindow(w: widget());
403 Q_ASSERT(result != nullptr);
404 return result;
405}
406
407void QDesignerTaskMenu::createMenuBar()
408{
409 if (QDesignerFormWindowInterface *fw = formWindow()) {
410 QMainWindow *mw = qobject_cast<QMainWindow*>(object: fw->mainContainer());
411 if (!mw) {
412 // ### warning message
413 return;
414 }
415
416 CreateMenuBarCommand *cmd = new CreateMenuBarCommand(fw);
417 cmd->init(mainWindow: mw);
418 fw->commandHistory()->push(cmd);
419 }
420}
421
422void QDesignerTaskMenu::addToolBar(Qt::ToolBarArea area)
423{
424 if (QDesignerFormWindowInterface *fw = formWindow()) {
425 QMainWindow *mw = qobject_cast<QMainWindow*>(object: fw->mainContainer());
426 if (!mw) {
427 // ### warning message
428 return;
429 }
430
431 AddToolBarCommand *cmd = new AddToolBarCommand(fw);
432 cmd->init(mainWindow: mw, area);
433 fw->commandHistory()->push(cmd);
434 }
435}
436
437void QDesignerTaskMenu::createStatusBar()
438{
439 if (QDesignerFormWindowInterface *fw = formWindow()) {
440 QMainWindow *mw = qobject_cast<QMainWindow*>(object: fw->mainContainer());
441 if (!mw) {
442 // ### warning message
443 return;
444 }
445
446 CreateStatusBarCommand *cmd = new CreateStatusBarCommand(fw);
447 cmd->init(mainWindow: mw);
448 fw->commandHistory()->push(cmd);
449 }
450}
451
452void QDesignerTaskMenu::removeStatusBar()
453{
454 if (QDesignerFormWindowInterface *fw = formWindow()) {
455 QMainWindow *mw = qobject_cast<QMainWindow*>(object: fw->mainContainer());
456 if (!mw) {
457 // ### warning message
458 return;
459 }
460
461 DeleteStatusBarCommand *cmd = new DeleteStatusBarCommand(fw);
462 cmd->init(statusBar: mw->findChild<QStatusBar *>(aName: QString(), options: Qt::FindDirectChildrenOnly));
463 fw->commandHistory()->push(cmd);
464 }
465}
466
467QList<QAction*> QDesignerTaskMenu::taskActions() const
468{
469 QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(w: 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*>(object: formWindow->mainContainer())) {
477 if (isMainContainer || mw->centralWidget() == widget()) {
478 if (mw->findChild<QMenuBar *>(aName: QString(), options: Qt::FindDirectChildrenOnly) == nullptr)
479 actions.append(t: d->m_addMenuBar);
480
481 actions.append(t: d->m_addToolBar);
482 actions.append(t: d->m_addAreaSubMenu);
483 // ### create the status bar
484 if (mw->findChild<QStatusBar *>(aName: QString(), options: Qt::FindDirectChildrenOnly))
485 actions.append(t: d->m_removeStatusBar);
486 else
487 actions.append(t: d->m_addStatusBar);
488
489 actions.append(t: d->m_separator);
490 }
491 }
492 actions.append(t: d->m_changeObjectNameAction);
493 d->m_morphMenu->populate(w: d->m_widget, fw: formWindow, al&: actions);
494 d->m_formLayoutMenu->populate(w: d->m_widget, fw: formWindow, actions);
495 actions.append(t: d->m_separator2);
496 actions.append(t: d->m_changeToolTip);
497 actions.append(t: d->m_changeWhatsThis);
498 actions.append(t: d->m_changeStyleSheet);
499 actions.append(t: d->m_separator6);
500 actions.append(t: d->m_sizeActionsSubMenu);
501 if (d->m_layoutAlignmentMenu.setAlignment(core: formWindow->core(), w: d->m_widget))
502 actions.append(t: d->m_layoutAlignmentMenu.subMenuAction());
503
504 d->m_promotionTaskMenu->setMode(formWindow->isManaged(widget: d->m_widget) ?
505 PromotionTaskMenu::ModeManagedMultiSelection : PromotionTaskMenu::ModeUnmanagedMultiSelection);
506 d->m_promotionTaskMenu->addActions(fw: formWindow, flags: PromotionTaskMenu::LeadingSeparator, actionList&: actions);
507
508 if (isMainContainer && !qt_extension<QDesignerLanguageExtension*>(manager: formWindow->core()->extensionManager(), object: formWindow->core())) {
509 actions.append(t: d->m_separator5);
510 actions.append(t: d->m_containerFakeMethods);
511 }
512
513 if (isSlotNavigationEnabled(core: formWindow->core())) {
514 actions.append(t: d->m_separator7);
515 actions.append(t: d->m_navigateToSlot);
516 }
517
518 return actions;
519}
520
521void QDesignerTaskMenu::changeObjectName()
522{
523 QDesignerFormWindowInterface *fw = formWindow();
524 Q_ASSERT(fw != nullptr);
525
526 const QString oldObjectName = objName(core: fw->core(), object: 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, pm: CurrentWidgetMode, name: objectNameProperty, newValue: QVariant::fromValue(value: objectNameValue));
536 }
537 }
538}
539
540void 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*>(manager: fw->core()->extensionManager(), object: d->m_widget);
548 const int index = sheet->indexOf(name: propertyName);
549 if (index == -1) {
550 qDebug() << "** WARNING Invalid property" << propertyName << " passed to changeTextProperty!";
551 return;
552 }
553 PropertySheetStringValue textValue = qvariant_cast<PropertySheetStringValue>(v: 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(format: 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, name: propertyName, newValue: QVariant::fromValue(value: textValue));
587}
588
589void QDesignerTaskMenu::changeToolTip()
590{
591 changeTextProperty(QStringLiteral("toolTip"), windowTitle: tr(s: "Edit ToolTip"), pm: MultiSelectionMode, desiredFormat: Qt::AutoText);
592}
593
594void QDesignerTaskMenu::changeWhatsThis()
595{
596 changeTextProperty(QStringLiteral("whatsThis"), windowTitle: tr(s: "Edit WhatsThis"), pm: MultiSelectionMode, desiredFormat: Qt::AutoText);
597}
598
599void QDesignerTaskMenu::changeStyleSheet()
600{
601 if (QDesignerFormWindowInterface *fw = formWindow()) {
602 StyleSheetPropertyEditorDialog dlg(fw, fw, d->m_widget);
603 dlg.exec();
604 }
605}
606
607void QDesignerTaskMenu::containerFakeMethods()
608{
609 QDesignerFormWindowInterface *fw = formWindow();
610 if (!fw)
611 return;
612 SignalSlotDialog::editMetaDataBase(fw, object: d->m_widget, parent: fw);
613}
614
615bool QDesignerTaskMenu::isSlotNavigationEnabled(const QDesignerFormEditorInterface *core)
616{
617 return core->integration()->hasFeature(f: QDesignerIntegration::SlotNavigationFeature);
618}
619
620void QDesignerTaskMenu::slotNavigateToSlot()
621{
622 QDesignerFormEditorInterface *core = formWindow()->core();
623 Q_ASSERT(core);
624 navigateToSlot(core, o: widget());
625}
626
627void 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(objectName: objName(core, object),
639 signalSignature: method.signature,
640 parameterNames: 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.
646static 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(object: w, QStringLiteral("minimumSize"), newValue: 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(object: w, QStringLiteral("maximumSize"), newValue: maximumSize);
667 fw->commandHistory()->push(cmd);
668 }
669}
670
671void QDesignerTaskMenu::applySize(QAction *a)
672{
673 QDesignerFormWindowInterface *fw = formWindow();
674 if (!fw)
675 return;
676
677 const QWidgetList selection = applicableWidgets(fw, pm: 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(text: tr(s: "Set size constraint on %n widget(s)", c: nullptr, n: size));
684 for (int i = 0; i < size; i++)
685 createSizeCommand(fw, w: selection.at(i), flags: mask);
686 fw->commandHistory()->endMacro();
687}
688
689template <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 *>(object: 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(widget: 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
710QObjectList QDesignerTaskMenu::applicableObjects(const QDesignerFormWindowInterface *fw, PropertyMode pm) const
711{
712 QObjectList rc;
713 getApplicableObjects(fw, current: d->m_widget, pm, c: &rc);
714 return rc;
715}
716
717QWidgetList QDesignerTaskMenu::applicableWidgets(const QDesignerFormWindowInterface *fw, PropertyMode pm) const
718{
719 QWidgetList rc;
720 getApplicableObjects(fw, current: d->m_widget, pm, c: &rc);
721 return rc;
722}
723
724void QDesignerTaskMenu::setProperty(QDesignerFormWindowInterface *fw, PropertyMode pm, const QString &name, const QVariant &newValue)
725{
726 SetPropertyCommand* setPropertyCommand = new SetPropertyCommand(fw);
727 if (setPropertyCommand->init(list: applicableObjects(fw, pm), propertyName: name, newValue, referenceObject: d->m_widget)) {
728 fw->commandHistory()->push(cmd: setPropertyCommand);
729 } else {
730 delete setPropertyCommand;
731 qDebug() << "Unable to set property " << name << '.';
732 }
733}
734
735void 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(w: d->m_widget, alignment: newAlignment)) {
741 fw->commandHistory()->push(cmd);
742 } else {
743 delete cmd;
744 }
745}
746} // namespace qdesigner_internal
747
748QT_END_NAMESPACE
749

source code of qttools/src/designer/src/lib/shared/qdesigner_taskmenu.cpp