Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdesigner_taskmenu.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3// Qt-Security score:significant reason:default
4
12#include "layout_p.h"
17#include "metadatabase_p.h"
23#include "morphmenu_p.h"
28
29#include <shared_enums_p.h>
30
31#include <QtDesigner/abstractformwindow.h>
32#include <QtDesigner/abstractformwindowcursor.h>
33#include <QtDesigner/propertysheet.h>
34#include <QtDesigner/abstractformeditor.h>
35#include <QtDesigner/abstractlanguage.h>
36#include <QtDesigner/abstractintegration.h>
37#include <QtDesigner/qextensionmanager.h>
38
39#include <QtWidgets/qwidget.h>
40#include <QtWidgets/qmenubar.h>
41#include <QtWidgets/qmainwindow.h>
42#include <QtWidgets/qstatusbar.h>
43#include <QtWidgets/qdialogbuttonbox.h>
44#include <QtWidgets/qboxlayout.h>
45#include <QtWidgets/qpushbutton.h>
46
47#include <QtGui/qaction.h>
48#include <QtGui/qactiongroup.h>
49#include <QtGui/qundostack.h>
50
51#include <QtCore/qdebug.h>
52#include <QtCore/qcoreapplication.h>
53
55
56using namespace Qt::StringLiterals;
57
58static inline QAction *createSeparatorHelper(QObject *parent) {
59 QAction *rc = new QAction(parent);
60 rc->setSeparator(true);
61 return rc;
62}
63
64static QString objName(const QDesignerFormEditorInterface *core, QObject *object) {
66 = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), object);
67 Q_ASSERT(sheet != nullptr);
68
69 const int index = sheet->indexOf(u"objectName"_s);
70 const QVariant v = sheet->property(index);
71 if (v.canConvert<qdesigner_internal::PropertySheetStringValue>())
72 return v.value<qdesigner_internal::PropertySheetStringValue>().value();
73 return v.toString();
74}
75
77
78namespace {
79// --------------- ObjectNameDialog
80class ObjectNameDialog : public QDialog
81{
82 public:
83 ObjectNameDialog(QWidget *parent, const QString &oldName);
84 QString newObjectName() const;
85
86 private:
87 qdesigner_internal::TextPropertyEditor *m_editor;
88};
89
90ObjectNameDialog::ObjectNameDialog(QWidget *parent, const QString &oldName)
91 : QDialog(parent),
92 m_editor( new qdesigner_internal::TextPropertyEditor(this, qdesigner_internal::TextPropertyEditor::EmbeddingNone,
93 qdesigner_internal::ValidationObjectName))
94{
95 setWindowTitle(QCoreApplication::translate("ObjectNameDialog", "Change Object Name"));
96
97 QVBoxLayout *vboxLayout = new QVBoxLayout(this);
98 vboxLayout->addWidget(new QLabel(QCoreApplication::translate("ObjectNameDialog", "Object Name")));
99
100 m_editor->setText(oldName);
101 m_editor->selectAll();
102 m_editor->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
103 vboxLayout->addWidget(m_editor);
104
105 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
106 Qt::Horizontal, this);
107 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
108 okButton->setDefault(true);
109 vboxLayout->addWidget(buttonBox);
110
111 connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
112 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
113}
114
115QString ObjectNameDialog::newObjectName() const
116{
117 return m_editor->text();
118}
119} // namespace
120
121namespace qdesigner_internal {
122
123// Sub menu displaying the alignment options of a widget in a managed
124// grid/box layout cell.
127public:
129
130 QAction *subMenuAction() const { return m_subMenuAction; }
131
132 // Set up enabled state and checked actions according to widget (managed box/grid)
133 bool setAlignment(const QDesignerFormEditorInterface *core, QWidget *w);
134
135 // Return the currently checked alignment
137
138signals:
139 void changed();
140
141private:
142 enum Actions { HorizNone, Left, HorizCenter, Right, VerticalNone, Top, VerticalCenter, Bottom };
143 static QAction *createAction(const QString &text, int data, QMenu *menu, QActionGroup *ag);
144
145 QAction *m_subMenuAction;
146 QActionGroup *m_horizGroup;
147 QActionGroup *m_verticalGroup;
148 QAction *m_actions[Bottom + 1];
149};
150
151QAction *LayoutAlignmentMenu::createAction(const QString &text, int data, QMenu *menu, QActionGroup *ag)
152{
153 QAction * a = new QAction(text, nullptr);
154 a->setCheckable(true);
155 a->setData(QVariant(data));
156 menu->addAction(a);
157 ag->addAction(a);
158 return a;
159}
160
161LayoutAlignmentMenu::LayoutAlignmentMenu(QObject *parent) : QObject(parent),
162 m_subMenuAction(new QAction(QDesignerTaskMenu::tr("Layout Alignment"), parent)),
163 m_horizGroup(new QActionGroup(parent)),
164 m_verticalGroup(new QActionGroup(parent))
165{
166 m_horizGroup->setExclusive(true);
167 m_verticalGroup->setExclusive(true);
168 connect(m_horizGroup, &QActionGroup::triggered, this, &LayoutAlignmentMenu::changed);
169 connect(m_verticalGroup, &QActionGroup::triggered, this, &LayoutAlignmentMenu::changed);
170
171 QMenu *menu = new QMenu;
172 m_subMenuAction->setMenu(menu);
173
174 m_actions[HorizNone] = createAction(QDesignerTaskMenu::tr("No Horizontal Alignment"), 0, menu, m_horizGroup);
175 m_actions[Left] = createAction(QDesignerTaskMenu::tr("Left"), Qt::AlignLeft, menu, m_horizGroup);
176 m_actions[HorizCenter] = createAction(QDesignerTaskMenu::tr("Center Horizontally"), Qt::AlignHCenter, menu, m_horizGroup);
177 m_actions[Right] = createAction(QDesignerTaskMenu::tr("Right"), Qt::AlignRight, menu, m_horizGroup);
178 menu->addSeparator();
179 m_actions[VerticalNone] = createAction(QDesignerTaskMenu::tr("No Vertical Alignment"), 0, menu, m_verticalGroup);
180 m_actions[Top] = createAction(QDesignerTaskMenu::tr("Top"), Qt::AlignTop, menu, m_verticalGroup);
181 m_actions[VerticalCenter] = createAction(QDesignerTaskMenu::tr("Center Vertically"), Qt::AlignVCenter, menu, m_verticalGroup);
182 m_actions[Bottom] = createAction(QDesignerTaskMenu::tr("Bottom"), Qt::AlignBottom, menu, m_verticalGroup);
183}
184
185bool LayoutAlignmentMenu::setAlignment(const QDesignerFormEditorInterface *core, QWidget *w)
186{
187 bool enabled;
188 const Qt::Alignment alignment = LayoutAlignmentCommand::alignmentOf(core, w, &enabled);
189 m_subMenuAction->setEnabled(enabled);
190 if (!enabled) {
191 m_actions[HorizNone]->setChecked(true);
192 m_actions[VerticalNone]->setChecked(true);
193 return false;
194 }
195 // Get alignment
196 switch (alignment & Qt::AlignHorizontal_Mask) {
197 case Qt::AlignLeft:
198 m_actions[Left]->setChecked(true);
199 break;
200 case Qt::AlignHCenter:
201 m_actions[HorizCenter]->setChecked(true);
202 break;
203 case Qt::AlignRight:
204 m_actions[Right]->setChecked(true);
205 break;
206 default:
207 m_actions[HorizNone]->setChecked(true);
208 break;
209 }
210 switch (alignment & Qt::AlignVertical_Mask) {
211 case Qt::AlignTop:
212 m_actions[Top]->setChecked(true);
213 break;
214 case Qt::AlignVCenter:
215 m_actions[VerticalCenter]->setChecked(true);
216 break;
217 case Qt::AlignBottom:
218 m_actions[Bottom]->setChecked(true);
219 break;
220 default:
221 m_actions[VerticalNone]->setChecked(true);
222 break;
223 }
224 return true;
225}
226
228{
229 Qt::Alignment alignment;
230 if (const QAction *horizAction = m_horizGroup->checkedAction())
231 if (const int horizAlign = horizAction->data().toInt())
232 alignment |= static_cast<Qt::Alignment>(horizAlign);
233 if (const QAction *vertAction = m_verticalGroup->checkedAction())
234 if (const int vertAlign = vertAction->data().toInt())
235 alignment |= static_cast<Qt::Alignment>(vertAlign);
236 return alignment;
237}
238
239// -------------- QDesignerTaskMenuPrivate
272
274 m_q(nullptr),
283 m_changeObjectNameAction(new QAction(QDesignerTaskMenu::tr("Change objectName..."), parent)),
284 m_changeToolTip(new QAction(QDesignerTaskMenu::tr("Change toolTip..."), parent)),
285 m_changeWhatsThis(new QAction(QDesignerTaskMenu::tr("Change whatsThis..."), parent)),
286 m_changeStyleSheet(new QAction(QDesignerTaskMenu::tr("Change styleSheet..."), parent)),
289 m_addMenuBar(new QAction(QDesignerTaskMenu::tr("Create Menu Bar"), parent)),
290 m_addToolBar(new QAction(QDesignerTaskMenu::tr("Add Tool Bar"), parent)),
291 m_addAreaSubMenu(new QAction(QDesignerTaskMenu::tr("Add Tool Bar to Other Area"), parent)),
292 m_addStatusBar(new QAction(QDesignerTaskMenu::tr("Create Status Bar"), parent)),
293 m_removeStatusBar(new QAction(QDesignerTaskMenu::tr("Remove Status Bar"), parent)),
294 m_containerFakeMethods(new QAction(QDesignerTaskMenu::tr("Change signals/slots..."), parent)),
295 m_navigateToSlot(new QAction(QDesignerTaskMenu::tr("Go to slot..."), parent)),
299 m_sizeActionsSubMenu(new QAction(QDesignerTaskMenu::tr("Size Constraints"), parent))
300{
301 QMenu *sizeMenu = new QMenu;
302 m_sizeActionsSubMenu->setMenu(sizeMenu);
303 QAction *sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Minimum Width"));
304 sizeAction->setData(ApplyMinimumWidth);
305 sizeMenu->addAction(sizeAction);
306
307 sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Minimum Height"));
308 sizeAction->setData(ApplyMinimumHeight);
309 sizeMenu->addAction(sizeAction);
310
311 sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Minimum Size"));
312 sizeAction->setData(ApplyMinimumWidth|ApplyMinimumHeight);
313 sizeMenu->addAction(sizeAction);
314
315 sizeMenu->addSeparator();
316
317 sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Maximum Width"));
318 sizeAction->setData(ApplyMaximumWidth);
319 sizeMenu->addAction(sizeAction);
320
321 sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Maximum Height"));
322 sizeAction->setData(ApplyMaximumHeight);
323 sizeMenu->addAction(sizeAction);
324
325 sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Maximum Size"));
326 sizeAction->setData(ApplyMaximumWidth|ApplyMaximumHeight);
327 sizeMenu->addAction(sizeAction);
328}
329
330// --------- QDesignerTaskMenu
334{
335 d->m_q = this;
337
344 [this] () { this->addToolBar(Qt::TopToolBarArea); });
345 auto areaMenu = new QMenu;
347 areaMenu->addAction(QDesignerTaskMenu::tr("Left"), this,
348 [this] () { this->addToolBar(Qt::LeftToolBarArea); });
349 areaMenu->addAction(QDesignerTaskMenu::tr("Right"), this,
350 [this] () { this->addToolBar(Qt::RightToolBarArea); });
351 areaMenu->addAction(QDesignerTaskMenu::tr("Bottom"), this,
352 [this] () { this->addToolBar(Qt::BottomToolBarArea); });
360}
361
363{
364 delete d;
365}
366
371
373{
374 return d->m_widget;
375}
376
383
385{
388 if (!mw) {
389 // ### warning message
390 return;
391 }
392
394 cmd->init(mw);
396 }
397}
398
400{
403 if (!mw) {
404 // ### warning message
405 return;
406 }
407
409 cmd->init(mw, area);
411 }
412}
413
415{
418 if (!mw) {
419 // ### warning message
420 return;
421 }
422
424 cmd->init(mw);
426 }
427}
428
430{
433 if (!mw) {
434 // ### warning message
435 return;
436 }
437
441 }
442}
443
445{
448
449 const bool isMainContainer = formWindow->mainContainer() == widget();
450
452
454 if (isMainContainer || mw->centralWidget() == widget()) {
455 if (mw->findChild<QMenuBar *>(QString(), Qt::FindDirectChildrenOnly) == nullptr)
457
460 // ### create the status bar
463 else
465
467 }
468 }
480
484
488 }
489
493 }
494
495 return actions;
496}
497
499{
501 Q_ASSERT(fw != nullptr);
502
503 const QString oldObjectName = objName(fw->core(), widget());
504
506 if (dialog.exec() == QDialog::Accepted) {
511 setProperty(fw, CurrentWidgetMode, u"objectName"_s,
513 }
514 }
515}
516
518{
520 if (!fw)
521 return;
522 Q_ASSERT(d->m_widget->parentWidget() != nullptr);
523
525 const int index = sheet->indexOf(propertyName);
526 if (index == -1) {
527 qDebug() << "** WARNING Invalid property" << propertyName << " passed to changeTextProperty!";
528 return;
529 }
531 const QString oldText = textValue.value();
532 // Pop up respective dialog
533 bool accepted = false;
535 switch (desiredFormat) {
536 case Qt::PlainText: {
538 if (!windowTitle.isEmpty())
543 newText = dlg.text();
544 }
545 break;
546 default: {
548 if (!windowTitle.isEmpty())
554 }
555 break;
556 }
557 // change property
558 if (!accepted || oldText == newText)
559 return;
560
561
564}
565
567{
568 changeTextProperty(u"toolTip"_s, tr("Edit ToolTip"), MultiSelectionMode, Qt::AutoText);
569}
570
572{
573 changeTextProperty(u"whatsThis"_s, tr("Edit WhatsThis"), MultiSelectionMode, Qt::AutoText);
574}
575
577{
580 dlg.exec();
581 }
582}
583
585{
587 if (!fw)
588 return;
590}
591
596
598{
600 Q_ASSERT(core);
602}
603
606 const QString &defaultSignal)
607{
610 if (dialog.exec() != QDialog::Accepted)
611 return;
612 // TODO: Check whether signal is connected to slot
614 if (method.isValid()) {
618 }
619}
620
621// Add a command that takes over the value of the current geometry as
622// minimum/maximum size according to the flags.
623static void createSizeCommand(QDesignerFormWindowInterface *fw, QWidget *w, int flags)
624{
625 const QSize size = w->size();
627 QSize minimumSize = w-> minimumSize();
628 if (flags & ApplyMinimumWidth)
629 minimumSize.setWidth(size.width());
630 if (flags & ApplyMinimumHeight)
631 minimumSize.setHeight(size.height());
632 SetPropertyCommand* cmd = new SetPropertyCommand(fw);
633 cmd->init(w, u"minimumSize"_s, minimumSize);
634 fw->commandHistory()->push(cmd);
635 }
637 QSize maximumSize = w-> maximumSize();
638 if (flags & ApplyMaximumWidth)
639 maximumSize.setWidth(size.width());
640 if (flags & ApplyMaximumHeight)
641 maximumSize.setHeight(size.height());
642 SetPropertyCommand* cmd = new SetPropertyCommand(fw);
643 cmd->init(w, u"maximumSize"_s, maximumSize);
644 fw->commandHistory()->push(cmd);
645 }
646}
647
649{
651 if (!fw)
652 return;
653
655 if (selection.isEmpty())
656 return;
657
658 const int mask = a->data().toInt();
659 fw->commandHistory()->beginMacro(tr("Set size constraint on %n widget(s)", nullptr,
660 int(selection.size())));
661 for (auto *w : selection)
664}
665
666template <class Container>
667 static void getApplicableObjects(const QDesignerFormWindowInterface *fw, QWidget *current,
668 QDesignerTaskMenu::PropertyMode pm, Container *c)
669{
670 // Current is always first
671 c->push_back(current);
672 if (pm == QDesignerTaskMenu::CurrentWidgetMode)
673 return;
674 QDesignerObjectInspector *designerObjectInspector = qobject_cast<QDesignerObjectInspector *>(fw->core()->objectInspector());
675 if (!designerObjectInspector)
676 return; // Ooops, someone plugged an old-style Object Inspector
677 // Add managed or unmanaged selection according to current type, make current first
678 Selection s;
679 designerObjectInspector->getSelection(s);
680 const QWidgetList &source = fw->isManaged(current) ? s.managed : s.unmanaged;
681 for (auto *w : source) {
682 if (w != current) // was first
683 c->append(w);
684 }
685}
686
693
700
711
713{
717 if (cmd->init(d->m_widget, newAlignment)) {
719 } else {
720 delete cmd;
721 }
722}
723} // namespace qdesigner_internal
724
725QT_END_NAMESPACE
726
727#include "qdesigner_taskmenu.moc"
friend class QWidget
Definition qpainter.h:432
bool setAlignment(const QDesignerFormEditorInterface *core, QWidget *w)
QDesignerTaskMenuPrivate(QWidget *widget, QObject *parent)
Combined button and popup list for selecting options.
Auxiliary methods to store/retrieve settings.
static void createSizeCommand(QDesignerFormWindowInterface *fw, QWidget *w, int flags)
static void getApplicableObjects(const QDesignerFormWindowInterface *fw, QWidget *current, QDesignerTaskMenu::PropertyMode pm, Container *c)
static QString objName(const QDesignerFormEditorInterface *core, QObject *object)
static QAction * createSeparatorHelper(QObject *parent)
@ ApplyMaximumWidth
@ ApplyMaximumHeight
@ ApplyMinimumHeight
@ ApplyMinimumWidth