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 | |
41 | #ifndef CONNECTIONEDIT_H |
42 | #define CONNECTIONEDIT_H |
43 | |
44 | #include "shared_global_p.h" |
45 | |
46 | #include <QtCore/qhash.h> |
47 | #include <QtCore/qlist.h> |
48 | #include <QtCore/qvector.h> |
49 | #include <QtCore/qpointer.h> |
50 | |
51 | #include <QtWidgets/qwidget.h> |
52 | #include <QtGui/qpixmap.h> |
53 | #include <QtGui/qpolygon.h> |
54 | |
55 | #include <QtWidgets/qundostack.h> |
56 | |
57 | QT_BEGIN_NAMESPACE |
58 | |
59 | class QDesignerFormWindowInterface; |
60 | class QUndoStack; |
61 | class ; |
62 | |
63 | namespace qdesigner_internal { |
64 | |
65 | class Connection; |
66 | class ConnectionEdit; |
67 | |
68 | class QDESIGNER_SHARED_EXPORT CETypes |
69 | { |
70 | public: |
71 | using ConnectionList = QVector<Connection *>; |
72 | using ConnectionSet = QHash<Connection*, Connection*> ; |
73 | using WidgetSet = QHash<QWidget*, QWidget*>; |
74 | |
75 | class EndPoint { |
76 | public: |
77 | enum Type { Source, Target }; |
78 | explicit EndPoint(Connection *_con = nullptr, Type _type = Source) : con(_con), type(_type) {} |
79 | bool isNull() const { return con == nullptr; } |
80 | bool operator == (const EndPoint &other) const { return con == other.con && type == other.type; } |
81 | bool operator != (const EndPoint &other) const { return !operator == (other); } |
82 | Connection *con; |
83 | Type type; |
84 | }; |
85 | enum LineDir { UpDir = 0, DownDir, RightDir, LeftDir }; |
86 | }; |
87 | |
88 | class QDESIGNER_SHARED_EXPORT Connection : public CETypes |
89 | { |
90 | public: |
91 | explicit Connection(ConnectionEdit *edit); |
92 | explicit Connection(ConnectionEdit *edit, QObject *source, QObject *target); |
93 | virtual ~Connection() = default; |
94 | |
95 | QObject *object(EndPoint::Type type) const |
96 | { |
97 | return (type == EndPoint::Source ? m_source : m_target); |
98 | } |
99 | |
100 | QWidget *widget(EndPoint::Type type) const |
101 | { |
102 | return qobject_cast<QWidget*>(o: object(type)); |
103 | } |
104 | |
105 | QPoint endPointPos(EndPoint::Type type) const; |
106 | QRect endPointRect(EndPoint::Type) const; |
107 | void setEndPoint(EndPoint::Type type, QObject *w, const QPoint &pos) |
108 | { type == EndPoint::Source ? setSource(source: w, pos) : setTarget(target: w, pos); } |
109 | |
110 | bool isVisible() const; |
111 | virtual void updateVisibility(); |
112 | void setVisible(bool b); |
113 | |
114 | virtual QRegion region() const; |
115 | bool contains(const QPoint &pos) const; |
116 | virtual void paint(QPainter *p) const; |
117 | |
118 | void update(bool update_widgets = true) const; |
119 | void checkWidgets(); |
120 | |
121 | QString label(EndPoint::Type type) const |
122 | { return type == EndPoint::Source ? m_source_label : m_target_label; } |
123 | void setLabel(EndPoint::Type type, const QString &text); |
124 | QRect labelRect(EndPoint::Type type) const; |
125 | QPixmap labelPixmap(EndPoint::Type type) const |
126 | { return type == EndPoint::Source ? m_source_label_pm : m_target_label_pm; } |
127 | |
128 | ConnectionEdit *edit() const { return m_edit; } |
129 | |
130 | virtual void inserted() {} |
131 | virtual void removed() {} |
132 | |
133 | private: |
134 | QPoint m_source_pos, m_target_pos; |
135 | QObject *m_source, *m_target; |
136 | QVector<QPoint> m_knee_list; |
137 | QPolygonF m_arrow_head; |
138 | ConnectionEdit *m_edit; |
139 | QString m_source_label, m_target_label; |
140 | QPixmap m_source_label_pm, m_target_label_pm; |
141 | QRect m_source_rect, m_target_rect; |
142 | bool m_visible; |
143 | |
144 | void setSource(QObject *source, const QPoint &pos); |
145 | void setTarget(QObject *target, const QPoint &pos); |
146 | void updateKneeList(); |
147 | void trimLine(); |
148 | void updatePixmap(EndPoint::Type type); |
149 | LineDir labelDir(EndPoint::Type type) const; |
150 | bool ground() const; |
151 | QRect groundRect() const; |
152 | }; |
153 | |
154 | class QDESIGNER_SHARED_EXPORT ConnectionEdit : public QWidget, public CETypes |
155 | { |
156 | Q_OBJECT |
157 | public: |
158 | ConnectionEdit(QWidget *parent, QDesignerFormWindowInterface *form); |
159 | ~ConnectionEdit() override; |
160 | |
161 | inline const QPointer<QWidget> &background() const { return m_bg_widget; } |
162 | |
163 | void setSelected(Connection *con, bool sel); |
164 | bool selected(const Connection *con) const; |
165 | |
166 | int connectionCount() const { return m_con_list.size(); } |
167 | Connection *connection(int i) const { return m_con_list.at(i); } |
168 | int indexOfConnection(Connection *con) const { return m_con_list.indexOf(t: con); } |
169 | |
170 | virtual void setSource(Connection *con, const QString &obj_name); |
171 | virtual void setTarget(Connection *con, const QString &obj_name); |
172 | |
173 | QUndoStack *undoStack() const { return m_undo_stack; } |
174 | |
175 | void clear(); |
176 | |
177 | void showEvent(QShowEvent * /*e*/) override |
178 | { |
179 | updateBackground(); |
180 | } |
181 | |
182 | signals: |
183 | void aboutToAddConnection(int idx); |
184 | void connectionAdded(Connection *con); |
185 | void aboutToRemoveConnection(Connection *con); |
186 | void connectionRemoved(int idx); |
187 | void connectionSelected(Connection *con); |
188 | void widgetActivated(QWidget *wgt); |
189 | void connectionChanged(Connection *con); |
190 | |
191 | public slots: |
192 | void selectNone(); |
193 | void selectAll(); |
194 | virtual void deleteSelected(); |
195 | virtual void setBackground(QWidget *background); |
196 | virtual void updateBackground(); |
197 | virtual void widgetRemoved(QWidget *w); |
198 | virtual void objectRemoved(QObject *o); |
199 | |
200 | void updateLines(); |
201 | void enableUpdateBackground(bool enable); |
202 | |
203 | protected: |
204 | void paintEvent(QPaintEvent *e) override; |
205 | void mouseMoveEvent(QMouseEvent *e) override; |
206 | void mousePressEvent(QMouseEvent *e) override; |
207 | void mouseReleaseEvent(QMouseEvent *e) override; |
208 | void keyPressEvent(QKeyEvent *e) override; |
209 | void mouseDoubleClickEvent(QMouseEvent *e) override; |
210 | void resizeEvent(QResizeEvent *e) override; |
211 | void (QContextMenuEvent * event) override; |
212 | |
213 | virtual Connection *createConnection(QWidget *source, QWidget *target); |
214 | virtual void modifyConnection(Connection *con); |
215 | |
216 | virtual QWidget *widgetAt(const QPoint &pos) const; |
217 | virtual void (QMenu &); |
218 | void addConnection(Connection *con); |
219 | QRect widgetRect(QWidget *w) const; |
220 | |
221 | enum State { Editing, Connecting, Dragging }; |
222 | State state() const; |
223 | |
224 | virtual void endConnection(QWidget *target, const QPoint &pos); |
225 | |
226 | const ConnectionList &connectionList() const { return m_con_list; } |
227 | const ConnectionSet &selection() const { return m_sel_con_set; } |
228 | Connection *takeConnection(Connection *con); |
229 | Connection *newlyAddedConnection() { return m_tmp_con; } |
230 | void clearNewlyAddedConnection(); |
231 | |
232 | void findObjectsUnderMouse(const QPoint &pos); |
233 | |
234 | private: |
235 | void startConnection(QWidget *source, const QPoint &pos); |
236 | void continueConnection(QWidget *target, const QPoint &pos); |
237 | void abortConnection(); |
238 | |
239 | void startDrag(const EndPoint &end_point, const QPoint &pos); |
240 | void continueDrag(const QPoint &pos); |
241 | void endDrag(const QPoint &pos); |
242 | void adjustHotSopt(const EndPoint &end_point, const QPoint &pos); |
243 | Connection *connectionAt(const QPoint &pos) const; |
244 | EndPoint endPointAt(const QPoint &pos) const; |
245 | void paintConnection(QPainter *p, Connection *con, |
246 | WidgetSet *heavy_highlight_set, |
247 | WidgetSet *light_highlight_set) const; |
248 | void paintLabel(QPainter *p, EndPoint::Type type, Connection *con); |
249 | |
250 | |
251 | QPointer<QWidget> m_bg_widget; |
252 | QUndoStack *m_undo_stack; |
253 | bool m_enable_update_background; |
254 | |
255 | Connection *m_tmp_con; // the connection we are currently editing |
256 | ConnectionList m_con_list; |
257 | bool m_start_connection_on_drag; |
258 | EndPoint m_end_point_under_mouse; |
259 | QPointer<QWidget> m_widget_under_mouse; |
260 | |
261 | EndPoint m_drag_end_point; |
262 | QPoint m_old_source_pos, m_old_target_pos; |
263 | ConnectionSet m_sel_con_set; |
264 | const QColor m_inactive_color; |
265 | const QColor m_active_color; |
266 | |
267 | private: |
268 | friend class Connection; |
269 | friend class AddConnectionCommand; |
270 | friend class DeleteConnectionsCommand; |
271 | friend class SetEndPointCommand; |
272 | }; |
273 | |
274 | class QDESIGNER_SHARED_EXPORT CECommand : public QUndoCommand, public CETypes |
275 | { |
276 | public: |
277 | explicit CECommand(ConnectionEdit *edit) |
278 | : m_edit(edit) {} |
279 | |
280 | bool mergeWith(const QUndoCommand *) override { return false; } |
281 | |
282 | ConnectionEdit *edit() const { return m_edit; } |
283 | |
284 | private: |
285 | ConnectionEdit *m_edit; |
286 | }; |
287 | |
288 | class QDESIGNER_SHARED_EXPORT AddConnectionCommand : public CECommand |
289 | { |
290 | public: |
291 | AddConnectionCommand(ConnectionEdit *edit, Connection *con); |
292 | void redo() override; |
293 | void undo() override; |
294 | private: |
295 | Connection *m_con; |
296 | }; |
297 | |
298 | class QDESIGNER_SHARED_EXPORT DeleteConnectionsCommand : public CECommand |
299 | { |
300 | public: |
301 | DeleteConnectionsCommand(ConnectionEdit *edit, const ConnectionList &con_list); |
302 | void redo() override; |
303 | void undo() override; |
304 | private: |
305 | ConnectionList m_con_list; |
306 | }; |
307 | |
308 | } // namespace qdesigner_internal |
309 | |
310 | QT_END_NAMESPACE |
311 | |
312 | #endif // CONNECTIONEDIT_H |
313 | |