1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Designer of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "qdesigner_command_p.h"
30#include "qdesigner_propertycommand_p.h"
31#include "qdesigner_utils_p.h"
32#include "layout_p.h"
33#include "qlayout_widget_p.h"
34#include "qdesigner_widget_p.h"
35#include "qdesigner_menu_p.h"
36#include "shared_enums_p.h"
37#include "metadatabase_p.h"
38#include "formwindowbase_p.h"
39#include <abstractformbuilder.h>
40
41#include <QtDesigner/abstractformwindow.h>
42#include <QtDesigner/abstractformeditor.h>
43#include <QtDesigner/propertysheet.h>
44#include <QtDesigner/abstractactioneditor.h>
45#include <QtDesigner/abstractpropertyeditor.h>
46#include <QtDesigner/qextensionmanager.h>
47#include <QtDesigner/container.h>
48#include <QtDesigner/layoutdecoration.h>
49#include <QtDesigner/abstractwidgetfactory.h>
50#include <QtDesigner/abstractobjectinspector.h>
51#include <QtDesigner/abstractintegration.h>
52#include <QtDesigner/abstractformwindowcursor.h>
53#include <QtCore/qdebug.h>
54#include <QtCore/qtextstream.h>
55#include <QtCore/qqueue.h>
56
57#include <QtWidgets/qmenubar.h>
58#include <QtWidgets/qstatusbar.h>
59#include <QtWidgets/qtoolbar.h>
60#include <QtWidgets/qtoolbox.h>
61#include <QtWidgets/qstackedwidget.h>
62#include <QtWidgets/qtabwidget.h>
63#include <QtWidgets/qtablewidget.h>
64#include <QtWidgets/qtreewidget.h>
65#include <QtWidgets/qlistwidget.h>
66#include <QtWidgets/qcombobox.h>
67#include <QtWidgets/qsplitter.h>
68#include <QtWidgets/qdockwidget.h>
69#include <QtWidgets/qmainwindow.h>
70#include <QtWidgets/qwizard.h>
71#include <QtWidgets/qapplication.h>
72#include <QtWidgets/qformlayout.h>
73
74Q_DECLARE_METATYPE(QWidgetList)
75
76QT_BEGIN_NAMESPACE
77
78static inline void setPropertySheetWindowTitle(const QDesignerFormEditorInterface *core, QObject *o, const QString &t)
79{
80 if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(manager: core->extensionManager(), object: o)) {
81 const int idx = sheet->indexOf(QStringLiteral("windowTitle"));
82 if (idx != -1) {
83 sheet->setProperty(index: idx, value: t);
84 sheet->setChanged(index: idx, changed: true);
85 }
86 }
87}
88
89namespace qdesigner_internal {
90
91// Helpers for the dynamic properties that store Z/Widget order
92static const char *widgetOrderPropertyC = "_q_widgetOrder";
93static const char *zOrderPropertyC = "_q_zOrder";
94
95static void addToWidgetListDynamicProperty(QWidget *parentWidget, QWidget *widget, const char *name, int index = -1)
96{
97 QWidgetList list = qvariant_cast<QWidgetList>(v: parentWidget->property(name));
98 list.removeAll(t: widget);
99 if (index >= 0 && index < list.size()) {
100 list.insert(i: index, t: widget);
101 } else {
102 list.append(t: widget);
103 }
104 parentWidget->setProperty(name, value: QVariant::fromValue(value: list));
105}
106
107static int removeFromWidgetListDynamicProperty(QWidget *parentWidget, QWidget *widget, const char *name)
108{
109 QWidgetList list = qvariant_cast<QWidgetList>(v: parentWidget->property(name));
110 const int firstIndex = list.indexOf(t: widget);
111 if (firstIndex != -1) {
112 list.removeAll(t: widget);
113 parentWidget->setProperty(name, value: QVariant::fromValue(value: list));
114 }
115 return firstIndex;
116}
117
118// ---- InsertWidgetCommand ----
119InsertWidgetCommand::InsertWidgetCommand(QDesignerFormWindowInterface *formWindow) :
120 QDesignerFormWindowCommand(QString(), formWindow),
121 m_insertMode(QDesignerLayoutDecorationExtension::InsertWidgetMode),
122 m_layoutHelper(nullptr),
123 m_widgetWasManaged(false)
124{
125}
126
127InsertWidgetCommand::~InsertWidgetCommand()
128{
129 delete m_layoutHelper;
130}
131
132void InsertWidgetCommand::init(QWidget *widget, bool already_in_form, int layoutRow, int layoutColumn)
133{
134 m_widget = widget;
135
136 setText(QApplication::translate(context: "Command", key: "Insert '%1'").arg(a: widget->objectName()));
137
138 QWidget *parentWidget = m_widget->parentWidget();
139 QDesignerFormEditorInterface *core = formWindow()->core();
140 QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(manager: core->extensionManager(), object: parentWidget);
141
142 m_insertMode = deco ? deco->currentInsertMode() : QDesignerLayoutDecorationExtension::InsertWidgetMode;
143 if (layoutRow >= 0 && layoutColumn >= 0) {
144 m_cell.first = layoutRow;
145 m_cell.second = layoutColumn;
146 } else {
147 m_cell = deco ? deco->currentCell() : qMakePair(x: 0, y: 0);
148 }
149 m_widgetWasManaged = already_in_form;
150}
151
152static void recursiveUpdate(QWidget *w)
153{
154 w->update();
155
156 const QObjectList &l = w->children();
157 const QObjectList::const_iterator cend = l.end();
158 for ( QObjectList::const_iterator it = l.begin(); it != cend; ++it) {
159 if (QWidget *w = qobject_cast<QWidget*>(o: *it))
160 recursiveUpdate(w);
161 }
162}
163
164void InsertWidgetCommand::redo()
165{
166 QWidget *parentWidget = m_widget->parentWidget();
167 Q_ASSERT(parentWidget);
168
169 addToWidgetListDynamicProperty(parentWidget, widget: m_widget, name: widgetOrderPropertyC);
170 addToWidgetListDynamicProperty(parentWidget, widget: m_widget, name: zOrderPropertyC);
171
172 QDesignerFormEditorInterface *core = formWindow()->core();
173 QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(manager: core->extensionManager(), object: parentWidget);
174
175 if (deco != nullptr) {
176 const LayoutInfo::Type type = LayoutInfo::layoutType(core, layout: LayoutInfo::managedLayout(core, widget: parentWidget));
177 m_layoutHelper = LayoutHelper::createLayoutHelper(type);
178 m_layoutHelper->pushState(core, widgetWithManagedLayout: parentWidget);
179 if (type == LayoutInfo::Grid) {
180 switch (m_insertMode) {
181 case QDesignerLayoutDecorationExtension::InsertRowMode: {
182 deco->insertRow(row: m_cell.first);
183 } break;
184
185 case QDesignerLayoutDecorationExtension::InsertColumnMode: {
186 deco->insertColumn(column: m_cell.second);
187 } break;
188
189 default: break;
190 } // end switch
191 }
192 deco->insertWidget(widget: m_widget, cell: m_cell);
193 }
194
195 if (!m_widgetWasManaged)
196 formWindow()->manageWidget(widget: m_widget);
197 m_widget->show();
198 formWindow()->emitSelectionChanged();
199
200 if (parentWidget && parentWidget->layout()) {
201 recursiveUpdate(w: parentWidget);
202 parentWidget->layout()->invalidate();
203 }
204
205 refreshBuddyLabels();
206}
207
208void InsertWidgetCommand::undo()
209{
210 QWidget *parentWidget = m_widget->parentWidget();
211
212 QDesignerFormEditorInterface *core = formWindow()->core();
213 QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(manager: core->extensionManager(), object: parentWidget);
214
215 if (deco) {
216 deco->removeWidget(widget: m_widget);
217 m_layoutHelper->popState(core, widgetWithManagedLayout: parentWidget);
218 }
219
220 if (!m_widgetWasManaged) {
221 formWindow()->unmanageWidget(widget: m_widget);
222 m_widget->hide();
223 }
224
225 removeFromWidgetListDynamicProperty(parentWidget, widget: m_widget, name: widgetOrderPropertyC);
226 removeFromWidgetListDynamicProperty(parentWidget, widget: m_widget, name: zOrderPropertyC);
227
228 formWindow()->emitSelectionChanged();
229
230 refreshBuddyLabels();
231}
232
233void InsertWidgetCommand::refreshBuddyLabels()
234{
235 const auto label_list = formWindow()->findChildren<QLabel*>();
236 if (label_list.isEmpty())
237 return;
238
239 const QString buddyProperty = QStringLiteral("buddy");
240 const QByteArray objectNameU8 = m_widget->objectName().toUtf8();
241 // Re-set the buddy (The sheet locates the object by name and sets it)
242 for (QLabel *label : label_list) {
243 if (QDesignerPropertySheetExtension* sheet = propertySheet(object: label)) {
244 const int idx = sheet->indexOf(name: buddyProperty);
245 if (idx != -1) {
246 const QVariant value = sheet->property(index: idx);
247 if (value.toByteArray() == objectNameU8)
248 sheet->setProperty(index: idx, value);
249 }
250 }
251 }
252}
253
254// ---- ChangeZOrderCommand ----
255ChangeZOrderCommand::ChangeZOrderCommand(QDesignerFormWindowInterface *formWindow)
256 : QDesignerFormWindowCommand(QString(), formWindow)
257{
258}
259
260void ChangeZOrderCommand::init(QWidget *widget)
261{
262 Q_ASSERT(widget);
263
264 m_widget = widget;
265
266 setText(QApplication::translate(context: "Command", key: "Change Z-order of '%1'").arg(a: widget->objectName()));
267
268 m_oldParentZOrder = qvariant_cast<QWidgetList>(v: widget->parentWidget()->property(name: "_q_zOrder"));
269 const int index = m_oldParentZOrder.indexOf(t: m_widget);
270 if (index != -1 && index + 1 < m_oldParentZOrder.count())
271 m_oldPreceding = m_oldParentZOrder.at(i: index + 1);
272}
273
274void ChangeZOrderCommand::redo()
275{
276 m_widget->parentWidget()->setProperty(name: "_q_zOrder", value: QVariant::fromValue(value: reorderWidget(list: m_oldParentZOrder, widget: m_widget)));
277
278 reorder(widget: m_widget);
279}
280
281void ChangeZOrderCommand::undo()
282{
283 m_widget->parentWidget()->setProperty(name: "_q_zOrder", value: QVariant::fromValue(value: m_oldParentZOrder));
284
285 if (m_oldPreceding)
286 m_widget->stackUnder(m_oldPreceding);
287 else
288 m_widget->raise();
289}
290
291// ---- RaiseWidgetCommand ----
292RaiseWidgetCommand::RaiseWidgetCommand(QDesignerFormWindowInterface *formWindow)
293 : ChangeZOrderCommand(formWindow)
294{
295}
296
297void RaiseWidgetCommand::init(QWidget *widget)
298{
299 ChangeZOrderCommand::init(widget);
300 setText(QApplication::translate(context: "Command", key: "Raise '%1'").arg(a: widget->objectName()));
301}
302
303QWidgetList RaiseWidgetCommand::reorderWidget(const QWidgetList &list, QWidget *widget) const
304{
305 QWidgetList l = list;
306 l.removeAll(t: widget);
307 l.append(t: widget);
308 return l;
309}
310
311void RaiseWidgetCommand::reorder(QWidget *widget) const
312{
313 widget->raise();
314}
315
316// ---- LowerWidgetCommand ----
317LowerWidgetCommand::LowerWidgetCommand(QDesignerFormWindowInterface *formWindow)
318 : ChangeZOrderCommand(formWindow)
319{
320}
321
322QWidgetList LowerWidgetCommand::reorderWidget(const QWidgetList &list, QWidget *widget) const
323{
324 QWidgetList l = list;
325 l.removeAll(t: widget);
326 l.prepend(t: widget);
327 return l;
328}
329
330void LowerWidgetCommand::init(QWidget *widget)
331{
332 ChangeZOrderCommand::init(widget);
333 setText(QApplication::translate(context: "Command", key: "Lower '%1'").arg(a: widget->objectName()));
334}
335
336void LowerWidgetCommand::reorder(QWidget *widget) const
337{
338 widget->lower();
339}
340
341// ---- ManageWidgetCommandHelper
342ManageWidgetCommandHelper::ManageWidgetCommandHelper() = default;
343
344void ManageWidgetCommandHelper::init(const QDesignerFormWindowInterface *fw, QWidget *widget)
345{
346 m_widget = widget;
347 m_managedChildren.clear();
348
349 const QWidgetList children = m_widget->findChildren<QWidget *>();
350 if (children.isEmpty())
351 return;
352
353 m_managedChildren.reserve(asize: children.size());
354 const QWidgetList::const_iterator lcend = children.constEnd();
355 for (QWidgetList::const_iterator it = children.constBegin(); it != lcend; ++it)
356 if (fw->isManaged(widget: *it))
357 m_managedChildren.push_back(t: *it);
358}
359
360void ManageWidgetCommandHelper::init(QWidget *widget, const WidgetVector &managedChildren)
361{
362 m_widget = widget;
363 m_managedChildren = managedChildren;
364}
365
366void ManageWidgetCommandHelper::manage(QDesignerFormWindowInterface *fw)
367{
368 // Manage the managed children after parent
369 fw->manageWidget(widget: m_widget);
370 if (!m_managedChildren.isEmpty()) {
371 const WidgetVector::const_iterator lcend = m_managedChildren.constEnd();
372 for (WidgetVector::const_iterator it = m_managedChildren.constBegin(); it != lcend; ++it)
373 fw->manageWidget(widget: *it);
374 }
375}
376
377void ManageWidgetCommandHelper::unmanage(QDesignerFormWindowInterface *fw)
378{
379 // Unmanage the managed children first
380 if (!m_managedChildren.isEmpty()) {
381 const WidgetVector::const_iterator lcend = m_managedChildren.constEnd();
382 for (WidgetVector::const_iterator it = m_managedChildren.constBegin(); it != lcend; ++it)
383 fw->unmanageWidget(widget: *it);
384 }
385 fw->unmanageWidget(widget: m_widget);
386}
387
388// ---- DeleteWidgetCommand ----
389DeleteWidgetCommand::DeleteWidgetCommand(QDesignerFormWindowInterface *formWindow) :
390 QDesignerFormWindowCommand(QString(), formWindow),
391 m_layoutType(LayoutInfo::NoLayout),
392 m_layoutHelper(nullptr),
393 m_flags(0),
394 m_splitterIndex(-1),
395 m_layoutSimplified(false),
396 m_formItem(nullptr),
397 m_tabOrderIndex(-1),
398 m_widgetOrderIndex(-1),
399 m_zOrderIndex(-1)
400{
401}
402
403DeleteWidgetCommand::~DeleteWidgetCommand()
404{
405 delete m_layoutHelper;
406}
407
408void DeleteWidgetCommand::init(QWidget *widget, unsigned flags)
409{
410 m_widget = widget;
411 m_parentWidget = widget->parentWidget();
412 m_geometry = widget->geometry();
413 m_flags = flags;
414 m_layoutType = LayoutInfo::NoLayout;
415 m_splitterIndex = -1;
416 bool isManaged; // Check for a managed layout
417 QLayout *layout;
418 m_layoutType = LayoutInfo::laidoutWidgetType(core: formWindow()->core(), widget: m_widget, isManaged: &isManaged, layout: &layout);
419 if (!isManaged)
420 m_layoutType = LayoutInfo::NoLayout;
421 switch (m_layoutType) {
422 case LayoutInfo::HSplitter:
423 case LayoutInfo::VSplitter: {
424 QSplitter *splitter = qobject_cast<QSplitter *>(object: m_parentWidget);
425 Q_ASSERT(splitter);
426 m_splitterIndex = splitter->indexOf(w: widget);
427 }
428 break;
429 case LayoutInfo::NoLayout:
430 break;
431 default:
432 m_layoutHelper = LayoutHelper::createLayoutHelper(type: m_layoutType);
433 m_layoutPosition = m_layoutHelper->itemInfo(lt: layout, widget: m_widget);
434 break;
435 }
436
437 m_formItem = formWindow()->core()->metaDataBase()->item(object: formWindow());
438 m_tabOrderIndex = m_formItem->tabOrder().indexOf(t: widget);
439
440 // Build the list of managed children
441 m_manageHelper.init(fw: formWindow(), widget: m_widget);
442
443 setText(QApplication::translate(context: "Command", key: "Delete '%1'").arg(a: widget->objectName()));
444}
445
446void DeleteWidgetCommand::redo()
447{
448 formWindow()->clearSelection();
449 QDesignerFormEditorInterface *core = formWindow()->core();
450
451 if (QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(manager: core->extensionManager(), object: m_parentWidget)) {
452 const int count = c->count();
453 for (int i=0; i<count; ++i) {
454 if (c->widget(index: i) == m_widget) {
455 c->remove(index: i);
456 return;
457 }
458 }
459 }
460
461 m_widgetOrderIndex = removeFromWidgetListDynamicProperty(parentWidget: m_parentWidget, widget: m_widget, name: widgetOrderPropertyC);
462 m_zOrderIndex = removeFromWidgetListDynamicProperty(parentWidget: m_parentWidget, widget: m_widget, name: zOrderPropertyC);
463
464 if (QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(manager: core->extensionManager(), object: m_parentWidget))
465 deco->removeWidget(widget: m_widget);
466
467 if (m_layoutHelper)
468 switch (m_layoutType) {
469 case LayoutInfo::NoLayout:
470 case LayoutInfo::HSplitter:
471 case LayoutInfo::VSplitter:
472 break;
473 default:
474 // Attempt to simplify grids if a row/column becomes empty
475 m_layoutSimplified = (m_flags & DoNotSimplifyLayout) ? false : m_layoutHelper->canSimplify(core, widgetWithManagedLayout: m_parentWidget, restrictionArea: m_layoutPosition);
476 if (m_layoutSimplified) {
477 m_layoutHelper->pushState(core, widgetWithManagedLayout: m_parentWidget);
478 m_layoutHelper->simplify(core, widgetWithManagedLayout: m_parentWidget, restrictionArea: m_layoutPosition);
479 }
480 break;
481 }
482
483 if (!(m_flags & DoNotUnmanage))
484 m_manageHelper.unmanage(fw: formWindow());
485
486 m_widget->setParent(formWindow());
487 m_widget->hide();
488
489 if (m_tabOrderIndex != -1) {
490 QWidgetList tab_order = m_formItem->tabOrder();
491 tab_order.removeAt(i: m_tabOrderIndex);
492 m_formItem->setTabOrder(tab_order);
493 }
494}
495
496void DeleteWidgetCommand::undo()
497{
498 QDesignerFormEditorInterface *core = formWindow()->core();
499 formWindow()->clearSelection();
500
501 m_widget->setParent(m_parentWidget);
502
503 if (QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(manager: core->extensionManager(), object: m_parentWidget)) {
504 c->addWidget(widget: m_widget);
505 return;
506 }
507
508 addToWidgetListDynamicProperty(parentWidget: m_parentWidget, widget: m_widget, name: widgetOrderPropertyC, index: m_widgetOrderIndex);
509 addToWidgetListDynamicProperty(parentWidget: m_parentWidget, widget: m_widget, name: zOrderPropertyC, index: m_zOrderIndex);
510
511 m_widget->setGeometry(m_geometry);
512
513 if (!(m_flags & DoNotUnmanage))
514 m_manageHelper.manage(fw: formWindow());
515 // ### set up alignment
516 switch (m_layoutType) {
517 case LayoutInfo::NoLayout:
518 break;
519 case LayoutInfo::HSplitter:
520 case LayoutInfo::VSplitter: {
521 QSplitter *splitter = qobject_cast<QSplitter *>(object: m_widget->parent());
522 Q_ASSERT(splitter);
523 splitter->insertWidget(index: m_splitterIndex, widget: m_widget);
524 } break;
525 default: {
526 Q_ASSERT(m_layoutHelper);
527 if (m_layoutSimplified)
528 m_layoutHelper->popState(core, widgetWithManagedLayout: m_parentWidget);
529 QLayout *layout = LayoutInfo::managedLayout(core, widget: m_parentWidget);
530 Q_ASSERT(m_layoutType == LayoutInfo::layoutType(core, layout));
531 m_layoutHelper->insertWidget(lt: layout, info: m_layoutPosition, w: m_widget);
532 }
533 break;
534 }
535
536 m_widget->show();
537
538 if (m_tabOrderIndex != -1) {
539 QWidgetList tab_order = m_formItem->tabOrder();
540 tab_order.insert(i: m_tabOrderIndex, t: m_widget);
541 m_formItem->setTabOrder(tab_order);
542 }
543}
544
545// ---- ReparentWidgetCommand ----
546ReparentWidgetCommand::ReparentWidgetCommand(QDesignerFormWindowInterface *formWindow)
547 : QDesignerFormWindowCommand(QString(), formWindow)
548{
549}
550
551void ReparentWidgetCommand::init(QWidget *widget, QWidget *parentWidget)
552{
553 Q_ASSERT(widget);
554
555 m_widget = widget;
556 m_oldParentWidget = widget->parentWidget();
557 m_newParentWidget = parentWidget;
558
559 m_oldPos = m_widget->pos();
560 m_newPos = m_newParentWidget->mapFromGlobal(m_oldParentWidget->mapToGlobal(m_oldPos));
561
562 setText(QApplication::translate(context: "Command", key: "Reparent '%1'").arg(a: widget->objectName()));
563
564 m_oldParentList = qvariant_cast<QWidgetList>(v: m_oldParentWidget->property(name: "_q_widgetOrder"));
565 m_oldParentZOrder = qvariant_cast<QWidgetList>(v: m_oldParentWidget->property(name: "_q_zOrder"));
566}
567
568void ReparentWidgetCommand::redo()
569{
570 m_widget->setParent(m_newParentWidget);
571 m_widget->move(m_newPos);
572
573 QWidgetList oldList = m_oldParentList;
574 oldList.removeAll(t: m_widget);
575 m_oldParentWidget->setProperty(name: "_q_widgetOrder", value: QVariant::fromValue(value: oldList));
576
577 QWidgetList newList = qvariant_cast<QWidgetList>(v: m_newParentWidget->property(name: "_q_widgetOrder"));
578 newList.append(t: m_widget);
579 m_newParentWidget->setProperty(name: "_q_widgetOrder", value: QVariant::fromValue(value: newList));
580
581 QWidgetList oldZOrder = m_oldParentZOrder;
582 oldZOrder.removeAll(t: m_widget);
583 m_oldParentWidget->setProperty(name: "_q_zOrder", value: QVariant::fromValue(value: oldZOrder));
584
585 QWidgetList newZOrder = qvariant_cast<QWidgetList>(v: m_newParentWidget->property(name: "_q_zOrder"));
586 newZOrder.append(t: m_widget);
587 m_newParentWidget->setProperty(name: "_q_zOrder", value: QVariant::fromValue(value: newZOrder));
588
589 m_widget->show();
590 core()->objectInspector()->setFormWindow(formWindow());
591}
592
593void ReparentWidgetCommand::undo()
594{
595 m_widget->setParent(m_oldParentWidget);
596 m_widget->move(m_oldPos);
597
598 m_oldParentWidget->setProperty(name: "_q_widgetOrder", value: QVariant::fromValue(value: m_oldParentList));
599
600 QWidgetList newList = qvariant_cast<QWidgetList>(v: m_newParentWidget->property(name: "_q_widgetOrder"));
601 newList.removeAll(t: m_widget);
602 m_newParentWidget->setProperty(name: "_q_widgetOrder", value: QVariant::fromValue(value: newList));
603
604 m_oldParentWidget->setProperty(name: "_q_zOrder", value: QVariant::fromValue(value: m_oldParentZOrder));
605
606 QWidgetList newZOrder = qvariant_cast<QWidgetList>(v: m_newParentWidget->property(name: "_q_zOrder"));
607 newZOrder.removeAll(t: m_widget);
608 m_newParentWidget->setProperty(name: "_q_zOrder", value: QVariant::fromValue(value: newZOrder));
609
610 m_widget->show();
611 core()->objectInspector()->setFormWindow(formWindow());
612}
613
614PromoteToCustomWidgetCommand::PromoteToCustomWidgetCommand
615 (QDesignerFormWindowInterface *formWindow)
616 : QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Promote to custom widget"), formWindow)
617{
618}
619
620void PromoteToCustomWidgetCommand::init(const WidgetPointerList &widgets,const QString &customClassName)
621{
622 m_widgets = widgets;
623 m_customClassName = customClassName;
624}
625
626void PromoteToCustomWidgetCommand::redo()
627{
628 for (QWidget *w : qAsConst(t&: m_widgets)) {
629 if (w)
630 promoteWidget(core: core(), widget: w, customClassName: m_customClassName);
631 }
632 updateSelection();
633}
634
635void PromoteToCustomWidgetCommand::updateSelection()
636{
637 // Update class names in ObjectInspector, PropertyEditor
638 QDesignerFormWindowInterface *fw = formWindow();
639 QDesignerFormEditorInterface *core = fw->core();
640 core->objectInspector()->setFormWindow(fw);
641 if (QObject *o = core->propertyEditor()->object())
642 core->propertyEditor()->setObject(o);
643}
644
645void PromoteToCustomWidgetCommand::undo()
646{
647 for (QWidget *w : qAsConst(t&: m_widgets)) {
648 if (w)
649 demoteWidget(core: core(), widget: w);
650 }
651 updateSelection();
652}
653
654// ---- DemoteFromCustomWidgetCommand ----
655
656DemoteFromCustomWidgetCommand::DemoteFromCustomWidgetCommand
657 (QDesignerFormWindowInterface *formWindow) :
658 QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Demote from custom widget"), formWindow),
659 m_promote_cmd(formWindow)
660{
661}
662
663void DemoteFromCustomWidgetCommand::init(const WidgetList &promoted)
664{
665 m_promote_cmd.init(widgets: promoted, customClassName: promotedCustomClassName(core: core(), w: promoted.constFirst()));
666}
667
668void DemoteFromCustomWidgetCommand::redo()
669{
670 m_promote_cmd.undo();
671}
672
673void DemoteFromCustomWidgetCommand::undo()
674{
675 m_promote_cmd.redo();
676}
677
678// ---------- CursorSelectionState
679CursorSelectionState::CursorSelectionState() = default;
680
681void CursorSelectionState::save(const QDesignerFormWindowInterface *formWindow)
682{
683 const QDesignerFormWindowCursorInterface *cursor = formWindow->cursor();
684 m_selection.clear();
685 m_current = cursor->current();
686 if (cursor->hasSelection()) {
687 const int count = cursor->selectedWidgetCount();
688 for(int i = 0; i < count; i++)
689 m_selection.push_back(t: cursor->selectedWidget(index: i));
690 }
691}
692
693void CursorSelectionState::restore(QDesignerFormWindowInterface *formWindow) const
694{
695 if (m_selection.isEmpty()) {
696 formWindow->clearSelection(changePropertyDisplay: true);
697 } else {
698 // Select current as last
699 formWindow->clearSelection(changePropertyDisplay: false);
700 const WidgetPointerList::const_iterator cend = m_selection.constEnd();
701 for (WidgetPointerList::const_iterator it = m_selection.constBegin(); it != cend; ++it)
702 if (QWidget *w = *it)
703 if (w != m_current)
704 formWindow->selectWidget(w: *it, select: true);
705 if (m_current)
706 formWindow->selectWidget(w: m_current, select: true);
707 }
708}
709
710// ---- LayoutCommand ----
711
712LayoutCommand::LayoutCommand(QDesignerFormWindowInterface *formWindow) :
713 QDesignerFormWindowCommand(QString(), formWindow),
714 m_setup(false)
715{
716}
717
718LayoutCommand::~LayoutCommand()
719{
720 delete m_layout;
721}
722
723void LayoutCommand::init(QWidget *parentWidget, const QWidgetList &widgets,
724 LayoutInfo::Type layoutType, QWidget *layoutBase,
725 bool reparentLayoutWidget)
726{
727 m_parentWidget = parentWidget;
728 m_widgets = widgets;
729 formWindow()->simplifySelection(widgets: &m_widgets);
730 m_layout = Layout::createLayout(widgets, parentWidget, fw: formWindow(), layoutBase, layoutType);
731 m_layout->setReparentLayoutWidget(reparentLayoutWidget);
732
733 switch (layoutType) {
734 case LayoutInfo::Grid:
735 setText(QApplication::translate(context: "Command", key: "Lay out using grid"));
736 break;
737 case LayoutInfo::VBox:
738 setText(QApplication::translate(context: "Command", key: "Lay out vertically"));
739 break;
740 case LayoutInfo::HBox:
741 setText(QApplication::translate(context: "Command", key: "Lay out horizontally"));
742 break;
743 default:
744 break;
745 }
746 // Delayed setup to avoid confusion in case we are chained
747 // with a BreakLayout in a morph layout macro
748 m_setup = false;
749}
750
751void LayoutCommand::redo()
752{
753 if (!m_setup) {
754 m_layout->setup();
755 m_cursorSelectionState.save(formWindow: formWindow());
756 m_setup = true;
757 }
758 m_layout->doLayout();
759 core()->objectInspector()->setFormWindow(formWindow());
760}
761
762void LayoutCommand::undo()
763{
764 QDesignerFormEditorInterface *core = formWindow()->core();
765
766 QWidget *lb = m_layout->layoutBaseWidget();
767 QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(manager: core->extensionManager(), object: lb);
768 m_layout->undoLayout();
769 delete deco; // release the extension
770
771 // ### generalize (put in function)
772 if (!m_layoutBase && lb != nullptr && !(qobject_cast<QLayoutWidget*>(object: lb) || qobject_cast<QSplitter*>(object: lb))) {
773 core->metaDataBase()->add(object: lb);
774 lb->show();
775 }
776 m_cursorSelectionState.restore(formWindow: formWindow());
777 core->objectInspector()->setFormWindow(formWindow());
778}
779
780// ---- BreakLayoutCommand ----
781BreakLayoutCommand::BreakLayoutCommand(QDesignerFormWindowInterface *formWindow) :
782 QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Break layout"), formWindow),
783 m_layoutHelper(nullptr),
784 m_properties(nullptr),
785 m_propertyMask(0)
786{
787}
788
789BreakLayoutCommand::~BreakLayoutCommand()
790{
791 delete m_layoutHelper;
792 delete m_layout;
793 delete m_properties;
794}
795
796const LayoutProperties *BreakLayoutCommand::layoutProperties() const
797{
798 return m_properties;
799}
800
801int BreakLayoutCommand::propertyMask() const
802{
803 return m_propertyMask;
804}
805
806void BreakLayoutCommand::init(const QWidgetList &widgets, QWidget *layoutBase, bool reparentLayoutWidget)
807{
808 enum Type { SplitterLayout, LayoutHasMarginSpacing, LayoutHasState };
809
810 const QDesignerFormEditorInterface *core = formWindow()->core();
811 m_widgets = widgets;
812 m_layoutBase = core->widgetFactory()->containerOfWidget(w: layoutBase);
813 QLayout *layoutToBeBroken;
814 const LayoutInfo::Type layoutType = LayoutInfo::managedLayoutType(core, w: m_layoutBase, layout: &layoutToBeBroken);
815 m_layout = Layout::createLayout(widgets, parentWidget: m_layoutBase, fw: formWindow(), layoutBase, layoutType);
816 m_layout->setReparentLayoutWidget(reparentLayoutWidget);
817
818 Type type = LayoutHasState;
819 switch (layoutType) {
820 case LayoutInfo::NoLayout:
821 case LayoutInfo::HSplitter:
822 case LayoutInfo::VSplitter:
823 type = SplitterLayout;
824 break;
825 case LayoutInfo::HBox:
826 case LayoutInfo::VBox: // Margin/spacing need to be saved
827 type = LayoutHasMarginSpacing;
828 break;
829 default: // Margin/spacing need to be saved + has a state (empty rows/columns of a grid)
830 type = LayoutHasState;
831 break;
832 }
833 Q_ASSERT(m_layout != nullptr);
834 m_layout->sort();
835
836
837 if (type >= LayoutHasMarginSpacing) {
838 m_properties = new LayoutProperties;
839 m_propertyMask = m_properties->fromPropertySheet(core, l: layoutToBeBroken, mask: LayoutProperties::AllProperties);
840 }
841 if (type >= LayoutHasState)
842 m_layoutHelper = LayoutHelper::createLayoutHelper(type: layoutType);
843 m_cursorSelectionState.save(formWindow: formWindow());
844}
845
846void BreakLayoutCommand::redo()
847{
848 if (!m_layout)
849 return;
850
851 QDesignerFormEditorInterface *core = formWindow()->core();
852 QWidget *lb = m_layout->layoutBaseWidget();
853 QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(manager: core->extensionManager(), object: lb);
854 formWindow()->clearSelection(changePropertyDisplay: false);
855 if (m_layoutHelper)
856 m_layoutHelper->pushState(core, widgetWithManagedLayout: m_layoutBase);
857 m_layout->breakLayout();
858 delete deco; // release the extension
859
860 for (QWidget *widget : qAsConst(t&: m_widgets)) {
861 widget->resize(widget->size().expandedTo(otherSize: QSize(16, 16)));
862 }
863 // Update unless we are in an intermediate state of morphing layout
864 // in which a QLayoutWidget will have no layout at all.
865 if (m_layout->reparentLayoutWidget())
866 core->objectInspector()->setFormWindow(formWindow());
867}
868
869void BreakLayoutCommand::undo()
870{
871 if (!m_layout)
872 return;
873
874 formWindow()->clearSelection(changePropertyDisplay: false);
875 m_layout->doLayout();
876 if (m_layoutHelper)
877 m_layoutHelper->popState(core: formWindow()->core(), widgetWithManagedLayout: m_layoutBase);
878
879 QLayout *layoutToRestored = LayoutInfo::managedLayout(core: formWindow()->core(), widget: m_layoutBase);
880 if (m_properties && m_layoutBase && layoutToRestored)
881 m_properties->toPropertySheet(core: formWindow()->core(), l: layoutToRestored, mask: m_propertyMask);
882 m_cursorSelectionState.restore(formWindow: formWindow());
883 core()->objectInspector()->setFormWindow(formWindow());
884}
885// ---- SimplifyLayoutCommand
886SimplifyLayoutCommand::SimplifyLayoutCommand(QDesignerFormWindowInterface *formWindow) :
887 QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Simplify Grid Layout"), formWindow),
888 m_area(0, 0, 32767, 32767),
889 m_layoutBase(nullptr),
890 m_layoutHelper(nullptr),
891 m_layoutSimplified(false)
892{
893}
894
895SimplifyLayoutCommand::~SimplifyLayoutCommand()
896{
897 delete m_layoutHelper;
898}
899
900bool SimplifyLayoutCommand::canSimplify(QDesignerFormEditorInterface *core, const QWidget *w, int *layoutType)
901{
902 if (!w)
903 return false;
904 QLayout *layout;
905 const LayoutInfo::Type type = LayoutInfo::managedLayoutType(core, w, layout: &layout);
906 if (layoutType)
907 *layoutType = type;
908 if (!layout)
909 return false;
910 switch (type) { // Known negatives
911 case LayoutInfo::NoLayout:
912 case LayoutInfo::UnknownLayout:
913 case LayoutInfo::HSplitter:
914 case LayoutInfo::VSplitter:
915 case LayoutInfo::HBox:
916 case LayoutInfo::VBox:
917 return false;
918 default:
919 break;
920 }
921 switch (type) {
922 case LayoutInfo::Grid:
923 return QLayoutSupport::canSimplifyQuickCheck(qobject_cast<QGridLayout*>(object: layout));
924 case LayoutInfo::Form:
925 return QLayoutSupport::canSimplifyQuickCheck(fl: qobject_cast<const QFormLayout*>(object: layout));
926 default:
927 break;
928 }
929 return false;
930}
931
932bool SimplifyLayoutCommand::init(QWidget *layoutBase)
933{
934 QDesignerFormEditorInterface *core = formWindow()->core();
935 m_layoutSimplified = false;
936 int type;
937 if (canSimplify(core, w: layoutBase, layoutType: &type)) {
938 m_layoutBase = layoutBase;
939 m_layoutHelper = LayoutHelper::createLayoutHelper(type);
940 m_layoutSimplified = m_layoutHelper->canSimplify(core, widgetWithManagedLayout: layoutBase, restrictionArea: m_area);
941 }
942 return m_layoutSimplified;
943}
944
945void SimplifyLayoutCommand::redo()
946{
947 const QDesignerFormEditorInterface *core = formWindow()->core();
948 if (m_layoutSimplified) {
949 m_layoutHelper->pushState(core, widgetWithManagedLayout: m_layoutBase);
950 m_layoutHelper->simplify(core, widgetWithManagedLayout: m_layoutBase, restrictionArea: m_area);
951 }
952}
953void SimplifyLayoutCommand::undo()
954{
955 if (m_layoutSimplified)
956 m_layoutHelper->popState(core: formWindow()->core(), widgetWithManagedLayout: m_layoutBase);
957}
958
959// ---- ToolBoxCommand ----
960ToolBoxCommand::ToolBoxCommand(QDesignerFormWindowInterface *formWindow) :
961 QDesignerFormWindowCommand(QString(), formWindow),
962 m_index(-1)
963{
964}
965
966ToolBoxCommand::~ToolBoxCommand() = default;
967
968void ToolBoxCommand::init(QToolBox *toolBox)
969{
970 m_toolBox = toolBox;
971 m_index = m_toolBox->currentIndex();
972 m_widget = m_toolBox->widget(index: m_index);
973 m_itemText = m_toolBox->itemText(index: m_index);
974 m_itemIcon = m_toolBox->itemIcon(index: m_index);
975}
976
977void ToolBoxCommand::removePage()
978{
979 m_toolBox->removeItem(index: m_index);
980
981 m_widget->hide();
982 m_widget->setParent(formWindow());
983 formWindow()->clearSelection();
984 formWindow()->selectWidget(w: m_toolBox, select: true);
985
986}
987
988void ToolBoxCommand::addPage()
989{
990 m_widget->setParent(m_toolBox);
991 m_toolBox->insertItem(index: m_index, widget: m_widget, icon: m_itemIcon, text: m_itemText);
992 m_toolBox->setCurrentIndex(m_index);
993
994 QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(manager: formWindow()->core()->extensionManager(), object: m_toolBox);
995 if (sheet) {
996 qdesigner_internal::PropertySheetStringValue itemText(m_itemText);
997 sheet->setProperty(index: sheet->indexOf(QStringLiteral("currentItemText")), value: QVariant::fromValue(value: itemText));
998 }
999
1000 m_widget->show();
1001 formWindow()->clearSelection();
1002 formWindow()->selectWidget(w: m_toolBox, select: true);
1003}
1004
1005// ---- MoveToolBoxPageCommand ----
1006MoveToolBoxPageCommand::MoveToolBoxPageCommand(QDesignerFormWindowInterface *formWindow) :
1007 ToolBoxCommand(formWindow),
1008 m_newIndex(-1),
1009 m_oldIndex(-1)
1010{
1011}
1012
1013MoveToolBoxPageCommand::~MoveToolBoxPageCommand() = default;
1014
1015void MoveToolBoxPageCommand::init(QToolBox *toolBox, QWidget *page, int newIndex)
1016{
1017 ToolBoxCommand::init(toolBox);
1018 setText(QApplication::translate(context: "Command", key: "Move Page"));
1019
1020 m_widget = page;
1021 m_oldIndex = m_toolBox->indexOf(widget: m_widget);
1022 m_itemText = m_toolBox->itemText(index: m_oldIndex);
1023 m_itemIcon = m_toolBox->itemIcon(index: m_oldIndex);
1024 m_newIndex = newIndex;
1025}
1026
1027void MoveToolBoxPageCommand::redo()
1028{
1029 m_toolBox->removeItem(index: m_oldIndex);
1030 m_toolBox->insertItem(index: m_newIndex, widget: m_widget, icon: m_itemIcon, text: m_itemText);
1031}
1032
1033void MoveToolBoxPageCommand::undo()
1034{
1035 m_toolBox->removeItem(index: m_newIndex);
1036 m_toolBox->insertItem(index: m_oldIndex, widget: m_widget, icon: m_itemIcon, text: m_itemText);
1037}
1038
1039// ---- DeleteToolBoxPageCommand ----
1040DeleteToolBoxPageCommand::DeleteToolBoxPageCommand(QDesignerFormWindowInterface *formWindow)
1041 : ToolBoxCommand(formWindow)
1042{
1043}
1044
1045DeleteToolBoxPageCommand::~DeleteToolBoxPageCommand() = default;
1046
1047void DeleteToolBoxPageCommand::init(QToolBox *toolBox)
1048{
1049 ToolBoxCommand::init(toolBox);
1050 setText(QApplication::translate(context: "Command", key: "Delete Page"));
1051}
1052
1053void DeleteToolBoxPageCommand::redo()
1054{
1055 removePage();
1056 cheapUpdate();
1057}
1058
1059void DeleteToolBoxPageCommand::undo()
1060{
1061 addPage();
1062 cheapUpdate();
1063}
1064
1065// ---- AddToolBoxPageCommand ----
1066AddToolBoxPageCommand::AddToolBoxPageCommand(QDesignerFormWindowInterface *formWindow)
1067 : ToolBoxCommand(formWindow)
1068{
1069}
1070
1071AddToolBoxPageCommand::~AddToolBoxPageCommand() = default;
1072
1073void AddToolBoxPageCommand::init(QToolBox *toolBox)
1074{
1075 init(toolBox, mode: InsertBefore);
1076}
1077
1078void AddToolBoxPageCommand::init(QToolBox *toolBox, InsertionMode mode)
1079{
1080 m_toolBox = toolBox;
1081
1082 m_index = m_toolBox->currentIndex();
1083 if (mode == InsertAfter)
1084 m_index++;
1085 m_widget = new QDesignerWidget(formWindow(), m_toolBox);
1086 m_itemText = QApplication::translate(context: "Command", key: "Page");
1087 m_itemIcon = QIcon();
1088 m_widget->setObjectName(QStringLiteral("page"));
1089 formWindow()->ensureUniqueObjectName(object: m_widget);
1090
1091 setText(QApplication::translate(context: "Command", key: "Insert Page"));
1092
1093 QDesignerFormEditorInterface *core = formWindow()->core();
1094 core->metaDataBase()->add(object: m_widget);
1095}
1096
1097void AddToolBoxPageCommand::redo()
1098{
1099 addPage();
1100 cheapUpdate();
1101}
1102
1103void AddToolBoxPageCommand::undo()
1104{
1105 removePage();
1106 cheapUpdate();
1107}
1108
1109// ---- TabWidgetCommand ----
1110TabWidgetCommand::TabWidgetCommand(QDesignerFormWindowInterface *formWindow) :
1111 QDesignerFormWindowCommand(QString(), formWindow),
1112 m_index(-1)
1113{
1114}
1115
1116TabWidgetCommand::~TabWidgetCommand() = default;
1117
1118void TabWidgetCommand::init(QTabWidget *tabWidget)
1119{
1120 m_tabWidget = tabWidget;
1121 m_index = m_tabWidget->currentIndex();
1122 m_widget = m_tabWidget->widget(index: m_index);
1123 m_itemText = m_tabWidget->tabText(index: m_index);
1124 m_itemIcon = m_tabWidget->tabIcon(index: m_index);
1125}
1126
1127void TabWidgetCommand::removePage()
1128{
1129 m_tabWidget->removeTab(index: m_index);
1130
1131 m_widget->hide();
1132 m_widget->setParent(formWindow());
1133 m_tabWidget->setCurrentIndex(qMin(a: m_index, b: m_tabWidget->count()));
1134
1135 formWindow()->clearSelection();
1136 formWindow()->selectWidget(w: m_tabWidget, select: true);
1137}
1138
1139void TabWidgetCommand::addPage()
1140{
1141 m_widget->setParent(nullptr);
1142 m_tabWidget->insertTab(index: m_index, widget: m_widget, icon: m_itemIcon, label: m_itemText);
1143 m_widget->show();
1144 m_tabWidget->setCurrentIndex(m_index);
1145
1146 QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(manager: formWindow()->core()->extensionManager(), object: m_tabWidget);
1147 if (sheet) {
1148 qdesigner_internal::PropertySheetStringValue itemText(m_itemText);
1149 sheet->setProperty(index: sheet->indexOf(QStringLiteral("currentTabText")), value: QVariant::fromValue(value: itemText));
1150 }
1151
1152 formWindow()->clearSelection();
1153 formWindow()->selectWidget(w: m_tabWidget, select: true);
1154}
1155
1156// ---- DeleteTabPageCommand ----
1157DeleteTabPageCommand::DeleteTabPageCommand(QDesignerFormWindowInterface *formWindow)
1158 : TabWidgetCommand(formWindow)
1159{
1160}
1161
1162DeleteTabPageCommand::~DeleteTabPageCommand() = default;
1163
1164void DeleteTabPageCommand::init(QTabWidget *tabWidget)
1165{
1166 TabWidgetCommand::init(tabWidget);
1167 setText(QApplication::translate(context: "Command", key: "Delete Page"));
1168}
1169
1170void DeleteTabPageCommand::redo()
1171{
1172 removePage();
1173 cheapUpdate();
1174}
1175
1176void DeleteTabPageCommand::undo()
1177{
1178 addPage();
1179 cheapUpdate();
1180}
1181
1182// ---- AddTabPageCommand ----
1183AddTabPageCommand::AddTabPageCommand(QDesignerFormWindowInterface *formWindow)
1184 : TabWidgetCommand(formWindow)
1185{
1186}
1187
1188AddTabPageCommand::~AddTabPageCommand() = default;
1189
1190void AddTabPageCommand::init(QTabWidget *tabWidget)
1191{
1192 init(tabWidget, mode: InsertBefore);
1193}
1194
1195void AddTabPageCommand::init(QTabWidget *tabWidget, InsertionMode mode)
1196{
1197 m_tabWidget = tabWidget;
1198
1199 m_index = m_tabWidget->currentIndex();
1200 if (mode == InsertAfter)
1201 m_index++;
1202 m_widget = new QDesignerWidget(formWindow(), m_tabWidget);
1203 m_itemText = QApplication::translate(context: "Command", key: "Page");
1204 m_itemIcon = QIcon();
1205 m_widget->setObjectName(QStringLiteral("tab"));
1206 formWindow()->ensureUniqueObjectName(object: m_widget);
1207
1208 setText(QApplication::translate(context: "Command", key: "Insert Page"));
1209
1210 QDesignerFormEditorInterface *core = formWindow()->core();
1211 core->metaDataBase()->add(object: m_widget);
1212}
1213
1214void AddTabPageCommand::redo()
1215{
1216 addPage();
1217 cheapUpdate();
1218}
1219
1220void AddTabPageCommand::undo()
1221{
1222 removePage();
1223 cheapUpdate();
1224}
1225
1226// ---- MoveTabPageCommand ----
1227MoveTabPageCommand::MoveTabPageCommand(QDesignerFormWindowInterface *formWindow) :
1228 TabWidgetCommand(formWindow),
1229 m_newIndex(-1),
1230 m_oldIndex(-1)
1231{
1232}
1233
1234MoveTabPageCommand::~MoveTabPageCommand() = default;
1235
1236void MoveTabPageCommand::init(QTabWidget *tabWidget, QWidget *page,
1237 const QIcon &icon, const QString &label,
1238 int index, int newIndex)
1239{
1240 TabWidgetCommand::init(tabWidget);
1241 setText(QApplication::translate(context: "Command", key: "Move Page"));
1242
1243 m_page = page;
1244 m_newIndex = newIndex;
1245 m_oldIndex = index;
1246 m_label = label;
1247 m_icon = icon;
1248}
1249
1250void MoveTabPageCommand::redo()
1251{
1252 m_tabWidget->removeTab(index: m_oldIndex);
1253 m_tabWidget->insertTab(index: m_newIndex, widget: m_page, icon: m_icon, label: m_label);
1254 m_tabWidget->setCurrentIndex(m_newIndex);
1255}
1256
1257void MoveTabPageCommand::undo()
1258{
1259 m_tabWidget->removeTab(index: m_newIndex);
1260 m_tabWidget->insertTab(index: m_oldIndex, widget: m_page, icon: m_icon, label: m_label);
1261 m_tabWidget->setCurrentIndex(m_oldIndex);
1262}
1263
1264// ---- StackedWidgetCommand ----
1265StackedWidgetCommand::StackedWidgetCommand(QDesignerFormWindowInterface *formWindow) :
1266 QDesignerFormWindowCommand(QString(), formWindow),
1267 m_index(-1)
1268{
1269}
1270
1271StackedWidgetCommand::~StackedWidgetCommand() = default;
1272
1273void StackedWidgetCommand::init(QStackedWidget *stackedWidget)
1274{
1275 m_stackedWidget = stackedWidget;
1276 m_index = m_stackedWidget->currentIndex();
1277 m_widget = m_stackedWidget->widget(m_index);
1278}
1279
1280void StackedWidgetCommand::removePage()
1281{
1282 m_stackedWidget->removeWidget(w: m_stackedWidget->widget(m_index));
1283
1284 m_widget->hide();
1285 m_widget->setParent(formWindow());
1286
1287 formWindow()->clearSelection();
1288 formWindow()->selectWidget(w: m_stackedWidget, select: true);
1289}
1290
1291void StackedWidgetCommand::addPage()
1292{
1293 m_stackedWidget->insertWidget(index: m_index, w: m_widget);
1294
1295 m_widget->show();
1296 m_stackedWidget->setCurrentIndex(m_index);
1297
1298 formWindow()->clearSelection();
1299 formWindow()->selectWidget(w: m_stackedWidget, select: true);
1300}
1301
1302// ---- MoveStackedWidgetCommand ----
1303MoveStackedWidgetCommand::MoveStackedWidgetCommand(QDesignerFormWindowInterface *formWindow) :
1304 StackedWidgetCommand(formWindow),
1305 m_newIndex(-1),
1306 m_oldIndex(-1)
1307{
1308}
1309
1310MoveStackedWidgetCommand::~MoveStackedWidgetCommand() = default;
1311
1312void MoveStackedWidgetCommand::init(QStackedWidget *stackedWidget, QWidget *page, int newIndex)
1313{
1314 StackedWidgetCommand::init(stackedWidget);
1315 setText(QApplication::translate(context: "Command", key: "Move Page"));
1316
1317 m_widget = page;
1318 m_newIndex = newIndex;
1319 m_oldIndex = m_stackedWidget->indexOf(m_widget);
1320}
1321
1322void MoveStackedWidgetCommand::redo()
1323{
1324 m_stackedWidget->removeWidget(w: m_widget);
1325 m_stackedWidget->insertWidget(index: m_newIndex, w: m_widget);
1326}
1327
1328void MoveStackedWidgetCommand::undo()
1329{
1330 m_stackedWidget->removeWidget(w: m_widget);
1331 m_stackedWidget->insertWidget(index: m_oldIndex, w: m_widget);
1332}
1333
1334// ---- DeleteStackedWidgetPageCommand ----
1335DeleteStackedWidgetPageCommand::DeleteStackedWidgetPageCommand(QDesignerFormWindowInterface *formWindow)
1336 : StackedWidgetCommand(formWindow)
1337{
1338}
1339
1340DeleteStackedWidgetPageCommand::~DeleteStackedWidgetPageCommand() = default;
1341
1342void DeleteStackedWidgetPageCommand::init(QStackedWidget *stackedWidget)
1343{
1344 StackedWidgetCommand::init(stackedWidget);
1345 setText(QApplication::translate(context: "Command", key: "Delete Page"));
1346}
1347
1348void DeleteStackedWidgetPageCommand::redo()
1349{
1350 removePage();
1351 cheapUpdate();
1352}
1353
1354void DeleteStackedWidgetPageCommand::undo()
1355{
1356 addPage();
1357 cheapUpdate();
1358}
1359
1360// ---- AddStackedWidgetPageCommand ----
1361AddStackedWidgetPageCommand::AddStackedWidgetPageCommand(QDesignerFormWindowInterface *formWindow)
1362 : StackedWidgetCommand(formWindow)
1363{
1364}
1365
1366AddStackedWidgetPageCommand::~AddStackedWidgetPageCommand() = default;
1367
1368void AddStackedWidgetPageCommand::init(QStackedWidget *stackedWidget)
1369{
1370 init(stackedWidget, mode: InsertBefore);
1371}
1372
1373void AddStackedWidgetPageCommand::init(QStackedWidget *stackedWidget, InsertionMode mode)
1374{
1375 m_stackedWidget = stackedWidget;
1376
1377 m_index = m_stackedWidget->currentIndex();
1378 if (mode == InsertAfter)
1379 m_index++;
1380 m_widget = new QDesignerWidget(formWindow(), m_stackedWidget);
1381 m_widget->setObjectName(QStringLiteral("page"));
1382 formWindow()->ensureUniqueObjectName(object: m_widget);
1383
1384 setText(QApplication::translate(context: "Command", key: "Insert Page"));
1385
1386 QDesignerFormEditorInterface *core = formWindow()->core();
1387 core->metaDataBase()->add(object: m_widget);
1388}
1389
1390void AddStackedWidgetPageCommand::redo()
1391{
1392 addPage();
1393 cheapUpdate();
1394}
1395
1396void AddStackedWidgetPageCommand::undo()
1397{
1398 removePage();
1399 cheapUpdate();
1400}
1401
1402// ---- TabOrderCommand ----
1403TabOrderCommand::TabOrderCommand(QDesignerFormWindowInterface *formWindow)
1404 : QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Change Tab order"), formWindow),
1405 m_widgetItem(nullptr)
1406{
1407}
1408
1409void TabOrderCommand::init(const QWidgetList &newTabOrder)
1410{
1411 QDesignerFormEditorInterface *core = formWindow()->core();
1412 Q_ASSERT(core);
1413
1414 m_widgetItem = core->metaDataBase()->item(object: formWindow());
1415 Q_ASSERT(m_widgetItem);
1416 m_oldTabOrder = m_widgetItem->tabOrder();
1417 m_newTabOrder = newTabOrder;
1418}
1419
1420void TabOrderCommand::redo()
1421{
1422 m_widgetItem->setTabOrder(m_newTabOrder);
1423}
1424
1425void TabOrderCommand::undo()
1426{
1427 m_widgetItem->setTabOrder(m_oldTabOrder);
1428}
1429
1430// ---- CreateMenuBarCommand ----
1431CreateMenuBarCommand::CreateMenuBarCommand(QDesignerFormWindowInterface *formWindow)
1432 : QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Create Menu Bar"), formWindow)
1433{
1434}
1435
1436void CreateMenuBarCommand::init(QMainWindow *mainWindow)
1437{
1438 m_mainWindow = mainWindow;
1439 QDesignerFormEditorInterface *core = formWindow()->core();
1440 m_menuBar = qobject_cast<QMenuBar*>(object: core->widgetFactory()->createWidget(QStringLiteral("QMenuBar"), parentWidget: m_mainWindow));
1441 core->widgetFactory()->initialize(object: m_menuBar);
1442}
1443
1444void CreateMenuBarCommand::redo()
1445{
1446 QDesignerFormEditorInterface *core = formWindow()->core();
1447 QDesignerContainerExtension *c;
1448 c = qt_extension<QDesignerContainerExtension*>(manager: core->extensionManager(), object: m_mainWindow);
1449 c->addWidget(widget: m_menuBar);
1450
1451 m_menuBar->setObjectName(QStringLiteral("menuBar"));
1452 formWindow()->ensureUniqueObjectName(object: m_menuBar);
1453 core->metaDataBase()->add(object: m_menuBar);
1454 formWindow()->emitSelectionChanged();
1455 m_menuBar->setFocus();
1456}
1457
1458void CreateMenuBarCommand::undo()
1459{
1460 QDesignerFormEditorInterface *core = formWindow()->core();
1461 QDesignerContainerExtension *c;
1462 c = qt_extension<QDesignerContainerExtension*>(manager: core->extensionManager(), object: m_mainWindow);
1463 for (int i = 0; i < c->count(); ++i) {
1464 if (c->widget(index: i) == m_menuBar) {
1465 c->remove(index: i);
1466 break;
1467 }
1468 }
1469
1470 core->metaDataBase()->remove(object: m_menuBar);
1471 formWindow()->emitSelectionChanged();
1472}
1473
1474// ---- DeleteMenuBarCommand ----
1475DeleteMenuBarCommand::DeleteMenuBarCommand(QDesignerFormWindowInterface *formWindow)
1476 : QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Delete Menu Bar"), formWindow)
1477{
1478}
1479
1480void DeleteMenuBarCommand::init(QMenuBar *menuBar)
1481{
1482 m_menuBar = menuBar;
1483 m_mainWindow = qobject_cast<QMainWindow*>(object: menuBar->parentWidget());
1484}
1485
1486void DeleteMenuBarCommand::redo()
1487{
1488 if (m_mainWindow) {
1489 QDesignerContainerExtension *c;
1490 c = qt_extension<QDesignerContainerExtension*>(manager: core()->extensionManager(), object: m_mainWindow);
1491 Q_ASSERT(c != nullptr);
1492 for (int i=0; i<c->count(); ++i) {
1493 if (c->widget(index: i) == m_menuBar) {
1494 c->remove(index: i);
1495 break;
1496 }
1497 }
1498 }
1499
1500 core()->metaDataBase()->remove(object: m_menuBar);
1501 m_menuBar->hide();
1502 m_menuBar->setParent(formWindow());
1503 formWindow()->emitSelectionChanged();
1504}
1505
1506void DeleteMenuBarCommand::undo()
1507{
1508 if (m_mainWindow) {
1509 m_menuBar->setParent(m_mainWindow);
1510 QDesignerContainerExtension *c;
1511 c = qt_extension<QDesignerContainerExtension*>(manager: core()->extensionManager(), object: m_mainWindow);
1512
1513 c->addWidget(widget: m_menuBar);
1514
1515 core()->metaDataBase()->add(object: m_menuBar);
1516 m_menuBar->show();
1517 formWindow()->emitSelectionChanged();
1518 }
1519}
1520
1521// ---- CreateStatusBarCommand ----
1522CreateStatusBarCommand::CreateStatusBarCommand(QDesignerFormWindowInterface *formWindow)
1523 : QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Create Status Bar"), formWindow)
1524{
1525}
1526
1527void CreateStatusBarCommand::init(QMainWindow *mainWindow)
1528{
1529 m_mainWindow = mainWindow;
1530 QDesignerFormEditorInterface *core = formWindow()->core();
1531 m_statusBar = qobject_cast<QStatusBar*>(object: core->widgetFactory()->createWidget(QStringLiteral("QStatusBar"), parentWidget: m_mainWindow));
1532 core->widgetFactory()->initialize(object: m_statusBar);
1533}
1534
1535void CreateStatusBarCommand::redo()
1536{
1537 QDesignerFormEditorInterface *core = formWindow()->core();
1538 QDesignerContainerExtension *c;
1539 c = qt_extension<QDesignerContainerExtension*>(manager: core->extensionManager(), object: m_mainWindow);
1540 c->addWidget(widget: m_statusBar);
1541
1542 m_statusBar->setObjectName(QStringLiteral("statusBar"));
1543 formWindow()->ensureUniqueObjectName(object: m_statusBar);
1544 core->metaDataBase()->add(object: m_statusBar);
1545 formWindow()->emitSelectionChanged();
1546}
1547
1548void CreateStatusBarCommand::undo()
1549{
1550 QDesignerFormEditorInterface *core = formWindow()->core();
1551 QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(manager: core->extensionManager(), object: m_mainWindow);
1552 for (int i = 0; i < c->count(); ++i) {
1553 if (c->widget(index: i) == m_statusBar) {
1554 c->remove(index: i);
1555 break;
1556 }
1557 }
1558
1559 core->metaDataBase()->remove(object: m_statusBar);
1560 formWindow()->emitSelectionChanged();
1561}
1562
1563// ---- DeleteStatusBarCommand ----
1564DeleteStatusBarCommand::DeleteStatusBarCommand(QDesignerFormWindowInterface *formWindow)
1565 : QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Delete Status Bar"), formWindow)
1566{
1567}
1568
1569void DeleteStatusBarCommand::init(QStatusBar *statusBar)
1570{
1571 m_statusBar = statusBar;
1572 m_mainWindow = qobject_cast<QMainWindow*>(object: statusBar->parentWidget());
1573}
1574
1575void DeleteStatusBarCommand::redo()
1576{
1577 if (m_mainWindow) {
1578 QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(manager: core()->extensionManager(), object: m_mainWindow);
1579 Q_ASSERT(c != nullptr);
1580 for (int i=0; i<c->count(); ++i) {
1581 if (c->widget(index: i) == m_statusBar) {
1582 c->remove(index: i);
1583 break;
1584 }
1585 }
1586 }
1587
1588 core()->metaDataBase()->remove(object: m_statusBar);
1589 m_statusBar->hide();
1590 m_statusBar->setParent(formWindow());
1591 formWindow()->emitSelectionChanged();
1592}
1593
1594void DeleteStatusBarCommand::undo()
1595{
1596 if (m_mainWindow) {
1597 m_statusBar->setParent(m_mainWindow);
1598 QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(manager: core()->extensionManager(), object: m_mainWindow);
1599
1600 c->addWidget(widget: m_statusBar);
1601
1602 core()->metaDataBase()->add(object: m_statusBar);
1603 m_statusBar->show();
1604 formWindow()->emitSelectionChanged();
1605 }
1606}
1607
1608// ---- AddToolBarCommand ----
1609AddToolBarCommand::AddToolBarCommand(QDesignerFormWindowInterface *formWindow)
1610 : QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Add Tool Bar"), formWindow)
1611{
1612}
1613
1614void AddToolBarCommand::init(QMainWindow *mainWindow, Qt::ToolBarArea area)
1615{
1616 m_mainWindow = mainWindow;
1617 QDesignerWidgetFactoryInterface * wf = formWindow()->core()->widgetFactory();
1618 // Pass on 0 parent first to avoid reparenting flicker.
1619 m_toolBar = qobject_cast<QToolBar*>(object: wf->createWidget(QStringLiteral("QToolBar"), parentWidget: nullptr));
1620 m_toolBar->setProperty(name: "_q_desiredArea", value: QVariant(area));
1621 wf->initialize(object: m_toolBar);
1622 m_toolBar->hide();
1623}
1624
1625void AddToolBarCommand::redo()
1626{
1627 QDesignerFormEditorInterface *core = formWindow()->core();
1628 core->metaDataBase()->add(object: m_toolBar);
1629
1630 QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(manager: core->extensionManager(), object: m_mainWindow);
1631 c->addWidget(widget: m_toolBar);
1632
1633 m_toolBar->setObjectName(QStringLiteral("toolBar"));
1634 formWindow()->ensureUniqueObjectName(object: m_toolBar);
1635 setPropertySheetWindowTitle(core, o: m_toolBar, t: m_toolBar->objectName());
1636 formWindow()->emitSelectionChanged();
1637}
1638
1639void AddToolBarCommand::undo()
1640{
1641 QDesignerFormEditorInterface *core = formWindow()->core();
1642 core->metaDataBase()->remove(object: m_toolBar);
1643 QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(manager: core->extensionManager(), object: m_mainWindow);
1644 for (int i = 0; i < c->count(); ++i) {
1645 if (c->widget(index: i) == m_toolBar) {
1646 c->remove(index: i);
1647 break;
1648 }
1649 }
1650 formWindow()->emitSelectionChanged();
1651}
1652
1653// ---- DockWidgetCommand:: ----
1654DockWidgetCommand::DockWidgetCommand(const QString &description, QDesignerFormWindowInterface *formWindow)
1655 : QDesignerFormWindowCommand(description, formWindow)
1656{
1657}
1658
1659DockWidgetCommand::~DockWidgetCommand() = default;
1660
1661void DockWidgetCommand::init(QDockWidget *dockWidget)
1662{
1663 m_dockWidget = dockWidget;
1664}
1665
1666// ---- AddDockWidgetCommand ----
1667AddDockWidgetCommand::AddDockWidgetCommand(QDesignerFormWindowInterface *formWindow)
1668 : QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Add Dock Window"), formWindow)
1669{
1670}
1671
1672void AddDockWidgetCommand::init(QMainWindow *mainWindow, QDockWidget *dockWidget)
1673{
1674 m_mainWindow = mainWindow;
1675 m_dockWidget = dockWidget;
1676}
1677
1678void AddDockWidgetCommand::init(QMainWindow *mainWindow)
1679{
1680 m_mainWindow = mainWindow;
1681 QDesignerFormEditorInterface *core = formWindow()->core();
1682 m_dockWidget = qobject_cast<QDockWidget*>(object: core->widgetFactory()->createWidget(QStringLiteral("QDockWidget"), parentWidget: m_mainWindow));
1683}
1684
1685void AddDockWidgetCommand::redo()
1686{
1687 QDesignerFormEditorInterface *core = formWindow()->core();
1688 QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(manager: core->extensionManager(), object: m_mainWindow);
1689 c->addWidget(widget: m_dockWidget);
1690
1691 m_dockWidget->setObjectName(QStringLiteral("dockWidget"));
1692 formWindow()->ensureUniqueObjectName(object: m_dockWidget);
1693 formWindow()->manageWidget(widget: m_dockWidget);
1694 formWindow()->emitSelectionChanged();
1695}
1696
1697void AddDockWidgetCommand::undo()
1698{
1699 QDesignerFormEditorInterface *core = formWindow()->core();
1700 QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(manager: core->extensionManager(), object: m_mainWindow);
1701 for (int i = 0; i < c->count(); ++i) {
1702 if (c->widget(index: i) == m_dockWidget) {
1703 c->remove(index: i);
1704 break;
1705 }
1706 }
1707
1708 formWindow()->unmanageWidget(widget: m_dockWidget);
1709 formWindow()->emitSelectionChanged();
1710}
1711
1712// ---- AdjustWidgetSizeCommand ----
1713AdjustWidgetSizeCommand::AdjustWidgetSizeCommand(QDesignerFormWindowInterface *formWindow)
1714 : QDesignerFormWindowCommand(QString(), formWindow)
1715{
1716}
1717
1718void AdjustWidgetSizeCommand::init(QWidget *widget)
1719{
1720 m_widget = widget;
1721 setText(QApplication::translate(context: "Command", key: "Adjust Size of '%1'").arg(a: widget->objectName()));
1722}
1723
1724QWidget *AdjustWidgetSizeCommand::widgetForAdjust() const
1725{
1726 QDesignerFormWindowInterface *fw = formWindow();
1727 // Return the outer, embedding widget if it is the main container
1728 if (Utils::isCentralWidget(fw, widget: m_widget))
1729 return fw->core()->integration()->containerWindow(widget: m_widget);
1730 return m_widget;
1731}
1732
1733void AdjustWidgetSizeCommand::redo()
1734{
1735 QWidget *aw = widgetForAdjust();
1736 m_geometry = aw->geometry();
1737 QApplication::processEvents(flags: QEventLoop::ExcludeUserInputEvents);
1738 aw->adjustSize();
1739 const bool isMainContainer = aw != m_widget;
1740 if (!isMainContainer) {
1741 /* When doing adjustsize on a selected non-laid out child that has been enlarged
1742 * and pushed partially over the top/left edge[s], it is possible that it "disappears"
1743 * when shrinking. In that case, move it back so that it remains visible. */
1744 if (aw->parentWidget()->layout() == nullptr) {
1745 const QRect contentsRect = aw->parentWidget()->contentsRect();
1746 const QRect newGeometry = aw->geometry();
1747 QPoint newPos = m_geometry.topLeft();
1748 if (newGeometry.bottom() <= contentsRect.y())
1749 newPos.setY(contentsRect.y());
1750 if (newGeometry.right() <= contentsRect.x())
1751 newPos.setX(contentsRect.x());
1752 if (newPos != m_geometry.topLeft())
1753 aw->move(newPos);
1754 }
1755 }
1756 updatePropertyEditor();
1757}
1758
1759void AdjustWidgetSizeCommand::undo()
1760{
1761 QWidget *aw = widgetForAdjust();
1762 aw->resize(m_geometry.size());
1763 if (m_geometry.topLeft() != aw->geometry().topLeft())
1764 aw->move(m_geometry.topLeft());
1765 updatePropertyEditor();
1766}
1767
1768void AdjustWidgetSizeCommand::updatePropertyEditor() const
1769{
1770 if (QDesignerPropertyEditorInterface *propertyEditor = formWindow()->core()->propertyEditor()) {
1771 if (propertyEditor->object() == m_widget)
1772 propertyEditor->setPropertyValue(QStringLiteral("geometry"), value: m_widget->geometry(), changed: true);
1773 }
1774}
1775// ------------ ChangeFormLayoutItemRoleCommand
1776
1777ChangeFormLayoutItemRoleCommand::ChangeFormLayoutItemRoleCommand(QDesignerFormWindowInterface *formWindow) :
1778 QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Change Form Layout Item Geometry"), formWindow),
1779 m_operation(SpanningToLabel)
1780{
1781}
1782
1783void ChangeFormLayoutItemRoleCommand::init(QWidget *widget, Operation op)
1784{
1785 m_widget = widget;
1786 m_operation = op;
1787}
1788
1789void ChangeFormLayoutItemRoleCommand::redo()
1790{
1791 doOperation(op: m_operation);
1792}
1793
1794void ChangeFormLayoutItemRoleCommand::undo()
1795{
1796 doOperation(op: reverseOperation(op: m_operation));
1797}
1798
1799ChangeFormLayoutItemRoleCommand::Operation ChangeFormLayoutItemRoleCommand::reverseOperation(Operation op)
1800{
1801 switch (op) {
1802 case SpanningToLabel:
1803 return LabelToSpanning;
1804 case SpanningToField:
1805 return FieldToSpanning;
1806 case LabelToSpanning:
1807 return SpanningToLabel;
1808 case FieldToSpanning:
1809 return SpanningToField;
1810 }
1811 return SpanningToField;
1812}
1813
1814void ChangeFormLayoutItemRoleCommand::doOperation(Operation op)
1815{
1816 QFormLayout *fl = ChangeFormLayoutItemRoleCommand::managedFormLayoutOf(core: formWindow()->core(), w: m_widget);
1817 const int index = fl->indexOf(m_widget);
1818 Q_ASSERT(index != -1);
1819 int row;
1820 QFormLayout::ItemRole role;
1821 fl->getItemPosition (index, rowPtr: &row, rolePtr: &role);
1822 Q_ASSERT(index != -1);
1823 QLayoutItem *item = fl->takeAt(index);
1824 const QRect area = QRect(0, row, 2, 1);
1825 switch (op) {
1826 case SpanningToLabel:
1827 fl->setItem(row, role: QFormLayout::LabelRole, item);
1828 QLayoutSupport::createEmptyCells(formLayout: fl);
1829 break;
1830 case SpanningToField:
1831 fl->setItem(row, role: QFormLayout::FieldRole, item);
1832 QLayoutSupport::createEmptyCells(formLayout: fl);
1833 break;
1834 case LabelToSpanning:
1835 case FieldToSpanning:
1836 QLayoutSupport::removeEmptyCells(formLayout: fl, area);
1837 fl->setItem(row, role: QFormLayout::SpanningRole, item);
1838 break;
1839 }
1840}
1841
1842unsigned ChangeFormLayoutItemRoleCommand::possibleOperations(QDesignerFormEditorInterface *core, QWidget *w)
1843{
1844 QFormLayout *fl = managedFormLayoutOf(core, w);
1845 if (!fl)
1846 return 0;
1847 const int index = fl->indexOf(w);
1848 if (index == -1)
1849 return 0;
1850 int row, col, colspan;
1851 getFormLayoutItemPosition(formLayout: fl, index, rowPtr: &row, columnPtr: &col, rowspanPtr: nullptr, colspanPtr: &colspan);
1852 // Spanning item?
1853 if (colspan > 1)
1854 return SpanningToLabel|SpanningToField;
1855 // Is the neighbouring column free, that is, can the current item be expanded?
1856 const QFormLayout::ItemRole neighbouringRole = col == 0 ? QFormLayout::FieldRole : QFormLayout::LabelRole;
1857 const bool empty = LayoutInfo::isEmptyItem(item: fl->itemAt(row, role: neighbouringRole));
1858 if (empty)
1859 return col == 0 ? LabelToSpanning : FieldToSpanning;
1860 return 0;
1861}
1862
1863QFormLayout *ChangeFormLayoutItemRoleCommand::managedFormLayoutOf(QDesignerFormEditorInterface *core, QWidget *w)
1864{
1865 if (QLayout *layout = LayoutInfo::managedLayout(core, widget: w->parentWidget()))
1866 if (QFormLayout *fl = qobject_cast<QFormLayout *>(object: layout))
1867 return fl;
1868 return nullptr;
1869}
1870
1871// ---- ChangeLayoutItemGeometry ----
1872ChangeLayoutItemGeometry::ChangeLayoutItemGeometry(QDesignerFormWindowInterface *formWindow)
1873 : QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Change Layout Item Geometry"), formWindow)
1874{
1875}
1876
1877void ChangeLayoutItemGeometry::init(QWidget *widget, int row, int column, int rowspan, int colspan)
1878{
1879 m_widget = widget;
1880 Q_ASSERT(m_widget->parentWidget() != nullptr);
1881
1882 QLayout *layout = LayoutInfo::managedLayout(core: formWindow()->core(), widget: m_widget->parentWidget());
1883 Q_ASSERT(layout != nullptr);
1884
1885 QGridLayout *grid = qobject_cast<QGridLayout*>(object: layout);
1886 Q_ASSERT(grid != nullptr);
1887
1888 const int itemIndex = grid->indexOf(m_widget);
1889 Q_ASSERT(itemIndex != -1);
1890
1891 int current_row, current_column, current_rowspan, current_colspan;
1892 grid->getItemPosition(idx: itemIndex, row: &current_row, column: &current_column, rowSpan: &current_rowspan, columnSpan: &current_colspan);
1893
1894 m_oldInfo.setRect(ax: current_column, ay: current_row, aw: current_colspan, ah: current_rowspan);
1895 m_newInfo.setRect(ax: column, ay: row, aw: colspan, ah: rowspan);
1896}
1897
1898void ChangeLayoutItemGeometry::changeItemPosition(const QRect &g)
1899{
1900 QLayout *layout = LayoutInfo::managedLayout(core: formWindow()->core(), widget: m_widget->parentWidget());
1901 Q_ASSERT(layout != nullptr);
1902
1903 QGridLayout *grid = qobject_cast<QGridLayout*>(object: layout);
1904 Q_ASSERT(grid != nullptr);
1905
1906 const int itemIndex = grid->indexOf(m_widget);
1907 Q_ASSERT(itemIndex != -1);
1908
1909 QLayoutItem *item = grid->takeAt(index: itemIndex);
1910 delete item;
1911
1912 if (!QLayoutSupport::removeEmptyCells(gridLayout: grid, area: g))
1913 qWarning() << "ChangeLayoutItemGeometry::changeItemPosition: Nonempty cell at " << g << '.';
1914
1915 grid->addWidget(m_widget, row: g.top(), column: g.left(), rowSpan: g.height(), columnSpan: g.width());
1916
1917 grid->invalidate();
1918 grid->activate();
1919
1920 QLayoutSupport::createEmptyCells(gridLayout: grid);
1921
1922 formWindow()->clearSelection(changePropertyDisplay: false);
1923 formWindow()->selectWidget(w: m_widget, select: true);
1924}
1925
1926void ChangeLayoutItemGeometry::redo()
1927{
1928 changeItemPosition(g: m_newInfo);
1929}
1930
1931void ChangeLayoutItemGeometry::undo()
1932{
1933 changeItemPosition(g: m_oldInfo);
1934}
1935
1936// ---- ContainerWidgetCommand ----
1937ContainerWidgetCommand::ContainerWidgetCommand(QDesignerFormWindowInterface *formWindow) :
1938 QDesignerFormWindowCommand(QString(), formWindow),
1939 m_index(-1)
1940{
1941}
1942
1943ContainerWidgetCommand::~ContainerWidgetCommand() = default;
1944
1945QDesignerContainerExtension *ContainerWidgetCommand::containerExtension() const
1946{
1947 QExtensionManager *mgr = core()->extensionManager();
1948 return qt_extension<QDesignerContainerExtension*>(manager: mgr, object: m_containerWidget);
1949}
1950
1951void ContainerWidgetCommand::init(QWidget *containerWidget)
1952{
1953 m_containerWidget = containerWidget;
1954
1955 if (QDesignerContainerExtension *c = containerExtension()) {
1956 m_index = c->currentIndex();
1957 m_widget = c->widget(index: m_index);
1958 }
1959}
1960
1961void ContainerWidgetCommand::removePage()
1962{
1963 if (QDesignerContainerExtension *c = containerExtension()) {
1964 if (const int count = c->count()) {
1965 // Undo add after last?
1966 const int deleteIndex = m_index >= 0 ? m_index : count - 1;
1967 c->remove(index: deleteIndex);
1968 m_widget->hide();
1969 m_widget->setParent(formWindow());
1970 }
1971 }
1972}
1973
1974void ContainerWidgetCommand::addPage()
1975{
1976 if (QDesignerContainerExtension *c = containerExtension()) {
1977 int newCurrentIndex;
1978 if (m_index >= 0) {
1979 c->insertWidget(index: m_index, widget: m_widget);
1980 newCurrentIndex = m_index;
1981 } else {
1982 c->addWidget(widget: m_widget);
1983 newCurrentIndex = c->count() -1 ;
1984 }
1985 m_widget->show();
1986 c->setCurrentIndex(newCurrentIndex);
1987 }
1988}
1989
1990// ---- DeleteContainerWidgetPageCommand ----
1991DeleteContainerWidgetPageCommand::DeleteContainerWidgetPageCommand(QDesignerFormWindowInterface *formWindow)
1992 : ContainerWidgetCommand(formWindow)
1993{
1994}
1995
1996DeleteContainerWidgetPageCommand::~DeleteContainerWidgetPageCommand() = default;
1997
1998void DeleteContainerWidgetPageCommand::init(QWidget *containerWidget, ContainerType ct)
1999{
2000 ContainerWidgetCommand::init(containerWidget);
2001 switch (ct) {
2002 case WizardContainer:
2003 case PageContainer:
2004 setText(QApplication::translate(context: "Command", key: "Delete Page"));
2005 break;
2006 case MdiContainer:
2007 setText(QApplication::translate(context: "Command", key: "Delete Subwindow"));
2008 break;
2009 }
2010}
2011
2012void DeleteContainerWidgetPageCommand::redo()
2013{
2014 removePage();
2015 cheapUpdate();
2016}
2017
2018void DeleteContainerWidgetPageCommand::undo()
2019{
2020 addPage();
2021 cheapUpdate();
2022}
2023
2024// ---- AddContainerWidgetPageCommand ----
2025AddContainerWidgetPageCommand::AddContainerWidgetPageCommand(QDesignerFormWindowInterface *formWindow)
2026 : ContainerWidgetCommand(formWindow)
2027{
2028}
2029
2030AddContainerWidgetPageCommand::~AddContainerWidgetPageCommand() = default;
2031
2032void AddContainerWidgetPageCommand::init(QWidget *containerWidget, ContainerType ct, InsertionMode mode)
2033{
2034 m_containerWidget = containerWidget;
2035
2036 if (QDesignerContainerExtension *c = containerExtension()) {
2037 m_index = c->currentIndex();
2038 if (m_index >= 0 && mode == InsertAfter)
2039 m_index++;
2040 m_widget = nullptr;
2041 const QDesignerFormEditorInterface *core = formWindow()->core();
2042 switch (ct) {
2043 case PageContainer:
2044 setText(QApplication::translate(context: "Command", key: "Insert Page"));
2045 m_widget = new QDesignerWidget(formWindow(), m_containerWidget);
2046 m_widget->setObjectName(QStringLiteral("page"));
2047 break;
2048 case MdiContainer:
2049 setText(QApplication::translate(context: "Command", key: "Insert Subwindow"));
2050 m_widget = new QDesignerWidget(formWindow(), m_containerWidget);
2051 m_widget->setObjectName(QStringLiteral("subwindow"));
2052 setPropertySheetWindowTitle(core, o: m_widget, t: QApplication::translate(context: "Command", key: "Subwindow"));
2053 break;
2054 case WizardContainer: // Apply style, don't manage
2055 m_widget = core->widgetFactory()->createWidget(QStringLiteral("QWizardPage"), parentWidget: nullptr);
2056 break;
2057 }
2058 formWindow()->ensureUniqueObjectName(object: m_widget);
2059 core->metaDataBase()->add(object: m_widget);
2060 }
2061}
2062
2063void AddContainerWidgetPageCommand::redo()
2064{
2065 addPage();
2066 cheapUpdate();
2067}
2068
2069void AddContainerWidgetPageCommand::undo()
2070{
2071 removePage();
2072 cheapUpdate();
2073}
2074
2075ChangeCurrentPageCommand::ChangeCurrentPageCommand(QDesignerFormWindowInterface *formWindow)
2076 :
2077 QDesignerFormWindowCommand(QString(), formWindow), m_oldIndex(0), m_newIndex(0)
2078{
2079}
2080
2081ChangeCurrentPageCommand::~ChangeCurrentPageCommand() = default;
2082
2083QDesignerContainerExtension *ChangeCurrentPageCommand::containerExtension() const
2084{
2085 QExtensionManager *mgr = core()->extensionManager();
2086 return qt_extension<QDesignerContainerExtension*>(manager: mgr, object: m_containerWidget);
2087}
2088
2089void ChangeCurrentPageCommand::init(QWidget *containerWidget, int newIndex)
2090{
2091 m_containerWidget = containerWidget;
2092
2093 if (QDesignerContainerExtension *c = containerExtension()) {
2094 m_newIndex = newIndex;
2095 m_oldIndex = c->currentIndex();
2096 m_widget = c->widget(index: m_oldIndex);
2097 }
2098}
2099
2100void ChangeCurrentPageCommand::redo()
2101{
2102 containerExtension()->setCurrentIndex(m_newIndex);
2103}
2104
2105void ChangeCurrentPageCommand::undo()
2106{
2107 containerExtension()->setCurrentIndex(m_oldIndex);
2108}
2109
2110static const int itemRoles[] = {
2111 Qt::DecorationPropertyRole,
2112 Qt::DisplayPropertyRole,
2113 Qt::ToolTipPropertyRole,
2114 Qt::StatusTipPropertyRole,
2115 Qt::WhatsThisPropertyRole,
2116 Qt::FontRole,
2117 Qt::TextAlignmentRole,
2118 Qt::BackgroundRole,
2119 Qt::ForegroundRole,
2120 Qt::CheckStateRole
2121};
2122
2123template<class T>
2124static void copyRoleFromItem(ItemData *id, int role, const T *item)
2125{
2126 QVariant v = item->data(role);
2127 if (v.isValid())
2128 id->m_properties.insert(akey: role, avalue: v);
2129}
2130
2131template<class T>
2132static void copyRolesFromItem(ItemData *id, const T *item, bool editor)
2133{
2134 static const Qt::ItemFlags defaultFlags = T().flags();
2135
2136 for (int i : itemRoles)
2137 copyRoleFromItem<T>(id, i, item);
2138
2139 if (editor)
2140 copyRoleFromItem<T>(id, ItemFlagsShadowRole, item);
2141 else if (item->flags() != defaultFlags)
2142 id->m_properties.insert(akey: ItemFlagsShadowRole, avalue: QVariant::fromValue(value: int(item->flags())));
2143}
2144
2145template<class T>
2146static void copyRolesToItem(const ItemData *id, T *item, DesignerIconCache *iconCache, bool editor)
2147{
2148 QHash<int, QVariant>::const_iterator it = id->m_properties.constBegin(),
2149 end = id->m_properties.constEnd();
2150 for (; it != end; ++it)
2151 if (it.value().isValid()) {
2152 if (!editor && it.key() == ItemFlagsShadowRole) {
2153 item->setFlags((Qt::ItemFlags)it.value().toInt());
2154 } else {
2155 item->setData(it.key(), it.value());
2156 switch (it.key()) {
2157 case Qt::DecorationPropertyRole:
2158 if (iconCache)
2159 item->setIcon(iconCache->icon(value: qvariant_cast<PropertySheetIconValue>(v: it.value())));
2160 break;
2161 case Qt::DisplayPropertyRole:
2162 item->setText(qvariant_cast<PropertySheetStringValue>(v: it.value()).value());
2163 break;
2164 case Qt::ToolTipPropertyRole:
2165 item->setToolTip(qvariant_cast<PropertySheetStringValue>(v: it.value()).value());
2166 break;
2167 case Qt::StatusTipPropertyRole:
2168 item->setStatusTip(qvariant_cast<PropertySheetStringValue>(v: it.value()).value());
2169 break;
2170 case Qt::WhatsThisPropertyRole:
2171 item->setWhatsThis(qvariant_cast<PropertySheetStringValue>(v: it.value()).value());
2172 break;
2173 }
2174 }
2175 }
2176
2177 if (editor)
2178 item->setFlags(item->flags() | Qt::ItemIsEditable);
2179}
2180
2181ItemData::ItemData(const QListWidgetItem *item, bool editor)
2182{
2183 copyRolesFromItem<QListWidgetItem>(id: this, item, editor);
2184}
2185
2186QListWidgetItem *ItemData::createListItem(DesignerIconCache *iconCache, bool editor) const
2187{
2188 QListWidgetItem *item = new QListWidgetItem();
2189 copyRolesToItem(id: this, item, iconCache, editor);
2190 return item;
2191}
2192
2193ItemData::ItemData(const QTableWidgetItem *item, bool editor)
2194{
2195 copyRolesFromItem(id: this, item, editor);
2196}
2197
2198QTableWidgetItem *ItemData::createTableItem(DesignerIconCache *iconCache, bool editor) const
2199{
2200 QTableWidgetItem *item = new QTableWidgetItem;
2201 copyRolesToItem(id: this, item, iconCache, editor);
2202 return item;
2203}
2204
2205static void copyRoleFromItem(ItemData *id, int role, const QTreeWidgetItem *item, int column)
2206{
2207 QVariant v = item->data(column, role);
2208 if (v.isValid())
2209 id->m_properties.insert(akey: role, avalue: v);
2210}
2211
2212ItemData::ItemData(const QTreeWidgetItem *item, int column)
2213{
2214 copyRoleFromItem(id: this, role: Qt::EditRole, item, column);
2215 PropertySheetStringValue str(item->text(column));
2216 m_properties.insert(akey: Qt::DisplayPropertyRole, avalue: QVariant::fromValue(value: str));
2217
2218 for (int i : itemRoles)
2219 copyRoleFromItem(id: this, role: i, item, column);
2220}
2221
2222void ItemData::fillTreeItemColumn(QTreeWidgetItem *item, int column, DesignerIconCache *iconCache) const
2223{
2224 QHash<int, QVariant>::const_iterator it = m_properties.constBegin(), end = m_properties.constEnd();
2225 for (; it != end; ++it)
2226 if (it.value().isValid()) {
2227 item->setData(column, role: it.key(), value: it.value());
2228 switch (it.key()) {
2229 case Qt::DecorationPropertyRole:
2230 if (iconCache)
2231 item->setIcon(column, aicon: iconCache->icon(value: qvariant_cast<PropertySheetIconValue>(v: it.value())));
2232 break;
2233 case Qt::DisplayPropertyRole:
2234 item->setText(column, atext: qvariant_cast<PropertySheetStringValue>(v: it.value()).value());
2235 break;
2236 case Qt::ToolTipPropertyRole:
2237 item->setToolTip(column, atoolTip: qvariant_cast<PropertySheetStringValue>(v: it.value()).value());
2238 break;
2239 case Qt::StatusTipPropertyRole:
2240 item->setStatusTip(column, astatusTip: qvariant_cast<PropertySheetStringValue>(v: it.value()).value());
2241 break;
2242 case Qt::WhatsThisPropertyRole:
2243 item->setWhatsThis(column, awhatsThis: qvariant_cast<PropertySheetStringValue>(v: it.value()).value());
2244 break;
2245 }
2246 }
2247}
2248
2249ListContents::ListContents(const QTreeWidgetItem *item)
2250{
2251 for (int i = 0; i < item->columnCount(); i++)
2252 m_items.append(t: ItemData(item, i));
2253}
2254
2255QTreeWidgetItem *ListContents::createTreeItem(DesignerIconCache *iconCache) const
2256{
2257 QTreeWidgetItem *item = new QTreeWidgetItem;
2258 int i = 0;
2259 for (const ItemData &id : m_items)
2260 id.fillTreeItemColumn(item, column: i++, iconCache);
2261 return item;
2262}
2263
2264void ListContents::createFromListWidget(const QListWidget *listWidget, bool editor)
2265{
2266 m_items.clear();
2267
2268 for (int i = 0; i < listWidget->count(); i++)
2269 m_items.append(t: ItemData(listWidget->item(row: i), editor));
2270}
2271
2272void ListContents::applyToListWidget(QListWidget *listWidget, DesignerIconCache *iconCache,
2273 bool editor, Qt::Alignment alignmentDefault) const
2274{
2275 listWidget->clear();
2276
2277 int i = 0;
2278 for (const ItemData &entry : m_items) {
2279 auto *item = entry.isValid()
2280 ? entry.createListItem(iconCache, editor)
2281 : new QListWidgetItem(TableWidgetContents::defaultHeaderText(i));
2282 if (item->textAlignment() == 0)
2283 item->setTextAlignment(alignmentDefault);
2284 listWidget->addItem(aitem: item);
2285 i++;
2286 }
2287}
2288
2289void ListContents::createFromComboBox(const QComboBox *comboBox)
2290{
2291 m_items.clear();
2292
2293 const int count = comboBox->count();
2294 for (int i = 0; i < count; i++) {
2295 // We might encounter items added in a custom combo
2296 // constructor. Ignore those.
2297 const QVariant textValue = comboBox->itemData(index: i, role: Qt::DisplayPropertyRole);
2298 if (!textValue.isNull()) {
2299 ItemData entry;
2300 entry.m_properties.insert(akey: Qt::DisplayPropertyRole, avalue: textValue);
2301 const QVariant iconValue = comboBox->itemData(index: i, role: Qt::DecorationPropertyRole);
2302 if (!iconValue.isNull())
2303 entry.m_properties.insert(akey: Qt::DecorationPropertyRole, avalue: iconValue);
2304 m_items.append(t: entry);
2305 }
2306 }
2307}
2308
2309void ListContents::applyToComboBox(QComboBox *comboBox, DesignerIconCache *iconCache) const
2310{
2311 comboBox->clear();
2312
2313 for (const ItemData &hash : m_items) {
2314 QIcon icon;
2315 if (iconCache)
2316 icon = iconCache->icon(value: qvariant_cast<PropertySheetIconValue>(
2317 v: hash.m_properties[Qt::DecorationPropertyRole]));
2318 QVariant var = hash.m_properties[Qt::DisplayPropertyRole];
2319 PropertySheetStringValue str = qvariant_cast<PropertySheetStringValue>(v: var);
2320 comboBox->addItem(aicon: icon, atext: str.value());
2321 comboBox->setItemData(index: comboBox->count() - 1,
2322 value: var,
2323 role: Qt::DisplayPropertyRole);
2324 comboBox->setItemData(index: comboBox->count() - 1,
2325 value: hash.m_properties[Qt::DecorationPropertyRole],
2326 role: Qt::DecorationPropertyRole);
2327 }
2328}
2329
2330// --------- TableWidgetContents
2331
2332TableWidgetContents::TableWidgetContents() = default;
2333
2334void TableWidgetContents::clear()
2335{
2336 m_horizontalHeader.m_items.clear();
2337 m_verticalHeader.m_items.clear();
2338 m_items.clear();
2339 m_columnCount = 0;
2340 m_rowCount = 0;
2341}
2342
2343QString TableWidgetContents::defaultHeaderText(int i)
2344{
2345 return QString::number(i + 1);
2346}
2347
2348bool TableWidgetContents::nonEmpty(const QTableWidgetItem *item, int headerColumn)
2349{
2350 static const Qt::ItemFlags defaultFlags = QTableWidgetItem().flags();
2351
2352 if (item->flags() != defaultFlags)
2353 return true;
2354
2355 QString text = qvariant_cast<PropertySheetStringValue>(v: item->data(role: Qt::DisplayPropertyRole)).value();
2356 if (!text.isEmpty()) {
2357 if (headerColumn < 0 || text != defaultHeaderText(i: headerColumn))
2358 return true;
2359 } else {
2360 // FIXME: This doesn't seem to make sense
2361 return true;
2362 }
2363
2364 for (int i : itemRoles) {
2365 if (i != Qt::DisplayPropertyRole && item->data(role: i).isValid())
2366 return true;
2367 }
2368
2369 return false;
2370}
2371
2372void TableWidgetContents::insertHeaderItem(const QTableWidgetItem *item, int i, ListContents *header, bool editor)
2373{
2374 if (nonEmpty(item, headerColumn: i))
2375 header->m_items.append(t: ItemData(item, editor));
2376 else
2377 header->m_items.append(t: ItemData());
2378}
2379
2380void TableWidgetContents::fromTableWidget(const QTableWidget *tableWidget, bool editor)
2381{
2382 clear();
2383 m_columnCount = tableWidget->columnCount();
2384 m_rowCount = tableWidget->rowCount();
2385 // horiz header: Legacy behaviour: auto-generate number for empty items
2386 for (int col = 0; col < m_columnCount; col++)
2387 if (const QTableWidgetItem *item = tableWidget->horizontalHeaderItem(column: col))
2388 insertHeaderItem(item, i: col, header: &m_horizontalHeader, editor);
2389 // vertical header: Legacy behaviour: auto-generate number for empty items
2390 for (int row = 0; row < m_rowCount; row++)
2391 if (const QTableWidgetItem *item = tableWidget->verticalHeaderItem(row))
2392 insertHeaderItem(item, i: row, header: &m_verticalHeader, editor);
2393 // cell data
2394 for (int col = 0; col < m_columnCount; col++)
2395 for (int row = 0; row < m_rowCount; row++)
2396 if (const QTableWidgetItem *item = tableWidget->item(row, column: col))
2397 if (nonEmpty(item, headerColumn: -1))
2398 m_items.insert(akey: CellRowColumnAddress(row, col), avalue: ItemData(item, editor));
2399}
2400
2401void TableWidgetContents::applyToTableWidget(QTableWidget *tableWidget, DesignerIconCache *iconCache, bool editor) const
2402{
2403 tableWidget->clear();
2404
2405 tableWidget->setColumnCount(m_columnCount);
2406 tableWidget->setRowCount(m_rowCount);
2407
2408 // horiz header
2409 int col = 0;
2410 for (const ItemData &id : m_horizontalHeader.m_items) {
2411 if (id.isValid())
2412 tableWidget->setHorizontalHeaderItem(column: col, item: id.createTableItem(iconCache, editor));
2413 col++;
2414 }
2415 // vertical header
2416 int row = 0;
2417 for (const ItemData &id : m_verticalHeader.m_items) {
2418 if (id.isValid())
2419 tableWidget->setVerticalHeaderItem(row, item: id.createTableItem(iconCache, editor));
2420 row++;
2421 }
2422 // items
2423 const TableItemMap::const_iterator icend = m_items.constEnd();
2424 for (TableItemMap::const_iterator it = m_items.constBegin(); it != icend; ++ it)
2425 tableWidget->setItem(row: it.key().first, column: it.key().second, item: it.value().createTableItem(iconCache, editor));
2426}
2427
2428bool TableWidgetContents::operator==(const TableWidgetContents &rhs) const
2429{
2430 if (m_columnCount != rhs.m_columnCount || m_rowCount != rhs.m_rowCount)
2431 return false;
2432
2433 return m_horizontalHeader.m_items == rhs.m_horizontalHeader.m_items &&
2434 m_verticalHeader.m_items == rhs.m_verticalHeader.m_items &&
2435 m_items == rhs.m_items;
2436}
2437
2438// ---- ChangeTableContentsCommand ----
2439ChangeTableContentsCommand::ChangeTableContentsCommand(QDesignerFormWindowInterface *formWindow) :
2440 QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Change Table Contents"),
2441 formWindow), m_iconCache(nullptr)
2442{
2443 FormWindowBase *fwb = qobject_cast<FormWindowBase *>(object: formWindow);
2444 if (fwb)
2445 m_iconCache = fwb->iconCache();
2446}
2447
2448void ChangeTableContentsCommand::init(QTableWidget *tableWidget,
2449 const TableWidgetContents &oldCont, const TableWidgetContents &newCont)
2450{
2451 m_tableWidget = tableWidget;
2452 m_oldContents = oldCont;
2453 m_newContents = newCont;
2454}
2455
2456void ChangeTableContentsCommand::redo()
2457{
2458 m_newContents.applyToTableWidget(tableWidget: m_tableWidget, iconCache: m_iconCache, editor: false);
2459 QMetaObject::invokeMethod(obj: m_tableWidget, member: "updateGeometries");
2460}
2461
2462void ChangeTableContentsCommand::undo()
2463{
2464 m_oldContents.applyToTableWidget(tableWidget: m_tableWidget, iconCache: m_iconCache, editor: false);
2465 QMetaObject::invokeMethod(obj: m_tableWidget, member: "updateGeometries");
2466}
2467
2468// --------- TreeWidgetContents
2469TreeWidgetContents::ItemContents::ItemContents(const QTreeWidgetItem *item, bool editor) :
2470 ListContents(item)
2471{
2472 static const Qt::ItemFlags defaultFlags = QTreeWidgetItem().flags();
2473
2474 if (editor) {
2475 QVariant v = item->data(column: 0, role: ItemFlagsShadowRole);
2476 m_itemFlags = v.isValid() ? v.toInt() : -1;
2477 } else {
2478 m_itemFlags = (item->flags() != defaultFlags) ? int(item->flags()) : -1;
2479 }
2480
2481 for (int i = 0; i < item->childCount(); i++)
2482 m_children.append(t: ItemContents(item->child(index: i), editor));
2483}
2484
2485QTreeWidgetItem *TreeWidgetContents::ItemContents::createTreeItem(DesignerIconCache *iconCache, bool editor) const
2486{
2487 QTreeWidgetItem *item = ListContents::createTreeItem(iconCache);
2488
2489 if (editor)
2490 item->setFlags(item->flags() | Qt::ItemIsEditable);
2491
2492 if (m_itemFlags != -1) {
2493 if (editor)
2494 item->setData(column: 0, role: ItemFlagsShadowRole, value: QVariant::fromValue(value: m_itemFlags));
2495 else
2496 item->setFlags((Qt::ItemFlags)m_itemFlags);
2497 }
2498
2499 for (const ItemContents &ic : m_children)
2500 item->addChild(child: ic.createTreeItem(iconCache, editor));
2501
2502 return item;
2503}
2504
2505bool TreeWidgetContents::ItemContents::operator==(const TreeWidgetContents::ItemContents &rhs) const
2506{
2507 return
2508 m_itemFlags == rhs.m_itemFlags &&
2509 m_items == rhs.m_items &&
2510 m_children == rhs.m_children;
2511}
2512
2513void TreeWidgetContents::clear()
2514{
2515 m_headerItem.m_items.clear();
2516 m_rootItems.clear();
2517}
2518
2519void TreeWidgetContents::fromTreeWidget(const QTreeWidget *treeWidget, bool editor)
2520{
2521 clear();
2522 m_headerItem = ListContents(treeWidget->headerItem());
2523 for (int col = 0; col < treeWidget->topLevelItemCount(); col++)
2524 m_rootItems.append(t: ItemContents(treeWidget->topLevelItem(index: col), editor));
2525}
2526
2527void TreeWidgetContents::applyToTreeWidget(QTreeWidget *treeWidget, DesignerIconCache *iconCache, bool editor) const
2528{
2529 treeWidget->clear();
2530
2531 treeWidget->setColumnCount(m_headerItem.m_items.count());
2532 treeWidget->setHeaderItem(m_headerItem.createTreeItem(iconCache));
2533 for (const ItemContents &ic : m_rootItems)
2534 treeWidget->addTopLevelItem(item: ic.createTreeItem(iconCache, editor));
2535 treeWidget->expandAll();
2536}
2537
2538bool TreeWidgetContents::operator==(const TreeWidgetContents &rhs) const
2539{
2540 return
2541 m_headerItem == rhs.m_headerItem &&
2542 m_rootItems == rhs.m_rootItems;
2543}
2544
2545// ---- ChangeTreeContentsCommand ----
2546ChangeTreeContentsCommand::ChangeTreeContentsCommand(QDesignerFormWindowInterface *formWindow)
2547 : QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Change Tree Contents"), formWindow),
2548 m_iconCache(nullptr)
2549{
2550 FormWindowBase *fwb = qobject_cast<FormWindowBase *>(object: formWindow);
2551 if (fwb)
2552 m_iconCache = fwb->iconCache();
2553}
2554
2555void ChangeTreeContentsCommand::init(QTreeWidget *treeWidget,
2556 const TreeWidgetContents &oldState, const TreeWidgetContents &newState)
2557{
2558 m_treeWidget = treeWidget;
2559 m_oldState = oldState;
2560 m_newState = newState;
2561}
2562
2563void ChangeTreeContentsCommand::redo()
2564{
2565 m_newState.applyToTreeWidget(treeWidget: m_treeWidget, iconCache: m_iconCache, editor: false);
2566}
2567
2568void ChangeTreeContentsCommand::undo()
2569{
2570 m_oldState.applyToTreeWidget(treeWidget: m_treeWidget, iconCache: m_iconCache, editor: false);
2571}
2572
2573// ---- ChangeListContentsCommand ----
2574ChangeListContentsCommand::ChangeListContentsCommand(QDesignerFormWindowInterface *formWindow)
2575 : QDesignerFormWindowCommand(QString(), formWindow), m_iconCache(nullptr)
2576{
2577 FormWindowBase *fwb = qobject_cast<FormWindowBase *>(object: formWindow);
2578 if (fwb)
2579 m_iconCache = fwb->iconCache();
2580}
2581
2582void ChangeListContentsCommand::init(QListWidget *listWidget,
2583 const ListContents &oldItems, const ListContents &items)
2584{
2585 m_listWidget = listWidget;
2586 m_comboBox = nullptr;
2587
2588 m_newItemsState = items;
2589 m_oldItemsState = oldItems;
2590}
2591
2592void ChangeListContentsCommand::init(QComboBox *comboBox,
2593 const ListContents &oldItems, const ListContents &items)
2594{
2595 m_listWidget = nullptr;
2596 m_comboBox = comboBox;
2597
2598 m_newItemsState = items;
2599 m_oldItemsState = oldItems;
2600}
2601
2602void ChangeListContentsCommand::redo()
2603{
2604 if (m_listWidget)
2605 m_newItemsState.applyToListWidget(listWidget: m_listWidget, iconCache: m_iconCache, editor: false);
2606 else if (m_comboBox)
2607 m_newItemsState.applyToComboBox(comboBox: m_comboBox, iconCache: m_iconCache);
2608}
2609
2610void ChangeListContentsCommand::undo()
2611{
2612 if (m_listWidget)
2613 m_oldItemsState.applyToListWidget(listWidget: m_listWidget, iconCache: m_iconCache, editor: false);
2614 else if (m_comboBox)
2615 m_oldItemsState.applyToComboBox(comboBox: m_comboBox, iconCache: m_iconCache);
2616}
2617
2618// ---- AddActionCommand ----
2619
2620AddActionCommand::AddActionCommand(QDesignerFormWindowInterface *formWindow) :
2621 QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Add action"), formWindow)
2622{
2623 m_action = nullptr;
2624}
2625
2626void AddActionCommand::init(QAction *action)
2627{
2628 Q_ASSERT(m_action == nullptr);
2629 m_action = action;
2630}
2631
2632void AddActionCommand::redo()
2633{
2634 core()->actionEditor()->setFormWindow(formWindow());
2635 core()->actionEditor()->manageAction(action: m_action);
2636}
2637
2638void AddActionCommand::undo()
2639{
2640 core()->actionEditor()->setFormWindow(formWindow());
2641 core()->actionEditor()->unmanageAction(action: m_action);
2642}
2643
2644// ---- RemoveActionCommand ----
2645
2646RemoveActionCommand::RemoveActionCommand(QDesignerFormWindowInterface *formWindow) :
2647 QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Remove action"), formWindow),
2648 m_action(0)
2649{
2650}
2651
2652static RemoveActionCommand::ActionData findActionIn(QAction *action)
2653{
2654 RemoveActionCommand::ActionData result;
2655 // We only want menus and toolbars, no toolbuttons.
2656 const QWidgetList &associatedWidgets = action->associatedWidgets();
2657 for (QWidget *widget : associatedWidgets) {
2658 if (qobject_cast<const QMenu *>(object: widget) || qobject_cast<const QToolBar *>(object: widget)) {
2659 const auto actionList = widget->actions();
2660 const int size = actionList.size();
2661 for (int i = 0; i < size; ++i) {
2662 if (actionList.at(i) == action) {
2663 QAction *before = nullptr;
2664 if (i + 1 < size)
2665 before = actionList.at(i: i + 1);
2666 result.append(t: RemoveActionCommand::ActionDataItem(before, widget));
2667 break;
2668 }
2669 }
2670 }
2671 }
2672 return result;
2673}
2674
2675void RemoveActionCommand::init(QAction *action)
2676{
2677 Q_ASSERT(m_action == nullptr);
2678 m_action = action;
2679
2680 m_actionData = findActionIn(action);
2681}
2682
2683void RemoveActionCommand::redo()
2684{
2685 QDesignerFormWindowInterface *fw = formWindow();
2686 for (const ActionDataItem &item : qAsConst(t&: m_actionData)) {
2687 item.widget->removeAction(action: m_action);
2688 }
2689 // Notify components (for example, signal slot editor)
2690 if (qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(object: fw))
2691 fwb->emitObjectRemoved(o: m_action);
2692
2693 core()->actionEditor()->setFormWindow(fw);
2694 core()->actionEditor()->unmanageAction(action: m_action);
2695 if (!m_actionData.isEmpty())
2696 core()->objectInspector()->setFormWindow(fw);
2697}
2698
2699void RemoveActionCommand::undo()
2700{
2701 core()->actionEditor()->setFormWindow(formWindow());
2702 core()->actionEditor()->manageAction(action: m_action);
2703 for (const ActionDataItem &item : qAsConst(t&: m_actionData))
2704 item.widget->insertAction(before: item.before, action: m_action);
2705 if (!m_actionData.isEmpty())
2706 core()->objectInspector()->setFormWindow(formWindow());
2707}
2708
2709// ---- ActionInsertionCommand ----
2710
2711ActionInsertionCommand::ActionInsertionCommand(const QString &text, QDesignerFormWindowInterface *formWindow) :
2712 QDesignerFormWindowCommand(text, formWindow),
2713 m_parentWidget(nullptr),
2714 m_action(nullptr),
2715 m_beforeAction(nullptr),
2716 m_update(false)
2717{
2718}
2719
2720void ActionInsertionCommand::init(QWidget *parentWidget, QAction *action, QAction *beforeAction, bool update)
2721{
2722 Q_ASSERT(m_parentWidget == nullptr);
2723 Q_ASSERT(m_action == nullptr);
2724
2725 m_parentWidget = parentWidget;
2726 m_action = action;
2727 m_beforeAction = beforeAction;
2728 m_update = update;
2729}
2730
2731void ActionInsertionCommand::insertAction()
2732{
2733 Q_ASSERT(m_action != nullptr);
2734 Q_ASSERT(m_parentWidget != nullptr);
2735
2736 if (m_beforeAction)
2737 m_parentWidget->insertAction(before: m_beforeAction, action: m_action);
2738 else
2739 m_parentWidget->addAction(action: m_action);
2740
2741 if (m_update) {
2742 cheapUpdate();
2743 if (QMenu *menu = m_action->menu())
2744 selectUnmanagedObject(unmanagedObject: menu);
2745 else
2746 selectUnmanagedObject(unmanagedObject: m_action);
2747 PropertyHelper::triggerActionChanged(a: m_action); // Update Used column in action editor.
2748 }
2749}
2750void ActionInsertionCommand::removeAction()
2751{
2752 Q_ASSERT(m_action != nullptr);
2753 Q_ASSERT(m_parentWidget != nullptr);
2754
2755 if (QDesignerMenu *menu = qobject_cast<QDesignerMenu*>(object: m_parentWidget))
2756 menu->hideSubMenu();
2757
2758 m_parentWidget->removeAction(action: m_action);
2759
2760 if (m_update) {
2761 cheapUpdate();
2762 selectUnmanagedObject(unmanagedObject: m_parentWidget);
2763 PropertyHelper::triggerActionChanged(a: m_action); // Update Used column in action editor.
2764 }
2765}
2766
2767InsertActionIntoCommand::InsertActionIntoCommand(QDesignerFormWindowInterface *formWindow) :
2768 ActionInsertionCommand(QApplication::translate(context: "Command", key: "Add action"), formWindow)
2769{
2770}
2771// ---- RemoveActionFromCommand ----
2772
2773RemoveActionFromCommand::RemoveActionFromCommand(QDesignerFormWindowInterface *formWindow) :
2774 ActionInsertionCommand(QApplication::translate(context: "Command", key: "Remove action"), formWindow)
2775{
2776}
2777
2778// ---- AddMenuActionCommand ----
2779
2780MenuActionCommand::MenuActionCommand(const QString &text, QDesignerFormWindowInterface *formWindow) :
2781 QDesignerFormWindowCommand(text, formWindow),
2782 m_action(nullptr),
2783 m_actionBefore(nullptr),
2784 m_menuParent(nullptr),
2785 m_associatedWidget(nullptr),
2786 m_objectToSelect(nullptr)
2787{
2788}
2789
2790void MenuActionCommand::init(QAction *action, QAction *actionBefore,
2791 QWidget *associatedWidget, QWidget *objectToSelect)
2792{
2793 QMenu *menu = action->menu();
2794 Q_ASSERT(menu);
2795 m_menuParent = menu->parentWidget();
2796 m_action = action;
2797 m_actionBefore = actionBefore;
2798 m_associatedWidget = associatedWidget;
2799 m_objectToSelect = objectToSelect;
2800}
2801
2802void MenuActionCommand::insertMenu()
2803{
2804 core()->metaDataBase()->add(object: m_action);
2805 QMenu *menu = m_action->menu();
2806 if (m_menuParent && menu->parentWidget() != m_menuParent)
2807 menu->setParent(m_menuParent);
2808 core()->metaDataBase()->add(object: menu);
2809 m_associatedWidget->insertAction(before: m_actionBefore, action: m_action);
2810 cheapUpdate();
2811 selectUnmanagedObject(unmanagedObject: menu);
2812}
2813
2814void MenuActionCommand::removeMenu()
2815{
2816 m_action->menu()->setParent(nullptr);
2817 QMenu *menu = m_action->menu();
2818 core()->metaDataBase()->remove(object: menu);
2819 menu->setParent(nullptr);
2820 core()->metaDataBase()->remove(object: m_action);
2821 m_associatedWidget->removeAction(action: m_action);
2822 cheapUpdate();
2823 selectUnmanagedObject(unmanagedObject: m_objectToSelect);
2824}
2825
2826AddMenuActionCommand::AddMenuActionCommand(QDesignerFormWindowInterface *formWindow) :
2827 MenuActionCommand(QApplication::translate(context: "Command", key: "Add menu"), formWindow)
2828{
2829}
2830
2831// ---- RemoveMenuActionCommand ----
2832RemoveMenuActionCommand::RemoveMenuActionCommand(QDesignerFormWindowInterface *formWindow) :
2833 MenuActionCommand(QApplication::translate(context: "Command", key: "Remove menu"), formWindow)
2834{
2835}
2836
2837// ---- CreateSubmenuCommand ----
2838CreateSubmenuCommand::CreateSubmenuCommand(QDesignerFormWindowInterface *formWindow) :
2839 QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Create submenu"), formWindow),
2840 m_action(nullptr),
2841 m_menu(nullptr),
2842 m_objectToSelect(nullptr)
2843{
2844}
2845
2846void CreateSubmenuCommand::init(QDesignerMenu *menu, QAction *action, QObject *objectToSelect)
2847{
2848 m_menu = menu;
2849 m_action = action;
2850 m_objectToSelect = objectToSelect;
2851}
2852
2853void CreateSubmenuCommand::redo()
2854{
2855 m_menu->createRealMenuAction(action: m_action);
2856 cheapUpdate();
2857 if (m_objectToSelect)
2858 selectUnmanagedObject(unmanagedObject: m_objectToSelect);
2859}
2860
2861void CreateSubmenuCommand::undo()
2862{
2863 m_menu->removeRealMenu(action: m_action);
2864 cheapUpdate();
2865 selectUnmanagedObject(unmanagedObject: m_menu);
2866}
2867
2868// ---- DeleteToolBarCommand ----
2869DeleteToolBarCommand::DeleteToolBarCommand(QDesignerFormWindowInterface *formWindow)
2870 : QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Delete Tool Bar"), formWindow)
2871{
2872}
2873
2874void DeleteToolBarCommand::init(QToolBar *toolBar)
2875{
2876 m_toolBar = toolBar;
2877 m_mainWindow = qobject_cast<QMainWindow*>(object: toolBar->parentWidget());
2878}
2879
2880void DeleteToolBarCommand::redo()
2881{
2882 if (m_mainWindow) {
2883 QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(manager: core()->extensionManager(), object: m_mainWindow);
2884 Q_ASSERT(c != nullptr);
2885 for (int i=0; i<c->count(); ++i) {
2886 if (c->widget(index: i) == m_toolBar) {
2887 c->remove(index: i);
2888 break;
2889 }
2890 }
2891 }
2892
2893 core()->metaDataBase()->remove(object: m_toolBar);
2894 m_toolBar->hide();
2895 m_toolBar->setParent(formWindow());
2896 formWindow()->emitSelectionChanged();
2897}
2898
2899void DeleteToolBarCommand::undo()
2900{
2901 if (m_mainWindow) {
2902 m_toolBar->setParent(m_mainWindow);
2903 QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(manager: core()->extensionManager(), object: m_mainWindow);
2904
2905 c->addWidget(widget: m_toolBar);
2906
2907 core()->metaDataBase()->add(object: m_toolBar);
2908 m_toolBar->show();
2909 formWindow()->emitSelectionChanged();
2910 }
2911}
2912
2913} // namespace qdesigner_internal
2914
2915QT_END_NAMESPACE
2916

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