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