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 #ifndef FORMWINDOW_H
30 #define FORMWINDOW_H
31 
32 #include "formeditor_global.h"
33 #include <formwindowbase_p.h>
34 
35 // Qt
36 #include <QtWidgets/qundostack.h>
37 #include <QtCore/qhash.h>
38 #include <QtCore/qlist.h>
39 #include <QtCore/qmap.h>
40 #include <QtCore/qset.h>
41 #include <QtCore/qpointer.h>
42 
43 QT_BEGIN_NAMESPACE
44 
45 class QDesignerDnDItemInterface;
46 class QDesignerTaskMenuExtension;
47 class DomConnections;
48 class DomUI;
49 
50 class QWidget;
51 class QAction;
52 class QLabel;
53 class QTimer;
54 class QAction;
55 class QMenu;
56 class QRubberBand;
57 
58 namespace qdesigner_internal {
59 
60 class FormEditor;
61 class FormWindowCursor;
62 class WidgetEditorTool;
63 class FormWindowWidgetStack;
64 class FormWindowManager;
65 class FormWindowDnDItem;
66 class SetPropertyCommand;
67 
68 class QT_FORMEDITOR_EXPORT FormWindow: public FormWindowBase
69 {
70     Q_OBJECT
71 
72 public:
73     enum HandleOperation
74     {
75         NoHandleOperation,
76         ResizeHandleOperation,
77         ChangeLayoutSpanHandleOperation
78     };
79 
80     explicit FormWindow(FormEditor *core, QWidget *parent = nullptr, Qt::WindowFlags flags = {});
81     ~FormWindow() override;
82 
83     QDesignerFormEditorInterface *core() const override;
84 
85     QDesignerFormWindowCursorInterface *cursor() const override;
86 
87     // Overwritten: FormWindowBase
88     QWidget *formContainer() const override;
89 
90     int toolCount() const override;
91     int currentTool() const override;
92     void setCurrentTool(int index) override;
93     QDesignerFormWindowToolInterface *tool(int index) const override;
94     void registerTool(QDesignerFormWindowToolInterface *tool) override;
95 
96     QString author() const override;
97     void setAuthor(const QString &author) override;
98 
99     QString comment() const override;
100     void setComment(const QString &comment) override;
101 
102     void layoutDefault(int *margin, int *spacing) override;
103     void setLayoutDefault(int margin, int spacing) override;
104 
105     void layoutFunction(QString *margin, QString *spacing) override;
106     void setLayoutFunction(const QString &margin, const QString &spacing) override;
107 
108     QString pixmapFunction() const override;
109     void setPixmapFunction(const QString &pixmapFunction) override;
110 
111     QString exportMacro() const override;
112     void setExportMacro(const QString &exportMacro) override;
113 
114     QStringList includeHints() const override;
115     void setIncludeHints(const QStringList &includeHints) override;
116 
117     QString fileName() const override;
118     void setFileName(const QString &fileName) override;
119 
120     QString contents() const override;
121     bool setContents(QIODevice *dev, QString *errorMessage = nullptr) override;
122     bool setContents(const QString &) override;
123 
124     QDir absoluteDir() const override;
125 
126     void simplifySelection(QWidgetList *sel) const override;
127 
128     void ensureUniqueObjectName(QObject *object) override;
129 
130     QWidget *mainContainer() const override;
131     void setMainContainer(QWidget *mainContainer) override;
132     bool isMainContainer(const QWidget *w) const;
133 
134     QWidget *currentWidget() const;
135 
136     bool hasInsertedChildren(QWidget *w) const;
137 
138     QWidgetList selectedWidgets() const;
139     void clearSelection(bool changePropertyDisplay = true) override;
140     bool isWidgetSelected(QWidget *w) const;
141     void selectWidget(QWidget *w, bool select = true) override;
142 
143     void selectWidgets();
144     void repaintSelection();
145     void updateSelection(QWidget *w);
146     void updateChildSelections(QWidget *w);
147     void raiseChildSelections(QWidget *w);
148     void raiseSelection(QWidget *w);
149 
150     inline const QWidgetList& widgets() const { return m_widgets; }
151     inline int widgetCount() const { return m_widgets.count(); }
152     inline QWidget *widgetAt(int index) const { return m_widgets.at(index); }
153 
154     QWidgetList widgets(QWidget *widget) const;
155 
156     QWidget *createWidget(DomUI *ui, const QRect &rect, QWidget *target);
157 
158     bool isManaged(QWidget *w) const override;
159 
160     void manageWidget(QWidget *w) override;
161     void unmanageWidget(QWidget *w) override;
162 
163     QUndoStack *commandHistory() const override;
164     void beginCommand(const QString &description) override;
165     void endCommand() override;
166 
167     bool blockSelectionChanged(bool blocked) override;
168     void emitSelectionChanged() override;
169 
170     bool unify(QObject *w, QString &s, bool changeIt);
171 
172     bool isDirty() const override;
173     void setDirty(bool dirty) override;
174 
175     static FormWindow *findFormWindow(QWidget *w);
176 
177     virtual QWidget *containerAt(const QPoint &pos);
178     QWidget *widgetAt(const QPoint &pos) override;
179     void highlightWidget(QWidget *w, const QPoint &pos, HighlightMode mode = Highlight) override;
180 
181     void updateOrderIndicators();
182 
183     bool handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event);
184 
185     QStringList resourceFiles() const override;
186     void addResourceFile(const QString &path) override;
187     void removeResourceFile(const QString &path) override;
188 
189     void resizeWidget(QWidget *widget, const QRect &geometry);
190 
191     bool dropDockWidget(QDesignerDnDItemInterface *item, const QPoint &global_mouse_pos);
192     bool dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, QWidget *target,
193                      const QPoint &global_mouse_pos) override;
194 
195     QWidget *findContainer(QWidget *w, bool excludeLayout) const override;
196     // for WidgetSelection only.
197     QWidget *designerWidget(QWidget *w) const;
198 
199     //  Initialize and return a popup menu for a managed widget
200     QMenu *initializePopupMenu(QWidget *managedWidget) override;
201 
202 #if QT_CONFIG(clipboard)
203     void paste(PasteMode pasteMode) override;
204 #endif
205     QEditorFormBuilder *createFormBuilder() override;
206 
207     bool eventFilter(QObject *watched, QEvent *event) override;
208 
209     HandleOperation handleOperation() const { return m_handleOperation; }
210     void setHandleOperation(HandleOperation o) { m_handleOperation = o; }
211 
212 signals:
213     void contextMenuRequested(QMenu *menu, QWidget *widget);
214 
215 public slots:
216     void deleteWidgets();
217     void raiseWidgets();
218     void lowerWidgets();
219 #if QT_CONFIG(clipboard)
220     void copy();
221     void cut();
222     void paste();
223 #endif
224     void selectAll();
225 
226     void createLayout(int type, QWidget *container = nullptr);
227     void morphLayout(QWidget *container, int newType);
228     void breakLayout(QWidget *w);
229 
230     void editContents();
231 
232 protected:
233     virtual QMenu *createPopupMenu(QWidget *w);
234     void resizeEvent(QResizeEvent *e) override;
235 
236     void insertWidget(QWidget *w, const QRect &rect, QWidget *target, bool already_in_form = false);
237 
238 private slots:
239     void selectionChangedTimerDone();
240     void checkSelection();
241     void checkSelectionNow();
242     void slotSelectWidget(QAction *);
243     void slotCleanChanged(bool);
244 
245 private:
246     enum MouseState {
247         NoMouseState,
248         // Double click received
249         MouseDoubleClicked,
250         // Drawing selection rubber band rectangle
251         MouseDrawRubber,
252         // Started a move operation
253         MouseMoveDrag,
254         // Click on a widget whose parent is selected. Defer selection to release
255         MouseDeferredSelection
256     };
257     MouseState m_mouseState;
258     QPointer<QWidget> m_lastClickedWidget;
259 
260     void init();
261     void initializeCoreTools();
262 
263     int getValue(const QRect &rect, int key, bool size) const;
264     int calcValue(int val, bool forward, bool snap, int snapOffset) const;
265     void handleClickSelection(QWidget *managedWidget, unsigned mouseFlags);
266 
267     bool frameNeeded(QWidget *w) const;
268 
269     enum RectType { Insert, Rubber };
270 
271     void startRectDraw(const QPoint &global, QWidget *, RectType t);
272     void continueRectDraw(const QPoint &global, QWidget *, RectType t);
273     void endRectDraw();
274 
275     QWidget *containerAt(const QPoint &pos, QWidget *notParentOf);
276 
277     void checkPreviewGeometry(QRect &r);
278 
279     bool handleContextMenu(QWidget *widget, QWidget *managedWidget, QContextMenuEvent *e);
280     bool handleMouseButtonDblClickEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e);
281     bool handleMousePressEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e);
282     bool handleMouseMoveEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e);
283     bool handleMouseReleaseEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e);
284     bool handleKeyPressEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e);
285     bool handleKeyReleaseEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e);
286 
287     bool isCentralWidget(QWidget *w) const;
288 
289     bool setCurrentWidget(QWidget *currentWidget);
290     bool trySelectWidget(QWidget *w, bool select);
291 
292     void dragWidgetWithinForm(QWidget *widget, const QRect &targetGeometry, QWidget *targetContainer);
293 
294     void setCursorToAll(const QCursor &c, QWidget *start);
295 
296     QPoint mapToForm(const QWidget *w, const QPoint &pos) const;
297     bool canBeBuddy(QWidget *w) const;
298 
299     QWidget *findTargetContainer(QWidget *widget) const;
300 
301     void clearMainContainer();
302 
303     static int widgetDepth(const QWidget *w);
304     static bool isChildOf(const QWidget *c, const QWidget *p);
305 
306     void editWidgets() override;
307 
308     void updateWidgets();
309 
310     void handleArrowKeyEvent(int key, Qt::KeyboardModifiers modifiers);
311 
312     void layoutSelection(int type);
313     void layoutContainer(QWidget *w, int type);
314 
315 private:
316     QWidget *innerContainer(QWidget *outerContainer) const;
317     QWidget *containerForPaste() const;
318     QAction *createSelectAncestorSubMenu(QWidget *w);
319     void selectSingleWidget(QWidget *w);
320 
321     FormEditor *m_core;
322     FormWindowCursor *m_cursor;
323     QWidget *m_mainContainer = nullptr;
324     QWidget *m_currentWidget = nullptr;
325 
326     bool m_blockSelectionChanged = false;
327 
328     QPoint m_rectAnchor;
329     QRect m_currRect;
330 
331     QWidgetList m_widgets;
332     QSet<QWidget*> m_insertedWidgets;
333 
334     class Selection;
335     Selection *m_selection;
336 
337     QPoint m_startPos;
338 
339     QUndoStack m_undoStack;
340 
341     QString m_fileName;
342 
343     using PaletteAndFill = QPair<QPalette ,bool>;
344     using WidgetPaletteMap = QMap<QWidget*, PaletteAndFill>;
345     WidgetPaletteMap m_palettesBeforeHighlight;
346 
347     QRubberBand *m_rubberBand = nullptr;
348 
349     QTimer *m_selectionChangedTimer = nullptr;
350     QTimer *m_checkSelectionTimer = nullptr;
351     QTimer *m_geometryChangedTimer = nullptr;
352 
353     FormWindowWidgetStack *m_widgetStack;
354     WidgetEditorTool *m_widgetEditor = nullptr;
355 
356     QStringList m_resourceFiles;
357 
358     QString m_comment;
359     QString m_author;
360     QString m_pixmapFunction;
361     int m_defaultMargin, m_defaultSpacing;
362     QString m_marginFunction, m_spacingFunction;
363     QString m_exportMacro;
364     QStringList m_includeHints;
365 
366     QPoint m_contextMenuPosition;
367     HandleOperation m_handleOperation = NoHandleOperation;
368 
369 private:
370     friend class WidgetEditorTool;
371 };
372 
373 }  // namespace qdesigner_internal
374 
375 QT_END_NAMESPACE
376 
377 #endif // FORMWINDOW_H
378