work towards timeline/nodeview interactivity

This commit is contained in:
itsmattkc
2021-05-17 11:14:56 +10:00
parent 8e9859b2b3
commit f2d64728f9
15 changed files with 204 additions and 132 deletions
+4 -10
View File
@@ -28,8 +28,7 @@ PanelManager* PanelManager::instance_ = nullptr;
PanelManager::PanelManager(QObject *parent) :
QObject(parent),
locked_(false),
last_focused_panel_(nullptr)
locked_(false)
{
}
@@ -46,11 +45,11 @@ const QList<PanelWidget *> &PanelManager::panels()
return focus_history_;
}
PanelWidget *PanelManager::CurrentlyFocused() const
PanelWidget *PanelManager::CurrentlyFocused(bool enable_hover) const
{
// If hover focus is enabled, find the currently hovered panel and return it (if no panel is hovered, resort to
// default behavior)
if (Config::Current()["HoverFocus"].toBool()) {
if (enable_hover && Config::Current()[QStringLiteral("HoverFocus")].toBool()) {
PanelWidget* hovered = CurrentlyHovered();
if (hovered != nullptr) {
@@ -111,7 +110,7 @@ void PanelManager::FocusChanged(QWidget *old, QWidget *now)
if (panel_cast_test) {
if (last_focused_panel_ != panel_cast_test) {
if (focus_history_.first() != panel_cast_test) {
// If so, bump this to the top of the focus history
int panel_index = focus_history_.indexOf(panel_cast_test);
@@ -130,7 +129,6 @@ void PanelManager::FocusChanged(QWidget *old, QWidget *now)
focus_history_.move(panel_index, 0);
}
last_focused_panel_ = panel_cast_test;
emit FocusedPanelChanged(panel_cast_test);
}
@@ -158,10 +156,6 @@ void PanelManager::PanelDestroyed()
PanelWidget* panel = static_cast<PanelWidget*>(sender());
focus_history_.removeOne(panel);
if (last_focused_panel_ == panel) {
last_focused_panel_ = focus_history_.isEmpty() ? nullptr : focus_history_.first();
}
}
}
+8 -11
View File
@@ -65,14 +65,12 @@ public:
/**
* @brief Return the currently focused widget, or nullptr if nothing is focused
*
* This result == CurrentlyFocused() if HoverFocus is true
* This result == CurrentlyFocused() if HoverFocus is true and panel is hovered
*/
PanelWidget* CurrentlyFocused() const;
PanelWidget* CurrentlyFocused(bool enable_hover = true) const;
/**
* @brief Return the widget that the mouse is currently hovering over, or nullptr if nothing is hovered over
*
* This result == CurrentlyFocused() if HoverFocus is true
*/
PanelWidget* CurrentlyHovered() const;
@@ -155,13 +153,6 @@ private:
*/
static PanelManager* instance_;
/**
* @brief The last panel that was focused
*
* Stored to prevent emitting FocusedPanelChanged() multiple times for the same panel
*/
PanelWidget* last_focused_panel_;
private slots:
/**
* @brief Processing if a panel gets deleted
@@ -195,6 +186,12 @@ T *PanelManager::CreatePanel(QWidget *parent)
// Connect destroy signal so we can remove it from focus history
connect(panel, &PanelWidget::destroyed, this, &PanelManager::PanelDestroyed, Qt::DirectConnection);
if (focus_history_.size() == 1) {
// This is the first panel, focus it
panel->SetBorderVisible(true);
emit FocusedPanelChanged(panel);
}
return panel;
}
+1 -7
View File
@@ -33,13 +33,7 @@ TimelinePanel::TimelinePanel(QWidget *parent) :
Retranslate();
connect(tw, &TimelineWidget::BlocksSelected, this, &TimelinePanel::BlocksSelected);
connect(tw, &TimelineWidget::BlocksDeselected, this, &TimelinePanel::BlocksDeselected);
}
void TimelinePanel::Clear()
{
static_cast<TimelineWidget*>(GetTimeBasedWidget())->Clear();
connect(tw, &TimelineWidget::BlockSelectionChanged, this, &TimelinePanel::BlockSelectionChanged);
}
void TimelinePanel::SplitAtPlayhead()
+1 -5
View File
@@ -35,8 +35,6 @@ class TimelinePanel : public TimeBasedPanel
public:
TimelinePanel(QWidget* parent);
void Clear();
void SplitAtPlayhead();
QByteArray SaveSplitterState() const;
@@ -98,9 +96,7 @@ protected:
virtual void Retranslate() override;
signals:
void BlocksSelected(const QVector<Block*>& selected_blocks);
void BlocksDeselected(const QVector<Block*>& deselected_blocks);
void BlockSelectionChanged(const QVector<Block*>& selected_blocks);
};
+30 -6
View File
@@ -126,6 +126,17 @@ void NodeView::SetGraph(NodeGraph *graph, const QVector<void*> &nodes)
item->SetNodePosition(it.value());
}
}
for (auto it=scene_.item_map().cbegin(); it!=scene_.item_map().cend(); it++) {
Node *node = it.key();
for (auto jt=node->input_connections().cbegin(); jt!=node->input_connections().cend(); jt++) {
const NodeOutput &output = jt->second;
if (scene_.item_map().contains(output.node())) {
// Create edge since both input and output exist
scene_.AddEdge(output, jt->first);
}
}
}
}
}
@@ -913,23 +924,26 @@ void NodeView::AddNode(Node *node)
void NodeView::RemoveNode(Node *node)
{
if (filter_mode_ == kFilterShowAll) {
scene_.RemoveNode(node);
}
scene_.RemoveNode(node);
}
void NodeView::AddEdge(const NodeOutput &output, const NodeInput &input)
{
if (filter_mode_ == kFilterShowAll) {
scene_.AddEdge(output, input);
} else if (filter_mode_ == kFilterShowSelective) {
Node *output_node = output.node();
Node *input_node = input.node();
if (scene_.item_map().contains(output_node) && scene_.item_map().contains(input_node)) {
scene_.AddEdge(output, input);
}
}
}
void NodeView::RemoveEdge(const NodeOutput &output, const NodeInput &input)
{
if (filter_mode_ == kFilterShowAll) {
scene_.RemoveEdge(output, input);
}
scene_.RemoveEdge(output, input);
}
void NodeView::AddNodePosition(Node *node, void *relative, const QPointF &pos)
@@ -940,6 +954,16 @@ void NodeView::AddNodePosition(Node *node, void *relative, const QPointF &pos)
if (!item) {
item = scene_.AddNode(node);
// Add input edges
for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) {
AddEdge(it->second, it->first);
}
// Add output edges
for (auto it=node->output_connections().cbegin(); it!=node->output_connections().cend(); it++) {
AddEdge(it->first, it->second);
}
}
item->SetNodePosition(pos);
+76 -63
View File
@@ -80,6 +80,82 @@ void NodeViewEdge::SetHighlighted(bool e)
void NodeViewEdge::SetPoints(const QPointF &start, const QPointF &end, bool input_is_expanded)
{
cached_start_ = start;
cached_end_ = end;
cached_input_is_expanded_ = input_is_expanded;
UpdateCurve();
}
void NodeViewEdge::SetFlowDirection(NodeViewCommon::FlowDirection dir)
{
flow_dir_ = dir;
if (from_item_ && to_item_) {
Adjust();
}
}
void NodeViewEdge::SetCurved(bool e)
{
curved_ = e;
UpdateCurve();
}
void NodeViewEdge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
QPalette::ColorGroup group;
QPalette::ColorRole role;
if (connected_) {
group = QPalette::Active;
} else {
group = QPalette::Disabled;
}
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);
painter->setPen(QPen(edge_color, edge_width_));
painter->setBrush(Qt::NoBrush);
painter->drawPath(path());
// Draw arrow
painter->setPen(Qt::NoPen);
painter->setBrush(edge_color);
painter->drawPolygon(arrow_);
}
void NodeViewEdge::Init()
{
connected_ = false;
highlighted_ = false;
flow_dir_ = NodeViewCommon::kLeftToRight;
curved_ = true;
setFlag(QGraphicsItem::ItemIsSelectable);
// 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;
arrow_size_ = QFontMetrics(QFont()).height() / 2;
}
void NodeViewEdge::UpdateCurve()
{
const QPointF &start = cached_start_;
const QPointF &end = cached_end_;
const bool input_is_expanded = cached_input_is_expanded_;
QPainterPath path;
path.moveTo(start);
@@ -156,67 +232,4 @@ void NodeViewEdge::SetPoints(const QPointF &start, const QPointF &end, bool inpu
arrow_bounding_rect_.adjust(-arrow_size_, -arrow_size_, arrow_size_, arrow_size_);
}
void NodeViewEdge::SetFlowDirection(NodeViewCommon::FlowDirection dir)
{
flow_dir_ = dir;
if (from_item_ && to_item_) {
Adjust();
}
}
void NodeViewEdge::SetCurved(bool e)
{
curved_ = e;
update();
}
void NodeViewEdge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
QPalette::ColorGroup group;
QPalette::ColorRole role;
if (connected_) {
group = QPalette::Active;
} else {
group = QPalette::Disabled;
}
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);
painter->setPen(QPen(edge_color, edge_width_));
painter->setBrush(Qt::NoBrush);
painter->drawPath(path());
// Draw arrow
painter->setPen(Qt::NoPen);
painter->setBrush(edge_color);
painter->drawPolygon(arrow_);
}
void NodeViewEdge::Init()
{
connected_ = false;
highlighted_ = false;
flow_dir_ = NodeViewCommon::kLeftToRight;
curved_ = true;
setFlag(QGraphicsItem::ItemIsSelectable);
// 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;
arrow_size_ = QFontMetrics(QFont()).height() / 2;
}
}
+6
View File
@@ -122,6 +122,8 @@ protected:
private:
void Init();
void UpdateCurve();
NodeOutput output_;
NodeInput input_;
@@ -148,6 +150,10 @@ private:
QRectF arrow_bounding_rect_;
QPointF cached_start_;
QPointF cached_end_;
bool cached_input_is_expanded_;
};
}
+29 -18
View File
@@ -97,24 +97,9 @@ QPointF NodeViewItem::GetNodePosition() const
void NodeViewItem::SetNodePosition(const QPointF &pos)
{
switch (flow_dir_) {
case NodeViewCommon::kLeftToRight:
setPos(pos.x() * DefaultItemHorizontalPadding(),
pos.y() * DefaultItemVerticalPadding());
break;
case NodeViewCommon::kRightToLeft:
setPos(-pos.x() * DefaultItemHorizontalPadding(),
pos.y() * DefaultItemVerticalPadding());
break;
case NodeViewCommon::kTopToBottom:
setPos(pos.y() * DefaultItemHorizontalPadding(),
pos.x() * DefaultItemVerticalPadding());
break;
case NodeViewCommon::kBottomToTop:
setPos(pos.y() * DefaultItemHorizontalPadding(),
-pos.x() * DefaultItemVerticalPadding());
break;
}
cached_node_pos_ = pos;
UpdateNodePosition();
}
int NodeViewItem::DefaultTextPadding()
@@ -466,6 +451,8 @@ QPointF NodeViewItem::GetOutputPoint(const QString& output) const
void NodeViewItem::SetFlowDirection(NodeViewCommon::FlowDirection dir)
{
flow_dir_ = dir;
UpdateNodePosition();
}
QPointF NodeViewItem::GetInputPointInternal(int index, const QPointF& source_pos) const
@@ -490,4 +477,28 @@ QPointF NodeViewItem::GetInputPointInternal(int index, const QPointF& source_pos
}
}
void NodeViewItem::UpdateNodePosition()
{
const QPointF &pos = cached_node_pos_;
switch (flow_dir_) {
case NodeViewCommon::kLeftToRight:
setPos(pos.x() * DefaultItemHorizontalPadding(),
pos.y() * DefaultItemVerticalPadding());
break;
case NodeViewCommon::kRightToLeft:
setPos(-pos.x() * DefaultItemHorizontalPadding(),
pos.y() * DefaultItemVerticalPadding());
break;
case NodeViewCommon::kTopToBottom:
setPos(pos.y() * DefaultItemHorizontalPadding(),
pos.x() * DefaultItemVerticalPadding());
break;
case NodeViewCommon::kBottomToTop:
setPos(pos.y() * DefaultItemHorizontalPadding(),
-pos.x() * DefaultItemVerticalPadding());
break;
}
}
}
+7
View File
@@ -136,6 +136,11 @@ private:
*/
QPointF GetInputPointInternal(int index, const QPointF &source_pos) const;
/**
* @brief Internal update function when logical position changes
*/
void UpdateNodePosition();
/**
* @brief Reference to attached Node
*/
@@ -167,6 +172,8 @@ private:
QVector<NodeViewEdge*> edges_;
QPointF cached_node_pos_;
};
}
+6 -4
View File
@@ -179,10 +179,12 @@ void NodeViewScene::AddEdge(const NodeOutput &output, const NodeInput &input)
void NodeViewScene::RemoveEdge(const NodeOutput &output, const NodeInput &input)
{
NodeViewEdge* edge = EdgeToUIObject(output, input);
edge->from_item()->RemoveEdge(edge);
edge->to_item()->RemoveEdge(edge);
edges_.removeOne(edge);
delete edge;
if (edge) {
edge->from_item()->RemoveEdge(edge);
edge->to_item()->RemoveEdge(edge);
edges_.removeOne(edge);
delete edge;
}
}
int NodeViewScene::DetermineWeight(Node *n)
+9 -4
View File
@@ -871,7 +871,7 @@ void TimelineWidget::RemoveBlock(Block *block)
selected_blocks_.removeAt(select_index);
RemoveSelection(block);
emit BlocksDeselected({block});
SignalBlockSelectionChange();
}
}
@@ -1087,6 +1087,11 @@ void TimelineWidget::SetScrollZoomsByDefaultOnAllViews(bool e)
}
}
void TimelineWidget::SignalBlockSelectionChange()
{
emit BlockSelectionChanged(selected_blocks_);
}
void TimelineWidget::AddGhost(TimelineViewGhostItem *ghost)
{
ghost_items_.append(ghost);
@@ -1168,7 +1173,7 @@ void TimelineWidget::SignalSelectedBlocks(QVector<Block *> input, bool filter)
selected_blocks_.append(input);
emit BlocksSelected(input);
emit SignalBlockSelectionChange();
}
void TimelineWidget::SignalDeselectedBlocks(const QVector<Block *> &deselected_blocks)
@@ -1181,14 +1186,14 @@ void TimelineWidget::SignalDeselectedBlocks(const QVector<Block *> &deselected_b
selected_blocks_.removeOne(b);
}
emit BlocksDeselected(deselected_blocks);
emit SignalBlockSelectionChange();
}
void TimelineWidget::SignalDeselectedAllBlocks()
{
if (!selected_blocks_.isEmpty()) {
emit BlocksDeselected(selected_blocks_);
selected_blocks_.clear();
SignalBlockSelectionChange();
}
}
+3 -3
View File
@@ -234,9 +234,7 @@ public:
};
signals:
void BlocksSelected(const QVector<Block*>& selected_blocks);
void BlocksDeselected(const QVector<Block*>& deselected_blocks);
void BlockSelectionChanged(const QVector<Block*>& selected_blocks);
protected:
virtual void resizeEvent(QResizeEvent *event) override;
@@ -355,6 +353,8 @@ private slots:
void SetScrollZoomsByDefaultOnAllViews(bool e);
void SignalBlockSelectionChange();
};
}
+5 -1
View File
@@ -387,8 +387,12 @@ void ImportTool::DropGhosts(bool insert)
clip->set_length_and_media_out(ghost->GetLength());
clip->SetLabel(footage_stream.footage->GetLabel());
command->add_child(new NodeAddCommand(dst_graph, clip));
command->add_child(new NodeSetPositionToOffsetOfAnotherNodeCommand(clip, footage_stream.footage, clip, QPointF(2, 0)));
command->add_child(new NodeSetPositionToOffsetOfAnotherNodeCommand(clip, footage_stream.footage, nullptr, QPointF(2, 0)));
// Position clip in its own context
command->add_child(new NodeSetPositionCommand(clip, clip, QPointF(0, 0), false));
// Position footage in its context
command->add_child(new NodeSetPositionCommand(footage_stream.footage, clip, QPointF(-2, 0), false));
switch (Track::Reference::TypeFromString(footage_stream.output)) {
+17
View File
@@ -466,6 +466,22 @@ void MainWindow::StatusBarDoubleClicked()
task_man_panel_->raise();
}
void MainWindow::TimelinePanelSelectionChanged(const QVector<Block *> &blocks)
{
TimelinePanel *panel = static_cast<TimelinePanel *>(sender());
if (PanelManager::instance()->CurrentlyFocused(false) == panel) {
QVector<void *> context(blocks.size());
for (int i=0; i<blocks.size(); i++) {
context[i] = blocks.at(i);
}
ViewerOutput *viewer = panel->GetConnectedViewer();
node_panel_->SetGraph(viewer ? viewer->parent() : nullptr, context);
}
}
#ifdef Q_OS_LINUX
void MainWindow::ShowNouveauWarning()
{
@@ -539,6 +555,7 @@ TimelinePanel* MainWindow::AppendTimelinePanel()
connect(panel, &TimelinePanel::TimeChanged, param_panel_, &ParamPanel::SetTimestamp);
connect(panel, &TimelinePanel::TimeChanged, table_panel_, &NodeTablePanel::SetTimestamp);
connect(panel, &TimelinePanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTimestamp);
connect(panel, &TimelinePanel::BlockSelectionChanged, this, &MainWindow::TimelinePanelSelectionChanged);
connect(param_panel_, &ParamPanel::TimeChanged, panel, &TimelinePanel::SetTimestamp);
connect(curve_panel_, &ParamPanel::TimeChanged, panel, &TimelinePanel::SetTimestamp);
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, panel, &TimelinePanel::SetTimestamp);
+2
View File
@@ -190,6 +190,8 @@ private slots:
void ShowNouveauWarning();
#endif
void TimelinePanelSelectionChanged(const QVector<Block*> &blocks);
};
}