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_command2_p.h"
30#include "formwindowbase_p.h"
31#include "layoutinfo_p.h"
32#include "qdesigner_command_p.h"
33#include "widgetfactory_p.h"
34#include "qlayout_widget_p.h"
35
36#include <QtDesigner/abstractformeditor.h>
37#include <QtDesigner/abstractmetadatabase.h>
38
39#include <QtWidgets/qapplication.h>
40#include <QtWidgets/qlayout.h>
41
42QT_BEGIN_NAMESPACE
43
44namespace qdesigner_internal {
45
46MorphLayoutCommand::MorphLayoutCommand(QDesignerFormWindowInterface *formWindow) :
47 QDesignerFormWindowCommand(QString(), formWindow),
48 m_breakLayoutCommand(new BreakLayoutCommand(formWindow)),
49 m_layoutCommand(new LayoutCommand(formWindow)),
50 m_newType(LayoutInfo::VBox),
51 m_layoutBase(nullptr)
52{
53}
54
55MorphLayoutCommand::~MorphLayoutCommand()
56{
57 delete m_layoutCommand;
58 delete m_breakLayoutCommand;
59}
60
61bool MorphLayoutCommand::init(QWidget *w, int newType)
62{
63 int oldType;
64 QDesignerFormWindowInterface *fw = formWindow();
65 if (!canMorph(formWindow: fw, w, ptrToCurrentType: &oldType) || oldType == newType)
66 return false;
67 m_layoutBase = w;
68 m_newType = newType;
69 // Find all managed widgets
70 m_widgets.clear();
71 const QLayout *layout = LayoutInfo::managedLayout(core: fw->core(), widget: w);
72 const int count = layout->count();
73 for (int i = 0; i < count ; i++) {
74 if (QWidget *w = layout->itemAt(index: i)->widget())
75 if (fw->isManaged(widget: w))
76 m_widgets.push_back(t: w);
77 }
78 const bool reparentLayoutWidget = false; // leave QLayoutWidget intact
79 m_breakLayoutCommand->init(widgets: m_widgets, layoutBase: m_layoutBase, reparentLayoutWidget);
80 m_layoutCommand->init(parentWidget: m_layoutBase, widgets: m_widgets, layoutType: static_cast<LayoutInfo::Type>(m_newType), layoutBase: m_layoutBase, reparentLayoutWidget);
81 setText(formatDescription(core: core(), w: m_layoutBase, oldType, newType));
82 return true;
83}
84
85bool MorphLayoutCommand::canMorph(const QDesignerFormWindowInterface *formWindow, QWidget *w, int *ptrToCurrentType)
86{
87 if (ptrToCurrentType)
88 *ptrToCurrentType = LayoutInfo::NoLayout;
89 // We want a managed widget or a container page
90 // with a level-0 managed layout
91 QDesignerFormEditorInterface *core = formWindow->core();
92 QLayout *layout = LayoutInfo::managedLayout(core, widget: w);
93 if (!layout)
94 return false;
95 const LayoutInfo::Type type = LayoutInfo::layoutType(core, layout);
96 if (ptrToCurrentType)
97 *ptrToCurrentType = type;
98 switch (type) {
99 case LayoutInfo::HBox:
100 case LayoutInfo::VBox:
101 case LayoutInfo::Grid:
102 case LayoutInfo::Form:
103 return true;
104 break;
105 case LayoutInfo::NoLayout:
106 case LayoutInfo::HSplitter: // Nothing doing
107 case LayoutInfo::VSplitter:
108 case LayoutInfo::UnknownLayout:
109 break;
110 }
111 return false;
112}
113
114void MorphLayoutCommand::redo()
115{
116 m_breakLayoutCommand->redo();
117 m_layoutCommand->redo();
118 /* Transfer applicable properties which is a cross-section of the modified
119 * properties except object name. */
120 if (const LayoutProperties *properties = m_breakLayoutCommand->layoutProperties()) {
121 const int oldMask = m_breakLayoutCommand->propertyMask();
122 QLayout *newLayout = LayoutInfo::managedLayout(core: core(), widget: m_layoutBase);
123 const int newMask = LayoutProperties::visibleProperties(layout: newLayout);
124 const int applicableMask = (oldMask & newMask) & ~LayoutProperties::ObjectNameProperty;
125 if (applicableMask)
126 properties->toPropertySheet(core: core(), l: newLayout, mask: applicableMask);
127 }
128}
129
130void MorphLayoutCommand::undo()
131{
132 m_layoutCommand->undo();
133 m_breakLayoutCommand->undo();
134}
135
136QString MorphLayoutCommand::formatDescription(QDesignerFormEditorInterface * /* core*/, const QWidget *w, int oldType, int newType)
137{
138 const QString oldName = LayoutInfo::layoutName(t: static_cast<LayoutInfo::Type>(oldType));
139 const QString newName = LayoutInfo::layoutName(t: static_cast<LayoutInfo::Type>(newType));
140 const QString widgetName = qobject_cast<const QLayoutWidget*>(object: w) ? w->layout()->objectName() : w->objectName();
141 return QApplication::translate(context: "Command", key: "Change layout of '%1' from %2 to %3").arg(a1: widgetName, a2: oldName, a3: newName);
142}
143
144LayoutAlignmentCommand::LayoutAlignmentCommand(QDesignerFormWindowInterface *formWindow) :
145 QDesignerFormWindowCommand(QApplication::translate(context: "Command", key: "Change layout alignment"), formWindow),
146 m_widget(nullptr)
147{
148}
149
150bool LayoutAlignmentCommand::init(QWidget *w, Qt::Alignment alignment)
151{
152 bool enabled;
153 m_newAlignment = alignment;
154 m_oldAlignment = LayoutAlignmentCommand::alignmentOf(core: core(), w, enabled: &enabled);
155 m_widget = w;
156 return enabled;
157}
158
159void LayoutAlignmentCommand::redo()
160{
161 LayoutAlignmentCommand::applyAlignment(core: core(), w: m_widget, a: m_newAlignment);
162}
163
164void LayoutAlignmentCommand::undo()
165{
166 LayoutAlignmentCommand::applyAlignment(core: core(), w: m_widget, a: m_oldAlignment);
167}
168
169// Find out alignment and return whether command is enabled.
170Qt::Alignment LayoutAlignmentCommand::alignmentOf(const QDesignerFormEditorInterface *core, QWidget *w, bool *enabledIn)
171{
172 bool managed;
173 QLayout *layout;
174
175 if (enabledIn)
176 *enabledIn = false;
177 // Can only work on a managed layout
178 const LayoutInfo::Type type = LayoutInfo::laidoutWidgetType(core, widget: w, isManaged: &managed, layout: &layout);
179 const bool enabled = layout && managed &&
180 (type == LayoutInfo::HBox || type == LayoutInfo::VBox
181 || type == LayoutInfo::Grid);
182 if (!enabled)
183 return {};
184 // Get alignment
185 const int index = layout->indexOf(w);
186 Q_ASSERT(index >= 0);
187 if (enabledIn)
188 *enabledIn = true;
189 return layout->itemAt(index)->alignment();
190}
191
192void LayoutAlignmentCommand::applyAlignment(const QDesignerFormEditorInterface *core, QWidget *w, Qt::Alignment a)
193{
194 // Find layout and apply to item
195 QLayout *layout;
196 LayoutInfo::laidoutWidgetType(core, widget: w, isManaged: nullptr, layout: &layout);
197 if (layout) {
198 const int index = layout->indexOf(w);
199 if (index >= 0) {
200 layout->itemAt(index)->setAlignment(a);
201 layout->update();
202 }
203 }
204}
205
206} // namespace qdesigner_internal
207
208QT_END_NAMESPACE
209

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