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 //
30 //  W A R N I N G
31 //  -------------
32 //
33 // This file is not part of the Qt API.  It exists for the convenience
34 // of Qt Designer.  This header
35 // file may change from version to version without notice, or even be removed.
36 //
37 // We mean it.
38 //
39 
40 #ifndef QLAYOUT_WIDGET_H
41 #define QLAYOUT_WIDGET_H
42 
43 #include "shared_global_p.h"
44 
45 #include <QtDesigner/layoutdecoration.h>
46 
47 #include <QtCore/qpointer.h>
48 #include <QtCore/qvariant.h>
49 #include <QtWidgets/qwidget.h>
50 #include <QtWidgets/qlayout.h>
51 
52 QT_BEGIN_NAMESPACE
53 
54 class QDesignerFormWindowInterface;
55 class QDesignerFormEditorInterface;
56 class QGridLayout;
57 class QFormLayout;
58 
59 namespace qdesigner_internal {
60 // ---- LayoutProperties: Helper struct that stores all layout-relevant properties
61 //      with functions to retrieve and apply to property sheets. Can be used to store the state
62 //      for undo commands and while rebuilding layouts.
63 struct QDESIGNER_SHARED_EXPORT LayoutProperties
64 {
65     LayoutProperties();
66     void clear();
67 
68     enum Margins { LeftMargin, TopMargin, RightMargin, BottomMargin, MarginCount };
69     enum Spacings { Spacing, HorizSpacing, VertSpacing, SpacingsCount };
70 
71     enum PropertyMask {
72         ObjectNameProperty  = 0x1,
73         LeftMarginProperty = 0x2, TopMarginProperty = 0x4, RightMarginProperty = 0x8, BottomMarginProperty = 0x10,
74         SpacingProperty = 0x20, HorizSpacingProperty = 0x40, VertSpacingProperty = 0x80,
75         SizeConstraintProperty = 0x100,
76         FieldGrowthPolicyProperty = 0x200, RowWrapPolicyProperty = 0x400, LabelAlignmentProperty = 0x0800, FormAlignmentProperty = 0x1000,
77         BoxStretchProperty = 0x2000, GridRowStretchProperty = 0x4000, GridColumnStretchProperty = 0x8000,
78         GridRowMinimumHeightProperty = 0x10000, GridColumnMinimumWidthProperty = 0x20000,
79         AllProperties = 0xFFFF};
80 
81     // return a PropertyMask of visible properties
82     static int visibleProperties(const QLayout *layout);
83 
84     // Retrieve from /apply to sheet: A property mask is returned indicating the properties found in the sheet
85     int fromPropertySheet(const QDesignerFormEditorInterface *core, QLayout *l, int mask = AllProperties);
86     int toPropertySheet(const QDesignerFormEditorInterface *core, QLayout *l, int mask = AllProperties, bool applyChanged = true) const;
87 
88     int m_margins[MarginCount];
89     bool m_marginsChanged[MarginCount];
90 
91     int m_spacings[SpacingsCount];
92     bool m_spacingsChanged[SpacingsCount];
93 
94     QVariant m_objectName; // receives a PropertySheetStringValue
95     bool m_objectNameChanged;
96     QVariant m_sizeConstraint;
97     bool m_sizeConstraintChanged;
98 
99     bool m_fieldGrowthPolicyChanged;
100     QVariant m_fieldGrowthPolicy;
101     bool m_rowWrapPolicyChanged;
102     QVariant m_rowWrapPolicy;
103     bool m_labelAlignmentChanged;
104     QVariant m_labelAlignment;
105     bool m_formAlignmentChanged;
106     QVariant m_formAlignment;
107 
108     bool m_boxStretchChanged;
109     QVariant m_boxStretch;
110 
111     bool m_gridRowStretchChanged;
112     QVariant m_gridRowStretch;
113 
114     bool m_gridColumnStretchChanged;
115     QVariant m_gridColumnStretch;
116 
117     bool m_gridRowMinimumHeightChanged;
118     QVariant m_gridRowMinimumHeight;
119 
120     bool m_gridColumnMinimumWidthChanged;
121     QVariant  m_gridColumnMinimumWidth;
122 };
123 
124 // -- LayoutHelper: For use with the 'insert widget'/'delete widget' command,
125 //    able to store and restore states.
126 //    This could become part of 'QDesignerLayoutDecorationExtensionV2',
127 //    but to keep any existing old extensions working, it is provided as
128 //    separate class with a factory function.
129 class LayoutHelper {
130 protected:
131     LayoutHelper();
132 
133 public:
134     Q_DISABLE_COPY(LayoutHelper)
135 
136     virtual ~LayoutHelper();
137 
138     static LayoutHelper *createLayoutHelper(int type);
139 
140     static int indexOf(const QLayout *lt, const QWidget *widget);
141 
142     // Return area of an item (x == columns)
143     QRect itemInfo(QLayout *lt, const QWidget *widget) const;
144 
145     virtual QRect itemInfo(QLayout *lt, int index) const = 0;
146     virtual void insertWidget(QLayout *lt, const QRect &info, QWidget *w) = 0;
147     virtual void removeWidget(QLayout *lt, QWidget *widget) = 0;
148     // Since 4.5: The 'morphing' feature requires an API for replacing widgets on layouts.
149     virtual void replaceWidget(QLayout *lt, QWidget *before, QWidget *after) = 0;
150 
151     // Simplify a grid, remove empty columns, rows within the rectangle
152     // The DeleteWidget command restricts the area to be simplified.
153     virtual bool canSimplify(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout, const QRect &restrictionArea) const = 0;
154     virtual void simplify(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout, const QRect &restrictionArea) = 0;
155 
156     // Push and pop a state. Can be used for implementing undo for
157     // simplify/row, column insertion commands, provided that
158     // the widgets remain the same.
159     virtual void pushState(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout)  = 0;
160     virtual void popState(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout) = 0;
161 };
162 
163 // Base class for layout decoration extensions.
164 class QDESIGNER_SHARED_EXPORT QLayoutSupport: public QObject, public QDesignerLayoutDecorationExtension
165 {
166     Q_OBJECT
167     Q_INTERFACES(QDesignerLayoutDecorationExtension)
168 
169 protected:
170     QLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, LayoutHelper *helper, QObject *parent = nullptr);
171 
172 public:
173     ~QLayoutSupport() override;
174 
formWindow()175     inline QDesignerFormWindowInterface *formWindow() const   { return m_formWindow; }
176 
177     // DecorationExtension V2
helper()178     LayoutHelper* helper() const                              { return m_helper; }
179 
180     // DecorationExtension
currentIndex()181     int currentIndex() const override                  { return m_currentIndex; }
182 
currentInsertMode()183     InsertMode currentInsertMode() const override      { return m_currentInsertMode; }
184 
currentCell()185     QPair<int, int> currentCell() const  override      { return m_currentCell; }
186 
187     int findItemAt(const QPoint &pos) const override;
188     int indexOf(QWidget *widget) const override;
189     int indexOf(QLayoutItem *item) const override;
190 
191     void adjustIndicator(const QPoint &pos, int index) override;
192 
193     QWidgetList widgets(QLayout *layout) const override;
194 
195     // Pad empty cells with dummy spacers. Called by layouting commands.
196     static void createEmptyCells(QGridLayout *gridLayout);
197     // remove dummy spacers in the area. Returns false if there are non-empty items in the way
198     static bool removeEmptyCells(QGridLayout *gridLayout, const QRect &area);
199     static void createEmptyCells(QFormLayout *formLayout); // ditto.
200     static bool removeEmptyCells(QFormLayout *formLayout, const QRect &area);
201 
202     // grid helpers: find item index
203     static int findItemAt(QGridLayout *, int row, int column);
204     // grid helpers: Quick check whether simplify should be enabled for grids. May return false positives.
205     static bool canSimplifyQuickCheck(const QGridLayout *);
206     static bool canSimplifyQuickCheck(const QFormLayout *fl);
207     // Factory function, create layout support according to layout type of widget
208     static QLayoutSupport *createLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, QObject *parent = nullptr);
209 
210 protected:
211     // figure out insertion position and mode from indicator on empty cell if supported
212     virtual void setCurrentCellFromIndicatorOnEmptyCell(int index) = 0;
213     // figure out insertion position and mode from indicator
214     virtual void setCurrentCellFromIndicator(Qt::Orientation indicatorOrientation, int index, int increment) = 0;
215 
216     // Overwrite to return the extended geometry of an item, that is,
217     // if it is a border item, include the widget border for the indicator to work correctly
218     virtual QRect extendedGeometry(int index) const = 0;
219     virtual bool supportsIndicatorOrientation(Qt::Orientation indicatorOrientation) const = 0;
220 
221     QRect itemInfo(int index) const override;
222     QLayout *layout() const;
223     QGridLayout *gridLayout() const;
widget()224     QWidget *widget() const              { return m_widget; }
225 
226     void setInsertMode(InsertMode im);
227     void setCurrentCell(const QPair<int, int> &cell);
228 
229 private:
230     enum Indicator { LeftIndicator, TopIndicator, RightIndicator, BottomIndicator, NumIndicators };
231 
232     void hideIndicator(Indicator i);
233     void showIndicator(Indicator i, const QRect &geometry, const QPalette &);
234 
235     QDesignerFormWindowInterface *m_formWindow;
236     LayoutHelper* m_helper;
237 
238     QPointer<QWidget> m_widget;
239     QPointer<QWidget> m_indicators[NumIndicators];
240     int m_currentIndex;
241     InsertMode m_currentInsertMode;
242     QPair<int, int> m_currentCell;
243 };
244 } // namespace qdesigner_internal
245 
246 // Red layout widget.
247 class QDESIGNER_SHARED_EXPORT QLayoutWidget: public QWidget
248 {
249     Q_OBJECT
250 public:
251     explicit QLayoutWidget(QDesignerFormWindowInterface *formWindow, QWidget *parent = nullptr);
252 
253     int layoutLeftMargin() const;
254     void setLayoutLeftMargin(int layoutMargin);
255 
256     int layoutTopMargin() const;
257     void setLayoutTopMargin(int layoutMargin);
258 
259     int layoutRightMargin() const;
260     void setLayoutRightMargin(int layoutMargin);
261 
262     int layoutBottomMargin() const;
263     void setLayoutBottomMargin(int layoutMargin);
264 
formWindow()265     inline QDesignerFormWindowInterface *formWindow() const    { return m_formWindow; }
266 
267 protected:
268     bool event(QEvent *e) override;
269     void paintEvent(QPaintEvent *e) override;
270 
271 private:
272     QDesignerFormWindowInterface *m_formWindow;
273     int m_leftMargin;
274     int m_topMargin;
275     int m_rightMargin;
276     int m_bottomMargin;
277 };
278 
279 QT_END_NAMESPACE
280 
281 #endif // QDESIGNER_WIDGET_H
282