implement context item in node view
This commit is contained in:
@@ -34,6 +34,8 @@ set(OLIVE_SOURCES
|
||||
node/globals.h
|
||||
node/graph.cpp
|
||||
node/graph.h
|
||||
node/group.cpp
|
||||
node/group.h
|
||||
node/hashtraverser.cpp
|
||||
node/hashtraverser.h
|
||||
node/inputdragger.cpp
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "group.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeGroup::NodeGroup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef NODEGROUP_H
|
||||
#define NODEGROUP_H
|
||||
|
||||
#include "node.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeGroup : public Node
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeGroup();
|
||||
|
||||
void SetNodes(Node *nodes);
|
||||
|
||||
private:
|
||||
QVector<Node*> nodes_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // NODEGROUP_H
|
||||
@@ -168,17 +168,46 @@ public:
|
||||
|
||||
QString ToString() const
|
||||
{
|
||||
QString type_string;
|
||||
|
||||
if (type_ == Track::kVideo) {
|
||||
type_string = QStringLiteral("v");
|
||||
} else if (type_ == Track::kAudio) {
|
||||
type_string = QStringLiteral("a");
|
||||
} else {
|
||||
QString type_string = TypeToString(type_);
|
||||
if (type_string.isEmpty()) {
|
||||
return QString();
|
||||
} else {
|
||||
return QStringLiteral("%1:%2").arg(type_string, QString::number(index_));
|
||||
}
|
||||
}
|
||||
|
||||
/// For IDs that shouldn't change between localizations
|
||||
static QString TypeToString(Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case kVideo:
|
||||
return QStringLiteral("v");
|
||||
case kAudio:
|
||||
return QStringLiteral("a");
|
||||
case kSubtitle:
|
||||
return QStringLiteral("s");
|
||||
case kCount:
|
||||
break;
|
||||
}
|
||||
|
||||
return QStringLiteral("%1:%2").arg(type_string, QString::number(index_));
|
||||
return QString();
|
||||
}
|
||||
|
||||
/// For human-facing strings
|
||||
static QString TypeToTranslatedString(Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case kVideo:
|
||||
return tr("V");
|
||||
case kAudio:
|
||||
return tr("A");
|
||||
case kSubtitle:
|
||||
return tr("S");
|
||||
case kCount:
|
||||
break;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
static Type TypeFromString(const QString& s)
|
||||
|
||||
@@ -19,6 +19,8 @@ set(OLIVE_SOURCES
|
||||
widget/nodeview/nodeview.cpp
|
||||
widget/nodeview/nodeview.h
|
||||
widget/nodeview/nodeviewcommon.h
|
||||
widget/nodeview/nodeviewcontext.cpp
|
||||
widget/nodeview/nodeviewcontext.h
|
||||
widget/nodeview/nodeviewedge.cpp
|
||||
widget/nodeview/nodeviewedge.h
|
||||
widget/nodeview/nodeviewitem.cpp
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "node/audio/volume/volume.h"
|
||||
#include "node/distort/transform/transformdistortnode.h"
|
||||
#include "node/factory.h"
|
||||
#include "node/group.h"
|
||||
#include "node/traverser.h"
|
||||
#include "widget/menu/menushared.h"
|
||||
#include "widget/timebased/timebasedview.h"
|
||||
@@ -62,7 +63,7 @@ NodeView::NodeView(QWidget *parent) :
|
||||
|
||||
ConnectSelectionChangedSignal();
|
||||
|
||||
SetFlowDirection(NodeViewCommon::kTopToBottom);
|
||||
SetFlowDirection(NodeViewCommon::kLeftToRight);
|
||||
|
||||
UpdateSceneBoundingRect();
|
||||
connect(&scene_, &QGraphicsScene::changed, this, &NodeView::UpdateSceneBoundingRect);
|
||||
@@ -85,7 +86,23 @@ NodeView::~NodeView()
|
||||
|
||||
void NodeView::SetGraph(NodeGraph *graph, const QVector<Node*> &nodes)
|
||||
{
|
||||
bool graph_changed = graph_ != graph;
|
||||
// Remove contexts that are no longer in the list
|
||||
foreach (Node *n, filter_nodes_) {
|
||||
if (!nodes.contains(n)) {
|
||||
scene_.RemoveContext(n);
|
||||
}
|
||||
}
|
||||
|
||||
// Add contexts that are now in the list
|
||||
foreach (Node *n, nodes) {
|
||||
if (!filter_nodes_.contains(n)) {
|
||||
scene_.AddContext(n);
|
||||
}
|
||||
}
|
||||
|
||||
filter_nodes_ = nodes;
|
||||
|
||||
/*bool graph_changed = graph_ != graph;
|
||||
bool context_changed = last_set_filter_nodes_ != nodes;
|
||||
|
||||
if (graph_changed || context_changed) {
|
||||
@@ -144,7 +161,7 @@ void NodeView::SetGraph(NodeGraph *graph, const QVector<Node*> &nodes)
|
||||
// Center on something
|
||||
QMetaObject::invokeMethod(this, &NodeView::CenterOnItemsBoundingRect, Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void NodeView::ClearGraph()
|
||||
@@ -850,6 +867,15 @@ void NodeView::ShowContextMenu(const QPoint &pos)
|
||||
Core::instance()->LabelNodes(scene_.GetSelectedNodes());
|
||||
});
|
||||
|
||||
// Grouping
|
||||
if (selected.size() == 1 && dynamic_cast<NodeGroup*>(selected.first()->GetNode())) {
|
||||
QAction *ungroup_action = m.addAction(tr("Ungroup"));
|
||||
connect(ungroup_action, &QAction::triggered, this, &NodeView::UngroupNodes);
|
||||
} else {
|
||||
QAction *group_action = m.addAction(tr("Group"));
|
||||
connect(group_action, &QAction::triggered, this, &NodeView::GroupNodes);
|
||||
}
|
||||
|
||||
// Color menu
|
||||
MenuShared::instance()->AddColorCodingMenu(&m);
|
||||
|
||||
@@ -1603,6 +1629,17 @@ void NodeView::RepositionContexts()
|
||||
}
|
||||
}
|
||||
|
||||
void NodeView::GroupNodes()
|
||||
{
|
||||
/*NodeGroup *group = new NodeGroup();
|
||||
selected_nodes_*/
|
||||
}
|
||||
|
||||
void NodeView::UngroupNodes()
|
||||
{
|
||||
static_cast<NodeGroup*>(selected_nodes_.first());
|
||||
}
|
||||
|
||||
NodeViewItem *NodeView::UpdateNodeItem(Node *node, bool ignore_own_context)
|
||||
{
|
||||
// Get UI item or create if it doesn't exist
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "node/graph.h"
|
||||
#include "node/nodecopypaste.h"
|
||||
#include "nodeviewedge.h"
|
||||
#include "nodeviewcontext.h"
|
||||
#include "nodeviewminimap.h"
|
||||
#include "nodeviewscene.h"
|
||||
#include "widget/handmovableview/handmovableview.h"
|
||||
@@ -303,6 +304,10 @@ private slots:
|
||||
|
||||
void RepositionContexts();
|
||||
|
||||
void GroupNodes();
|
||||
|
||||
void UngroupNodes();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
#include "nodeviewcontext.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QCoreApplication>
|
||||
#include <QGraphicsScene>
|
||||
#include <QPen>
|
||||
#include <QStyleOptionGraphicsItem>
|
||||
|
||||
#include "node/block/block.h"
|
||||
#include "node/output/track/track.h"
|
||||
#include "nodeviewitem.h"
|
||||
#include "ui/colorcoding.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
#define super QGraphicsRectItem
|
||||
|
||||
NodeViewContext::NodeViewContext(QGraphicsItem *item) :
|
||||
super(item)
|
||||
{
|
||||
setFlag(ItemIsMovable);
|
||||
setFlag(ItemIsSelectable);
|
||||
|
||||
// Set default label text
|
||||
SetContext(nullptr);
|
||||
}
|
||||
|
||||
void NodeViewContext::SetContext(Node *node)
|
||||
{
|
||||
context_ = node;
|
||||
|
||||
if (context_) {
|
||||
if (Block *block = dynamic_cast<Block*>(node)) {
|
||||
lbl_ = QCoreApplication::translate("NodeViewContext",
|
||||
"%1 [%2] :: %3 - %4").arg(block->GetLabelAndName(),
|
||||
Track::Reference::TypeToTranslatedString(block->track()->type()),
|
||||
block->in().toString(),
|
||||
block->out().toString());
|
||||
} else {
|
||||
lbl_ = node->GetLabelAndName();
|
||||
}
|
||||
|
||||
Color c = node->color();
|
||||
setPen(QPen(c.toQColor(), 2));
|
||||
|
||||
c.set_alpha(0.5f);
|
||||
setBrush(c.toQColor());
|
||||
} else {
|
||||
lbl_ = QCoreApplication::translate("NodeViewContext", "(None)");
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewContext::AddChild(Node *node)
|
||||
{
|
||||
NodeViewItem *item = new NodeViewItem(this);
|
||||
item->SetNode(node);
|
||||
}
|
||||
|
||||
qreal GetTextOffset(const QFontMetricsF &fm)
|
||||
{
|
||||
return fm.height()/2;
|
||||
}
|
||||
|
||||
void NodeViewContext::UpdateRect()
|
||||
{
|
||||
QFont f;
|
||||
QFontMetricsF fm(f);
|
||||
qreal lbl_offset = GetTextOffset(fm);
|
||||
|
||||
QRectF rect = childrenBoundingRect();
|
||||
int pad = NodeViewItem::DefaultItemHeight();
|
||||
rect.adjust(-pad, - lbl_offset*2 - fm.height() - pad, pad, pad);
|
||||
setRect(rect);
|
||||
}
|
||||
|
||||
void NodeViewContext::SetFlowDirection(NodeViewCommon::FlowDirection dir)
|
||||
{
|
||||
auto children = childItems();
|
||||
foreach (auto child, children) {
|
||||
if (NodeViewItem *item = dynamic_cast<NodeViewItem*>(child)) {
|
||||
item->SetFlowDirection(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewContext::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
QPen p = pen();
|
||||
|
||||
if (option->state & QStyle::State_Selected) {
|
||||
p.setStyle(Qt::DotLine);
|
||||
}
|
||||
|
||||
painter->setPen(p);
|
||||
painter->setBrush(brush());
|
||||
|
||||
int rounded = painter->fontMetrics().height();
|
||||
painter->drawRoundedRect(rect(), rounded, rounded);
|
||||
|
||||
painter->setPen(context_ ? ColorCoding::GetUISelectorColor(context_->color()) : Qt::white);
|
||||
|
||||
int offset = GetTextOffset(painter->fontMetrics());
|
||||
|
||||
QRectF text_rect = rect();
|
||||
text_rect.adjust(offset, offset, -offset, -offset);
|
||||
painter->drawText(text_rect, lbl_);
|
||||
}
|
||||
|
||||
QVariant NodeViewContext::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
{
|
||||
return super::itemChange(change, value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef NODEVIEWCONTEXT_H
|
||||
#define NODEVIEWCONTEXT_H
|
||||
|
||||
#include <QGraphicsRectItem>
|
||||
#include <QGraphicsTextItem>
|
||||
|
||||
#include "node/node.h"
|
||||
#include "nodeviewcommon.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeViewContext : public QGraphicsRectItem
|
||||
{
|
||||
public:
|
||||
NodeViewContext(QGraphicsItem *item = nullptr);
|
||||
|
||||
void SetContext(Node *node);
|
||||
|
||||
void AddChild(Node *node);
|
||||
|
||||
void UpdateRect();
|
||||
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
|
||||
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
|
||||
|
||||
protected:
|
||||
virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
|
||||
|
||||
private:
|
||||
Node *context_;
|
||||
|
||||
QString lbl_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // NODEVIEWCONTEXT_H
|
||||
@@ -406,6 +406,10 @@ QVariant NodeViewItem::itemChange(QGraphicsItem::GraphicsItemChange change, cons
|
||||
{
|
||||
if (change == ItemPositionHasChanged && node_) {
|
||||
ReadjustAllEdges();
|
||||
|
||||
if (NodeViewContext *ctx = dynamic_cast<NodeViewContext*>(parentItem())) {
|
||||
ctx->UpdateRect();
|
||||
}
|
||||
}
|
||||
|
||||
return QGraphicsItem::itemChange(change, value);
|
||||
|
||||
@@ -194,6 +194,31 @@ void NodeViewScene::RemoveEdge(Node *output, const NodeInput &input)
|
||||
}
|
||||
}
|
||||
|
||||
NodeViewContext *NodeViewScene::AddContext(Node *node)
|
||||
{
|
||||
NodeViewContext *context_item = context_map_.value(node);
|
||||
|
||||
if (!context_item) {
|
||||
context_item = new NodeViewContext();
|
||||
context_item->SetContext(node);
|
||||
context_item->setPos(0, 0);
|
||||
addItem(context_item);
|
||||
|
||||
const NodeGraph::PositionMap &map = node->parent()->GetNodesForContext(node);
|
||||
for (auto it=map.cbegin(); it!=map.cend(); it++) {
|
||||
context_item->AddChild(it.key());
|
||||
}
|
||||
context_item->UpdateRect();
|
||||
}
|
||||
|
||||
return context_item;
|
||||
}
|
||||
|
||||
void NodeViewScene::RemoveContext(Node *node)
|
||||
{
|
||||
delete context_map_.take(node);
|
||||
}
|
||||
|
||||
int NodeViewScene::DetermineWeight(Node *n)
|
||||
{
|
||||
QVector<Node*> inputs = n->GetImmediateDependencies();
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <QTimer>
|
||||
|
||||
#include "node/graph.h"
|
||||
#include "nodeviewcontext.h"
|
||||
#include "nodeviewedge.h"
|
||||
#include "nodeviewitem.h"
|
||||
|
||||
@@ -99,6 +100,9 @@ public slots:
|
||||
NodeViewEdge *AddEdge(Node *output, const NodeInput& input);
|
||||
void RemoveEdge(Node *output, const NodeInput& input);
|
||||
|
||||
NodeViewContext *AddContext(Node *node);
|
||||
void RemoveContext(Node *node);
|
||||
|
||||
/**
|
||||
* @brief Set whether edges in this scene should be curved or not
|
||||
*/
|
||||
@@ -113,6 +117,8 @@ private:
|
||||
|
||||
void DisconnectNode(Node *n);
|
||||
|
||||
QHash<Node*, NodeViewContext*> context_map_;
|
||||
|
||||
QHash<Node*, NodeViewItem*> item_map_;
|
||||
|
||||
QVector<NodeViewEdge*> edges_;
|
||||
|
||||
Reference in New Issue
Block a user