change: change code style to Linux style except indent.
This commit is contained in:
+1296
-1155
File diff suppressed because it is too large
Load Diff
+149
-143
@@ -33,7 +33,8 @@
|
||||
#include "widget/handmovableview/handmovableview.h"
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A widget for viewing and editing node graphs
|
||||
@@ -41,248 +42,253 @@ namespace olive {
|
||||
* This widget takes a NodeGraph object and constructs a QGraphicsScene representing its data, viewing and allowing
|
||||
* the user to make modifications to it.
|
||||
*/
|
||||
class NodeView : public HandMovableView
|
||||
{
|
||||
Q_OBJECT
|
||||
class NodeView : public HandMovableView {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeView(QWidget* parent = nullptr);
|
||||
NodeView(QWidget *parent = nullptr);
|
||||
|
||||
virtual ~NodeView() override;
|
||||
virtual ~NodeView() override;
|
||||
|
||||
void SetContexts(const QVector<Node *> &nodes);
|
||||
void SetContexts(const QVector<Node *> &nodes);
|
||||
|
||||
const QVector<Node*> &GetContexts() const
|
||||
{
|
||||
if (overlay_view_) {
|
||||
return overlay_view_->GetContexts();
|
||||
} else {
|
||||
return contexts_;
|
||||
}
|
||||
}
|
||||
const QVector<Node *> &GetContexts() const
|
||||
{
|
||||
if (overlay_view_) {
|
||||
return overlay_view_->GetContexts();
|
||||
} else {
|
||||
return contexts_;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsGroupOverlay() const
|
||||
{
|
||||
return overlay_view_;
|
||||
}
|
||||
bool IsGroupOverlay() const
|
||||
{
|
||||
return overlay_view_;
|
||||
}
|
||||
|
||||
void CloseContextsBelongingToProject(Project *project);
|
||||
void CloseContextsBelongingToProject(Project *project);
|
||||
|
||||
void ClearGraph();
|
||||
void ClearGraph();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Delete selected nodes from graph (user-friendly/undoable)
|
||||
*/
|
||||
void DeleteSelected();
|
||||
void DeleteSelected();
|
||||
|
||||
void SelectAll();
|
||||
void DeselectAll();
|
||||
void SelectAll();
|
||||
void DeselectAll();
|
||||
|
||||
void Select(const QVector<Node::ContextPair> &nodes, bool center_view_on_item);
|
||||
void Select(const QVector<Node::ContextPair> &nodes,
|
||||
bool center_view_on_item);
|
||||
|
||||
void CopySelected(bool cut);
|
||||
void Paste();
|
||||
void CopySelected(bool cut);
|
||||
void Paste();
|
||||
|
||||
void Duplicate();
|
||||
void Duplicate();
|
||||
|
||||
void SetColorLabel(int index);
|
||||
void SetColorLabel(int index);
|
||||
|
||||
void ZoomIn();
|
||||
void ZoomIn();
|
||||
|
||||
void ZoomOut();
|
||||
void ZoomOut();
|
||||
|
||||
const QVector<Node*> &GetCurrentContexts() const
|
||||
{
|
||||
return contexts_;
|
||||
}
|
||||
const QVector<Node *> &GetCurrentContexts() const
|
||||
{
|
||||
return contexts_;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetMiniMapEnabled(bool e)
|
||||
{
|
||||
minimap_->setVisible(e);
|
||||
}
|
||||
void SetMiniMapEnabled(bool e)
|
||||
{
|
||||
minimap_->setVisible(e);
|
||||
}
|
||||
|
||||
void ShowAddMenu()
|
||||
{
|
||||
Menu *m = CreateAddMenu(nullptr);
|
||||
m->exec(QCursor::pos());
|
||||
delete m;
|
||||
}
|
||||
void ShowAddMenu()
|
||||
{
|
||||
Menu *m = CreateAddMenu(nullptr);
|
||||
m->exec(QCursor::pos());
|
||||
delete m;
|
||||
}
|
||||
|
||||
void CenterOnItemsBoundingRect();
|
||||
void CenterOnItemsBoundingRect();
|
||||
|
||||
void CenterOnNode(olive::Node *n);
|
||||
void CenterOnNode(olive::Node *n);
|
||||
|
||||
void LabelSelectedNodes();
|
||||
void LabelSelectedNodes();
|
||||
|
||||
signals:
|
||||
void NodesSelected(const QVector<Node*>& nodes);
|
||||
void NodesSelected(const QVector<Node *> &nodes);
|
||||
|
||||
void NodesDeselected(const QVector<Node*>& nodes);
|
||||
void NodesDeselected(const QVector<Node *> &nodes);
|
||||
|
||||
void NodeSelectionChanged(const QVector<Node*>& nodes);
|
||||
void NodeSelectionChangedWithContexts(const QVector<Node::ContextPair>& nodes);
|
||||
void NodeSelectionChanged(const QVector<Node *> &nodes);
|
||||
void
|
||||
NodeSelectionChangedWithContexts(const QVector<Node::ContextPair> &nodes);
|
||||
|
||||
void NodeGroupOpened(NodeGroup *group);
|
||||
void NodeGroupClosed();
|
||||
void NodeGroupOpened(NodeGroup *group);
|
||||
void NodeGroupClosed();
|
||||
|
||||
void EscPressed();
|
||||
void EscPressed();
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent *event) override;
|
||||
virtual void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
|
||||
virtual void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
virtual void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
virtual void dropEvent(QDropEvent *event) override;
|
||||
virtual void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||
virtual void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
virtual void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
virtual void dropEvent(QDropEvent *event) override;
|
||||
virtual void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
virtual void ZoomIntoCursorPosition(QWheelEvent *event, double multiplier, const QPointF &cursor_pos) override;
|
||||
virtual void ZoomIntoCursorPosition(QWheelEvent *event, double multiplier,
|
||||
const QPointF &cursor_pos) override;
|
||||
|
||||
virtual bool event(QEvent *event) override;
|
||||
virtual bool event(QEvent *event) override;
|
||||
|
||||
virtual bool eventFilter(QObject *object, QEvent *event) override;
|
||||
virtual bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
|
||||
private:
|
||||
void DetachItemsFromCursor(bool delete_nodes_too = true);
|
||||
void DetachItemsFromCursor(bool delete_nodes_too = true);
|
||||
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
|
||||
void MoveAttachedNodesToCursor(const QPoint &p);
|
||||
void ProcessMovingAttachedNodes(const QPoint &pos);
|
||||
QVector<Node*> ProcessDroppingAttachedNodes(MultiUndoCommand *command, Node *select_context, const QPoint &pos);
|
||||
Node *GetContextAtMousePos(const QPoint &p);
|
||||
void MoveAttachedNodesToCursor(const QPoint &p);
|
||||
void ProcessMovingAttachedNodes(const QPoint &pos);
|
||||
QVector<Node *> ProcessDroppingAttachedNodes(MultiUndoCommand *command,
|
||||
Node *select_context,
|
||||
const QPoint &pos);
|
||||
Node *GetContextAtMousePos(const QPoint &p);
|
||||
|
||||
void ConnectSelectionChangedSignal();
|
||||
void DisconnectSelectionChangedSignal();
|
||||
void ConnectSelectionChangedSignal();
|
||||
void DisconnectSelectionChangedSignal();
|
||||
|
||||
void ZoomFromKeyboard(double multiplier);
|
||||
void ZoomFromKeyboard(double multiplier);
|
||||
|
||||
void ClearCreateEdgeInputIfNecessary();
|
||||
void ClearCreateEdgeInputIfNecessary();
|
||||
|
||||
QPointF GetEstimatedPositionForContext(NodeViewItem *item, Node *context) const;
|
||||
QPointF GetEstimatedPositionForContext(NodeViewItem *item,
|
||||
Node *context) const;
|
||||
|
||||
NodeViewItem *GetAssumedItemForSelectedNode(Node *node);
|
||||
bool GetAssumedPositionForSelectedNode(Node *node, Node::Position *pos);
|
||||
NodeViewItem *GetAssumedItemForSelectedNode(Node *node);
|
||||
bool GetAssumedPositionForSelectedNode(Node *node, Node::Position *pos);
|
||||
|
||||
Menu *CreateAddMenu(Menu *parent);
|
||||
Menu *CreateAddMenu(Menu *parent);
|
||||
|
||||
void PositionNewEdge(const QPoint &pos);
|
||||
void PositionNewEdge(const QPoint &pos);
|
||||
|
||||
void AddContext(Node *n);
|
||||
void AddContext(Node *n);
|
||||
|
||||
void RemoveContext(Node *n);
|
||||
void RemoveContext(Node *n);
|
||||
|
||||
bool IsItemAttachedToCursor(NodeViewItem *item) const;
|
||||
bool IsItemAttachedToCursor(NodeViewItem *item) const;
|
||||
|
||||
void ExpandItem(NodeViewItem *item);
|
||||
void ExpandItem(NodeViewItem *item);
|
||||
|
||||
void CollapseItem(NodeViewItem *item);
|
||||
void CollapseItem(NodeViewItem *item);
|
||||
|
||||
void EndEdgeDrag(bool cancel = false);
|
||||
void EndEdgeDrag(bool cancel = false);
|
||||
|
||||
void PostPaste(const QVector<Node*> &new_nodes, const Node::PositionMap &map);
|
||||
void PostPaste(const QVector<Node *> &new_nodes,
|
||||
const Node::PositionMap &map);
|
||||
|
||||
void ResizeOverlay();
|
||||
void ResizeOverlay();
|
||||
|
||||
NodeViewMiniMap *minimap_;
|
||||
NodeViewMiniMap *minimap_;
|
||||
|
||||
NodeViewContext *GetContextItemFromNodeItem(NodeViewItem *item);
|
||||
NodeViewContext *GetContextItemFromNodeItem(NodeViewItem *item);
|
||||
|
||||
struct AttachedItem {
|
||||
NodeViewItem* item;
|
||||
Node *node;
|
||||
QPointF original_pos;
|
||||
};
|
||||
struct AttachedItem {
|
||||
NodeViewItem *item;
|
||||
Node *node;
|
||||
QPointF original_pos;
|
||||
};
|
||||
|
||||
void SetAttachedItems(const QVector<AttachedItem> &items);
|
||||
QVector<AttachedItem> attached_items_;
|
||||
void SetAttachedItems(const QVector<AttachedItem> &items);
|
||||
QVector<AttachedItem> attached_items_;
|
||||
|
||||
NodeViewEdge* drop_edge_;
|
||||
NodeInput drop_input_;
|
||||
NodeViewEdge *drop_edge_;
|
||||
NodeInput drop_input_;
|
||||
|
||||
NodeViewEdge* create_edge_;
|
||||
NodeViewItem* create_edge_output_item_;
|
||||
NodeViewItem* create_edge_input_item_;
|
||||
NodeInput create_edge_input_;
|
||||
bool create_edge_already_exists_;
|
||||
bool create_edge_from_output_;
|
||||
NodeViewEdge *create_edge_;
|
||||
NodeViewItem *create_edge_output_item_;
|
||||
NodeViewItem *create_edge_input_item_;
|
||||
NodeInput create_edge_input_;
|
||||
bool create_edge_already_exists_;
|
||||
bool create_edge_from_output_;
|
||||
|
||||
QVector<NodeViewItem*> create_edge_expanded_items_;
|
||||
QVector<NodeViewItem *> create_edge_expanded_items_;
|
||||
|
||||
NodeViewScene scene_;
|
||||
NodeViewScene scene_;
|
||||
|
||||
QVector<Node*> selected_nodes_;
|
||||
QVector<Node *> selected_nodes_;
|
||||
|
||||
QVector<Node*> contexts_;
|
||||
QVector<Node*> last_set_filter_nodes_;
|
||||
QMap<Node*, QPointF> context_offsets_;
|
||||
QVector<Node *> contexts_;
|
||||
QVector<Node *> last_set_filter_nodes_;
|
||||
QMap<Node *, QPointF> context_offsets_;
|
||||
|
||||
QMap<NodeViewItem*, QPointF> dragging_items_;
|
||||
QMap<NodeViewItem *, QPointF> dragging_items_;
|
||||
|
||||
NodeView* overlay_view_;
|
||||
NodeView *overlay_view_;
|
||||
|
||||
double scale_;
|
||||
double scale_;
|
||||
|
||||
bool dont_emit_selection_signals_;
|
||||
bool dont_emit_selection_signals_;
|
||||
|
||||
static const double kMinimumScale;
|
||||
static const double kMinimumScale;
|
||||
|
||||
static const int kMaximumContexts;
|
||||
static const int kMaximumContexts;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
/**
|
||||
* @brief Receiver for when the scene's selected items change
|
||||
*/
|
||||
void UpdateSelectionCache();
|
||||
void UpdateSelectionCache();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Receiver for when the user right clicks (or otherwise requests a context menu)
|
||||
*/
|
||||
void ShowContextMenu(const QPoint &pos);
|
||||
void ShowContextMenu(const QPoint &pos);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Receiver for when the user requests a new node from the add menu
|
||||
*/
|
||||
void CreateNodeSlot(QAction* action);
|
||||
void CreateNodeSlot(QAction *action);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Receiver for setting the direction from the context menu
|
||||
*/
|
||||
void ContextMenuSetDirection(QAction* action);
|
||||
void ContextMenuSetDirection(QAction *action);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Opens the selected node in a Viewer
|
||||
*/
|
||||
void OpenSelectedNodeInViewer();
|
||||
void OpenSelectedNodeInViewer();
|
||||
|
||||
void UpdateSceneBoundingRect();
|
||||
void UpdateSceneBoundingRect();
|
||||
|
||||
void RepositionMiniMap();
|
||||
void RepositionMiniMap();
|
||||
|
||||
void UpdateViewportOnMiniMap();
|
||||
void UpdateViewportOnMiniMap();
|
||||
|
||||
void MoveToScenePoint(const QPointF &pos);
|
||||
void MoveToScenePoint(const QPointF &pos);
|
||||
|
||||
void NodeRemovedFromGraph();
|
||||
void NodeRemovedFromGraph();
|
||||
|
||||
void GroupNodes();
|
||||
void GroupNodes();
|
||||
|
||||
void UngroupNodes();
|
||||
void UngroupNodes();
|
||||
|
||||
void ShowNodeProperties();
|
||||
void ShowNodeProperties();
|
||||
|
||||
void ItemAboutToBeDeleted(NodeViewItem *item);
|
||||
|
||||
void CloseOverlay();
|
||||
void ItemAboutToBeDeleted(NodeViewItem *item);
|
||||
|
||||
void CloseOverlay();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,43 +25,49 @@
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class NodeViewCommon {
|
||||
public:
|
||||
enum FlowDirection {
|
||||
kInvalidDirection = -1,
|
||||
kTopToBottom,
|
||||
kBottomToTop,
|
||||
kLeftToRight,
|
||||
kRightToLeft
|
||||
};
|
||||
enum FlowDirection {
|
||||
kInvalidDirection = -1,
|
||||
kTopToBottom,
|
||||
kBottomToTop,
|
||||
kLeftToRight,
|
||||
kRightToLeft
|
||||
};
|
||||
|
||||
static Qt::Orientation GetFlowOrientation(FlowDirection dir) {
|
||||
if (dir == kTopToBottom || dir == kBottomToTop) {
|
||||
return Qt::Vertical;
|
||||
} else {
|
||||
return Qt::Horizontal;
|
||||
}
|
||||
}
|
||||
static Qt::Orientation GetFlowOrientation(FlowDirection dir)
|
||||
{
|
||||
if (dir == kTopToBottom || dir == kBottomToTop) {
|
||||
return Qt::Vertical;
|
||||
} else {
|
||||
return Qt::Horizontal;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsFlowVertical(FlowDirection dir)
|
||||
{
|
||||
return dir == kTopToBottom || dir == kBottomToTop;
|
||||
}
|
||||
static bool IsFlowVertical(FlowDirection dir)
|
||||
{
|
||||
return dir == kTopToBottom || dir == kBottomToTop;
|
||||
}
|
||||
|
||||
static bool IsFlowHorizontal(FlowDirection dir)
|
||||
{
|
||||
return dir == kLeftToRight || dir == kRightToLeft;
|
||||
}
|
||||
|
||||
static bool DirectionsAreOpposing(FlowDirection a, FlowDirection b) {
|
||||
return ((a == NodeViewCommon::kLeftToRight && b == NodeViewCommon::kRightToLeft)
|
||||
|| (a == NodeViewCommon::kRightToLeft && b == NodeViewCommon::kLeftToRight)
|
||||
|| (a == NodeViewCommon::kTopToBottom && b == NodeViewCommon::kBottomToTop)
|
||||
|| (a == NodeViewCommon::kBottomToTop && b == NodeViewCommon::kTopToBottom));
|
||||
}
|
||||
static bool IsFlowHorizontal(FlowDirection dir)
|
||||
{
|
||||
return dir == kLeftToRight || dir == kRightToLeft;
|
||||
}
|
||||
|
||||
static bool DirectionsAreOpposing(FlowDirection a, FlowDirection b)
|
||||
{
|
||||
return ((a == NodeViewCommon::kLeftToRight &&
|
||||
b == NodeViewCommon::kRightToLeft) ||
|
||||
(a == NodeViewCommon::kRightToLeft &&
|
||||
b == NodeViewCommon::kLeftToRight) ||
|
||||
(a == NodeViewCommon::kTopToBottom &&
|
||||
b == NodeViewCommon::kBottomToTop) ||
|
||||
(a == NodeViewCommon::kBottomToTop &&
|
||||
b == NodeViewCommon::kTopToBottom));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -16,344 +16,379 @@
|
||||
#include "nodeviewitem.h"
|
||||
#include "ui/colorcoding.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super QGraphicsRectItem
|
||||
|
||||
NodeViewContext::NodeViewContext(Node *context, QGraphicsItem *item) :
|
||||
super(item),
|
||||
context_(context)
|
||||
NodeViewContext::NodeViewContext(Node *context, QGraphicsItem *item)
|
||||
: super(item)
|
||||
, context_(context)
|
||||
{
|
||||
Block *block = dynamic_cast<Block*>(context_);
|
||||
if (block && block->track() && block->track()->sequence()) {
|
||||
rational timebase = block->track()->sequence()->GetVideoParams().frame_rate_as_time_base();
|
||||
lbl_ = QCoreApplication::translate("NodeViewContext",
|
||||
"%1 [%2] :: %3 - %4").arg(block->GetLabelAndName(),
|
||||
Track::Reference::TypeToTranslatedString(block->track()->type()),
|
||||
QString::fromStdString(Timecode::time_to_timecode(block->in(), timebase, Core::instance()->GetTimecodeDisplay())),
|
||||
QString::fromStdString(Timecode::time_to_timecode(block->out(), timebase, Core::instance()->GetTimecodeDisplay())));
|
||||
} else {
|
||||
lbl_ = context_->GetLabelAndName();
|
||||
}
|
||||
Block *block = dynamic_cast<Block *>(context_);
|
||||
if (block && block->track() && block->track()->sequence()) {
|
||||
rational timebase = block->track()
|
||||
->sequence()
|
||||
->GetVideoParams()
|
||||
.frame_rate_as_time_base();
|
||||
lbl_ =
|
||||
QCoreApplication::translate("NodeViewContext", "%1 [%2] :: %3 - %4")
|
||||
.arg(block->GetLabelAndName(),
|
||||
Track::Reference::TypeToTranslatedString(
|
||||
block->track()->type()),
|
||||
QString::fromStdString(Timecode::time_to_timecode(
|
||||
block->in(), timebase,
|
||||
Core::instance()->GetTimecodeDisplay())),
|
||||
QString::fromStdString(Timecode::time_to_timecode(
|
||||
block->out(), timebase,
|
||||
Core::instance()->GetTimecodeDisplay())));
|
||||
} else {
|
||||
lbl_ = context_->GetLabelAndName();
|
||||
}
|
||||
|
||||
const Node::PositionMap &map = context_->GetContextPositions();
|
||||
for (auto it=map.cbegin(); it!=map.cend(); it++) {
|
||||
AddChild(it.key());
|
||||
}
|
||||
const Node::PositionMap &map = context_->GetContextPositions();
|
||||
for (auto it = map.cbegin(); it != map.cend(); it++) {
|
||||
AddChild(it.key());
|
||||
}
|
||||
|
||||
connect(context_, &Node::NodeAddedToContext, this, &NodeViewContext::AddChild, Qt::DirectConnection);
|
||||
connect(context_, &Node::NodePositionInContextChanged, this, &NodeViewContext::SetChildPosition, Qt::DirectConnection);
|
||||
connect(context_, &Node::NodeRemovedFromContext, this, &NodeViewContext::RemoveChild, Qt::DirectConnection);
|
||||
connect(context_, &Node::NodeAddedToContext, this,
|
||||
&NodeViewContext::AddChild, Qt::DirectConnection);
|
||||
connect(context_, &Node::NodePositionInContextChanged, this,
|
||||
&NodeViewContext::SetChildPosition, Qt::DirectConnection);
|
||||
connect(context_, &Node::NodeRemovedFromContext, this,
|
||||
&NodeViewContext::RemoveChild, Qt::DirectConnection);
|
||||
}
|
||||
|
||||
NodeViewContext::~NodeViewContext()
|
||||
{
|
||||
// Delete edges before items, because the edge constructor references the items
|
||||
qDeleteAll(edges_);
|
||||
edges_.clear();
|
||||
// Delete edges before items, because the edge constructor references the items
|
||||
qDeleteAll(edges_);
|
||||
edges_.clear();
|
||||
}
|
||||
|
||||
void NodeViewContext::AddChild(Node *node)
|
||||
{
|
||||
if (!context_) {
|
||||
return;
|
||||
}
|
||||
if (!context_) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodeViewItem *item = new NodeViewItem(node, context_, this);
|
||||
item->SetFlowDirection(flow_dir_);
|
||||
NodeViewItem *item = new NodeViewItem(node, context_, this);
|
||||
item->SetFlowDirection(flow_dir_);
|
||||
|
||||
AddNodeInternal(node, item);
|
||||
AddNodeInternal(node, item);
|
||||
|
||||
if (NodeGroup *group = dynamic_cast<NodeGroup*>(node)) {
|
||||
for (auto it=group->GetContextPositions().cbegin(); it!=group->GetContextPositions().cend(); it++) {
|
||||
// Use this item as the representative for all of these nodes too
|
||||
AddNodeInternal(it.key(), item);
|
||||
}
|
||||
if (NodeGroup *group = dynamic_cast<NodeGroup *>(node)) {
|
||||
for (auto it = group->GetContextPositions().cbegin();
|
||||
it != group->GetContextPositions().cend(); it++) {
|
||||
// Use this item as the representative for all of these nodes too
|
||||
AddNodeInternal(it.key(), item);
|
||||
}
|
||||
|
||||
connect(group, &NodeGroup::NodeAddedToContext, this, &NodeViewContext::GroupAddedNode);
|
||||
connect(group, &NodeGroup::NodeRemovedFromContext, this, &NodeViewContext::GroupRemovedNode);
|
||||
}
|
||||
connect(group, &NodeGroup::NodeAddedToContext, this,
|
||||
&NodeViewContext::GroupAddedNode);
|
||||
connect(group, &NodeGroup::NodeRemovedFromContext, this,
|
||||
&NodeViewContext::GroupRemovedNode);
|
||||
}
|
||||
|
||||
UpdateRect();
|
||||
UpdateRect();
|
||||
}
|
||||
|
||||
void NodeViewContext::SetChildPosition(Node *node, const QPointF &pos)
|
||||
{
|
||||
item_map_.value(node)->SetNodePosition(pos);
|
||||
item_map_.value(node)->SetNodePosition(pos);
|
||||
}
|
||||
|
||||
void NodeViewContext::RemoveChild(Node *node)
|
||||
{
|
||||
disconnect(node, &Node::InputConnected, this, &NodeViewContext::ChildInputConnected);
|
||||
disconnect(node, &Node::InputDisconnected, this, &NodeViewContext::ChildInputDisconnected);
|
||||
disconnect(node, &Node::InputConnected, this,
|
||||
&NodeViewContext::ChildInputConnected);
|
||||
disconnect(node, &Node::InputDisconnected, this,
|
||||
&NodeViewContext::ChildInputDisconnected);
|
||||
|
||||
if (NodeGroup *group = dynamic_cast<NodeGroup*>(node)) {
|
||||
disconnect(group, &NodeGroup::NodeAddedToContext, this, &NodeViewContext::GroupAddedNode);
|
||||
disconnect(group, &NodeGroup::NodeRemovedFromContext, this, &NodeViewContext::GroupRemovedNode);
|
||||
}
|
||||
if (NodeGroup *group = dynamic_cast<NodeGroup *>(node)) {
|
||||
disconnect(group, &NodeGroup::NodeAddedToContext, this,
|
||||
&NodeViewContext::GroupAddedNode);
|
||||
disconnect(group, &NodeGroup::NodeRemovedFromContext, this,
|
||||
&NodeViewContext::GroupRemovedNode);
|
||||
}
|
||||
|
||||
NodeViewItem *item = item_map_.take(node);
|
||||
NodeViewItem *item = item_map_.take(node);
|
||||
|
||||
// Remove from scene before emitting signal so that any drag functions that might be happening
|
||||
// now can be handled before the item is destroyed
|
||||
scene()->removeItem(item);
|
||||
// Remove from scene before emitting signal so that any drag functions that might be happening
|
||||
// now can be handled before the item is destroyed
|
||||
scene()->removeItem(item);
|
||||
|
||||
emit ItemAboutToBeDeleted(item);
|
||||
emit ItemAboutToBeDeleted(item);
|
||||
|
||||
// Delete edges first because the edge destructor will try to reference item (maybe that should
|
||||
// be changed...)
|
||||
QVector<NodeViewEdge*> edges_to_remove = item->GetAllEdgesRecursively();
|
||||
foreach (NodeViewEdge *edge, edges_to_remove) {
|
||||
if (node == item->GetNode() || edge->output() == node || edge->input().node() == node) {
|
||||
ChildInputDisconnected(edge->output(), edge->input());
|
||||
}
|
||||
}
|
||||
// Delete edges first because the edge destructor will try to reference item (maybe that should
|
||||
// be changed...)
|
||||
QVector<NodeViewEdge *> edges_to_remove = item->GetAllEdgesRecursively();
|
||||
foreach (NodeViewEdge *edge, edges_to_remove) {
|
||||
if (node == item->GetNode() || edge->output() == node ||
|
||||
edge->input().node() == node) {
|
||||
ChildInputDisconnected(edge->output(), edge->input());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this item is specifically for this node and the node is a group. If so, remove it for
|
||||
// all other entries in the map.
|
||||
if (item->GetNode() == node) {
|
||||
if (dynamic_cast<NodeGroup*>(item->GetNode())) {
|
||||
for (auto it=item_map_.begin(); it!=item_map_.end(); ) {
|
||||
if (it.value() == item) {
|
||||
it = item_map_.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if this item is specifically for this node and the node is a group. If so, remove it for
|
||||
// all other entries in the map.
|
||||
if (item->GetNode() == node) {
|
||||
if (dynamic_cast<NodeGroup *>(item->GetNode())) {
|
||||
for (auto it = item_map_.begin(); it != item_map_.end();) {
|
||||
if (it.value() == item) {
|
||||
it = item_map_.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete item;
|
||||
}
|
||||
delete item;
|
||||
}
|
||||
|
||||
UpdateRect();
|
||||
UpdateRect();
|
||||
}
|
||||
|
||||
void NodeViewContext::ChildInputConnected(Node *output, const NodeInput &input)
|
||||
{
|
||||
// Add edge
|
||||
if (!input.IsHidden()) {
|
||||
if (NodeViewItem* output_item = item_map_.value(output)) {
|
||||
AddEdgeInternal(output, input, output_item, item_map_.value(input.node())->GetItemForInput(input));
|
||||
}
|
||||
}
|
||||
// Add edge
|
||||
if (!input.IsHidden()) {
|
||||
if (NodeViewItem *output_item = item_map_.value(output)) {
|
||||
AddEdgeInternal(
|
||||
output, input, output_item,
|
||||
item_map_.value(input.node())->GetItemForInput(input));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NodeViewContext::ChildInputDisconnected(Node *output, const NodeInput &input)
|
||||
bool NodeViewContext::ChildInputDisconnected(Node *output,
|
||||
const NodeInput &input)
|
||||
{
|
||||
// Remove edge
|
||||
for (int i=0; i<edges_.size(); i++) {
|
||||
NodeViewEdge *e = edges_.at(i);
|
||||
if (e->output() == output && e->input() == input) {
|
||||
delete e;
|
||||
edges_.removeAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Remove edge
|
||||
for (int i = 0; i < edges_.size(); i++) {
|
||||
NodeViewEdge *e = edges_.at(i);
|
||||
if (e->output() == output && e->input() == input) {
|
||||
delete e;
|
||||
edges_.removeAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
qreal GetTextOffset(const QFontMetricsF &fm)
|
||||
{
|
||||
return fm.height()/2;
|
||||
return fm.height() / 2;
|
||||
}
|
||||
|
||||
void NodeViewContext::UpdateRect()
|
||||
{
|
||||
QFont f;
|
||||
QFontMetricsF fm(f);
|
||||
qreal lbl_offset = GetTextOffset(fm);
|
||||
QFont f;
|
||||
QFontMetricsF fm(f);
|
||||
qreal lbl_offset = GetTextOffset(fm);
|
||||
|
||||
QRectF cbr = childrenBoundingRect();
|
||||
QRectF rect = cbr;
|
||||
int pad = NodeViewItem::DefaultItemHeight();
|
||||
rect.adjust(-pad, - lbl_offset*2 - fm.height() - pad, pad, pad);
|
||||
setRect(rect);
|
||||
QRectF cbr = childrenBoundingRect();
|
||||
QRectF rect = cbr;
|
||||
int pad = NodeViewItem::DefaultItemHeight();
|
||||
rect.adjust(-pad, -lbl_offset * 2 - fm.height() - pad, pad, pad);
|
||||
setRect(rect);
|
||||
|
||||
last_titlebar_height_ = rect.y() + (cbr.y() - rect.y()) - pad;
|
||||
last_titlebar_height_ = rect.y() + (cbr.y() - rect.y()) - pad;
|
||||
}
|
||||
|
||||
void NodeViewContext::SetFlowDirection(NodeViewCommon::FlowDirection dir)
|
||||
{
|
||||
flow_dir_ = dir;
|
||||
flow_dir_ = dir;
|
||||
|
||||
foreach (NodeViewItem *item, item_map_) {
|
||||
item->SetFlowDirection(dir);
|
||||
}
|
||||
foreach (NodeViewItem *item, item_map_) {
|
||||
item->SetFlowDirection(dir);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewContext::SetCurvedEdges(bool e)
|
||||
{
|
||||
curved_edges_ = e;
|
||||
curved_edges_ = e;
|
||||
|
||||
foreach (NodeViewEdge *edge, edges_) {
|
||||
edge->SetCurved(e);
|
||||
}
|
||||
foreach (NodeViewEdge *edge, edges_) {
|
||||
edge->SetCurved(e);
|
||||
}
|
||||
}
|
||||
|
||||
int NodeViewContext::DeleteSelected(NodeViewDeleteCommand *command)
|
||||
{
|
||||
int count = 0;
|
||||
int count = 0;
|
||||
|
||||
// Delete any selected edges
|
||||
foreach (NodeViewEdge *edge, edges_) {
|
||||
if (edge->isSelected()) {
|
||||
command->AddEdge(edge->output(), edge->input());
|
||||
}
|
||||
}
|
||||
// Delete any selected edges
|
||||
foreach (NodeViewEdge *edge, edges_) {
|
||||
if (edge->isSelected()) {
|
||||
command->AddEdge(edge->output(), edge->input());
|
||||
}
|
||||
}
|
||||
|
||||
// Delete any selected nodes
|
||||
foreach (NodeViewItem *node, item_map_) {
|
||||
if (node->isSelected()) {
|
||||
command->AddNode(node->GetNode(), context_);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
// Delete any selected nodes
|
||||
foreach (NodeViewItem *node, item_map_) {
|
||||
if (node->isSelected()) {
|
||||
command->AddNode(node->GetNode(), context_);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
return count;
|
||||
}
|
||||
|
||||
void NodeViewContext::Select(const QVector<Node *> &nodes)
|
||||
{
|
||||
foreach (Node *n, nodes) {
|
||||
if (NodeViewItem *item = item_map_.value(n)) {
|
||||
item->setSelected(true);
|
||||
}
|
||||
}
|
||||
foreach (Node *n, nodes) {
|
||||
if (NodeViewItem *item = item_map_.value(n)) {
|
||||
item->setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVector<NodeViewItem *> NodeViewContext::GetSelectedItems() const
|
||||
{
|
||||
QVector<NodeViewItem *> items;
|
||||
QVector<NodeViewItem *> items;
|
||||
|
||||
for (auto it=item_map_.cbegin(); it!=item_map_.cend(); it++) {
|
||||
if (it.value()->isSelected()) {
|
||||
if (!items.contains(it.value())) {
|
||||
items.append(it.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it = item_map_.cbegin(); it != item_map_.cend(); it++) {
|
||||
if (it.value()->isSelected()) {
|
||||
if (!items.contains(it.value())) {
|
||||
items.append(it.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
return items;
|
||||
}
|
||||
|
||||
QPointF NodeViewContext::MapScenePosToNodePosInContext(const QPointF &pos) const
|
||||
{
|
||||
for (auto it=item_map_.cbegin(); it!=item_map_.cend(); it++) {
|
||||
QPointF pos_inside_parent = it.value()->mapToParent(it.value()->mapFromScene(pos));
|
||||
return NodeViewItem::ScreenToNodePoint(pos_inside_parent, flow_dir_);
|
||||
}
|
||||
return QPointF(0, 0);
|
||||
for (auto it = item_map_.cbegin(); it != item_map_.cend(); it++) {
|
||||
QPointF pos_inside_parent =
|
||||
it.value()->mapToParent(it.value()->mapFromScene(pos));
|
||||
return NodeViewItem::ScreenToNodePoint(pos_inside_parent, flow_dir_);
|
||||
}
|
||||
return QPointF(0, 0);
|
||||
}
|
||||
|
||||
void NodeViewContext::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
void NodeViewContext::paint(QPainter *painter,
|
||||
const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget)
|
||||
{
|
||||
// Set pen and brush
|
||||
Color color = context_->color();
|
||||
QColor c = QtUtils::toQColor(color);
|
||||
QPen pen(c, 2);
|
||||
if (option->state & QStyle::State_Selected) {
|
||||
pen.setStyle(Qt::DotLine);
|
||||
}
|
||||
painter->setPen(pen);
|
||||
// Set pen and brush
|
||||
Color color = context_->color();
|
||||
QColor c = QtUtils::toQColor(color);
|
||||
QPen pen(c, 2);
|
||||
if (option->state & QStyle::State_Selected) {
|
||||
pen.setStyle(Qt::DotLine);
|
||||
}
|
||||
painter->setPen(pen);
|
||||
|
||||
QColor bg = c;
|
||||
bg.setAlpha(128);
|
||||
painter->setBrush(bg);
|
||||
QColor bg = c;
|
||||
bg.setAlpha(128);
|
||||
painter->setBrush(bg);
|
||||
|
||||
// Draw semi-transparent rect for whole item
|
||||
int rounded = painter->fontMetrics().height();
|
||||
painter->drawRoundedRect(rect(), rounded, rounded);
|
||||
// Draw semi-transparent rect for whole item
|
||||
int rounded = painter->fontMetrics().height();
|
||||
painter->drawRoundedRect(rect(), rounded, rounded);
|
||||
|
||||
// Draw solid background for titlebar
|
||||
QRectF titlebar_rect = rect();
|
||||
titlebar_rect.setHeight(last_titlebar_height_ - rect().top());
|
||||
painter->setClipRect(titlebar_rect);
|
||||
painter->setBrush(c);
|
||||
painter->drawRoundedRect(rect(), rounded, rounded);
|
||||
painter->setClipping(false);
|
||||
// Draw solid background for titlebar
|
||||
QRectF titlebar_rect = rect();
|
||||
titlebar_rect.setHeight(last_titlebar_height_ - rect().top());
|
||||
painter->setClipRect(titlebar_rect);
|
||||
painter->setBrush(c);
|
||||
painter->drawRoundedRect(rect(), rounded, rounded);
|
||||
painter->setClipping(false);
|
||||
|
||||
// Draw titlebar text
|
||||
painter->setPen(ColorCoding::GetUISelectorColor(color));
|
||||
// Draw titlebar text
|
||||
painter->setPen(ColorCoding::GetUISelectorColor(color));
|
||||
|
||||
int offset = GetTextOffset(painter->fontMetrics());
|
||||
int offset = GetTextOffset(painter->fontMetrics());
|
||||
|
||||
QRectF text_rect = rect();
|
||||
text_rect.adjust(offset, offset, -offset, -offset);
|
||||
painter->drawText(text_rect, lbl_);
|
||||
QRectF text_rect = rect();
|
||||
text_rect.adjust(offset, offset, -offset, -offset);
|
||||
painter->drawText(text_rect, lbl_);
|
||||
}
|
||||
|
||||
QVariant NodeViewContext::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
QVariant NodeViewContext::itemChange(GraphicsItemChange change,
|
||||
const QVariant &value)
|
||||
{
|
||||
return super::itemChange(change, value);
|
||||
return super::itemChange(change, value);
|
||||
}
|
||||
|
||||
void NodeViewContext::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
bool clicked_inside_titlebar = (event->pos().y() < last_titlebar_height_);
|
||||
bool clicked_inside_titlebar = (event->pos().y() < last_titlebar_height_);
|
||||
|
||||
setFlag(ItemIsMovable, clicked_inside_titlebar);
|
||||
setFlag(ItemIsSelectable, clicked_inside_titlebar);
|
||||
setFlag(ItemIsMovable, clicked_inside_titlebar);
|
||||
setFlag(ItemIsSelectable, clicked_inside_titlebar);
|
||||
|
||||
super::mousePressEvent(event);
|
||||
super::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void NodeViewContext::AddNodeInternal(Node *node, NodeViewItem *item)
|
||||
{
|
||||
connect(node, &Node::InputConnected, this, &NodeViewContext::ChildInputConnected);
|
||||
connect(node, &Node::InputDisconnected, this, &NodeViewContext::ChildInputDisconnected);
|
||||
connect(node, &Node::InputConnected, this,
|
||||
&NodeViewContext::ChildInputConnected);
|
||||
connect(node, &Node::InputDisconnected, this,
|
||||
&NodeViewContext::ChildInputDisconnected);
|
||||
|
||||
item_map_.insert(node, item);
|
||||
item_map_.insert(node, item);
|
||||
|
||||
if (node == context_) {
|
||||
item->SetLabelAsOutput(true);
|
||||
}
|
||||
if (node == context_) {
|
||||
item->SetLabelAsOutput(true);
|
||||
}
|
||||
|
||||
for (auto it=node->output_connections().cbegin(); it!=node->output_connections().cend(); it++) {
|
||||
if (!it->second.IsHidden()) {
|
||||
if (NodeViewItem *other_item = item_map_.value(it->second.node())) {
|
||||
AddEdgeInternal(node, it->second, item, other_item->GetItemForInput(it->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it = node->output_connections().cbegin();
|
||||
it != node->output_connections().cend(); it++) {
|
||||
if (!it->second.IsHidden()) {
|
||||
if (NodeViewItem *other_item = item_map_.value(it->second.node())) {
|
||||
AddEdgeInternal(node, it->second, item,
|
||||
other_item->GetItemForInput(it->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) {
|
||||
if (!it->first.IsHidden()) {
|
||||
if (NodeViewItem *other_item = item_map_.value(it->second)) {
|
||||
AddEdgeInternal(it->second, it->first, other_item, item->GetItemForInput(it->first));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it = node->input_connections().cbegin();
|
||||
it != node->input_connections().cend(); it++) {
|
||||
if (!it->first.IsHidden()) {
|
||||
if (NodeViewItem *other_item = item_map_.value(it->second)) {
|
||||
AddEdgeInternal(it->second, it->first, other_item,
|
||||
item->GetItemForInput(it->first));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewContext::AddEdgeInternal(Node *output, const NodeInput& input, NodeViewItem *from, NodeViewItem *to)
|
||||
void NodeViewContext::AddEdgeInternal(Node *output, const NodeInput &input,
|
||||
NodeViewItem *from, NodeViewItem *to)
|
||||
{
|
||||
if (from == to) {
|
||||
return;
|
||||
}
|
||||
if (from == to) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodeViewEdge* edge_ui = new NodeViewEdge(output, input, from, to, this);
|
||||
NodeViewEdge *edge_ui = new NodeViewEdge(output, input, from, to, this);
|
||||
|
||||
edge_ui->Adjust();
|
||||
edge_ui->SetCurved(curved_edges_);
|
||||
edge_ui->Adjust();
|
||||
edge_ui->SetCurved(curved_edges_);
|
||||
|
||||
edges_.append(edge_ui);
|
||||
edges_.append(edge_ui);
|
||||
}
|
||||
|
||||
void NodeViewContext::GroupAddedNode(Node *node)
|
||||
{
|
||||
NodeGroup *group = static_cast<NodeGroup*>(sender());
|
||||
NodeGroup *group = static_cast<NodeGroup *>(sender());
|
||||
|
||||
AddNodeInternal(node, item_map_.value(group));
|
||||
AddNodeInternal(node, item_map_.value(group));
|
||||
}
|
||||
|
||||
void NodeViewContext::GroupRemovedNode(Node *node)
|
||||
{
|
||||
NodeGroup *group = static_cast<NodeGroup*>(sender());
|
||||
NodeGroup *group = static_cast<NodeGroup *>(sender());
|
||||
|
||||
if (item_map_.value(node) == item_map_.value(group)) {
|
||||
item_map_.remove(node);
|
||||
}
|
||||
if (item_map_.value(node) == item_map_.value(group)) {
|
||||
item_map_.remove(node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,85 +9,88 @@
|
||||
#include "nodeviewcommon.h"
|
||||
#include "nodeviewedge.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeViewContext : public QObject, public QGraphicsRectItem
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeViewContext : public QObject, public QGraphicsRectItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeViewContext(Node *context, QGraphicsItem *item = nullptr);
|
||||
NodeViewContext(Node *context, QGraphicsItem *item = nullptr);
|
||||
|
||||
virtual ~NodeViewContext() override;
|
||||
virtual ~NodeViewContext() override;
|
||||
|
||||
Node *GetContext() const
|
||||
{
|
||||
return context_;
|
||||
}
|
||||
Node *GetContext() const
|
||||
{
|
||||
return context_;
|
||||
}
|
||||
|
||||
void UpdateRect();
|
||||
void UpdateRect();
|
||||
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
|
||||
void SetCurvedEdges(bool e);
|
||||
void SetCurvedEdges(bool e);
|
||||
|
||||
int DeleteSelected(NodeViewDeleteCommand *command);
|
||||
int DeleteSelected(NodeViewDeleteCommand *command);
|
||||
|
||||
void Select(const QVector<Node*> &nodes);
|
||||
void Select(const QVector<Node *> &nodes);
|
||||
|
||||
QVector<NodeViewItem*> GetSelectedItems() const;
|
||||
QVector<NodeViewItem *> GetSelectedItems() const;
|
||||
|
||||
QPointF MapScenePosToNodePosInContext(const QPointF &pos) const;
|
||||
QPointF MapScenePosToNodePosInContext(const QPointF &pos) const;
|
||||
|
||||
NodeViewItem *GetItemFromMap(Node *node) const
|
||||
{
|
||||
return item_map_.value(node);
|
||||
}
|
||||
NodeViewItem *GetItemFromMap(Node *node) const
|
||||
{
|
||||
return item_map_.value(node);
|
||||
}
|
||||
|
||||
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
|
||||
virtual void paint(QPainter *painter,
|
||||
const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget = nullptr) override;
|
||||
|
||||
public slots:
|
||||
void AddChild(Node *node);
|
||||
void AddChild(Node *node);
|
||||
|
||||
void SetChildPosition(Node *node, const QPointF &pos);
|
||||
void SetChildPosition(Node *node, const QPointF &pos);
|
||||
|
||||
void RemoveChild(Node *node);
|
||||
void RemoveChild(Node *node);
|
||||
|
||||
void ChildInputConnected(Node *output, const NodeInput& input);
|
||||
void ChildInputConnected(Node *output, const NodeInput &input);
|
||||
|
||||
bool ChildInputDisconnected(Node *output, const NodeInput& input);
|
||||
bool ChildInputDisconnected(Node *output, const NodeInput &input);
|
||||
|
||||
signals:
|
||||
void ItemAboutToBeDeleted(NodeViewItem *item);
|
||||
void ItemAboutToBeDeleted(NodeViewItem *item);
|
||||
|
||||
protected:
|
||||
virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
|
||||
virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change,
|
||||
const QVariant &value) override;
|
||||
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
void AddNodeInternal(Node *node, NodeViewItem *item);
|
||||
void AddNodeInternal(Node *node, NodeViewItem *item);
|
||||
|
||||
void AddEdgeInternal(Node *output, const NodeInput& input, NodeViewItem *from, NodeViewItem *to);
|
||||
void AddEdgeInternal(Node *output, const NodeInput &input,
|
||||
NodeViewItem *from, NodeViewItem *to);
|
||||
|
||||
Node *context_;
|
||||
Node *context_;
|
||||
|
||||
QString lbl_;
|
||||
QString lbl_;
|
||||
|
||||
NodeViewCommon::FlowDirection flow_dir_;
|
||||
NodeViewCommon::FlowDirection flow_dir_;
|
||||
|
||||
bool curved_edges_;
|
||||
bool curved_edges_;
|
||||
|
||||
int last_titlebar_height_;
|
||||
int last_titlebar_height_;
|
||||
|
||||
QMap<Node*, NodeViewItem*> item_map_;
|
||||
QMap<Node *, NodeViewItem *> item_map_;
|
||||
|
||||
QVector<NodeViewEdge*> edges_;
|
||||
QVector<NodeViewEdge *> edges_;
|
||||
|
||||
private slots:
|
||||
void GroupAddedNode(Node *node);
|
||||
|
||||
void GroupRemovedNode(Node *node);
|
||||
void GroupAddedNode(Node *node);
|
||||
|
||||
void GroupRemovedNode(Node *node);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -30,226 +30,230 @@
|
||||
#include "nodeviewitem.h"
|
||||
#include "nodeviewscene.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super QGraphicsPathItem
|
||||
|
||||
NodeViewEdge::NodeViewEdge(Node *output, const NodeInput &input,
|
||||
NodeViewItem* from_item, NodeViewItem* to_item,
|
||||
QGraphicsItem* parent) :
|
||||
super(parent),
|
||||
output_(output),
|
||||
input_(input),
|
||||
from_item_(from_item),
|
||||
to_item_(to_item)
|
||||
NodeViewItem *from_item, NodeViewItem *to_item,
|
||||
QGraphicsItem *parent)
|
||||
: super(parent)
|
||||
, output_(output)
|
||||
, input_(input)
|
||||
, from_item_(from_item)
|
||||
, to_item_(to_item)
|
||||
{
|
||||
Init();
|
||||
SetConnected(true);
|
||||
Init();
|
||||
SetConnected(true);
|
||||
|
||||
from_item_->AddEdge(this);
|
||||
to_item_->AddEdge(this);
|
||||
from_item_->AddEdge(this);
|
||||
to_item_->AddEdge(this);
|
||||
}
|
||||
|
||||
NodeViewEdge::NodeViewEdge(QGraphicsItem *parent) :
|
||||
QGraphicsPathItem(parent),
|
||||
from_item_(nullptr),
|
||||
to_item_(nullptr)
|
||||
NodeViewEdge::NodeViewEdge(QGraphicsItem *parent)
|
||||
: QGraphicsPathItem(parent)
|
||||
, from_item_(nullptr)
|
||||
, to_item_(nullptr)
|
||||
{
|
||||
Init();
|
||||
Init();
|
||||
}
|
||||
|
||||
NodeViewEdge::~NodeViewEdge()
|
||||
{
|
||||
if (from_item_) {
|
||||
from_item_->RemoveEdge(this);
|
||||
}
|
||||
if (from_item_) {
|
||||
from_item_->RemoveEdge(this);
|
||||
}
|
||||
|
||||
if (to_item_) {
|
||||
to_item_->RemoveEdge(this);
|
||||
}
|
||||
if (to_item_) {
|
||||
to_item_->RemoveEdge(this);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewEdge::set_from_item(NodeViewItem *i)
|
||||
{
|
||||
if (from_item_) {
|
||||
from_item_->RemoveEdge(this);
|
||||
}
|
||||
if (from_item_) {
|
||||
from_item_->RemoveEdge(this);
|
||||
}
|
||||
|
||||
from_item_ = i;
|
||||
from_item_ = i;
|
||||
|
||||
if (from_item_) {
|
||||
from_item_->AddEdge(this);
|
||||
}
|
||||
if (from_item_) {
|
||||
from_item_->AddEdge(this);
|
||||
}
|
||||
|
||||
Adjust();
|
||||
Adjust();
|
||||
}
|
||||
|
||||
void NodeViewEdge::set_to_item(NodeViewItem *i)
|
||||
{
|
||||
if (to_item_) {
|
||||
to_item_->RemoveEdge(this);
|
||||
}
|
||||
if (to_item_) {
|
||||
to_item_->RemoveEdge(this);
|
||||
}
|
||||
|
||||
to_item_ = i;
|
||||
to_item_ = i;
|
||||
|
||||
if (to_item_) {
|
||||
to_item_->AddEdge(this);
|
||||
}
|
||||
if (to_item_) {
|
||||
to_item_->AddEdge(this);
|
||||
}
|
||||
|
||||
Adjust();
|
||||
Adjust();
|
||||
}
|
||||
|
||||
void NodeViewEdge::Adjust()
|
||||
{
|
||||
// Draw a line between the two
|
||||
SetPoints(from_item()->GetOutputPoint(), to_item()->GetInputPoint());
|
||||
// Draw a line between the two
|
||||
SetPoints(from_item()->GetOutputPoint(), to_item()->GetInputPoint());
|
||||
}
|
||||
|
||||
void NodeViewEdge::SetConnected(bool c)
|
||||
{
|
||||
connected_ = c;
|
||||
connected_ = c;
|
||||
|
||||
update();
|
||||
update();
|
||||
}
|
||||
|
||||
void NodeViewEdge::SetHighlighted(bool e)
|
||||
{
|
||||
highlighted_ = e;
|
||||
highlighted_ = e;
|
||||
|
||||
update();
|
||||
update();
|
||||
}
|
||||
|
||||
void NodeViewEdge::SetPoints(const QPointF &start, const QPointF &end)
|
||||
{
|
||||
cached_start_ = start;
|
||||
cached_end_ = end;
|
||||
cached_start_ = start;
|
||||
cached_end_ = end;
|
||||
|
||||
UpdateCurve();
|
||||
UpdateCurve();
|
||||
}
|
||||
|
||||
void NodeViewEdge::SetCurved(bool e)
|
||||
{
|
||||
curved_ = e;
|
||||
curved_ = e;
|
||||
|
||||
UpdateCurve();
|
||||
UpdateCurve();
|
||||
}
|
||||
|
||||
void NodeViewEdge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
|
||||
void NodeViewEdge::paint(QPainter *painter,
|
||||
const QStyleOptionGraphicsItem *option, QWidget *)
|
||||
{
|
||||
QPalette::ColorGroup group;
|
||||
QPalette::ColorRole role;
|
||||
QPalette::ColorGroup group;
|
||||
QPalette::ColorRole role;
|
||||
|
||||
if (connected_) {
|
||||
group = QPalette::Active;
|
||||
} else {
|
||||
group = QPalette::Disabled;
|
||||
}
|
||||
if (connected_) {
|
||||
group = QPalette::Active;
|
||||
} else {
|
||||
group = QPalette::Disabled;
|
||||
}
|
||||
|
||||
if (highlighted_ != bool(option->state & QStyle::State_Selected)) {
|
||||
role = QPalette::Highlight;
|
||||
} else {
|
||||
role = QPalette::Text;
|
||||
}
|
||||
if (highlighted_ != bool(option->state & QStyle::State_Selected)) {
|
||||
role = QPalette::Highlight;
|
||||
} else {
|
||||
role = QPalette::Text;
|
||||
}
|
||||
|
||||
// Draw main path
|
||||
QColor edge_color = qApp->palette().color(group, role);
|
||||
// Draw main path
|
||||
QColor edge_color = qApp->palette().color(group, role);
|
||||
|
||||
painter->setPen(QPen(edge_color, edge_width_));
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawPath(path());
|
||||
painter->setPen(QPen(edge_color, edge_width_));
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawPath(path());
|
||||
}
|
||||
|
||||
void NodeViewEdge::Init()
|
||||
{
|
||||
connected_ = false;
|
||||
highlighted_ = false;
|
||||
curved_ = true;
|
||||
connected_ = false;
|
||||
highlighted_ = false;
|
||||
curved_ = true;
|
||||
|
||||
setFlag(QGraphicsItem::ItemIsSelectable);
|
||||
setFlag(QGraphicsItem::ItemIsSelectable);
|
||||
|
||||
// Ensures this UI object is drawn behind other objects
|
||||
setZValue(-1);
|
||||
// Ensures this UI object is drawn behind other objects
|
||||
setZValue(-1);
|
||||
|
||||
// Use font metrics to set edge width for basic high DPI support
|
||||
edge_width_ = QFontMetrics(QFont()).height() / 12;
|
||||
// Use font metrics to set edge width for basic high DPI support
|
||||
edge_width_ = QFontMetrics(QFont()).height() / 12;
|
||||
}
|
||||
|
||||
void NodeViewEdge::UpdateCurve()
|
||||
{
|
||||
const QPointF &start = cached_start_;
|
||||
const QPointF &end = cached_end_;
|
||||
const QPointF &start = cached_start_;
|
||||
const QPointF &end = cached_end_;
|
||||
|
||||
QPainterPath path;
|
||||
path.moveTo(start);
|
||||
QPainterPath path;
|
||||
path.moveTo(start);
|
||||
|
||||
double angle = std::atan2(end.y() - start.y(), end.x() - start.x());
|
||||
double angle = std::atan2(end.y() - start.y(), end.x() - start.x());
|
||||
|
||||
if (curved_) {
|
||||
if (curved_) {
|
||||
double half_x = lerp(start.x(), end.x(), 0.5);
|
||||
double half_y = lerp(start.y(), end.y(), 0.5);
|
||||
|
||||
double half_x = lerp(start.x(), end.x(), 0.5);
|
||||
double half_y = lerp(start.y(), end.y(), 0.5);
|
||||
QPointF cp1, cp2;
|
||||
|
||||
QPointF cp1, cp2;
|
||||
NodeViewCommon::FlowDirection from_flow =
|
||||
from_item_ ? from_item_->GetFlowDirection() :
|
||||
NodeViewCommon::kInvalidDirection;
|
||||
NodeViewCommon::FlowDirection to_flow =
|
||||
to_item_ ? to_item_->GetFlowDirection() :
|
||||
NodeViewCommon::kInvalidDirection;
|
||||
|
||||
NodeViewCommon::FlowDirection from_flow = from_item_ ? from_item_->GetFlowDirection() : NodeViewCommon::kInvalidDirection;
|
||||
NodeViewCommon::FlowDirection to_flow = to_item_ ? to_item_->GetFlowDirection() : NodeViewCommon::kInvalidDirection;
|
||||
if (from_flow == NodeViewCommon::kInvalidDirection &&
|
||||
to_flow == NodeViewCommon::kInvalidDirection) {
|
||||
// This is a technically unsupported scenario, but to avoid issues, we'll use a fallback
|
||||
from_flow = NodeViewCommon::kLeftToRight;
|
||||
to_flow = NodeViewCommon::kLeftToRight;
|
||||
} else if (from_flow == NodeViewCommon::kInvalidDirection) {
|
||||
from_flow = to_flow;
|
||||
} else if (to_flow == NodeViewCommon::kInvalidDirection) {
|
||||
to_flow = from_flow;
|
||||
}
|
||||
|
||||
if (from_flow == NodeViewCommon::kInvalidDirection && to_flow == NodeViewCommon::kInvalidDirection) {
|
||||
// This is a technically unsupported scenario, but to avoid issues, we'll use a fallback
|
||||
from_flow = NodeViewCommon::kLeftToRight;
|
||||
to_flow = NodeViewCommon::kLeftToRight;
|
||||
} else if (from_flow == NodeViewCommon::kInvalidDirection) {
|
||||
from_flow = to_flow;
|
||||
} else if (to_flow == NodeViewCommon::kInvalidDirection) {
|
||||
to_flow = from_flow;
|
||||
}
|
||||
if (NodeViewCommon::GetFlowOrientation(from_flow) == Qt::Horizontal) {
|
||||
cp1 = QPointF(half_x, start.y());
|
||||
} else {
|
||||
cp1 = QPointF(start.x(), half_y);
|
||||
}
|
||||
|
||||
if (NodeViewCommon::GetFlowOrientation(from_flow) == Qt::Horizontal) {
|
||||
cp1 = QPointF(half_x, start.y());
|
||||
} else {
|
||||
cp1 = QPointF(start.x(), half_y);
|
||||
}
|
||||
if (NodeViewCommon::GetFlowOrientation(to_flow) == Qt::Horizontal) {
|
||||
cp2 = QPointF(half_x, end.y());
|
||||
} else {
|
||||
cp2 = QPointF(end.x(), half_y);
|
||||
}
|
||||
|
||||
if (NodeViewCommon::GetFlowOrientation(to_flow) == Qt::Horizontal) {
|
||||
cp2 = QPointF(half_x, end.y());
|
||||
} else {
|
||||
cp2 = QPointF(end.x(), half_y);
|
||||
}
|
||||
path.cubicTo(cp1, cp2, end);
|
||||
|
||||
path.cubicTo(cp1, cp2, end);
|
||||
if (!qFuzzyCompare(start.x(), end.x())) {
|
||||
double continue_x = end.x() - std::cos(angle);
|
||||
|
||||
if (!qFuzzyCompare(start.x(), end.x())) {
|
||||
double continue_x = end.x() - std::cos(angle);
|
||||
double x1 = start.x();
|
||||
double x2 = cp1.x();
|
||||
double x3 = cp2.x();
|
||||
double x4 = end.x();
|
||||
double y1 = start.y();
|
||||
double y2 = cp1.y();
|
||||
double y3 = cp2.y();
|
||||
double y4 = end.y();
|
||||
|
||||
double x1 = start.x();
|
||||
double x2 = cp1.x();
|
||||
double x3 = cp2.x();
|
||||
double x4 = end.x();
|
||||
double y1 = start.y();
|
||||
double y2 = cp1.y();
|
||||
double y3 = cp2.y();
|
||||
double y4 = end.y();
|
||||
if (start.x() >= end.x()) {
|
||||
std::swap(x1, x4);
|
||||
std::swap(x2, x3);
|
||||
std::swap(y1, y4);
|
||||
std::swap(y2, y3);
|
||||
}
|
||||
|
||||
if (start.x() >= end.x()) {
|
||||
std::swap(x1, x4);
|
||||
std::swap(x2, x3);
|
||||
std::swap(y1, y4);
|
||||
std::swap(y2, y3);
|
||||
}
|
||||
double t = Bezier::CubicXtoT(continue_x, x1, x2, x3, x4);
|
||||
double y = Bezier::CubicTtoY(y1, y2, y3, y4, t);
|
||||
|
||||
double t = Bezier::CubicXtoT(continue_x, x1, x2, x3, x4);
|
||||
double y = Bezier::CubicTtoY(y1, y2, y3, y4, t);
|
||||
angle = std::atan2(end.y() - y, end.x() - continue_x);
|
||||
}
|
||||
|
||||
angle = std::atan2(end.y() - y, end.x() - continue_x);
|
||||
}
|
||||
} else {
|
||||
path.lineTo(end);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
path.lineTo(end);
|
||||
|
||||
}
|
||||
|
||||
setPath(mapFromScene(path));
|
||||
setPath(mapFromScene(path));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
#include "nodeviewcommon.h"
|
||||
#include "node/node.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class NodeViewItem;
|
||||
|
||||
@@ -36,49 +37,47 @@ class NodeViewItem;
|
||||
*
|
||||
* A fairly simple line widget use to visualize a connection between two node parameters (a NodeEdge).
|
||||
*/
|
||||
class NodeViewEdge : public QGraphicsPathItem
|
||||
{
|
||||
class NodeViewEdge : public QGraphicsPathItem {
|
||||
public:
|
||||
NodeViewEdge(Node *output, const NodeInput& input,
|
||||
NodeViewItem* from_item, NodeViewItem* to_item,
|
||||
QGraphicsItem* parent = nullptr);
|
||||
NodeViewEdge(Node *output, const NodeInput &input, NodeViewItem *from_item,
|
||||
NodeViewItem *to_item, QGraphicsItem *parent = nullptr);
|
||||
|
||||
NodeViewEdge(QGraphicsItem* parent = nullptr);
|
||||
NodeViewEdge(QGraphicsItem *parent = nullptr);
|
||||
|
||||
virtual ~NodeViewEdge() override;
|
||||
virtual ~NodeViewEdge() override;
|
||||
|
||||
Node *output() const
|
||||
{
|
||||
return output_;
|
||||
}
|
||||
Node *output() const
|
||||
{
|
||||
return output_;
|
||||
}
|
||||
|
||||
const NodeInput& input() const
|
||||
{
|
||||
return input_;
|
||||
}
|
||||
const NodeInput &input() const
|
||||
{
|
||||
return input_;
|
||||
}
|
||||
|
||||
int element() const
|
||||
{
|
||||
return element_;
|
||||
}
|
||||
int element() const
|
||||
{
|
||||
return element_;
|
||||
}
|
||||
|
||||
NodeViewItem* from_item() const
|
||||
{
|
||||
return from_item_;
|
||||
}
|
||||
NodeViewItem *from_item() const
|
||||
{
|
||||
return from_item_;
|
||||
}
|
||||
|
||||
NodeViewItem* to_item() const
|
||||
{
|
||||
return to_item_;
|
||||
}
|
||||
NodeViewItem *to_item() const
|
||||
{
|
||||
return to_item_;
|
||||
}
|
||||
|
||||
void set_from_item(NodeViewItem *i);
|
||||
void set_from_item(NodeViewItem *i);
|
||||
|
||||
void set_to_item(NodeViewItem *i);
|
||||
void set_to_item(NodeViewItem *i);
|
||||
|
||||
void Adjust();
|
||||
void Adjust();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set the connected state of this line
|
||||
*
|
||||
* When the edge is not connected, it visually depicts this by coloring the line grey. When an edge is connected or
|
||||
@@ -88,59 +87,60 @@ public:
|
||||
* Using SetEdge() automatically sets this to true. Under most circumstances this should be left alone, and only
|
||||
* be set when an edge is being created/dragged.
|
||||
*/
|
||||
void SetConnected(bool c);
|
||||
void SetConnected(bool c);
|
||||
|
||||
bool IsConnected() const
|
||||
{
|
||||
return connected_;
|
||||
}
|
||||
bool IsConnected() const
|
||||
{
|
||||
return connected_;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set highlighted state
|
||||
*
|
||||
* Changes color of edge.
|
||||
*/
|
||||
void SetHighlighted(bool e);
|
||||
void SetHighlighted(bool e);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set points to create curve from
|
||||
*/
|
||||
void SetPoints(const QPointF& start, const QPointF& end);
|
||||
void SetPoints(const QPointF &start, const QPointF &end);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set whether edges should be drawn as curved or as straight lines
|
||||
*/
|
||||
void SetCurved(bool e);
|
||||
void SetCurved(bool e);
|
||||
|
||||
protected:
|
||||
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
|
||||
virtual void paint(QPainter *painter,
|
||||
const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget = nullptr) override;
|
||||
|
||||
private:
|
||||
void Init();
|
||||
void Init();
|
||||
|
||||
void UpdateCurve();
|
||||
void UpdateCurve();
|
||||
|
||||
Node *output_;
|
||||
Node *output_;
|
||||
|
||||
NodeInput input_;
|
||||
NodeInput input_;
|
||||
|
||||
int element_;
|
||||
int element_;
|
||||
|
||||
NodeViewItem* from_item_;
|
||||
NodeViewItem *from_item_;
|
||||
|
||||
NodeViewItem* to_item_;
|
||||
NodeViewItem *to_item_;
|
||||
|
||||
int edge_width_;
|
||||
int edge_width_;
|
||||
|
||||
bool connected_;
|
||||
bool connected_;
|
||||
|
||||
bool highlighted_;
|
||||
bool highlighted_;
|
||||
|
||||
bool curved_;
|
||||
|
||||
QPointF cached_start_;
|
||||
QPointF cached_end_;
|
||||
bool curved_;
|
||||
|
||||
QPointF cached_start_;
|
||||
QPointF cached_end_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+122
-115
@@ -30,7 +30,8 @@
|
||||
#include "nodeviewcommon.h"
|
||||
#include "nodeviewitemconnector.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class NodeViewItem;
|
||||
class NodeViewEdge;
|
||||
@@ -42,195 +43,201 @@ class NodeViewEdge;
|
||||
*
|
||||
* To retrieve the NodeViewItem for a certain Node, use NodeView::NodeToUIObject().
|
||||
*/
|
||||
class NodeViewItem : public QObject, public QGraphicsRectItem
|
||||
{
|
||||
Q_OBJECT
|
||||
class NodeViewItem : public QObject, public QGraphicsRectItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeViewItem(Node *node, const QString &input, int element, Node *context, QGraphicsItem* parent = nullptr);
|
||||
NodeViewItem(Node *node, Node *context, QGraphicsItem* parent = nullptr) :
|
||||
NodeViewItem(node, QString(), -1, context, parent)
|
||||
{
|
||||
}
|
||||
NodeViewItem(Node *node, const QString &input, int element, Node *context,
|
||||
QGraphicsItem *parent = nullptr);
|
||||
NodeViewItem(Node *node, Node *context, QGraphicsItem *parent = nullptr)
|
||||
: NodeViewItem(node, QString(), -1, context, parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~NodeViewItem() override;
|
||||
virtual ~NodeViewItem() override;
|
||||
|
||||
Node::Position GetNodePositionData() const;
|
||||
QPointF GetNodePosition() const;
|
||||
void SetNodePosition(const QPointF& pos);
|
||||
void SetNodePosition(const Node::Position& pos);
|
||||
Node::Position GetNodePositionData() const;
|
||||
QPointF GetNodePosition() const;
|
||||
void SetNodePosition(const QPointF &pos);
|
||||
void SetNodePosition(const Node::Position &pos);
|
||||
|
||||
QVector<NodeViewEdge*> GetAllEdgesRecursively() const;
|
||||
QVector<NodeViewEdge *> GetAllEdgesRecursively() const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Get currently attached node
|
||||
*/
|
||||
Node* GetNode() const
|
||||
{
|
||||
return node_;
|
||||
}
|
||||
Node *GetNode() const
|
||||
{
|
||||
return node_;
|
||||
}
|
||||
|
||||
NodeInput GetInput() const
|
||||
{
|
||||
return NodeInput(node_, input_, element_);
|
||||
}
|
||||
NodeInput GetInput() const
|
||||
{
|
||||
return NodeInput(node_, input_, element_);
|
||||
}
|
||||
|
||||
Node *GetContext() const
|
||||
{
|
||||
return context_;
|
||||
}
|
||||
Node *GetContext() const
|
||||
{
|
||||
return context_;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Get expanded state
|
||||
*/
|
||||
bool IsExpanded() const
|
||||
{
|
||||
return expanded_;
|
||||
}
|
||||
bool IsExpanded() const
|
||||
{
|
||||
return expanded_;
|
||||
}
|
||||
|
||||
const QVector<NodeViewEdge*> &edges() const
|
||||
{
|
||||
return edges_;
|
||||
}
|
||||
const QVector<NodeViewEdge *> &edges() const
|
||||
{
|
||||
return edges_;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set expanded state
|
||||
*/
|
||||
void SetExpanded(bool e, bool hide_titlebar = false);
|
||||
void ToggleExpanded();
|
||||
void SetExpanded(bool e, bool hide_titlebar = false);
|
||||
void ToggleExpanded();
|
||||
|
||||
QPointF GetInputPoint() const;
|
||||
QPointF GetOutputPoint() const;
|
||||
QPointF GetInputPoint() const;
|
||||
QPointF GetOutputPoint() const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Sets the direction nodes are flowing
|
||||
*/
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
|
||||
NodeViewCommon::FlowDirection GetFlowDirection() const
|
||||
{
|
||||
return flow_dir_;
|
||||
}
|
||||
NodeViewCommon::FlowDirection GetFlowDirection() const
|
||||
{
|
||||
return flow_dir_;
|
||||
}
|
||||
|
||||
static int DefaultTextPadding();
|
||||
static int DefaultTextPadding();
|
||||
|
||||
static int DefaultItemHeight();
|
||||
static int DefaultItemHeight();
|
||||
|
||||
static int DefaultItemWidth();
|
||||
static int DefaultItemWidth();
|
||||
|
||||
static int DefaultItemBorder();
|
||||
static int DefaultItemBorder();
|
||||
|
||||
static QPointF NodeToScreenPoint(QPointF p, NodeViewCommon::FlowDirection direction);
|
||||
static QPointF ScreenToNodePoint(QPointF p, NodeViewCommon::FlowDirection direction);
|
||||
static QPointF NodeToScreenPoint(QPointF p,
|
||||
NodeViewCommon::FlowDirection direction);
|
||||
static QPointF ScreenToNodePoint(QPointF p,
|
||||
NodeViewCommon::FlowDirection direction);
|
||||
|
||||
static qreal DefaultItemHorizontalPadding(NodeViewCommon::FlowDirection dir);
|
||||
static qreal DefaultItemVerticalPadding(NodeViewCommon::FlowDirection dir);
|
||||
qreal DefaultItemHorizontalPadding() const;
|
||||
qreal DefaultItemVerticalPadding() const;
|
||||
static qreal
|
||||
DefaultItemHorizontalPadding(NodeViewCommon::FlowDirection dir);
|
||||
static qreal DefaultItemVerticalPadding(NodeViewCommon::FlowDirection dir);
|
||||
qreal DefaultItemHorizontalPadding() const;
|
||||
qreal DefaultItemVerticalPadding() const;
|
||||
|
||||
void AddEdge(NodeViewEdge* edge);
|
||||
void RemoveEdge(NodeViewEdge* edge);
|
||||
void AddEdge(NodeViewEdge *edge);
|
||||
void RemoveEdge(NodeViewEdge *edge);
|
||||
|
||||
bool IsLabelledAsOutputOfContext() const
|
||||
{
|
||||
return label_as_output_;
|
||||
}
|
||||
bool IsLabelledAsOutputOfContext() const
|
||||
{
|
||||
return label_as_output_;
|
||||
}
|
||||
|
||||
void SetLabelAsOutput(bool e);
|
||||
void SetLabelAsOutput(bool e);
|
||||
|
||||
void SetHighlighted(bool e);
|
||||
void SetHighlighted(bool e);
|
||||
|
||||
NodeViewItem *GetItemForInput(NodeInput input);
|
||||
NodeViewItem *GetItemForInput(NodeInput input);
|
||||
|
||||
bool IsOutputItem() const
|
||||
{
|
||||
return input_.isEmpty();
|
||||
}
|
||||
bool IsOutputItem() const
|
||||
{
|
||||
return input_.isEmpty();
|
||||
}
|
||||
|
||||
void ReadjustAllEdges();
|
||||
void ReadjustAllEdges();
|
||||
|
||||
void UpdateFlowDirectionOfInputItem(NodeViewItem *child);
|
||||
void UpdateFlowDirectionOfInputItem(NodeViewItem *child);
|
||||
|
||||
bool CanBeExpanded() const;
|
||||
bool CanBeExpanded() const;
|
||||
|
||||
protected:
|
||||
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
|
||||
virtual void paint(QPainter *painter,
|
||||
const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget = nullptr) override;
|
||||
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
|
||||
virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
|
||||
virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change,
|
||||
const QVariant &value) override;
|
||||
|
||||
private:
|
||||
void UpdateContextRect();
|
||||
void UpdateContextRect();
|
||||
|
||||
void DrawNodeTitle(QPainter *painter, QString text, const QRectF &rect, Qt::Alignment vertical_align, int icon_full_size);
|
||||
void DrawNodeTitle(QPainter *painter, QString text, const QRectF &rect,
|
||||
Qt::Alignment vertical_align, int icon_full_size);
|
||||
|
||||
int DrawExpandArrow(QPainter *painter);
|
||||
int DrawExpandArrow(QPainter *painter);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Internal update function when logical position changes
|
||||
*/
|
||||
void UpdateNodePosition();
|
||||
void UpdateNodePosition();
|
||||
|
||||
void UpdateInputConnectorPosition();
|
||||
void UpdateOutputConnectorPosition();
|
||||
void UpdateInputConnectorPosition();
|
||||
void UpdateOutputConnectorPosition();
|
||||
|
||||
bool IsInputValid(const QString &input);
|
||||
bool IsInputValid(const QString &input);
|
||||
|
||||
void SetRectSize(int height_units = 1);
|
||||
void SetRectSize(int height_units = 1);
|
||||
|
||||
void UpdateChildrenPositions();
|
||||
void UpdateChildrenPositions();
|
||||
|
||||
int GetLogicalHeightWithChildren() const;
|
||||
int GetLogicalHeightWithChildren() const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Reference to attached Node
|
||||
*/
|
||||
Node *node_;
|
||||
QString input_;
|
||||
int element_;
|
||||
Node *node_;
|
||||
QString input_;
|
||||
int element_;
|
||||
|
||||
Node *context_;
|
||||
Node *context_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Cached list of node inputs
|
||||
*/
|
||||
QVector<NodeViewItem*> children_;
|
||||
QVector<NodeViewItem *> children_;
|
||||
|
||||
/// Sizing variables to use when drawing
|
||||
int node_border_width_;
|
||||
/// Sizing variables to use when drawing
|
||||
int node_border_width_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Expanded state
|
||||
*/
|
||||
bool expanded_;
|
||||
bool expanded_;
|
||||
|
||||
bool highlighted_;
|
||||
bool highlighted_;
|
||||
|
||||
NodeViewCommon::FlowDirection flow_dir_;
|
||||
NodeViewCommon::FlowDirection flow_dir_;
|
||||
|
||||
QVector<NodeViewEdge*> edges_;
|
||||
QVector<NodeViewEdge *> edges_;
|
||||
|
||||
QPointF cached_node_pos_;
|
||||
QPointF cached_node_pos_;
|
||||
|
||||
QRect last_arrow_rect_;
|
||||
bool arrow_click_;
|
||||
QRect last_arrow_rect_;
|
||||
bool arrow_click_;
|
||||
|
||||
NodeViewItemConnector *input_connector_;
|
||||
NodeViewItemConnector *output_connector_;
|
||||
NodeViewItemConnector *input_connector_;
|
||||
NodeViewItemConnector *output_connector_;
|
||||
|
||||
bool has_connectable_inputs_;
|
||||
bool has_connectable_inputs_;
|
||||
|
||||
bool label_as_output_;
|
||||
bool label_as_output_;
|
||||
|
||||
private slots:
|
||||
void NodeAppearanceChanged();
|
||||
void NodeAppearanceChanged();
|
||||
|
||||
void RepopulateInputs();
|
||||
|
||||
void InputArraySizeChanged(const QString &input);
|
||||
void RepopulateInputs();
|
||||
|
||||
void InputArraySizeChanged(const QString &input);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -27,73 +27,75 @@
|
||||
|
||||
#include "nodeviewitem.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeViewItemConnector::NodeViewItemConnector(bool is_output, QGraphicsItem *parent) :
|
||||
QGraphicsPolygonItem(parent),
|
||||
output_(is_output)
|
||||
namespace olive
|
||||
{
|
||||
QColor c = qApp->palette().text().color();
|
||||
setPen(QPen(c, NodeViewItem::DefaultItemBorder()));
|
||||
setBrush(c);
|
||||
|
||||
NodeViewItemConnector::NodeViewItemConnector(bool is_output,
|
||||
QGraphicsItem *parent)
|
||||
: QGraphicsPolygonItem(parent)
|
||||
, output_(is_output)
|
||||
{
|
||||
QColor c = qApp->palette().text().color();
|
||||
setPen(QPen(c, NodeViewItem::DefaultItemBorder()));
|
||||
setBrush(c);
|
||||
}
|
||||
|
||||
void NodeViewItemConnector::SetFlowDirection(NodeViewCommon::FlowDirection dir)
|
||||
{
|
||||
QFont f;
|
||||
QFontMetricsF fm(f);
|
||||
QFont f;
|
||||
QFontMetricsF fm(f);
|
||||
|
||||
int triangle_sz = fm.height()/2;
|
||||
int triangle_sz_half = triangle_sz / 2;
|
||||
int triangle_sz = fm.height() / 2;
|
||||
int triangle_sz_half = triangle_sz / 2;
|
||||
|
||||
QPolygonF p;
|
||||
p.resize(3);
|
||||
QPolygonF p;
|
||||
p.resize(3);
|
||||
|
||||
switch (dir) {
|
||||
case NodeViewCommon::kLeftToRight:
|
||||
// Triangle pointing right
|
||||
p[0] = QPointF(0, -triangle_sz_half);
|
||||
p[1] = QPointF(triangle_sz_half, 0);
|
||||
p[2] = QPointF(0, triangle_sz_half);
|
||||
break;
|
||||
case NodeViewCommon::kTopToBottom:
|
||||
// Triangle pointing down
|
||||
p[0] = QPointF(-triangle_sz_half, 0);
|
||||
p[1] = QPointF(0, triangle_sz_half);
|
||||
p[2] = QPointF(triangle_sz_half, 0);
|
||||
break;
|
||||
case NodeViewCommon::kBottomToTop:
|
||||
// Triangle pointing up
|
||||
p[0] = QPointF(-triangle_sz_half, 0);
|
||||
p[1] = QPointF(0, -triangle_sz_half);
|
||||
p[2] = QPointF(triangle_sz_half, 0);
|
||||
break;
|
||||
case NodeViewCommon::kRightToLeft:
|
||||
// Triangle pointing left
|
||||
p[0] = QPointF(0, -triangle_sz_half);
|
||||
p[1] = QPointF(-triangle_sz_half, 0);
|
||||
p[2] = QPointF(0, triangle_sz_half);
|
||||
break;
|
||||
case NodeViewCommon::kInvalidDirection:
|
||||
break;
|
||||
}
|
||||
switch (dir) {
|
||||
case NodeViewCommon::kLeftToRight:
|
||||
// Triangle pointing right
|
||||
p[0] = QPointF(0, -triangle_sz_half);
|
||||
p[1] = QPointF(triangle_sz_half, 0);
|
||||
p[2] = QPointF(0, triangle_sz_half);
|
||||
break;
|
||||
case NodeViewCommon::kTopToBottom:
|
||||
// Triangle pointing down
|
||||
p[0] = QPointF(-triangle_sz_half, 0);
|
||||
p[1] = QPointF(0, triangle_sz_half);
|
||||
p[2] = QPointF(triangle_sz_half, 0);
|
||||
break;
|
||||
case NodeViewCommon::kBottomToTop:
|
||||
// Triangle pointing up
|
||||
p[0] = QPointF(-triangle_sz_half, 0);
|
||||
p[1] = QPointF(0, -triangle_sz_half);
|
||||
p[2] = QPointF(triangle_sz_half, 0);
|
||||
break;
|
||||
case NodeViewCommon::kRightToLeft:
|
||||
// Triangle pointing left
|
||||
p[0] = QPointF(0, -triangle_sz_half);
|
||||
p[1] = QPointF(-triangle_sz_half, 0);
|
||||
p[2] = QPointF(0, triangle_sz_half);
|
||||
break;
|
||||
case NodeViewCommon::kInvalidDirection:
|
||||
break;
|
||||
}
|
||||
|
||||
setPolygon(p);
|
||||
setPolygon(p);
|
||||
}
|
||||
|
||||
QPainterPath NodeViewItemConnector::shape() const
|
||||
{
|
||||
// Yes, we skip QGraphicsPolygonItem because it adds the polygon. QGraphicsItem adds the
|
||||
// boundingRect which we modify below
|
||||
return QGraphicsItem::shape(); // clazy:exclude=skipped-base-method
|
||||
// Yes, we skip QGraphicsPolygonItem because it adds the polygon. QGraphicsItem adds the
|
||||
// boundingRect which we modify below
|
||||
return QGraphicsItem::shape(); // clazy:exclude=skipped-base-method
|
||||
}
|
||||
|
||||
QRectF NodeViewItemConnector::boundingRect() const
|
||||
{
|
||||
QRectF b = this->polygon().boundingRect();
|
||||
const int radius = QFontMetrics(QFont()).height()/2;
|
||||
b.adjust(-radius, -radius, radius, radius);
|
||||
return b;
|
||||
QRectF b = this->polygon().boundingRect();
|
||||
const int radius = QFontMetrics(QFont()).height() / 2;
|
||||
b.adjust(-radius, -radius, radius, radius);
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,26 +25,25 @@
|
||||
|
||||
#include "nodeviewcommon.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeViewItemConnector : public QGraphicsPolygonItem
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class NodeViewItemConnector : public QGraphicsPolygonItem {
|
||||
public:
|
||||
NodeViewItemConnector(bool is_output, QGraphicsItem *parent = nullptr);
|
||||
NodeViewItemConnector(bool is_output, QGraphicsItem *parent = nullptr);
|
||||
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
|
||||
bool IsOutput() const
|
||||
{
|
||||
return output_;
|
||||
}
|
||||
bool IsOutput() const
|
||||
{
|
||||
return output_;
|
||||
}
|
||||
|
||||
virtual QPainterPath shape() const override;
|
||||
virtual QRectF boundingRect() const override;
|
||||
virtual QPainterPath shape() const override;
|
||||
virtual QRectF boundingRect() const override;
|
||||
|
||||
private:
|
||||
bool output_;
|
||||
|
||||
bool output_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,134 +22,139 @@
|
||||
|
||||
#include <QMouseEvent>
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super QGraphicsView
|
||||
|
||||
NodeViewMiniMap::NodeViewMiniMap(NodeViewScene *scene, QWidget *parent) :
|
||||
super(parent),
|
||||
resizing_(false)
|
||||
NodeViewMiniMap::NodeViewMiniMap(NodeViewScene *scene, QWidget *parent)
|
||||
: super(parent)
|
||||
, resizing_(false)
|
||||
{
|
||||
connect(scene, &QGraphicsScene::sceneRectChanged, this, &NodeViewMiniMap::SceneChanged);
|
||||
setScene(scene);
|
||||
connect(scene, &QGraphicsScene::sceneRectChanged, this,
|
||||
&NodeViewMiniMap::SceneChanged);
|
||||
setScene(scene);
|
||||
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setViewportUpdateMode(FullViewportUpdate);
|
||||
setFrameShape(QFrame::Panel);
|
||||
setFrameShadow(QFrame::Plain);
|
||||
setMouseTracking(true);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setViewportUpdateMode(FullViewportUpdate);
|
||||
setFrameShape(QFrame::Panel);
|
||||
setFrameShadow(QFrame::Plain);
|
||||
setMouseTracking(true);
|
||||
|
||||
QMetaObject::invokeMethod(this, &NodeViewMiniMap::SetDefaultSize, Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(this, &NodeViewMiniMap::SetDefaultSize,
|
||||
Qt::QueuedConnection);
|
||||
|
||||
resize_triangle_sz_ = fontMetrics().height() / 2;
|
||||
resize_triangle_sz_ = fontMetrics().height() / 2;
|
||||
}
|
||||
|
||||
void NodeViewMiniMap::SetViewportRect(const QPolygonF &rect)
|
||||
{
|
||||
viewport_rect_ = rect;
|
||||
viewport_rect_ = rect;
|
||||
|
||||
viewport()->update();
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void NodeViewMiniMap::drawForeground(QPainter *painter, const QRectF &rect)
|
||||
{
|
||||
super::drawForeground(painter, rect);
|
||||
super::drawForeground(painter, rect);
|
||||
|
||||
QColor viewport_color = palette().text().color();
|
||||
QColor viewport_color = palette().text().color();
|
||||
|
||||
// Draw resize triangle
|
||||
painter->save();
|
||||
painter->resetTransform();
|
||||
// Draw resize triangle
|
||||
painter->save();
|
||||
painter->resetTransform();
|
||||
|
||||
QPointF triangle[3] = {QPointF(0, 0), QPointF(resize_triangle_sz_, 0), QPointF(0, resize_triangle_sz_)};
|
||||
painter->setBrush(viewport_color);
|
||||
painter->setPen(viewport_color);
|
||||
painter->drawPolygon(triangle, 3);
|
||||
QPointF triangle[3] = { QPointF(0, 0), QPointF(resize_triangle_sz_, 0),
|
||||
QPointF(0, resize_triangle_sz_) };
|
||||
painter->setBrush(viewport_color);
|
||||
painter->setPen(viewport_color);
|
||||
painter->drawPolygon(triangle, 3);
|
||||
|
||||
painter->restore();
|
||||
painter->restore();
|
||||
|
||||
// Draw viewport rectangle
|
||||
viewport_color.setAlphaF(0.25);
|
||||
painter->setBrush(viewport_color);
|
||||
// Draw viewport rectangle
|
||||
viewport_color.setAlphaF(0.25);
|
||||
painter->setBrush(viewport_color);
|
||||
|
||||
painter->drawPolygon(viewport_rect_);
|
||||
painter->drawPolygon(viewport_rect_);
|
||||
}
|
||||
|
||||
void NodeViewMiniMap::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
super::resizeEvent(event);
|
||||
super::resizeEvent(event);
|
||||
|
||||
emit Resized();
|
||||
emit Resized();
|
||||
|
||||
SceneChanged(sceneRect());
|
||||
SceneChanged(sceneRect());
|
||||
}
|
||||
|
||||
void NodeViewMiniMap::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
if (MouseInsideResizeTriangle(event)) {
|
||||
// Resizing!
|
||||
resizing_ = true;
|
||||
resize_anchor_ = QCursor::pos();
|
||||
} else {
|
||||
EmitMoveSignal(event);
|
||||
}
|
||||
}
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
if (MouseInsideResizeTriangle(event)) {
|
||||
// Resizing!
|
||||
resizing_ = true;
|
||||
resize_anchor_ = QCursor::pos();
|
||||
} else {
|
||||
EmitMoveSignal(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewMiniMap::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->buttons() & Qt::LeftButton) {
|
||||
if (resizing_) {
|
||||
QPointF movement = QCursor::pos() - resize_anchor_;
|
||||
resize(QSize(width() - movement.x(), height() - movement.y()));
|
||||
resize_anchor_ = QCursor::pos();
|
||||
} else {
|
||||
EmitMoveSignal(event);
|
||||
}
|
||||
} else {
|
||||
if (MouseInsideResizeTriangle(event)) {
|
||||
setCursor(Qt::SizeFDiagCursor);
|
||||
} else {
|
||||
unsetCursor();
|
||||
}
|
||||
}
|
||||
if (event->buttons() & Qt::LeftButton) {
|
||||
if (resizing_) {
|
||||
QPointF movement = QCursor::pos() - resize_anchor_;
|
||||
resize(QSize(width() - movement.x(), height() - movement.y()));
|
||||
resize_anchor_ = QCursor::pos();
|
||||
} else {
|
||||
EmitMoveSignal(event);
|
||||
}
|
||||
} else {
|
||||
if (MouseInsideResizeTriangle(event)) {
|
||||
setCursor(Qt::SizeFDiagCursor);
|
||||
} else {
|
||||
unsetCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewMiniMap::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
resizing_ = false;
|
||||
resizing_ = false;
|
||||
}
|
||||
|
||||
void NodeViewMiniMap::SceneChanged(const QRectF &bounding)
|
||||
{
|
||||
double x_scale = double(this->width()) / bounding.width();
|
||||
double y_scale = double(this->height()) / bounding.height();
|
||||
double x_scale = double(this->width()) / bounding.width();
|
||||
double y_scale = double(this->height()) / bounding.height();
|
||||
|
||||
double min_scale = qMin(x_scale, y_scale);
|
||||
double min_scale = qMin(x_scale, y_scale);
|
||||
|
||||
QTransform transform;
|
||||
transform.scale(min_scale, min_scale);
|
||||
QTransform transform;
|
||||
transform.scale(min_scale, min_scale);
|
||||
|
||||
setTransform(transform);
|
||||
setTransform(transform);
|
||||
}
|
||||
|
||||
void NodeViewMiniMap::SetDefaultSize()
|
||||
{
|
||||
if (parentWidget()) {
|
||||
resize(parentWidget()->width()/4, parentWidget()->height()/4);
|
||||
}
|
||||
if (parentWidget()) {
|
||||
resize(parentWidget()->width() / 4, parentWidget()->height() / 4);
|
||||
}
|
||||
}
|
||||
|
||||
bool NodeViewMiniMap::MouseInsideResizeTriangle(QMouseEvent *event)
|
||||
{
|
||||
return event->pos().x() <= resize_triangle_sz_ && event->pos().y() <= resize_triangle_sz_;
|
||||
return event->pos().x() <= resize_triangle_sz_ &&
|
||||
event->pos().y() <= resize_triangle_sz_;
|
||||
}
|
||||
|
||||
void NodeViewMiniMap::EmitMoveSignal(QMouseEvent *event)
|
||||
{
|
||||
emit MoveToScenePoint(mapToScene(event->pos()));
|
||||
emit MoveToScenePoint(mapToScene(event->pos()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,50 +25,51 @@
|
||||
|
||||
#include "nodeviewscene.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeViewMiniMap : public QGraphicsView
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeViewMiniMap : public QGraphicsView {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeViewMiniMap(NodeViewScene *scene, QWidget *parent = nullptr);
|
||||
NodeViewMiniMap(NodeViewScene *scene, QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void SetViewportRect(const QPolygonF &rect);
|
||||
void SetViewportRect(const QPolygonF &rect);
|
||||
|
||||
signals:
|
||||
void Resized();
|
||||
void Resized();
|
||||
|
||||
void MoveToScenePoint(const QPointF &pos);
|
||||
void MoveToScenePoint(const QPointF &pos);
|
||||
|
||||
protected:
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override{}
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override
|
||||
{
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const QRectF &bounding);
|
||||
void SceneChanged(const QRectF &bounding);
|
||||
|
||||
void SetDefaultSize();
|
||||
void SetDefaultSize();
|
||||
|
||||
private:
|
||||
bool MouseInsideResizeTriangle(QMouseEvent *event);
|
||||
bool MouseInsideResizeTriangle(QMouseEvent *event);
|
||||
|
||||
void EmitMoveSignal(QMouseEvent *event);
|
||||
void EmitMoveSignal(QMouseEvent *event);
|
||||
|
||||
int resize_triangle_sz_;
|
||||
int resize_triangle_sz_;
|
||||
|
||||
QPolygonF viewport_rect_;
|
||||
QPolygonF viewport_rect_;
|
||||
|
||||
bool resizing_;
|
||||
|
||||
QPoint resize_anchor_;
|
||||
bool resizing_;
|
||||
|
||||
QPoint resize_anchor_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,94 +25,95 @@
|
||||
#include "nodeviewedge.h"
|
||||
#include "nodeviewitem.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
NodeViewScene::NodeViewScene(QObject *parent) :
|
||||
QGraphicsScene(parent),
|
||||
direction_(NodeViewCommon::kLeftToRight),
|
||||
curved_edges_(true)
|
||||
NodeViewScene::NodeViewScene(QObject *parent)
|
||||
: QGraphicsScene(parent)
|
||||
, direction_(NodeViewCommon::kLeftToRight)
|
||||
, curved_edges_(true)
|
||||
{
|
||||
}
|
||||
|
||||
void NodeViewScene::SetFlowDirection(NodeViewCommon::FlowDirection direction)
|
||||
{
|
||||
direction_ = direction;
|
||||
direction_ = direction;
|
||||
|
||||
foreach (NodeViewContext *ctx, context_map_) {
|
||||
ctx->SetFlowDirection(direction_);
|
||||
}
|
||||
foreach (NodeViewContext *ctx, context_map_) {
|
||||
ctx->SetFlowDirection(direction_);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewScene::SelectAll()
|
||||
{
|
||||
foreach (QGraphicsItem* i, items()) {
|
||||
i->setSelected(true);
|
||||
}
|
||||
foreach (QGraphicsItem *i, items()) {
|
||||
i->setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewScene::DeselectAll()
|
||||
{
|
||||
foreach (QGraphicsItem* i, items()) {
|
||||
i->setSelected(false);
|
||||
}
|
||||
foreach (QGraphicsItem *i, items()) {
|
||||
i->setSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<NodeViewItem *> NodeViewScene::GetSelectedItems() const
|
||||
{
|
||||
QVector<NodeViewItem *> items;
|
||||
QVector<NodeViewItem *> items;
|
||||
|
||||
foreach (NodeViewContext *ctx, context_map_) {
|
||||
items.append(ctx->GetSelectedItems());
|
||||
}
|
||||
foreach (NodeViewContext *ctx, context_map_) {
|
||||
items.append(ctx->GetSelectedItems());
|
||||
}
|
||||
|
||||
return items;
|
||||
return items;
|
||||
}
|
||||
|
||||
NodeViewContext *NodeViewScene::AddContext(Node *node)
|
||||
{
|
||||
NodeViewContext *context_item = context_map_.value(node);
|
||||
NodeViewContext *context_item = context_map_.value(node);
|
||||
|
||||
if (!context_item) {
|
||||
context_item = new NodeViewContext(node);
|
||||
if (!context_item) {
|
||||
context_item = new NodeViewContext(node);
|
||||
|
||||
context_item->SetFlowDirection(GetFlowDirection());
|
||||
context_item->SetCurvedEdges(GetEdgesAreCurved());
|
||||
context_item->SetFlowDirection(GetFlowDirection());
|
||||
context_item->SetCurvedEdges(GetEdgesAreCurved());
|
||||
|
||||
QPointF pos(0, 0);
|
||||
QRectF item_rect = context_item->rect();
|
||||
while (!items(item_rect).isEmpty()) {
|
||||
pos.setY(pos.y() + item_rect.height());
|
||||
item_rect = context_item->rect().translated(pos);
|
||||
}
|
||||
context_item->setPos(pos);
|
||||
QPointF pos(0, 0);
|
||||
QRectF item_rect = context_item->rect();
|
||||
while (!items(item_rect).isEmpty()) {
|
||||
pos.setY(pos.y() + item_rect.height());
|
||||
item_rect = context_item->rect().translated(pos);
|
||||
}
|
||||
context_item->setPos(pos);
|
||||
|
||||
addItem(context_item);
|
||||
addItem(context_item);
|
||||
|
||||
context_map_.insert(node, context_item);
|
||||
}
|
||||
context_map_.insert(node, context_item);
|
||||
}
|
||||
|
||||
return context_item;
|
||||
return context_item;
|
||||
}
|
||||
|
||||
void NodeViewScene::RemoveContext(Node *node)
|
||||
{
|
||||
delete context_map_.take(node);
|
||||
delete context_map_.take(node);
|
||||
}
|
||||
|
||||
Qt::Orientation NodeViewScene::GetFlowOrientation() const
|
||||
{
|
||||
return NodeViewCommon::GetFlowOrientation(direction_);
|
||||
return NodeViewCommon::GetFlowOrientation(direction_);
|
||||
}
|
||||
|
||||
void NodeViewScene::SetEdgesAreCurved(bool curved)
|
||||
{
|
||||
if (curved_edges_ != curved) {
|
||||
curved_edges_ = curved;
|
||||
if (curved_edges_ != curved) {
|
||||
curved_edges_ = curved;
|
||||
|
||||
foreach (NodeViewContext *ctx, context_map_) {
|
||||
ctx->SetCurvedEdges(curved_edges_);
|
||||
}
|
||||
}
|
||||
foreach (NodeViewContext *ctx, context_map_) {
|
||||
ctx->SetCurvedEdges(curved_edges_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,56 +30,55 @@
|
||||
#include "nodeviewitem.h"
|
||||
#include "undo/undostack.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeViewScene : public QGraphicsScene
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeViewScene : public QGraphicsScene {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeViewScene(QObject *parent = nullptr);
|
||||
NodeViewScene(QObject *parent = nullptr);
|
||||
|
||||
void SelectAll();
|
||||
void DeselectAll();
|
||||
void SelectAll();
|
||||
void DeselectAll();
|
||||
|
||||
QVector<NodeViewItem*> GetSelectedItems() const;
|
||||
QVector<NodeViewItem *> GetSelectedItems() const;
|
||||
|
||||
const QHash<Node*, NodeViewContext*> &context_map() const
|
||||
{
|
||||
return context_map_;
|
||||
}
|
||||
const QHash<Node *, NodeViewContext *> &context_map() const
|
||||
{
|
||||
return context_map_;
|
||||
}
|
||||
|
||||
Qt::Orientation GetFlowOrientation() const;
|
||||
Qt::Orientation GetFlowOrientation() const;
|
||||
|
||||
NodeViewCommon::FlowDirection GetFlowDirection() const
|
||||
{
|
||||
return direction_;
|
||||
}
|
||||
NodeViewCommon::FlowDirection GetFlowDirection() const
|
||||
{
|
||||
return direction_;
|
||||
}
|
||||
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection direction);
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection direction);
|
||||
|
||||
bool GetEdgesAreCurved() const
|
||||
{
|
||||
return curved_edges_;
|
||||
}
|
||||
bool GetEdgesAreCurved() const
|
||||
{
|
||||
return curved_edges_;
|
||||
}
|
||||
|
||||
public slots:
|
||||
NodeViewContext *AddContext(Node *node);
|
||||
void RemoveContext(Node *node);
|
||||
NodeViewContext *AddContext(Node *node);
|
||||
void RemoveContext(Node *node);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set whether edges in this scene should be curved or not
|
||||
*/
|
||||
void SetEdgesAreCurved(bool curved);
|
||||
void SetEdgesAreCurved(bool curved);
|
||||
|
||||
private:
|
||||
QHash<Node*, NodeViewContext*> context_map_;
|
||||
QHash<Node *, NodeViewContext *> context_map_;
|
||||
|
||||
Project* graph_;
|
||||
Project *graph_;
|
||||
|
||||
NodeViewCommon::FlowDirection direction_;
|
||||
|
||||
bool curved_edges_;
|
||||
NodeViewCommon::FlowDirection direction_;
|
||||
|
||||
bool curved_edges_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -5,51 +5,54 @@
|
||||
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super QWidget
|
||||
|
||||
NodeViewToolBar::NodeViewToolBar(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
NodeViewToolBar::NodeViewToolBar(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
add_node_btn_ = new QPushButton();
|
||||
connect(add_node_btn_, &QPushButton::clicked, this, &NodeViewToolBar::AddNodeClicked);
|
||||
layout->addWidget(add_node_btn_);
|
||||
add_node_btn_ = new QPushButton();
|
||||
connect(add_node_btn_, &QPushButton::clicked, this,
|
||||
&NodeViewToolBar::AddNodeClicked);
|
||||
layout->addWidget(add_node_btn_);
|
||||
|
||||
minimap_btn_ = new QPushButton();
|
||||
minimap_btn_->setCheckable(true);
|
||||
connect(minimap_btn_, &QPushButton::clicked, this, &NodeViewToolBar::MiniMapEnabledToggled);
|
||||
layout->addWidget(minimap_btn_);
|
||||
minimap_btn_ = new QPushButton();
|
||||
minimap_btn_->setCheckable(true);
|
||||
connect(minimap_btn_, &QPushButton::clicked, this,
|
||||
&NodeViewToolBar::MiniMapEnabledToggled);
|
||||
layout->addWidget(minimap_btn_);
|
||||
|
||||
layout->addStretch();
|
||||
layout->addStretch();
|
||||
|
||||
Retranslate();
|
||||
UpdateIcons();
|
||||
Retranslate();
|
||||
UpdateIcons();
|
||||
}
|
||||
|
||||
void NodeViewToolBar::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
} else if (e->type() == QEvent::StyleChange) {
|
||||
UpdateIcons();
|
||||
}
|
||||
super::changeEvent(e);
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
} else if (e->type() == QEvent::StyleChange) {
|
||||
UpdateIcons();
|
||||
}
|
||||
super::changeEvent(e);
|
||||
}
|
||||
|
||||
void NodeViewToolBar::Retranslate()
|
||||
{
|
||||
add_node_btn_->setToolTip(tr("Add Node"));
|
||||
minimap_btn_->setToolTip(tr("Toggle Mini-Map"));
|
||||
add_node_btn_->setToolTip(tr("Add Node"));
|
||||
minimap_btn_->setToolTip(tr("Toggle Mini-Map"));
|
||||
}
|
||||
|
||||
void NodeViewToolBar::UpdateIcons()
|
||||
{
|
||||
add_node_btn_->setIcon(icon::Add);
|
||||
minimap_btn_->setIcon(icon::MiniMap);
|
||||
add_node_btn_->setIcon(icon::Add);
|
||||
minimap_btn_->setIcon(icon::MiniMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,37 +4,36 @@
|
||||
#include <QPushButton>
|
||||
#include <QWidget>
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeViewToolBar : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeViewToolBar : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeViewToolBar(QWidget *parent = nullptr);
|
||||
NodeViewToolBar(QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void SetMiniMapEnabled(bool e)
|
||||
{
|
||||
minimap_btn_->setChecked(e);
|
||||
}
|
||||
void SetMiniMapEnabled(bool e)
|
||||
{
|
||||
minimap_btn_->setChecked(e);
|
||||
}
|
||||
|
||||
signals:
|
||||
void AddNodeClicked();
|
||||
void AddNodeClicked();
|
||||
|
||||
void MiniMapEnabledToggled(bool e);
|
||||
void MiniMapEnabledToggled(bool e);
|
||||
|
||||
protected:
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
|
||||
private:
|
||||
void Retranslate();
|
||||
void Retranslate();
|
||||
|
||||
void UpdateIcons();
|
||||
void UpdateIcons();
|
||||
|
||||
QPushButton *add_node_btn_;
|
||||
|
||||
QPushButton *minimap_btn_;
|
||||
QPushButton *add_node_btn_;
|
||||
|
||||
QPushButton *minimap_btn_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,30 +22,33 @@
|
||||
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeWidget::NodeWidget(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
namespace olive
|
||||
{
|
||||
QVBoxLayout *outer_layout = new QVBoxLayout(this);
|
||||
outer_layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
toolbar_ = new NodeViewToolBar();
|
||||
outer_layout->addWidget(toolbar_);
|
||||
NodeWidget::NodeWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QVBoxLayout *outer_layout = new QVBoxLayout(this);
|
||||
outer_layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
// Create NodeView widget
|
||||
node_view_ = new NodeView(this);
|
||||
outer_layout->addWidget(node_view_);
|
||||
toolbar_ = new NodeViewToolBar();
|
||||
outer_layout->addWidget(toolbar_);
|
||||
|
||||
// Connect toolbar to NodeView
|
||||
connect(toolbar_, &NodeViewToolBar::MiniMapEnabledToggled, node_view_, &NodeView::SetMiniMapEnabled);
|
||||
connect(toolbar_, &NodeViewToolBar::AddNodeClicked, node_view_, &NodeView::ShowAddMenu);
|
||||
// Create NodeView widget
|
||||
node_view_ = new NodeView(this);
|
||||
outer_layout->addWidget(node_view_);
|
||||
|
||||
// Set defaults
|
||||
toolbar_->SetMiniMapEnabled(true);
|
||||
node_view_->SetMiniMapEnabled(true);
|
||||
// Connect toolbar to NodeView
|
||||
connect(toolbar_, &NodeViewToolBar::MiniMapEnabledToggled, node_view_,
|
||||
&NodeView::SetMiniMapEnabled);
|
||||
connect(toolbar_, &NodeViewToolBar::AddNodeClicked, node_view_,
|
||||
&NodeView::ShowAddMenu);
|
||||
|
||||
setSizePolicy(node_view_->sizePolicy());
|
||||
// Set defaults
|
||||
toolbar_->SetMiniMapEnabled(true);
|
||||
node_view_->SetMiniMapEnabled(true);
|
||||
|
||||
setSizePolicy(node_view_->sizePolicy());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,30 +26,29 @@
|
||||
#include "nodeview.h"
|
||||
#include "nodeviewtoolbar.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeWidget : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeWidget(QWidget *parent = nullptr);
|
||||
NodeWidget(QWidget *parent = nullptr);
|
||||
|
||||
NodeView *view() const
|
||||
{
|
||||
return node_view_;
|
||||
}
|
||||
NodeView *view() const
|
||||
{
|
||||
return node_view_;
|
||||
}
|
||||
|
||||
void SetContexts(const QVector<Node*> &nodes)
|
||||
{
|
||||
node_view_->SetContexts(nodes);
|
||||
toolbar_->setEnabled(!nodes.isEmpty());
|
||||
}
|
||||
void SetContexts(const QVector<Node *> &nodes)
|
||||
{
|
||||
node_view_->SetContexts(nodes);
|
||||
toolbar_->setEnabled(!nodes.isEmpty());
|
||||
}
|
||||
|
||||
private:
|
||||
NodeView *node_view_;
|
||||
|
||||
NodeViewToolBar *toolbar_;
|
||||
NodeView *node_view_;
|
||||
|
||||
NodeViewToolBar *toolbar_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user