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 QMenu; 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 }; con(_con)78 explicit EndPoint(Connection *_con = nullptr, Type _type = Source) : con(_con), type(_type) {} isNull()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 object(EndPoint::Type type)95 QObject *object(EndPoint::Type type) const 96 { 97 return (type == EndPoint::Source ? m_source : m_target); 98 } 99 widget(EndPoint::Type type)100 QWidget *widget(EndPoint::Type type) const 101 { 102 return qobject_cast<QWidget*>(object(type)); 103 } 104 105 QPoint endPointPos(EndPoint::Type type) const; 106 QRect endPointRect(EndPoint::Type) const; setEndPoint(EndPoint::Type type,QObject * w,const QPoint & pos)107 void setEndPoint(EndPoint::Type type, QObject *w, const QPoint &pos) 108 { type == EndPoint::Source ? setSource(w, pos) : setTarget(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 label(EndPoint::Type type)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; labelPixmap(EndPoint::Type type)125 QPixmap labelPixmap(EndPoint::Type type) const 126 { return type == EndPoint::Source ? m_source_label_pm : m_target_label_pm; } 127 edit()128 ConnectionEdit *edit() const { return m_edit; } 129 inserted()130 virtual void inserted() {} removed()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 background()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 connectionCount()166 int connectionCount() const { return m_con_list.size(); } connection(int i)167 Connection *connection(int i) const { return m_con_list.at(i); } indexOfConnection(Connection * con)168 int indexOfConnection(Connection *con) const { return m_con_list.indexOf(con); } 169 170 virtual void setSource(Connection *con, const QString &obj_name); 171 virtual void setTarget(Connection *con, const QString &obj_name); 172 undoStack()173 QUndoStack *undoStack() const { return m_undo_stack; } 174 175 void clear(); 176 showEvent(QShowEvent *)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 contextMenuEvent(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 createContextMenu(QMenu &menu); 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 connectionList()226 const ConnectionList &connectionList() const { return m_con_list; } selection()227 const ConnectionSet &selection() const { return m_sel_con_set; } 228 Connection *takeConnection(Connection *con); newlyAddedConnection()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: CECommand(ConnectionEdit * edit)277 explicit CECommand(ConnectionEdit *edit) 278 : m_edit(edit) {} 279 mergeWith(const QUndoCommand *)280 bool mergeWith(const QUndoCommand *) override { return false; } 281 edit()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