1 // qjackctlGraph.h
2 //
3 /****************************************************************************
4 Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved.
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 *****************************************************************************/
21
22 #ifndef __qjackctlGraph_h
23 #define __qjackctlGraph_h
24
25 #include <QGraphicsView>
26
27 #include <QGraphicsPathItem>
28
29 #include <QColor>
30 #include <QIcon>
31
32 #include <QList>
33 #include <QHash>
34
35
36 // Forward decls.
37 class qjackctlGraphCanvas;
38 class qjackctlGraphNode;
39 class qjackctlGraphPort;
40 class qjackctlGraphConnect;
41 class qjackctlGraphCommand;
42
43 class qjackctlAliases;
44 class qjackctlAliasList;
45
46 class QStyleOptionGraphicsItem;
47
48 class QRubberBand;
49 class QUndoCommand;
50 class QUndoStack;
51 class QSettings;
52
53 class QGraphicsProxyWidget;
54 class QLineEdit;
55
56 class QMouseEvent;
57 class QWheelEvent;
58 class QKeyEvent;
59
60
61 //----------------------------------------------------------------------------
62 // qjackctlGraphItem -- Base graphics item.
63
64 class qjackctlGraphItem : public QGraphicsPathItem
65 {
66 public:
67
68 // Constructor.
69 qjackctlGraphItem(QGraphicsItem *parent = nullptr);
70
71 // Basic color accessors.
72 void setForeground(const QColor& color);
73 const QColor& foreground() const;
74
75 void setBackground(const QColor& color);
76 const QColor& background() const;
77
78 // Marking methods.
79 void setMarked(bool marked);
80 bool isMarked() const;
81
82 // Highlighting methods.
83 void setHighlight(bool hilite);
84 bool isHighlight() const;
85
86 // Raise item z-value (dynamic always-on-top).
87 void raise();
88
89 // Item modes.
90 enum Mode { None = 0,
91 Input = 1, Output = 2,
92 Duplex = Input | Output };
93
94 // Item hash/map key.
95 class ItemKey
96 {
97 public:
98
99 // Constructors.
100 ItemKey (const QString& name, Mode mode, uint type = 0)
m_name(name)101 : m_name(name), m_mode(mode), m_type(type) {}
ItemKey(const ItemKey & key)102 ItemKey (const ItemKey& key)
103 : m_name(key.name()), m_mode(key.mode()), m_type(key.type()) {}
104
105 // Key accessors.
name()106 const QString& name() const
107 { return m_name; }
mode()108 Mode mode() const
109 { return m_mode; }
type()110 uint type() const
111 { return m_type; }
112
113 // Hash/map key comparators.
114 bool operator== (const ItemKey& key) const
115 {
116 return ItemKey::type() == key.type()
117 && ItemKey::mode() == key.mode()
118 && ItemKey::name() == key.name();
119 }
120
121 private:
122
123 // Key fields.
124 QString m_name;
125 Mode m_mode;
126 uint m_type;
127 };
128
129 typedef QHash<ItemKey, qjackctlGraphItem *> ItemKeys;
130
131 // Item-type hash (static)
132 static uint itemType(const QByteArray& type_name);
133
134 // Rectangular editor extents.
135 virtual QRectF editorRect() const;
136
137 // Path and bounding rectangle override.
138 void setPath(const QPainterPath& path);
139
140 // Bounding rectangle accessor.
141 const QRectF& itemRect() const;
142
143 private:
144
145 // Instance variables.
146 QColor m_foreground;
147 QColor m_background;
148
149 bool m_marked;
150 bool m_hilite;
151
152 QRectF m_rect;
153 };
154
155
156 // Item hash function.
qHash(const qjackctlGraphItem::ItemKey & key)157 inline uint qHash ( const qjackctlGraphItem::ItemKey& key )
158 {
159 return qHash(key.name()) ^ qHash(uint(key.mode())) ^ qHash(key.type());
160 }
161
162
163 //----------------------------------------------------------------------------
164 // qjackctlGraphPort -- Port graphics item.
165
166 class qjackctlGraphPort : public qjackctlGraphItem
167 {
168 public:
169
170 // Constructor.
171 qjackctlGraphPort(qjackctlGraphNode *node,
172 const QString& name, Mode mode, uint type = 0);
173
174 // Destructor.
175 ~qjackctlGraphPort();
176
177 // Graphics item type.
178 enum { Type = QGraphicsItem::UserType + 2 };
179
type()180 int type() const { return Type; }
181
182 // Accessors.
183 qjackctlGraphNode *portNode() const;
184
185 void setPortName(const QString& name);
186 const QString& portName() const;
187
188 void setPortMode(Mode mode);
189 Mode portMode() const;
190
191 bool isInput() const;
192 bool isOutput() const;
193
194 void setPortType(uint type);
195 uint portType() const;
196
197 void setPortTitle(const QString& title);
198 const QString& portTitle() const;
199
200 void setPortIndex(int index);
201 int portIndex() const;
202
203 QPointF portPos() const;
204
205 // Connection-list methods.
206 void appendConnect(qjackctlGraphConnect *connect);
207 void removeConnect(qjackctlGraphConnect *connect);
208 void removeConnects();
209
210 qjackctlGraphConnect *findConnect(qjackctlGraphPort *port) const;
211
212 // Connect-list accessor.
213 const QList<qjackctlGraphConnect *>& connects() const;
214
215 // Selection propagation method...
216 void setSelectedEx(bool is_selected);
217
218 // Highlighting propagation method...
219 void setHighlightEx(bool is_highlight);
220
221 // Special port-type color business.
222 void updatePortTypeColors(qjackctlGraphCanvas *canvas);
223
224 // Port hash/map key.
225 class PortKey : public ItemKey
226 {
227 public:
228 // Constructors.
PortKey(qjackctlGraphPort * port)229 PortKey(qjackctlGraphPort *port)
230 : ItemKey(port->portName(), port->portMode(), port->portType()) {}
231 };
232
233 // Port sorting type.
234 enum SortType { PortName = 0, PortTitle, PortIndex };
235
236 static void setSortType(SortType sort_type);
237 static SortType sortType();
238
239 // Port sorting order.
240 enum SortOrder { Ascending = 0, Descending };
241
242 static void setSortOrder(SortOrder sort_order);
243 static SortOrder sortOrder();
244
245 // Port sorting comparators.
246 struct Compare {
operatorCompare247 bool operator()(qjackctlGraphPort *port1, qjackctlGraphPort *port2) const
248 { return qjackctlGraphPort::lessThan(port1, port2); }
249 };
250
251 struct ComparePos {
operatorComparePos252 bool operator()(qjackctlGraphPort *port1, qjackctlGraphPort *port2) const
253 { return (port1->scenePos().y() < port2->scenePos().y()); }
254 };
255
256 // Rectangular editor extents.
257 QRectF editorRect() const;
258
259 protected:
260
261 void paint(QPainter *painter,
262 const QStyleOptionGraphicsItem *option, QWidget *widget);
263
264 QVariant itemChange(GraphicsItemChange change, const QVariant& value);
265
266 // Natural decimal sorting comparators.
267 static bool lessThan(qjackctlGraphPort *port1, qjackctlGraphPort *port2);
268 static bool lessThan(const QString& s1, const QString& s2);
269
270 private:
271
272 // instance variables.
273 qjackctlGraphNode *m_node;
274
275 QString m_name;
276 Mode m_mode;
277 uint m_type;
278
279 QString m_title;
280 int m_index;
281
282 QGraphicsTextItem *m_text;
283
284 QList<qjackctlGraphConnect *> m_connects;
285
286 int m_selectx;
287 int m_hilitex;
288
289 static SortType g_sort_type;
290 static SortOrder g_sort_order;
291 };
292
293
294 //----------------------------------------------------------------------------
295 // qjackctlGraphNode -- Node graphics item.
296
297 class qjackctlGraphNode : public qjackctlGraphItem
298 {
299 public:
300
301 // Constructor.
302 qjackctlGraphNode(const QString& name, Mode mode, uint type = 0);
303
304 // Destructor..
305 ~qjackctlGraphNode();
306 // Graphics item type.
307 enum { Type = QGraphicsItem::UserType + 1 };
308
type()309 int type() const { return Type; }
310
311 // Accessors.
312 void setNodeName(const QString& name);
313 const QString& nodeName() const;
314
315 void setNodeMode(Mode mode);
316 Mode nodeMode() const;
317
318 void setNodeType(uint type);
319 uint nodeType() const;
320
321 void setNodeIcon(const QIcon& icon);
322 const QIcon& nodeIcon() const;
323
324 void setNodeTitle(const QString& title);
325 QString nodeTitle() const;
326
327 // Port-list methods.
328 qjackctlGraphPort *addPort(const QString& name, Mode mode, int type = 0);
329
330 qjackctlGraphPort *addInputPort(const QString& name, int type = 0);
331 qjackctlGraphPort *addOutputPort(const QString& name, int type = 0);
332
333 void removePort(qjackctlGraphPort *port);
334 void removePorts();
335
336 // Port finder (by name, mode and type)
337 qjackctlGraphPort *findPort(const QString& name, Mode mode, uint type = 0);
338
339 // Port-list accessor.
340 const QList<qjackctlGraphPort *>& ports() const;
341
342 // Reset port markings, destroy if unmarked.
343 void resetMarkedPorts();
344
345 // Path/shape updater.
346 void updatePath();
347
348 // Node hash key.
349 class NodeKey : public ItemKey
350 {
351 public:
352 // Constructors.
NodeKey(qjackctlGraphNode * node)353 NodeKey(qjackctlGraphNode *node)
354 : ItemKey(node->nodeName(), node->nodeMode(), node->nodeType()) {}
355 };
356
357 // Rectangular editor extents.
358 QRectF editorRect() const;
359
360 protected:
361
362 void paint(QPainter *painter,
363 const QStyleOptionGraphicsItem *option, QWidget *widget);
364
365 QVariant itemChange(GraphicsItemChange change, const QVariant& value);
366
367 private:
368
369 // Instance variables.
370 QString m_name;
371 Mode m_mode;
372 uint m_type;
373
374 QIcon m_icon;
375
376 QString m_title;
377
378 QGraphicsPixmapItem *m_pixmap;
379 QGraphicsTextItem *m_text;
380
381 qjackctlGraphPort::ItemKeys m_portkeys;
382 QList<qjackctlGraphPort *> m_ports;
383 };
384
385
386 //----------------------------------------------------------------------------
387 // qjackctlGraphConnect -- Connection-line graphics item.
388
389 class qjackctlGraphConnect : public qjackctlGraphItem
390 {
391 public:
392
393 // Constructor.
394 qjackctlGraphConnect();
395
396 // Destructor..
397 ~qjackctlGraphConnect();
398
399 // Graphics item type.
400 enum { Type = QGraphicsItem::UserType + 3 };
401
type()402 int type() const { return Type; }
403
404 // Accessors.
405 void setPort1(qjackctlGraphPort *port);
406 qjackctlGraphPort *port1() const;
407
408 void setPort2(qjackctlGraphPort *port);
409 qjackctlGraphPort *port2() const;
410
411 // Path/shaper updaters.
412 void updatePathTo(const QPointF& pos);
413 void updatePath();
414
415 // Selection propagation method...
416 void setSelectedEx(qjackctlGraphPort *port, bool is_selected);
417
418 // Highlighting propagation method...
419 void setHighlightEx(qjackctlGraphPort *port, bool is_highlight);
420
421 // Special port-type color business.
422 void updatePortTypeColors();
423
424 protected:
425
426 void paint(QPainter *painter,
427 const QStyleOptionGraphicsItem *option, QWidget *widget);
428
429 QVariant itemChange(GraphicsItemChange change, const QVariant& value);
430
431 QPainterPath shape() const;
432
433 private:
434
435 // Instance variables.
436 qjackctlGraphPort *m_port1;
437 qjackctlGraphPort *m_port2;
438 };
439
440
441 //----------------------------------------------------------------------------
442 // qjackctlGraphCanvas -- Canvas graphics scene/view.
443
444 class qjackctlGraphCanvas : public QGraphicsView
445 {
446 Q_OBJECT
447
448 public:
449
450 // Constructor.
451 qjackctlGraphCanvas(QWidget *parent = nullptr);
452
453 // Destructor.
454 ~qjackctlGraphCanvas();
455
456 // Accessors.
457 QGraphicsScene *scene() const;
458 QUndoStack *commands() const;
459
460 void setSettings(QSettings *settings);
461 QSettings *settings() const;
462
463 // Canvas methods.
464 void addItem(qjackctlGraphItem *item);
465 void removeItem(qjackctlGraphItem *item);
466
467 // Current item accessor.
468 qjackctlGraphItem *currentItem() const;
469
470 // Connection predicates.
471 bool canConnect() const;
472 bool canDisconnect() const;
473
474 // Edit predicates.
475 bool canRenameItem() const;
476
477 // Zooming methods.
478 void setZoom(qreal zoom);
479 qreal zoom() const;
480
481 void setZoomRange(bool zoomrange);
482 bool isZoomRange() const;
483
484 // Clean-up all un-marked nodes...
485 void resetNodes(uint node_type);
486 void clearNodes(uint node_type);
487
488 // Special node finder.
489 qjackctlGraphNode *findNode(
490 const QString& name, qjackctlGraphItem::Mode mode, uint type = 0) const;
491
492 // Port (dis)connections notifiers.
493 void emitConnected(qjackctlGraphPort *port1, qjackctlGraphPort *port2);
494 void emitDisconnected(qjackctlGraphPort *port1, qjackctlGraphPort *port2);
495
496 // Rename notifiers.
497 void emitRenamed(qjackctlGraphItem *item, const QString& name);
498
499 // Graph canvas state methods.
500 bool restoreState();
501 bool saveState() const;
502
503 // Graph colors management.
504 void setPortTypeColor(uint port_type, const QColor& color);
505 const QColor& portTypeColor(uint port_type);
506 void updatePortTypeColors(uint port_type = 0);
507 void clearPortTypeColors();
508
509 // Clear all selection.
510 void clearSelection();
511
512 // Clear all state.
513 void clear();
514
515 // Client/port aliases accessors.
516 void setAliases(qjackctlAliases *aliases);
517 qjackctlAliases *aliases() const;
518
519 signals:
520
521 // Node factory notifications.
522 void added(qjackctlGraphNode *node);
523 void removed(qjackctlGraphNode *node);
524
525 // Port (dis)connection notifications.
526 void connected(qjackctlGraphPort *port1, qjackctlGraphPort *port2);
527 void disconnected(qjackctlGraphPort *port1, qjackctlGraphPort *port2);
528
529 // Generic change notification.
530 void changed();
531
532 // Rename notification.
533 void renamed(qjackctlGraphItem *item, const QString& name);
534
535 public slots:
536
537 // Dis/connect selected items.
538 void connectItems();
539 void disconnectItems();
540
541 // Select actions.
542 void selectAll();
543 void selectNone();
544 void selectInvert();
545
546 // Edit actions.
547 void renameItem();
548
549 // Discrete zooming actions.
550 void zoomIn();
551 void zoomOut();
552 void zoomFit();
553 void zoomReset();
554
555 // Update all nodes.
556 void updateNodes();
557
558 protected slots:
559
560 // Rename item slots.
561 void textChanged(const QString&);
562 void editingFinished();
563
564 protected:
565
566 // Item finder (internal).
567 qjackctlGraphItem *itemAt(const QPointF& pos) const;
568
569 // Port (dis)connection commands.
570 void connectPorts(
571 qjackctlGraphPort *port1, qjackctlGraphPort *port2, bool is_connect);
572
573 // Mouse event handlers.
574 void mousePressEvent(QMouseEvent *event);
575 void mouseMoveEvent(QMouseEvent *event);
576 void mouseReleaseEvent(QMouseEvent *event);
577 void mouseDoubleClickEvent(QMouseEvent *event);
578
579 void wheelEvent(QWheelEvent *event);
580
581 // Keyboard event handler.
582 void keyPressEvent(QKeyEvent *event);
583
584 // Graph node key helper.
585 QString nodeKey(qjackctlGraphNode *node) const;
586
587 // Zoom in rectangle range.
588 void zoomFitRange(const QRectF& range_rect);
589
590 // Graph node position state methods.
591 bool restoreNodePos(qjackctlGraphNode *node);
592 bool saveNodePos(qjackctlGraphNode *node) const;
593
594 // Renaming editor position and size updater.
595 void updateEditorGeometry();
596
597 private:
598
599 // Mouse pointer dragging states.
600 enum DragState { DragNone = 0, DragStart, DragMove, DragScroll };
601
602 // Instance variables.
603 QGraphicsScene *m_scene;
604 DragState m_state;
605 QPointF m_pos;
606 qjackctlGraphItem *m_item;
607 qjackctlGraphConnect *m_connect;
608 QRubberBand *m_rubberband;
609 qreal m_zoom;
610 bool m_zoomrange;
611
612 qjackctlGraphNode::ItemKeys m_nodekeys;
613 QList<qjackctlGraphNode *> m_nodes;
614
615 QUndoStack *m_commands;
616 QSettings *m_settings;
617
618 QList<QGraphicsItem *> m_selected;
619 int m_selected_nodes;
620
621 // Graph port colors.
622 QHash<uint, QColor> m_port_colors;
623
624 // Item renaming stuff.
625 qjackctlGraphItem *m_edit_item;
626 QLineEdit *m_editor;
627 int m_edited;
628
629 // Original node position (for move command).
630 QPointF m_pos1;
631
632 // Client/port aliases database.
633 qjackctlAliases *m_aliases;
634 };
635
636
637 //----------------------------------------------------------------------------
638 // qjackctlGraphSect -- Generic graph driver
639
640 class qjackctlGraphSect
641 {
642 public:
643
644 // Constructor.
645 qjackctlGraphSect(qjackctlGraphCanvas *canvas);
646
647 // Destructor (virtual)
~qjackctlGraphSect()648 virtual ~qjackctlGraphSect() {}
649
650 // Accessors.
651 qjackctlGraphCanvas *canvas() const;
652
653 // Generic sect/graph methods.
654 void addItem(qjackctlGraphItem *item);
655 void removeItem(qjackctlGraphItem *item);
656
657 // Clean-up all un-marked items...
658 void resetItems(uint node_type);
659 void clearItems(uint node_type);
660
661 // Special node finder.
662 qjackctlGraphNode *findNode(
663 const QString& name, qjackctlGraphItem::Mode mode, int type = 0) const;
664
665 // Client/port renaming method.
666 virtual void renameItem(qjackctlGraphItem *item, const QString& name);
667
668 protected:
669
670 // Client/port item aliases accessor.
671 virtual QList<qjackctlAliasList *> item_aliases(
672 qjackctlGraphItem *item) const = 0;
673
674 private:
675
676 // Instance variables.
677 qjackctlGraphCanvas *m_canvas;
678
679 QList<qjackctlGraphConnect *> m_connects;
680 };
681
682
683 #endif // __qjackctlGraph_h
684
685 // end of qjackctlGraph.h
686