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// components/formeditor
30#include "formwindowmanager.h"
31#include "formwindow_dnditem.h"
32#include "formwindow.h"
33#include "formeditor.h"
34#include "widgetselection.h"
35#include "previewactiongroup.h"
36#include "formwindowsettings.h"
37
38// shared
39#include <widgetdatabase_p.h>
40#include <iconloader_p.h>
41#include <connectionedit_p.h>
42#include <qtresourcemodel_p.h>
43#include <qdesigner_dnditem_p.h>
44#include <qdesigner_command_p.h>
45#include <qdesigner_command2_p.h>
46#include <layoutinfo_p.h>
47#include <qlayout_widget_p.h>
48#include <qdesigner_objectinspector_p.h>
49#include <actioneditor_p.h>
50#include <shared_settings_p.h>
51#include <previewmanager_p.h>
52#include <abstractdialoggui_p.h>
53#include <widgetfactory_p.h>
54#include <spacer_widget_p.h>
55
56// SDK
57#include <QtDesigner/qextensionmanager.h>
58#include <QtDesigner/abstractlanguage.h>
59#include <QtDesigner/container.h>
60#include <QtDesigner/abstractwidgetbox.h>
61#include <QtDesigner/abstractintegration.h>
62
63#include <QtWidgets/qundogroup.h>
64#include <QtWidgets/qaction.h>
65#include <QtWidgets/qsplitter.h>
66#include <QtGui/qevent.h>
67#include <QtWidgets/qapplication.h>
68#include <QtWidgets/qsizegrip.h>
69#if QT_CONFIG(clipboard)
70#include <QtGui/qclipboard.h>
71#endif
72#include <QtWidgets/qmdiarea.h>
73#include <QtWidgets/qmdisubwindow.h>
74#include <QtWidgets/qmessagebox.h>
75
76#include <QtCore/qdebug.h>
77
78QT_BEGIN_NAMESPACE
79
80namespace {
81 enum { debugFWM = 0 };
82}
83
84static inline QString whatsThisFrom(const QString &str) { /// ### implement me!
85 return str;
86}
87
88// find the first child of w in a sequence
89template <class Iterator>
90static inline Iterator findFirstChildOf(Iterator it,Iterator end, const QWidget *w)
91{
92 for (;it != end; ++it) {
93 if (w->isAncestorOf(child: *it))
94 return it;
95 }
96 return it;
97}
98
99namespace qdesigner_internal {
100
101FormWindowManager::FormWindowManager(QDesignerFormEditorInterface *core, QObject *parent) :
102 QDesignerFormWindowManager(parent),
103 m_core(core),
104 m_activeFormWindow(nullptr),
105 m_previewManager(new PreviewManager(PreviewManager::SingleFormNonModalPreview, this)),
106 m_createLayoutContext(LayoutContainer),
107 m_morphLayoutContainer(nullptr),
108 m_actionGroupPreviewInStyle(nullptr),
109 m_actionShowFormWindowSettingsDialog(nullptr)
110{
111 setupActions();
112 qApp->installEventFilter(filterObj: this);
113}
114
115FormWindowManager::~FormWindowManager()
116{
117 qDeleteAll(c: m_formWindows);
118}
119
120QDesignerFormEditorInterface *FormWindowManager::core() const
121{
122 return m_core;
123}
124
125QDesignerFormWindowInterface *FormWindowManager::activeFormWindow() const
126{
127 return m_activeFormWindow;
128}
129
130int FormWindowManager::formWindowCount() const
131{
132 return m_formWindows.size();
133}
134
135QDesignerFormWindowInterface *FormWindowManager::formWindow(int index) const
136{
137 return m_formWindows.at(i: index);
138}
139
140bool FormWindowManager::eventFilter(QObject *o, QEvent *e)
141{
142 if (!o->isWidgetType())
143 return false;
144
145 // If we don't have an active form, we only listen for WindowActivate to speed up integrations
146 const QEvent::Type eventType = e->type();
147 if (m_activeFormWindow == nullptr && eventType != QEvent::WindowActivate)
148 return false;
149
150 switch (eventType) { // Uninteresting events
151 case QEvent::Create:
152 case QEvent::Destroy:
153 case QEvent::ActionAdded:
154 case QEvent::ActionChanged:
155 case QEvent::ActionRemoved:
156 case QEvent::ChildAdded:
157 case QEvent::ChildPolished:
158 case QEvent::ChildRemoved:
159#if QT_CONFIG(clipboard)
160 case QEvent::Clipboard:
161#endif
162 case QEvent::ContentsRectChange:
163 case QEvent::DeferredDelete:
164 case QEvent::FileOpen:
165 case QEvent::LanguageChange:
166 case QEvent::MetaCall:
167 case QEvent::ModifiedChange:
168 case QEvent::Paint:
169 case QEvent::PaletteChange:
170 case QEvent::ParentAboutToChange:
171 case QEvent::ParentChange:
172 case QEvent::Polish:
173 case QEvent::PolishRequest:
174 case QEvent::QueryWhatsThis:
175 case QEvent::StatusTip:
176 case QEvent::StyleChange:
177 case QEvent::Timer:
178 case QEvent::ToolBarChange:
179 case QEvent::ToolTip:
180 case QEvent::WhatsThis:
181 case QEvent::WhatsThisClicked:
182 case QEvent::WinIdChange:
183 case QEvent::DynamicPropertyChange:
184 case QEvent::HoverEnter:
185 case QEvent::HoverLeave:
186 case QEvent::HoverMove:
187 case QEvent::AcceptDropsChange:
188 return false;
189 default:
190 break;
191 }
192
193 QWidget *widget = static_cast<QWidget*>(o);
194
195 if (qobject_cast<WidgetHandle*>(object: widget)) { // ### remove me
196 return false;
197 }
198
199 FormWindow *fw = FormWindow::findFormWindow(w: widget);
200 if (fw == nullptr) {
201 return false;
202 }
203
204 if (QWidget *managedWidget = findManagedWidget(fw, w: widget)) {
205 // Prevent MDI subwindows from being closed by clicking at the title bar
206 if (managedWidget != widget && eventType == QEvent::Close) {
207 e->ignore();
208 return true;
209 }
210 switch (eventType) {
211 case QEvent::LayoutRequest:
212 // QTBUG-61439: Suppress layout request while changing the QGridLayout
213 // span of a QTabWidget, which sends LayoutRequest in resizeEvent().
214 if (fw->handleOperation() == FormWindow::ChangeLayoutSpanHandleOperation) {
215 e->ignore();
216 return true;
217 }
218 break;
219
220 case QEvent::WindowActivate: {
221 if (fw->parentWidget()->isWindow() && fw->isMainContainer(w: managedWidget) && activeFormWindow() != fw) {
222 setActiveFormWindow(fw);
223 }
224 } break;
225
226 case QEvent::WindowDeactivate: {
227 if (o == fw && o == activeFormWindow())
228 fw->repaintSelection();
229 } break;
230
231 case QEvent::KeyPress: {
232 QKeyEvent *ke = static_cast<QKeyEvent*>(e);
233 if (ke->key() == Qt::Key_Escape) {
234 ke->accept();
235 return true;
236 }
237 }
238 Q_FALLTHROUGH(); // don't break...
239
240 // Embedded Design: Drop on different form: Make sure the right form
241 // window/device is active before having the widget created by the factory
242 case QEvent::Drop:
243 if (activeFormWindow() != fw)
244 setActiveFormWindow(fw);
245 Q_FALLTHROUGH(); // don't break...
246 default: {
247 if (fw->handleEvent(widget, managedWidget, event: e)) {
248 return true;
249 }
250 } break;
251
252 } // end switch
253 }
254
255 return false;
256}
257
258void FormWindowManager::addFormWindow(QDesignerFormWindowInterface *w)
259{
260 FormWindow *formWindow = qobject_cast<FormWindow*>(object: w);
261 if (!formWindow || m_formWindows.contains(t: formWindow))
262 return;
263
264 connect(sender: formWindow, signal: &QDesignerFormWindowInterface::selectionChanged,
265 receiver: this, slot: &FormWindowManager::slotUpdateActions);
266 connect(sender: formWindow->commandHistory(), signal: &QUndoStack::indexChanged,
267 receiver: this, slot: &FormWindowManager::slotUpdateActions);
268 connect(sender: formWindow, signal: &QDesignerFormWindowInterface::toolChanged,
269 receiver: this, slot: &FormWindowManager::slotUpdateActions);
270
271 if (ActionEditor *ae = qobject_cast<ActionEditor *>(object: m_core->actionEditor())) {
272 connect(sender: w, signal: &QDesignerFormWindowInterface::mainContainerChanged,
273 receiver: ae, slot: &ActionEditor::mainContainerChanged);
274 }
275 if (QDesignerObjectInspector *oi = qobject_cast<QDesignerObjectInspector *>(object: m_core->objectInspector()))
276 connect(sender: w, signal: &QDesignerFormWindowInterface::mainContainerChanged,
277 receiver: oi, slot: &QDesignerObjectInspector::mainContainerChanged);
278
279 m_formWindows.append(t: formWindow);
280 emit formWindowAdded(formWindow);
281}
282
283void FormWindowManager::removeFormWindow(QDesignerFormWindowInterface *w)
284{
285 FormWindow *formWindow = qobject_cast<FormWindow*>(object: w);
286
287 int idx = m_formWindows.indexOf(t: formWindow);
288 if (!formWindow || idx == -1)
289 return;
290
291 formWindow->disconnect(receiver: this);
292 m_formWindows.removeAt(i: idx);
293 emit formWindowRemoved(formWindow);
294
295 if (formWindow == m_activeFormWindow)
296 setActiveFormWindow(nullptr);
297
298 // Make sure that widget box is enabled by default
299 if (m_formWindows.isEmpty() && m_core->widgetBox())
300 m_core->widgetBox()->setEnabled(true);
301
302}
303
304void FormWindowManager::setActiveFormWindow(QDesignerFormWindowInterface *w)
305{
306 FormWindow *formWindow = qobject_cast<FormWindow*>(object: w);
307
308 if (formWindow == m_activeFormWindow)
309 return;
310
311 FormWindow *old = m_activeFormWindow;
312
313 m_activeFormWindow = formWindow;
314
315 QtResourceSet *resourceSet = nullptr;
316 if (formWindow)
317 resourceSet = formWindow->resourceSet();
318 m_core->resourceModel()->setCurrentResourceSet(resourceSet);
319
320 slotUpdateActions();
321
322 if (m_activeFormWindow) {
323 m_activeFormWindow->repaintSelection();
324 if (old)
325 old->repaintSelection();
326 }
327
328 emit activeFormWindowChanged(formWindow: m_activeFormWindow);
329
330 if (m_activeFormWindow) {
331 m_activeFormWindow->emitSelectionChanged();
332 m_activeFormWindow->commandHistory()->setActive();
333 // Trigger setActiveSubWindow on mdi area unless we are in toplevel mode
334 QMdiSubWindow *mdiSubWindow = nullptr;
335 if (QWidget *formwindow = m_activeFormWindow->parentWidget()) {
336 mdiSubWindow = qobject_cast<QMdiSubWindow *>(object: formwindow->parentWidget());
337 }
338 if (mdiSubWindow) {
339 for (QWidget *parent = mdiSubWindow->parentWidget(); parent; parent = parent->parentWidget()) {
340 if (QMdiArea *mdiArea = qobject_cast<QMdiArea*>(object: parent)) {
341 mdiArea->setActiveSubWindow(mdiSubWindow);
342 break;
343 }
344 }
345 }
346 }
347}
348
349void FormWindowManager::closeAllPreviews()
350{
351 m_previewManager->closeAllPreviews();
352}
353
354QWidget *FormWindowManager::findManagedWidget(FormWindow *fw, QWidget *w)
355{
356 while (w && w != fw) {
357 if (fw->isManaged(w))
358 break;
359 w = w->parentWidget();
360 }
361 return w;
362}
363
364void FormWindowManager::setupActions()
365{
366#if QT_CONFIG(clipboard)
367 const QIcon cutIcon = QIcon::fromTheme(QStringLiteral("edit-cut"), fallback: createIconSet(QStringLiteral("editcut.png")));
368 m_actionCut = new QAction(cutIcon, tr(s: "Cu&t"), this);
369 m_actionCut->setObjectName(QStringLiteral("__qt_cut_action"));
370 m_actionCut->setShortcut(QKeySequence::Cut);
371 m_actionCut->setStatusTip(tr(s: "Cuts the selected widgets and puts them on the clipboard"));
372 m_actionCut->setWhatsThis(whatsThisFrom(QStringLiteral("Edit|Cut")));
373 connect(sender: m_actionCut, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::slotActionCutActivated);
374 m_actionCut->setEnabled(false);
375
376 const QIcon copyIcon = QIcon::fromTheme(QStringLiteral("edit-copy"), fallback: createIconSet(QStringLiteral("editcopy.png")));
377 m_actionCopy = new QAction(copyIcon, tr(s: "&Copy"), this);
378 m_actionCopy->setObjectName(QStringLiteral("__qt_copy_action"));
379 m_actionCopy->setShortcut(QKeySequence::Copy);
380 m_actionCopy->setStatusTip(tr(s: "Copies the selected widgets to the clipboard"));
381 m_actionCopy->setWhatsThis(whatsThisFrom(QStringLiteral("Edit|Copy")));
382 connect(sender: m_actionCopy, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::slotActionCopyActivated);
383 m_actionCopy->setEnabled(false);
384
385 const QIcon pasteIcon = QIcon::fromTheme(QStringLiteral("edit-paste"), fallback: createIconSet(QStringLiteral("editpaste.png")));
386 m_actionPaste = new QAction(pasteIcon, tr(s: "&Paste"), this);
387 m_actionPaste->setObjectName(QStringLiteral("__qt_paste_action"));
388 m_actionPaste->setShortcut(QKeySequence::Paste);
389 m_actionPaste->setStatusTip(tr(s: "Pastes the clipboard's contents"));
390 m_actionPaste->setWhatsThis(whatsThisFrom(QStringLiteral("Edit|Paste")));
391 connect(sender: m_actionPaste, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::slotActionPasteActivated);
392 m_actionPaste->setEnabled(false);
393#endif
394
395 m_actionDelete = new QAction(QIcon::fromTheme(QStringLiteral("edit-delete")), tr(s: "&Delete"), this);
396 m_actionDelete->setObjectName(QStringLiteral("__qt_delete_action"));
397 m_actionDelete->setStatusTip(tr(s: "Deletes the selected widgets"));
398 m_actionDelete->setWhatsThis(whatsThisFrom(QStringLiteral("Edit|Delete")));
399 connect(sender: m_actionDelete, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::slotActionDeleteActivated);
400 m_actionDelete->setEnabled(false);
401
402 m_actionSelectAll = new QAction(tr(s: "Select &All"), this);
403 m_actionSelectAll->setObjectName(QStringLiteral("__qt_select_all_action"));
404 m_actionSelectAll->setShortcut(QKeySequence::SelectAll);
405 m_actionSelectAll->setStatusTip(tr(s: "Selects all widgets"));
406 m_actionSelectAll->setWhatsThis(whatsThisFrom(QStringLiteral("Edit|Select All")));
407 connect(sender: m_actionSelectAll, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::slotActionSelectAllActivated);
408 m_actionSelectAll->setEnabled(false);
409
410 m_actionRaise = new QAction(createIconSet(QStringLiteral("editraise.png")), tr(s: "Bring to &Front"), this);
411 m_actionRaise->setObjectName(QStringLiteral("__qt_raise_action"));
412 m_actionRaise->setShortcut(Qt::CTRL | Qt::Key_L);
413 m_actionRaise->setStatusTip(tr(s: "Raises the selected widgets"));
414 m_actionRaise->setWhatsThis(tr(s: "Raises the selected widgets"));
415 connect(sender: m_actionRaise, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::slotActionRaiseActivated);
416 m_actionRaise->setEnabled(false);
417
418 m_actionLower = new QAction(createIconSet(QStringLiteral("editlower.png")), tr(s: "Send to &Back"), this);
419 m_actionLower->setObjectName(QStringLiteral("__qt_lower_action"));
420 m_actionLower->setShortcut(Qt::CTRL | Qt::Key_K);
421 m_actionLower->setStatusTip(tr(s: "Lowers the selected widgets"));
422 m_actionLower->setWhatsThis(tr(s: "Lowers the selected widgets"));
423 connect(sender: m_actionLower, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::slotActionLowerActivated);
424 m_actionLower->setEnabled(false);
425
426 m_actionAdjustSize = new QAction(createIconSet(QStringLiteral("adjustsize.png")), tr(s: "Adjust &Size"), this);
427 m_actionAdjustSize->setObjectName(QStringLiteral("__qt_adjust_size_action"));
428 m_actionAdjustSize->setShortcut(Qt::CTRL | Qt::Key_J);
429 m_actionAdjustSize->setStatusTip(tr(s: "Adjusts the size of the selected widget"));
430 m_actionAdjustSize->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Adjust Size")));
431 connect(sender: m_actionAdjustSize, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::slotActionAdjustSizeActivated);
432 m_actionAdjustSize->setEnabled(false);
433
434
435 m_actionHorizontalLayout = new QAction(createIconSet(QStringLiteral("edithlayout.png")), tr(s: "Lay Out &Horizontally"), this);
436 m_actionHorizontalLayout->setObjectName(QStringLiteral("__qt_horizontal_layout_action"));
437 m_actionHorizontalLayout->setShortcut(Qt::CTRL | Qt::Key_1);
438 m_actionHorizontalLayout->setStatusTip(tr(s: "Lays out the selected widgets horizontally"));
439 m_actionHorizontalLayout->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Lay Out Horizontally")));
440 m_actionHorizontalLayout->setData(LayoutInfo::HBox);
441 m_actionHorizontalLayout->setEnabled(false);
442 connect(sender: m_actionHorizontalLayout, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::createLayout);
443
444 m_actionVerticalLayout = new QAction(createIconSet(QStringLiteral("editvlayout.png")), tr(s: "Lay Out &Vertically"), this);
445 m_actionVerticalLayout->setObjectName(QStringLiteral("__qt_vertical_layout_action"));
446 m_actionVerticalLayout->setShortcut(Qt::CTRL | Qt::Key_2);
447 m_actionVerticalLayout->setStatusTip(tr(s: "Lays out the selected widgets vertically"));
448 m_actionVerticalLayout->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Lay Out Vertically")));
449 m_actionVerticalLayout->setData(LayoutInfo::VBox);
450 m_actionVerticalLayout->setEnabled(false);
451 connect(sender: m_actionVerticalLayout, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::createLayout);
452
453 QIcon formIcon = QIcon::fromTheme(QStringLiteral("designer-form-layout"), fallback: createIconSet(QStringLiteral("editform.png")));
454 m_actionFormLayout = new QAction(formIcon, tr(s: "Lay Out in a &Form Layout"), this);
455 m_actionFormLayout->setObjectName(QStringLiteral("__qt_form_layout_action"));
456 m_actionFormLayout->setShortcut(Qt::CTRL | Qt::Key_6);
457 m_actionFormLayout->setStatusTip(tr(s: "Lays out the selected widgets in a form layout"));
458 m_actionFormLayout->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Lay Out in a Form")));
459 m_actionFormLayout->setData(LayoutInfo::Form);
460 m_actionFormLayout->setEnabled(false);
461 connect(sender: m_actionFormLayout, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::createLayout);
462
463 m_actionGridLayout = new QAction(createIconSet(QStringLiteral("editgrid.png")), tr(s: "Lay Out in a &Grid"), this);
464 m_actionGridLayout->setObjectName(QStringLiteral("__qt_grid_layout_action"));
465 m_actionGridLayout->setShortcut(Qt::CTRL | Qt::Key_5);
466 m_actionGridLayout->setStatusTip(tr(s: "Lays out the selected widgets in a grid"));
467 m_actionGridLayout->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Lay Out in a Grid")));
468 m_actionGridLayout->setData(LayoutInfo::Grid);
469 m_actionGridLayout->setEnabled(false);
470 connect(sender: m_actionGridLayout, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::createLayout);
471
472 m_actionSplitHorizontal = new QAction(createIconSet(QStringLiteral("edithlayoutsplit.png")),
473 tr(s: "Lay Out Horizontally in S&plitter"), this);
474 m_actionSplitHorizontal->setObjectName(QStringLiteral("__qt_split_horizontal_action"));
475 m_actionSplitHorizontal->setShortcut(Qt::CTRL | Qt::Key_3);
476 m_actionSplitHorizontal->setStatusTip(tr(s: "Lays out the selected widgets horizontally in a splitter"));
477 m_actionSplitHorizontal->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Lay Out Horizontally in Splitter")));
478 m_actionSplitHorizontal->setData(LayoutInfo::HSplitter);
479 m_actionSplitHorizontal->setEnabled(false);
480 connect(sender: m_actionSplitHorizontal, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::createLayout);
481
482 m_actionSplitVertical = new QAction(createIconSet(QStringLiteral("editvlayoutsplit.png")),
483 tr(s: "Lay Out Vertically in Sp&litter"), this);
484 m_actionSplitVertical->setObjectName(QStringLiteral("__qt_split_vertical_action"));
485 m_actionSplitVertical->setShortcut(Qt::CTRL | Qt::Key_4);
486 m_actionSplitVertical->setStatusTip(tr(s: "Lays out the selected widgets vertically in a splitter"));
487 m_actionSplitVertical->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Lay Out Vertically in Splitter")));
488 connect(sender: m_actionSplitVertical, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::createLayout);
489 m_actionSplitVertical->setData(LayoutInfo::VSplitter);
490
491 m_actionSplitVertical->setEnabled(false);
492
493 m_actionBreakLayout = new QAction(createIconSet(QStringLiteral("editbreaklayout.png")), tr(s: "&Break Layout"), this);
494 m_actionBreakLayout->setObjectName(QStringLiteral("__qt_break_layout_action"));
495 m_actionBreakLayout->setShortcut(Qt::CTRL | Qt::Key_0);
496 m_actionBreakLayout->setStatusTip(tr(s: "Breaks the selected layout"));
497 m_actionBreakLayout->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Break Layout")));
498 connect(sender: m_actionBreakLayout, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::slotActionBreakLayoutActivated);
499 m_actionBreakLayout->setEnabled(false);
500
501 m_actionSimplifyLayout = new QAction(tr(s: "Si&mplify Grid Layout"), this);
502 m_actionSimplifyLayout->setObjectName(QStringLiteral("__qt_simplify_layout_action"));
503 m_actionSimplifyLayout->setStatusTip(tr(s: "Removes empty columns and rows"));
504 m_actionSimplifyLayout->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Simplify Layout")));
505 connect(sender: m_actionSimplifyLayout, signal: &QAction::triggered, receiver: this, slot: &FormWindowManager::slotActionSimplifyLayoutActivated);
506 m_actionSimplifyLayout->setEnabled(false);
507
508 m_actionDefaultPreview = new QAction(tr(s: "&Preview..."), this);
509 m_actionDefaultPreview->setObjectName(QStringLiteral("__qt_default_preview_action"));
510 m_actionDefaultPreview->setStatusTip(tr(s: "Preview current form"));
511 m_actionDefaultPreview->setWhatsThis(whatsThisFrom(QStringLiteral("Form|Preview")));
512 connect(sender: m_actionDefaultPreview, signal: &QAction::triggered,
513 receiver: this, slot: &FormWindowManager::showPreview);
514
515 m_undoGroup = new QUndoGroup(this);
516
517 m_actionUndo = m_undoGroup->createUndoAction(parent: this);
518 m_actionUndo->setEnabled(false);
519
520 m_actionUndo->setIcon(QIcon::fromTheme(QStringLiteral("edit-undo"), fallback: createIconSet(QStringLiteral("undo.png"))));
521 m_actionRedo = m_undoGroup->createRedoAction(parent: this);
522 m_actionRedo->setEnabled(false);
523 m_actionRedo->setIcon(QIcon::fromTheme(QStringLiteral("edit-redo"), fallback: createIconSet(QStringLiteral("redo.png"))));
524
525 m_actionShowFormWindowSettingsDialog = new QAction(tr(s: "Form &Settings..."), this);
526 m_actionShowFormWindowSettingsDialog->setObjectName(QStringLiteral("__qt_form_settings_action"));
527 connect(sender: m_actionShowFormWindowSettingsDialog, signal: &QAction::triggered,
528 receiver: this, slot: &FormWindowManager::slotActionShowFormWindowSettingsDialog);
529 m_actionShowFormWindowSettingsDialog->setEnabled(false);
530}
531
532#if QT_CONFIG(clipboard)
533void FormWindowManager::slotActionCutActivated()
534{
535 m_activeFormWindow->cut();
536}
537
538void FormWindowManager::slotActionCopyActivated()
539{
540 m_activeFormWindow->copy();
541 slotUpdateActions();
542}
543
544void FormWindowManager::slotActionPasteActivated()
545{
546 m_activeFormWindow->paste();
547}
548#endif
549
550void FormWindowManager::slotActionDeleteActivated()
551{
552 m_activeFormWindow->deleteWidgets();
553}
554
555void FormWindowManager::slotActionLowerActivated()
556{
557 m_activeFormWindow->lowerWidgets();
558}
559
560void FormWindowManager::slotActionRaiseActivated()
561{
562 m_activeFormWindow->raiseWidgets();
563}
564
565static inline QWidget *findLayoutContainer(const FormWindow *fw)
566{
567 QWidgetList l(fw->selectedWidgets());
568 fw->simplifySelection(sel: &l);
569 return l.isEmpty() ? fw->mainContainer() : l.constFirst();
570}
571
572void FormWindowManager::createLayout()
573{
574 QAction *a = qobject_cast<QAction *>(object: sender());
575 if (!a)
576 return;
577 const int type = a->data().toInt();
578 switch (m_createLayoutContext) {
579 case LayoutContainer:
580 // Cannot create a splitter on a container
581 if (type != LayoutInfo::HSplitter && type != LayoutInfo::VSplitter)
582 m_activeFormWindow->createLayout(type, container: findLayoutContainer(fw: m_activeFormWindow));
583 break;
584 case LayoutSelection:
585 m_activeFormWindow->createLayout(type);
586 break;
587 case MorphLayout:
588 m_activeFormWindow->morphLayout(container: m_morphLayoutContainer, newType: type);
589 break;
590 }
591}
592
593void FormWindowManager::slotActionBreakLayoutActivated()
594{
595 const QWidgetList layouts = layoutsToBeBroken();
596 if (layouts.isEmpty())
597 return;
598
599 if (debugFWM) {
600 qDebug() << "slotActionBreakLayoutActivated: " << layouts.size();
601 for (const QWidget *w : layouts)
602 qDebug() << w;
603 }
604
605 m_activeFormWindow->beginCommand(description: tr(s: "Break Layout"));
606 for (QWidget *layout : layouts)
607 m_activeFormWindow->breakLayout(w: layout);
608 m_activeFormWindow->endCommand();
609}
610
611void FormWindowManager::slotActionSimplifyLayoutActivated()
612{
613 Q_ASSERT(m_activeFormWindow != nullptr);
614 QWidgetList selectedWidgets = m_activeFormWindow->selectedWidgets();
615 m_activeFormWindow->simplifySelection(sel: &selectedWidgets);
616 if (selectedWidgets.size() != 1)
617 return;
618 SimplifyLayoutCommand *cmd = new SimplifyLayoutCommand(m_activeFormWindow);
619 if (cmd->init(layoutBase: selectedWidgets.constFirst())) {
620 m_activeFormWindow->commandHistory()->push(cmd);
621 } else {
622 delete cmd;
623 }
624}
625
626void FormWindowManager::slotActionAdjustSizeActivated()
627{
628 Q_ASSERT(m_activeFormWindow != nullptr);
629
630 m_activeFormWindow->beginCommand(description: tr(s: "Adjust Size"));
631
632 QWidgetList selectedWidgets = m_activeFormWindow->selectedWidgets();
633 m_activeFormWindow->simplifySelection(sel: &selectedWidgets);
634
635 if (selectedWidgets.isEmpty()) {
636 Q_ASSERT(m_activeFormWindow->mainContainer() != nullptr);
637 selectedWidgets.append(t: m_activeFormWindow->mainContainer());
638 }
639
640 // Always count the main container as unlaid-out
641 for (QWidget *widget : qAsConst(t&: selectedWidgets)) {
642 bool unlaidout = LayoutInfo::layoutType(core: core(), w: widget->parentWidget()) == LayoutInfo::NoLayout;
643 bool isMainContainer = m_activeFormWindow->isMainContainer(w: widget);
644
645 if (unlaidout || isMainContainer) {
646 AdjustWidgetSizeCommand *cmd = new AdjustWidgetSizeCommand(m_activeFormWindow);
647 cmd->init(widget);
648 m_activeFormWindow->commandHistory()->push(cmd);
649 }
650 }
651
652 m_activeFormWindow->endCommand();
653}
654
655void FormWindowManager::slotActionSelectAllActivated()
656{
657 m_activeFormWindow->selectAll();
658}
659
660void FormWindowManager::showPreview()
661{
662 slotActionGroupPreviewInStyle(style: QString(), deviceProfileIndex: -1);
663}
664
665void FormWindowManager::slotActionGroupPreviewInStyle(const QString &style, int deviceProfileIndex)
666{
667 QDesignerFormWindowInterface *fw = activeFormWindow();
668 if (!fw)
669 return;
670
671 QString errorMessage;
672 if (!m_previewManager->showPreview(fw, style, deviceProfileIndex, errorMessage: &errorMessage)) {
673 const QString title = tr(s: "Could not create form preview", c: "Title of warning message box");
674 core()->dialogGui()->message(parent: fw, context: QDesignerDialogGuiInterface::FormEditorMessage, icon: QMessageBox::Warning,
675 title, text: errorMessage);
676 }
677}
678
679// The user might click on a layout child or the actual layout container.
680QWidgetList FormWindowManager::layoutsToBeBroken(QWidget *w) const
681{
682 if (!w)
683 return QWidgetList();
684
685 if (debugFWM)
686 qDebug() << "layoutsToBeBroken: " << w;
687
688 QWidget *parent = w->parentWidget();
689 if (m_activeFormWindow->isMainContainer(w))
690 parent = nullptr;
691
692 QWidget *widget = core()->widgetFactory()->containerOfWidget(w);
693
694 // maybe we want to remove following block
695 const QDesignerWidgetDataBaseInterface *db = m_core->widgetDataBase();
696 const QDesignerWidgetDataBaseItemInterface *item = db->item(index: db->indexOfObject(object: widget));
697 if (!item) {
698 if (debugFWM)
699 qDebug() << "layoutsToBeBroken: Don't have an item, recursing for parent";
700 return layoutsToBeBroken(w: parent);
701 }
702
703 const bool layoutContainer = (item->isContainer() || m_activeFormWindow->isMainContainer(w: widget));
704
705 if (!layoutContainer) {
706 if (debugFWM)
707 qDebug() << "layoutsToBeBroken: Not a container, recursing for parent";
708 return layoutsToBeBroken(w: parent);
709 }
710
711 QLayout *widgetLayout = widget->layout();
712 QLayout *managedLayout = LayoutInfo::managedLayout(core: m_core, layout: widgetLayout);
713 if (!managedLayout) {
714 if (qobject_cast<const QSplitter *>(object: widget)) {
715 if (debugFWM)
716 qDebug() << "layoutsToBeBroken: Splitter special";
717 QWidgetList list = layoutsToBeBroken(w: parent);
718 list.append(t: widget);
719 return list;
720 }
721 if (debugFWM)
722 qDebug() << "layoutsToBeBroken: Is a container but doesn't have a managed layout (has an internal layout), returning 0";
723 return QWidgetList();
724 }
725
726 if (managedLayout) {
727 QWidgetList list;
728 if (debugFWM)
729 qDebug() << "layoutsToBeBroken: Is a container and has a layout";
730 if (qobject_cast<const QLayoutWidget *>(object: widget)) {
731 if (debugFWM)
732 qDebug() << "layoutsToBeBroken: red layout special case";
733 list = layoutsToBeBroken(w: parent);
734 }
735 list.append(t: widget);
736 return list;
737 }
738 if (debugFWM)
739 qDebug() << "layoutsToBeBroken: Is a container but doesn't have a layout at all, returning 0";
740 return QWidgetList();
741
742}
743
744QSet<QWidget *> FormWindowManager::getUnsortedLayoutsToBeBroken(bool firstOnly) const
745{
746 // Return a set of layouts to be broken.
747 QSet<QWidget *> layouts;
748
749 QWidgetList selection = m_activeFormWindow->selectedWidgets();
750 if (selection.isEmpty() && m_activeFormWindow->mainContainer())
751 selection.append(t: m_activeFormWindow->mainContainer());
752
753 for (QWidget *selectedWidget : qAsConst(t&: selection)) {
754 // find all layouts
755 const QWidgetList &list = layoutsToBeBroken(w: selectedWidget);
756 if (!list.isEmpty()) {
757 for (QWidget *widget : list)
758 layouts.insert(value: widget);
759 if (firstOnly)
760 return layouts;
761 }
762 }
763 return layouts;
764}
765
766bool FormWindowManager::hasLayoutsToBeBroken() const
767{
768 // Quick check for layouts to be broken
769 return !getUnsortedLayoutsToBeBroken(firstOnly: true).isEmpty();
770}
771
772QWidgetList FormWindowManager::layoutsToBeBroken() const
773{
774 // Get all layouts. This is a list of all 'red' layouts (QLayoutWidgets)
775 // up to the first 'real' widget with a layout in hierarchy order.
776 const QSet<QWidget *> unsortedLayouts = getUnsortedLayoutsToBeBroken(firstOnly: false);
777 // Sort in order of hierarchy
778 QWidgetList orderedLayoutList;
779 for (QWidget *wToBeInserted : unsortedLayouts) {
780 if (!orderedLayoutList.contains(t: wToBeInserted)) {
781 // try to find first child, use as insertion position, else append
782 const QWidgetList::iterator firstChildPos = findFirstChildOf(it: orderedLayoutList.begin(), end: orderedLayoutList.end(), w: wToBeInserted);
783 if (firstChildPos == orderedLayoutList.end()) {
784 orderedLayoutList.push_back(t: wToBeInserted);
785 } else {
786 orderedLayoutList.insert(before: firstChildPos, t: wToBeInserted);
787 }
788 }
789 }
790 return orderedLayoutList;
791}
792
793static inline bool hasManagedLayoutItems(const QDesignerFormEditorInterface *core, QWidget *w)
794{
795 if (const QLayout *ml = LayoutInfo::managedLayout(core, widget: w)) {
796 // Try to find managed items, ignore dummy grid spacers
797 const int count = ml->count();
798 for (int i = 0; i < count; i++)
799 if (!LayoutInfo::isEmptyItem(item: ml->itemAt(index: i)))
800 return true;
801 }
802 return false;
803}
804
805void FormWindowManager::slotUpdateActions()
806{
807 m_createLayoutContext = LayoutSelection;
808 m_morphLayoutContainer = nullptr;
809 bool canMorphIntoVBoxLayout = false;
810 bool canMorphIntoHBoxLayout = false;
811 bool canMorphIntoGridLayout = false;
812 bool canMorphIntoFormLayout = false;
813 int selectedWidgetCount = 0;
814 int laidoutWidgetCount = 0;
815 int unlaidoutWidgetCount = 0;
816#if QT_CONFIG(clipboard)
817 bool pasteAvailable = false;
818#endif
819 bool layoutAvailable = false;
820 bool breakAvailable = false;
821 bool simplifyAvailable = false;
822 bool layoutContainer = false;
823 bool canChangeZOrder = true;
824
825 do {
826 if (m_activeFormWindow == nullptr || m_activeFormWindow->currentTool() != 0)
827 break;
828
829 breakAvailable = hasLayoutsToBeBroken();
830
831 QWidgetList simplifiedSelection = m_activeFormWindow->selectedWidgets();
832
833 selectedWidgetCount = simplifiedSelection.count();
834#if QT_CONFIG(clipboard)
835 pasteAvailable = qApp->clipboard()->mimeData() && qApp->clipboard()->mimeData()->hasText();
836#endif
837
838 m_activeFormWindow->simplifySelection(sel: &simplifiedSelection);
839 QWidget *mainContainer = m_activeFormWindow->mainContainer();
840 if (simplifiedSelection.isEmpty() && mainContainer)
841 simplifiedSelection.append(t: mainContainer);
842
843 // Always count the main container as unlaid-out
844 const QWidgetList::const_iterator cend = simplifiedSelection.constEnd();
845 for (QWidgetList::const_iterator it = simplifiedSelection.constBegin(); it != cend; ++it) {
846 if (*it != mainContainer && LayoutInfo::isWidgetLaidout(core: m_core, widget: *it)) {
847 ++laidoutWidgetCount;
848 } else {
849 ++unlaidoutWidgetCount;
850 }
851 if (qobject_cast<const QLayoutWidget *>(object: *it) || qobject_cast<const Spacer *>(object: *it))
852 canChangeZOrder = false;
853 }
854
855 // Figure out layouts: Looking at a group of dangling widgets
856 if (simplifiedSelection.count() != 1) {
857 layoutAvailable = unlaidoutWidgetCount > 1;
858 //breakAvailable = false;
859 break;
860 }
861 // Manipulate layout of a single widget
862 m_createLayoutContext = LayoutSelection;
863 QWidget *widget = core()->widgetFactory()->containerOfWidget(w: simplifiedSelection.first());
864 if (widget == nullptr) // We are looking at a page-based container with 0 pages
865 break;
866
867 const QDesignerWidgetDataBaseInterface *db = m_core->widgetDataBase();
868 const QDesignerWidgetDataBaseItemInterface *item = db->item(index: db->indexOfObject(object: widget));
869 if (!item)
870 break;
871
872 QLayout *widgetLayout = LayoutInfo::internalLayout(widget);
873 QLayout *managedLayout = LayoutInfo::managedLayout(core: m_core, layout: widgetLayout);
874 // We don't touch a layout created by a custom widget
875 if (widgetLayout && !managedLayout)
876 break;
877
878 layoutContainer = (item->isContainer() || m_activeFormWindow->isMainContainer(w: widget));
879
880 layoutAvailable = layoutContainer && m_activeFormWindow->hasInsertedChildren(w: widget) && managedLayout == nullptr;
881 simplifyAvailable = SimplifyLayoutCommand::canSimplify(core: m_core, w: widget);
882 if (layoutAvailable) {
883 m_createLayoutContext = LayoutContainer;
884 } else {
885 /* Cannot create a layout, have some layouts to be broken and
886 * exactly one, non-empty layout with selected: check the morph layout options
887 * (Note that there might be > 1 layouts to broken if the selection
888 * is a red layout, however, we want the inner-most layout here). */
889 if (breakAvailable && simplifiedSelection.size() == 1
890 && hasManagedLayoutItems(core: m_core, w: widget)) {
891 int type;
892 m_morphLayoutContainer = widget; // Was: page of first selected
893 m_createLayoutContext = MorphLayout;
894 if (MorphLayoutCommand::canMorph(formWindow: m_activeFormWindow, w: m_morphLayoutContainer, ptrToCurrentType: &type)) {
895 canMorphIntoVBoxLayout = type != LayoutInfo::VBox;
896 canMorphIntoHBoxLayout = type != LayoutInfo::HBox;
897 canMorphIntoGridLayout = type != LayoutInfo::Grid;
898 canMorphIntoFormLayout = type != LayoutInfo::Form;
899 }
900 }
901 }
902 } while(false);
903
904#if QT_CONFIG(clipboard)
905 m_actionCut->setEnabled(selectedWidgetCount > 0);
906 m_actionCopy->setEnabled(selectedWidgetCount > 0);
907 m_actionPaste->setEnabled(pasteAvailable);
908#endif
909 m_actionDelete->setEnabled(selectedWidgetCount > 0);
910 m_actionLower->setEnabled(canChangeZOrder && selectedWidgetCount > 0);
911 m_actionRaise->setEnabled(canChangeZOrder && selectedWidgetCount > 0);
912
913
914 m_actionSelectAll->setEnabled(m_activeFormWindow != nullptr);
915
916 m_actionAdjustSize->setEnabled(unlaidoutWidgetCount > 0);
917
918 m_actionHorizontalLayout->setEnabled(layoutAvailable || canMorphIntoHBoxLayout);
919 m_actionVerticalLayout->setEnabled(layoutAvailable || canMorphIntoVBoxLayout);
920 m_actionSplitHorizontal->setEnabled(layoutAvailable && !layoutContainer);
921 m_actionSplitVertical->setEnabled(layoutAvailable && !layoutContainer);
922 m_actionFormLayout->setEnabled(layoutAvailable || canMorphIntoFormLayout);
923 m_actionGridLayout->setEnabled(layoutAvailable || canMorphIntoGridLayout);
924
925 m_actionBreakLayout->setEnabled(breakAvailable);
926 m_actionSimplifyLayout->setEnabled(simplifyAvailable);
927 m_actionShowFormWindowSettingsDialog->setEnabled(m_activeFormWindow != nullptr);
928}
929
930QDesignerFormWindowInterface *FormWindowManager::createFormWindow(QWidget *parentWidget, Qt::WindowFlags flags)
931{
932 FormWindow *formWindow = new FormWindow(qobject_cast<FormEditor*>(object: core()), parentWidget, flags);
933 formWindow->setProperty(name: WidgetFactory::disableStyleCustomPaintingPropertyC, value: QVariant(true));
934 addFormWindow(w: formWindow);
935 return formWindow;
936}
937
938QPixmap FormWindowManager::createPreviewPixmap() const
939{
940 const QDesignerFormWindowInterface *fw = activeFormWindow();
941 if (!fw)
942 return QPixmap();
943 QString errorMessage;
944 const QPixmap pix = m_previewManager->createPreviewPixmap(fw, style: QString(), errorMessage: &errorMessage);
945 if (pix.isNull() && !errorMessage.isEmpty())
946 qWarning(msg: "Preview pixmap creation failed: %s", qPrintable(errorMessage));
947 return pix;
948}
949
950void FormWindowManager::deviceProfilesChanged()
951{
952 if (m_actionGroupPreviewInStyle)
953 m_actionGroupPreviewInStyle->updateDeviceProfiles();
954}
955
956// DnD stuff
957
958void FormWindowManager::dragItems(const QList<QDesignerDnDItemInterface*> &item_list)
959{
960 QDesignerMimeData::execDrag(items: item_list, dragSource: m_core->topLevel());
961}
962
963QUndoGroup *FormWindowManager::undoGroup() const
964{
965 return m_undoGroup;
966}
967
968void FormWindowManager::slotActionShowFormWindowSettingsDialog()
969{
970 QDesignerFormWindowInterface *fw = activeFormWindow();
971 if (!fw)
972 return;
973
974 QDialog *settingsDialog = nullptr;
975 const bool wasDirty = fw->isDirty();
976
977 // Ask the language extension for a dialog. If not, create our own
978 if (QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension*>(manager: m_core->extensionManager(), object: m_core))
979 settingsDialog = lang->createFormWindowSettingsDialog(formWindow: fw, /*parent=*/ parentWidget: nullptr);
980
981 if (!settingsDialog)
982 settingsDialog = new FormWindowSettings(fw);
983
984 QString title = QFileInfo(fw->fileName()).fileName();
985 if (title.isEmpty()) // Grab the title from the outer window if no filename
986 if (const QWidget *window = m_core->integration()->containerWindow(widget: fw))
987 title = window->windowTitle();
988
989 settingsDialog->setWindowTitle(tr(s: "Form Settings - %1").arg(a: title));
990 if (settingsDialog->exec())
991 if (fw->isDirty() != wasDirty)
992 emit formWindowSettingsChanged(fw);
993
994 delete settingsDialog;
995}
996
997QAction *FormWindowManager::action(Action action) const
998{
999 switch (action) {
1000#if QT_CONFIG(clipboard)
1001 case QDesignerFormWindowManagerInterface::CutAction:
1002 return m_actionCut;
1003 case QDesignerFormWindowManagerInterface::CopyAction:
1004 return m_actionCopy;
1005 case QDesignerFormWindowManagerInterface::PasteAction:
1006 return m_actionPaste;
1007#endif
1008 case QDesignerFormWindowManagerInterface::DeleteAction:
1009 return m_actionDelete;
1010 case QDesignerFormWindowManagerInterface::SelectAllAction:
1011 return m_actionSelectAll;
1012 case QDesignerFormWindowManagerInterface::LowerAction:
1013 return m_actionLower;
1014 case QDesignerFormWindowManagerInterface::RaiseAction:
1015 return m_actionRaise;
1016 case QDesignerFormWindowManagerInterface::UndoAction:
1017 return m_actionUndo;
1018 case QDesignerFormWindowManagerInterface::RedoAction:
1019 return m_actionRedo;
1020 case QDesignerFormWindowManagerInterface::HorizontalLayoutAction:
1021 return m_actionHorizontalLayout;
1022 case QDesignerFormWindowManagerInterface::VerticalLayoutAction:
1023 return m_actionVerticalLayout;
1024 case QDesignerFormWindowManagerInterface::SplitHorizontalAction:
1025 return m_actionSplitHorizontal;
1026 case QDesignerFormWindowManagerInterface::SplitVerticalAction:
1027 return m_actionSplitVertical;
1028 case QDesignerFormWindowManagerInterface::GridLayoutAction:
1029 return m_actionGridLayout;
1030 case QDesignerFormWindowManagerInterface::FormLayoutAction:
1031 return m_actionFormLayout;
1032 case QDesignerFormWindowManagerInterface::BreakLayoutAction:
1033 return m_actionBreakLayout;
1034 case QDesignerFormWindowManagerInterface::AdjustSizeAction:
1035 return m_actionAdjustSize;
1036 case QDesignerFormWindowManagerInterface::SimplifyLayoutAction:
1037 return m_actionSimplifyLayout;
1038 case QDesignerFormWindowManagerInterface::DefaultPreviewAction:
1039 return m_actionDefaultPreview;
1040 case QDesignerFormWindowManagerInterface::FormWindowSettingsDialogAction:
1041 return m_actionShowFormWindowSettingsDialog;
1042 }
1043 qWarning(msg: "FormWindowManager::action: Unhanded enumeration value %d", action);
1044 return nullptr;
1045}
1046
1047QActionGroup *FormWindowManager::actionGroup(ActionGroup actionGroup) const
1048{
1049 switch (actionGroup) {
1050 case QDesignerFormWindowManagerInterface::StyledPreviewActionGroup:
1051 if (m_actionGroupPreviewInStyle == nullptr) {
1052 // Wish we could make the 'this' pointer mutable ;-)
1053 QObject *parent = const_cast<FormWindowManager*>(this);
1054 m_actionGroupPreviewInStyle = new PreviewActionGroup(m_core, parent);
1055 connect(sender: m_actionGroupPreviewInStyle, signal: &PreviewActionGroup::preview,
1056 receiver: this, slot: &FormWindowManager::slotActionGroupPreviewInStyle);
1057 }
1058 return m_actionGroupPreviewInStyle;
1059 }
1060 qWarning(msg: "FormWindowManager::actionGroup: Unhanded enumeration value %d", actionGroup);
1061 return nullptr;
1062}
1063
1064}
1065
1066QT_END_NAMESPACE
1067

source code of qttools/src/designer/src/components/formeditor/formwindowmanager.cpp