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 
78 QT_BEGIN_NAMESPACE
79 
80 namespace {
81     enum { debugFWM = 0 };
82 }
83 
whatsThisFrom(const QString & str)84 static inline QString whatsThisFrom(const QString &str) { /// ### implement me!
85     return str;
86 }
87 
88 // find the first child of w in a sequence
89 template <class Iterator>
findFirstChildOf(Iterator it,Iterator end,const QWidget * w)90 static inline Iterator findFirstChildOf(Iterator it,Iterator end, const QWidget *w)
91 {
92     for  (;it != end; ++it) {
93         if (w->isAncestorOf(*it))
94             return  it;
95     }
96     return it;
97 }
98 
99 namespace qdesigner_internal {
100 
FormWindowManager(QDesignerFormEditorInterface * core,QObject * parent)101 FormWindowManager::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(this);
113 }
114 
~FormWindowManager()115 FormWindowManager::~FormWindowManager()
116 {
117     qDeleteAll(m_formWindows);
118 }
119 
core() const120 QDesignerFormEditorInterface *FormWindowManager::core() const
121 {
122     return m_core;
123 }
124 
activeFormWindow() const125 QDesignerFormWindowInterface *FormWindowManager::activeFormWindow() const
126 {
127     return m_activeFormWindow;
128 }
129 
formWindowCount() const130 int FormWindowManager::formWindowCount() const
131 {
132     return m_formWindows.size();
133 }
134 
formWindow(int index) const135 QDesignerFormWindowInterface *FormWindowManager::formWindow(int index) const
136 {
137     return m_formWindows.at(index);
138 }
139 
eventFilter(QObject * o,QEvent * e)140 bool 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*>(widget)) { // ### remove me
196         return false;
197     }
198 
199     FormWindow *fw = FormWindow::findFormWindow(widget);
200     if (fw == nullptr) {
201         return false;
202     }
203 
204     if (QWidget *managedWidget = findManagedWidget(fw, 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(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, e)) {
248                 return true;
249             }
250         } break;
251 
252         } // end switch
253     }
254 
255     return false;
256 }
257 
addFormWindow(QDesignerFormWindowInterface * w)258 void FormWindowManager::addFormWindow(QDesignerFormWindowInterface *w)
259 {
260     FormWindow *formWindow = qobject_cast<FormWindow*>(w);
261     if (!formWindow || m_formWindows.contains(formWindow))
262         return;
263 
264     connect(formWindow, &QDesignerFormWindowInterface::selectionChanged,
265             this, &FormWindowManager::slotUpdateActions);
266     connect(formWindow->commandHistory(), &QUndoStack::indexChanged,
267             this, &FormWindowManager::slotUpdateActions);
268     connect(formWindow, &QDesignerFormWindowInterface::toolChanged,
269             this, &FormWindowManager::slotUpdateActions);
270 
271     if (ActionEditor *ae = qobject_cast<ActionEditor *>(m_core->actionEditor())) {
272         connect(w, &QDesignerFormWindowInterface::mainContainerChanged,
273                 ae, &ActionEditor::mainContainerChanged);
274     }
275     if (QDesignerObjectInspector *oi = qobject_cast<QDesignerObjectInspector *>(m_core->objectInspector()))
276         connect(w, &QDesignerFormWindowInterface::mainContainerChanged,
277                 oi, &QDesignerObjectInspector::mainContainerChanged);
278 
279     m_formWindows.append(formWindow);
280     emit formWindowAdded(formWindow);
281 }
282 
removeFormWindow(QDesignerFormWindowInterface * w)283 void FormWindowManager::removeFormWindow(QDesignerFormWindowInterface *w)
284 {
285     FormWindow *formWindow = qobject_cast<FormWindow*>(w);
286 
287     int idx = m_formWindows.indexOf(formWindow);
288     if (!formWindow || idx == -1)
289         return;
290 
291     formWindow->disconnect(this);
292     m_formWindows.removeAt(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 
setActiveFormWindow(QDesignerFormWindowInterface * w)304 void FormWindowManager::setActiveFormWindow(QDesignerFormWindowInterface *w)
305 {
306     FormWindow *formWindow = qobject_cast<FormWindow*>(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(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 *>(formwindow->parentWidget());
337         }
338         if (mdiSubWindow) {
339             for (QWidget *parent = mdiSubWindow->parentWidget(); parent; parent = parent->parentWidget()) {
340                 if (QMdiArea *mdiArea = qobject_cast<QMdiArea*>(parent)) {
341                     mdiArea->setActiveSubWindow(mdiSubWindow);
342                     break;
343                 }
344             }
345         }
346     }
347 }
348 
closeAllPreviews()349 void FormWindowManager::closeAllPreviews()
350 {
351     m_previewManager->closeAllPreviews();
352 }
353 
findManagedWidget(FormWindow * fw,QWidget * w)354 QWidget *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 
setupActions()364 void FormWindowManager::setupActions()
365 {
366 #if QT_CONFIG(clipboard)
367     const QIcon cutIcon = QIcon::fromTheme(QStringLiteral("edit-cut"), createIconSet(QStringLiteral("editcut.png")));
368     m_actionCut = new QAction(cutIcon, tr("Cu&t"), this);
369     m_actionCut->setObjectName(QStringLiteral("__qt_cut_action"));
370     m_actionCut->setShortcut(QKeySequence::Cut);
371     m_actionCut->setStatusTip(tr("Cuts the selected widgets and puts them on the clipboard"));
372     m_actionCut->setWhatsThis(whatsThisFrom(QStringLiteral("Edit|Cut")));
373     connect(m_actionCut, &QAction::triggered, this, &FormWindowManager::slotActionCutActivated);
374     m_actionCut->setEnabled(false);
375 
376     const QIcon copyIcon = QIcon::fromTheme(QStringLiteral("edit-copy"), createIconSet(QStringLiteral("editcopy.png")));
377     m_actionCopy = new QAction(copyIcon, tr("&Copy"), this);
378     m_actionCopy->setObjectName(QStringLiteral("__qt_copy_action"));
379     m_actionCopy->setShortcut(QKeySequence::Copy);
380     m_actionCopy->setStatusTip(tr("Copies the selected widgets to the clipboard"));
381     m_actionCopy->setWhatsThis(whatsThisFrom(QStringLiteral("Edit|Copy")));
382     connect(m_actionCopy, &QAction::triggered, this, &FormWindowManager::slotActionCopyActivated);
383     m_actionCopy->setEnabled(false);
384 
385     const QIcon pasteIcon = QIcon::fromTheme(QStringLiteral("edit-paste"), createIconSet(QStringLiteral("editpaste.png")));
386     m_actionPaste = new QAction(pasteIcon, tr("&Paste"), this);
387     m_actionPaste->setObjectName(QStringLiteral("__qt_paste_action"));
388     m_actionPaste->setShortcut(QKeySequence::Paste);
389     m_actionPaste->setStatusTip(tr("Pastes the clipboard's contents"));
390     m_actionPaste->setWhatsThis(whatsThisFrom(QStringLiteral("Edit|Paste")));
391     connect(m_actionPaste, &QAction::triggered, this, &FormWindowManager::slotActionPasteActivated);
392     m_actionPaste->setEnabled(false);
393 #endif
394 
395     m_actionDelete = new QAction(QIcon::fromTheme(QStringLiteral("edit-delete")), tr("&Delete"), this);
396     m_actionDelete->setObjectName(QStringLiteral("__qt_delete_action"));
397     m_actionDelete->setStatusTip(tr("Deletes the selected widgets"));
398     m_actionDelete->setWhatsThis(whatsThisFrom(QStringLiteral("Edit|Delete")));
399     connect(m_actionDelete, &QAction::triggered, this, &FormWindowManager::slotActionDeleteActivated);
400     m_actionDelete->setEnabled(false);
401 
402     m_actionSelectAll = new QAction(tr("Select &All"), this);
403     m_actionSelectAll->setObjectName(QStringLiteral("__qt_select_all_action"));
404     m_actionSelectAll->setShortcut(QKeySequence::SelectAll);
405     m_actionSelectAll->setStatusTip(tr("Selects all widgets"));
406     m_actionSelectAll->setWhatsThis(whatsThisFrom(QStringLiteral("Edit|Select All")));
407     connect(m_actionSelectAll, &QAction::triggered, this, &FormWindowManager::slotActionSelectAllActivated);
408     m_actionSelectAll->setEnabled(false);
409 
410     m_actionRaise = new QAction(createIconSet(QStringLiteral("editraise.png")), tr("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("Raises the selected widgets"));
414     m_actionRaise->setWhatsThis(tr("Raises the selected widgets"));
415     connect(m_actionRaise, &QAction::triggered, this, &FormWindowManager::slotActionRaiseActivated);
416     m_actionRaise->setEnabled(false);
417 
418     m_actionLower = new QAction(createIconSet(QStringLiteral("editlower.png")), tr("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("Lowers the selected widgets"));
422     m_actionLower->setWhatsThis(tr("Lowers the selected widgets"));
423     connect(m_actionLower, &QAction::triggered, this, &FormWindowManager::slotActionLowerActivated);
424     m_actionLower->setEnabled(false);
425 
426     m_actionAdjustSize = new QAction(createIconSet(QStringLiteral("adjustsize.png")), tr("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("Adjusts the size of the selected widget"));
430     m_actionAdjustSize->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Adjust Size")));
431     connect(m_actionAdjustSize, &QAction::triggered, this, &FormWindowManager::slotActionAdjustSizeActivated);
432     m_actionAdjustSize->setEnabled(false);
433 
434 
435     m_actionHorizontalLayout = new QAction(createIconSet(QStringLiteral("edithlayout.png")), tr("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("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(m_actionHorizontalLayout, &QAction::triggered, this, &FormWindowManager::createLayout);
443 
444     m_actionVerticalLayout = new QAction(createIconSet(QStringLiteral("editvlayout.png")), tr("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("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(m_actionVerticalLayout, &QAction::triggered, this, &FormWindowManager::createLayout);
452 
453     QIcon formIcon = QIcon::fromTheme(QStringLiteral("designer-form-layout"), createIconSet(QStringLiteral("editform.png")));
454     m_actionFormLayout = new QAction(formIcon, tr("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("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(m_actionFormLayout, &QAction::triggered, this, &FormWindowManager::createLayout);
462 
463     m_actionGridLayout = new QAction(createIconSet(QStringLiteral("editgrid.png")), tr("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("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(m_actionGridLayout, &QAction::triggered, this, &FormWindowManager::createLayout);
471 
472     m_actionSplitHorizontal = new QAction(createIconSet(QStringLiteral("edithlayoutsplit.png")),
473                                           tr("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("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(m_actionSplitHorizontal, &QAction::triggered, this, &FormWindowManager::createLayout);
481 
482     m_actionSplitVertical = new QAction(createIconSet(QStringLiteral("editvlayoutsplit.png")),
483                                         tr("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("Lays out the selected widgets vertically in a splitter"));
487     m_actionSplitVertical->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Lay Out Vertically in Splitter")));
488     connect(m_actionSplitVertical, &QAction::triggered, this, &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("&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("Breaks the selected layout"));
497     m_actionBreakLayout->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Break Layout")));
498     connect(m_actionBreakLayout, &QAction::triggered, this, &FormWindowManager::slotActionBreakLayoutActivated);
499     m_actionBreakLayout->setEnabled(false);
500 
501     m_actionSimplifyLayout = new QAction(tr("Si&mplify Grid Layout"), this);
502     m_actionSimplifyLayout->setObjectName(QStringLiteral("__qt_simplify_layout_action"));
503     m_actionSimplifyLayout->setStatusTip(tr("Removes empty columns and rows"));
504     m_actionSimplifyLayout->setWhatsThis(whatsThisFrom(QStringLiteral("Layout|Simplify Layout")));
505     connect(m_actionSimplifyLayout, &QAction::triggered, this, &FormWindowManager::slotActionSimplifyLayoutActivated);
506     m_actionSimplifyLayout->setEnabled(false);
507 
508     m_actionDefaultPreview = new QAction(tr("&Preview..."), this);
509     m_actionDefaultPreview->setObjectName(QStringLiteral("__qt_default_preview_action"));
510     m_actionDefaultPreview->setStatusTip(tr("Preview current form"));
511     m_actionDefaultPreview->setWhatsThis(whatsThisFrom(QStringLiteral("Form|Preview")));
512     connect(m_actionDefaultPreview, &QAction::triggered,
513             this, &FormWindowManager::showPreview);
514 
515     m_undoGroup = new QUndoGroup(this);
516 
517     m_actionUndo = m_undoGroup->createUndoAction(this);
518     m_actionUndo->setEnabled(false);
519 
520     m_actionUndo->setIcon(QIcon::fromTheme(QStringLiteral("edit-undo"), createIconSet(QStringLiteral("undo.png"))));
521     m_actionRedo = m_undoGroup->createRedoAction(this);
522     m_actionRedo->setEnabled(false);
523     m_actionRedo->setIcon(QIcon::fromTheme(QStringLiteral("edit-redo"), createIconSet(QStringLiteral("redo.png"))));
524 
525     m_actionShowFormWindowSettingsDialog = new QAction(tr("Form &Settings..."), this);
526     m_actionShowFormWindowSettingsDialog->setObjectName(QStringLiteral("__qt_form_settings_action"));
527     connect(m_actionShowFormWindowSettingsDialog, &QAction::triggered,
528             this, &FormWindowManager::slotActionShowFormWindowSettingsDialog);
529     m_actionShowFormWindowSettingsDialog->setEnabled(false);
530 }
531 
532 #if QT_CONFIG(clipboard)
slotActionCutActivated()533 void FormWindowManager::slotActionCutActivated()
534 {
535     m_activeFormWindow->cut();
536 }
537 
slotActionCopyActivated()538 void FormWindowManager::slotActionCopyActivated()
539 {
540     m_activeFormWindow->copy();
541     slotUpdateActions();
542 }
543 
slotActionPasteActivated()544 void FormWindowManager::slotActionPasteActivated()
545 {
546     m_activeFormWindow->paste();
547 }
548 #endif
549 
slotActionDeleteActivated()550 void FormWindowManager::slotActionDeleteActivated()
551 {
552     m_activeFormWindow->deleteWidgets();
553 }
554 
slotActionLowerActivated()555 void FormWindowManager::slotActionLowerActivated()
556 {
557     m_activeFormWindow->lowerWidgets();
558 }
559 
slotActionRaiseActivated()560 void FormWindowManager::slotActionRaiseActivated()
561 {
562     m_activeFormWindow->raiseWidgets();
563 }
564 
findLayoutContainer(const FormWindow * fw)565 static inline QWidget *findLayoutContainer(const FormWindow *fw)
566 {
567     QWidgetList l(fw->selectedWidgets());
568     fw->simplifySelection(&l);
569     return l.isEmpty() ? fw->mainContainer() : l.constFirst();
570 }
571 
createLayout()572 void FormWindowManager::createLayout()
573 {
574     QAction *a = qobject_cast<QAction *>(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, findLayoutContainer(m_activeFormWindow));
583         break;
584     case LayoutSelection:
585         m_activeFormWindow->createLayout(type);
586         break;
587     case MorphLayout:
588         m_activeFormWindow->morphLayout(m_morphLayoutContainer, type);
589         break;
590     }
591 }
592 
slotActionBreakLayoutActivated()593 void 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(tr("Break Layout"));
606     for (QWidget *layout : layouts)
607         m_activeFormWindow->breakLayout(layout);
608     m_activeFormWindow->endCommand();
609 }
610 
slotActionSimplifyLayoutActivated()611 void FormWindowManager::slotActionSimplifyLayoutActivated()
612 {
613     Q_ASSERT(m_activeFormWindow != nullptr);
614     QWidgetList selectedWidgets = m_activeFormWindow->selectedWidgets();
615     m_activeFormWindow->simplifySelection(&selectedWidgets);
616     if (selectedWidgets.size() != 1)
617         return;
618     SimplifyLayoutCommand *cmd = new SimplifyLayoutCommand(m_activeFormWindow);
619     if (cmd->init(selectedWidgets.constFirst())) {
620         m_activeFormWindow->commandHistory()->push(cmd);
621     } else {
622         delete cmd;
623     }
624 }
625 
slotActionAdjustSizeActivated()626 void FormWindowManager::slotActionAdjustSizeActivated()
627 {
628     Q_ASSERT(m_activeFormWindow != nullptr);
629 
630     m_activeFormWindow->beginCommand(tr("Adjust Size"));
631 
632     QWidgetList selectedWidgets = m_activeFormWindow->selectedWidgets();
633     m_activeFormWindow->simplifySelection(&selectedWidgets);
634 
635     if (selectedWidgets.isEmpty()) {
636         Q_ASSERT(m_activeFormWindow->mainContainer() != nullptr);
637         selectedWidgets.append(m_activeFormWindow->mainContainer());
638     }
639 
640     // Always count the main container as unlaid-out
641     for (QWidget *widget : qAsConst(selectedWidgets)) {
642         bool unlaidout = LayoutInfo::layoutType(core(), widget->parentWidget()) == LayoutInfo::NoLayout;
643         bool isMainContainer = m_activeFormWindow->isMainContainer(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 
slotActionSelectAllActivated()655 void FormWindowManager::slotActionSelectAllActivated()
656 {
657     m_activeFormWindow->selectAll();
658 }
659 
showPreview()660 void FormWindowManager::showPreview()
661 {
662     slotActionGroupPreviewInStyle(QString(), -1);
663 }
664 
slotActionGroupPreviewInStyle(const QString & style,int deviceProfileIndex)665 void 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)) {
673         const QString title = tr("Could not create form preview", "Title of warning message box");
674         core()->dialogGui()->message(fw, QDesignerDialogGuiInterface::FormEditorMessage, QMessageBox::Warning,
675                                      title, errorMessage);
676     }
677 }
678 
679 // The user might click on a layout child or the actual layout container.
layoutsToBeBroken(QWidget * w) const680 QWidgetList 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(db->indexOfObject(widget));
697     if (!item) {
698         if (debugFWM)
699             qDebug() << "layoutsToBeBroken: Don't have an item, recursing for parent";
700         return layoutsToBeBroken(parent);
701     }
702 
703     const bool layoutContainer = (item->isContainer() || m_activeFormWindow->isMainContainer(widget));
704 
705     if (!layoutContainer) {
706         if (debugFWM)
707             qDebug() << "layoutsToBeBroken: Not a container, recursing for parent";
708         return layoutsToBeBroken(parent);
709     }
710 
711     QLayout *widgetLayout = widget->layout();
712     QLayout *managedLayout = LayoutInfo::managedLayout(m_core, widgetLayout);
713     if (!managedLayout) {
714         if (qobject_cast<const QSplitter *>(widget)) {
715             if (debugFWM)
716                 qDebug() << "layoutsToBeBroken: Splitter special";
717             QWidgetList list = layoutsToBeBroken(parent);
718             list.append(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 *>(widget)) {
731             if (debugFWM)
732                 qDebug() << "layoutsToBeBroken: red layout special case";
733             list = layoutsToBeBroken(parent);
734         }
735         list.append(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 
getUnsortedLayoutsToBeBroken(bool firstOnly) const744 QSet<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(m_activeFormWindow->mainContainer());
752 
753     for (QWidget *selectedWidget : qAsConst(selection)) {
754         // find all layouts
755         const QWidgetList &list = layoutsToBeBroken(selectedWidget);
756         if (!list.isEmpty()) {
757             for (QWidget *widget : list)
758                 layouts.insert(widget);
759             if (firstOnly)
760                 return layouts;
761         }
762     }
763     return layouts;
764 }
765 
hasLayoutsToBeBroken() const766 bool FormWindowManager::hasLayoutsToBeBroken() const
767 {
768     // Quick check for layouts to be broken
769     return !getUnsortedLayoutsToBeBroken(true).isEmpty();
770 }
771 
layoutsToBeBroken() const772 QWidgetList 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(false);
777     // Sort in order of hierarchy
778     QWidgetList orderedLayoutList;
779     for (QWidget *wToBeInserted : unsortedLayouts) {
780         if (!orderedLayoutList.contains(wToBeInserted)) {
781             // try to find first child, use as insertion position, else append
782             const QWidgetList::iterator firstChildPos = findFirstChildOf(orderedLayoutList.begin(), orderedLayoutList.end(), wToBeInserted);
783             if (firstChildPos == orderedLayoutList.end()) {
784                 orderedLayoutList.push_back(wToBeInserted);
785             } else {
786                 orderedLayoutList.insert(firstChildPos, wToBeInserted);
787             }
788         }
789     }
790     return orderedLayoutList;
791 }
792 
hasManagedLayoutItems(const QDesignerFormEditorInterface * core,QWidget * w)793 static inline bool hasManagedLayoutItems(const QDesignerFormEditorInterface *core, QWidget *w)
794 {
795     if (const QLayout *ml = LayoutInfo::managedLayout(core, 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(ml->itemAt(i)))
800                 return true;
801     }
802     return false;
803 }
804 
slotUpdateActions()805 void 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(&simplifiedSelection);
839         QWidget *mainContainer = m_activeFormWindow->mainContainer();
840         if (simplifiedSelection.isEmpty() && mainContainer)
841             simplifiedSelection.append(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(m_core, *it)) {
847                 ++laidoutWidgetCount;
848             } else {
849                 ++unlaidoutWidgetCount;
850             }
851             if (qobject_cast<const QLayoutWidget *>(*it) || qobject_cast<const Spacer *>(*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(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(db->indexOfObject(widget));
869         if (!item)
870             break;
871 
872         QLayout *widgetLayout = LayoutInfo::internalLayout(widget);
873         QLayout *managedLayout = LayoutInfo::managedLayout(m_core, 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(widget));
879 
880         layoutAvailable = layoutContainer && m_activeFormWindow->hasInsertedChildren(widget) && managedLayout == nullptr;
881         simplifyAvailable = SimplifyLayoutCommand::canSimplify(m_core, 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(m_core, widget)) {
891                 int type;
892                 m_morphLayoutContainer = widget; // Was: page of first selected
893                 m_createLayoutContext = MorphLayout;
894                 if (MorphLayoutCommand::canMorph(m_activeFormWindow, m_morphLayoutContainer, &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 
createFormWindow(QWidget * parentWidget,Qt::WindowFlags flags)930 QDesignerFormWindowInterface *FormWindowManager::createFormWindow(QWidget *parentWidget, Qt::WindowFlags flags)
931 {
932     FormWindow *formWindow = new FormWindow(qobject_cast<FormEditor*>(core()), parentWidget, flags);
933     formWindow->setProperty(WidgetFactory::disableStyleCustomPaintingPropertyC, QVariant(true));
934     addFormWindow(formWindow);
935     return formWindow;
936 }
937 
createPreviewPixmap() const938 QPixmap 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, QString(), &errorMessage);
945     if (pix.isNull() && !errorMessage.isEmpty())
946         qWarning("Preview pixmap creation failed: %s", qPrintable(errorMessage));
947     return pix;
948 }
949 
deviceProfilesChanged()950 void FormWindowManager::deviceProfilesChanged()
951 {
952     if (m_actionGroupPreviewInStyle)
953         m_actionGroupPreviewInStyle->updateDeviceProfiles();
954 }
955 
956 // DnD stuff
957 
dragItems(const QList<QDesignerDnDItemInterface * > & item_list)958 void FormWindowManager::dragItems(const QList<QDesignerDnDItemInterface*> &item_list)
959 {
960     QDesignerMimeData::execDrag(item_list, m_core->topLevel());
961 }
962 
undoGroup() const963 QUndoGroup *FormWindowManager::undoGroup() const
964 {
965     return m_undoGroup;
966 }
967 
slotActionShowFormWindowSettingsDialog()968 void 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*>(m_core->extensionManager(), m_core))
979         settingsDialog = lang->createFormWindowSettingsDialog(fw, /*parent=*/ 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(fw))
987             title = window->windowTitle();
988 
989     settingsDialog->setWindowTitle(tr("Form Settings - %1").arg(title));
990     if (settingsDialog->exec())
991         if (fw->isDirty() != wasDirty)
992             emit formWindowSettingsChanged(fw);
993 
994     delete settingsDialog;
995 }
996 
action(Action action) const997 QAction *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("FormWindowManager::action: Unhanded enumeration value %d", action);
1044     return nullptr;
1045 }
1046 
actionGroup(ActionGroup actionGroup) const1047 QActionGroup *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(m_actionGroupPreviewInStyle, &PreviewActionGroup::preview,
1056                     this, &FormWindowManager::slotActionGroupPreviewInStyle);
1057         }
1058         return m_actionGroupPreviewInStyle;
1059     }
1060     qWarning("FormWindowManager::actionGroup: Unhanded enumeration value %d", actionGroup);
1061     return nullptr;
1062 }
1063 
1064 }
1065 
1066 QT_END_NAMESPACE
1067