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