diff --git a/app/panel/CMakeLists.txt b/app/panel/CMakeLists.txt index f93581c56..0b3f572b0 100644 --- a/app/panel/CMakeLists.txt +++ b/app/panel/CMakeLists.txt @@ -15,6 +15,7 @@ # along with this program. If not, see . add_subdirectory(node) +add_subdirectory(param) add_subdirectory(project) add_subdirectory(taskmanager) add_subdirectory(timeline) diff --git a/app/panel/node/node.cpp b/app/panel/node/node.cpp index 54ba33beb..9caad412b 100644 --- a/app/panel/node/node.cpp +++ b/app/panel/node/node.cpp @@ -26,6 +26,9 @@ NodePanel::NodePanel(QWidget *parent) : // Create NodeView widget node_view_ = new NodeView(this); + // Connect node view signals to this panel + connect(node_view_, SIGNAL(SelectionChanged(QList)), this, SIGNAL(SelectionChanged(QList))); + // Set it as the main widget of this panel setWidget(node_view_); diff --git a/app/panel/node/node.h b/app/panel/node/node.h index 28a59fd70..5e6c4b646 100644 --- a/app/panel/node/node.h +++ b/app/panel/node/node.h @@ -38,6 +38,12 @@ public: protected: virtual void changeEvent(QEvent* e) override; +signals: + /** + * @brief Wrapper for NodeView::SelectionChanged() + */ + void SelectionChanged(QList selected_nodes); + private: void Retranslate(); diff --git a/app/panel/param/CMakeLists.txt b/app/panel/param/CMakeLists.txt new file mode 100644 index 000000000..04e3682a5 --- /dev/null +++ b/app/panel/param/CMakeLists.txt @@ -0,0 +1,22 @@ +# Olive - Non-Linear Video Editor +# Copyright (C) 2019 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 . + +set(OLIVE_SOURCES + ${OLIVE_SOURCES} + panel/param/param.h + panel/param/param.cpp + PARENT_SCOPE +) diff --git a/app/panel/param/param.cpp b/app/panel/param/param.cpp new file mode 100644 index 000000000..5cf53fe85 --- /dev/null +++ b/app/panel/param/param.cpp @@ -0,0 +1,50 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 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 . + +***/ + +#include "param.h" + +ParamPanel::ParamPanel(QWidget* parent) : + PanelWidget(parent) +{ + view_ = new NodeParamView(this); + + setWidget(view_); + + Retranslate(); +} + +void ParamPanel::SetNodes(QList nodes) +{ + view_->SetNodes(nodes); +} + +void ParamPanel::changeEvent(QEvent *e) +{ + if (e->type() == QEvent::LanguageChange) { + Retranslate(); + } + QDockWidget::changeEvent(e); +} + +void ParamPanel::Retranslate() +{ + SetTitle(tr("Parameter Editor")); + SetSubtitle(tr("(none)")); +} diff --git a/app/panel/param/param.h b/app/panel/param/param.h new file mode 100644 index 000000000..6d1155840 --- /dev/null +++ b/app/panel/param/param.h @@ -0,0 +1,45 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 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 . + +***/ + +#ifndef PARAM_H +#define PARAM_H + +#include "widget/nodeparamview/nodeparamview.h" +#include "widget/panel/panel.h" + +class ParamPanel : public PanelWidget +{ + Q_OBJECT +public: + ParamPanel(QWidget* parent); + +public slots: + void SetNodes(QList nodes); + +protected: + virtual void changeEvent(QEvent* e); + +private: + void Retranslate(); + + NodeParamView* view_; +}; + +#endif // PARAM_H diff --git a/app/widget/CMakeLists.txt b/app/widget/CMakeLists.txt index 9092485ec..872fe3343 100644 --- a/app/widget/CMakeLists.txt +++ b/app/widget/CMakeLists.txt @@ -17,6 +17,7 @@ add_subdirectory(flowlayout) add_subdirectory(menu) add_subdirectory(nodeview) +add_subdirectory(nodeparamview) add_subdirectory(panel) add_subdirectory(playbackcontrols) add_subdirectory(projectexplorer) diff --git a/app/widget/nodeparamview/CMakeLists.txt b/app/widget/nodeparamview/CMakeLists.txt new file mode 100644 index 000000000..fa8e4a357 --- /dev/null +++ b/app/widget/nodeparamview/CMakeLists.txt @@ -0,0 +1,24 @@ +# Olive - Non-Linear Video Editor +# Copyright (C) 2019 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 . + +set(OLIVE_SOURCES + ${OLIVE_SOURCES} + widget/nodeparamview/nodeparamview.h + widget/nodeparamview/nodeparamview.cpp + widget/nodeparamview/nodeparamviewitem.h + widget/nodeparamview/nodeparamviewitem.cpp + PARENT_SCOPE +) diff --git a/app/widget/nodeparamview/nodeparamview.cpp b/app/widget/nodeparamview/nodeparamview.cpp new file mode 100644 index 000000000..853690cad --- /dev/null +++ b/app/widget/nodeparamview/nodeparamview.cpp @@ -0,0 +1,73 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 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 . + +***/ + +#include "nodeparamview.h" + +NodeParamView::NodeParamView(QWidget *parent) : + QWidget(parent) +{ + // Set new layout + layout_ = new QVBoxLayout(this); + layout_->setSpacing(0); + layout_->setMargin(0); + + // Add a stretch to allow empty space at the bottom of the layout + layout_->addStretch(); +} + +void NodeParamView::SetNodes(QList nodes) +{ + // If we already have item widgets, delete them all now + foreach (NodeParamViewItem* item, items_) { + delete item; + } + items_.clear(); + + // Set the internal list to the one we've received + nodes_ = nodes; + + // For each node, create a widget + foreach (Node* node, nodes_) { + + // See if we already have an item for this node type + + bool merged_node = false; + + foreach (NodeParamViewItem* existing_item, items_) { + if (existing_item->CanAddNode(node)) { + existing_item->AttachNode(node); + merged_node = true; + break; + } + } + + // If we couldn't merge this node into the existing item, create a new one + if (!merged_node) { + NodeParamViewItem* item = new NodeParamViewItem(this); + + item->AttachNode(node); + + // Insert the widget before the stretch + layout_->insertWidget(layout_->count() - 1, item); + + items_.append(item); + } + } +} diff --git a/app/widget/nodeparamview/nodeparamview.h b/app/widget/nodeparamview/nodeparamview.h new file mode 100644 index 000000000..685599148 --- /dev/null +++ b/app/widget/nodeparamview/nodeparamview.h @@ -0,0 +1,45 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 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 . + +***/ + +#ifndef NODEPARAMVIEW_H +#define NODEPARAMVIEW_H + +#include +#include + +#include "node/node.h" +#include "nodeparamviewitem.h" + +class NodeParamView : public QWidget +{ +public: + NodeParamView(QWidget* parent); + + void SetNodes(QList nodes); + +private: + QVBoxLayout* layout_; + + QList nodes_; + + QList items_; +}; + +#endif // NODEPARAMVIEW_H diff --git a/app/widget/nodeparamview/nodeparamviewitem.cpp b/app/widget/nodeparamview/nodeparamviewitem.cpp new file mode 100644 index 000000000..04f2a0e2c --- /dev/null +++ b/app/widget/nodeparamview/nodeparamviewitem.cpp @@ -0,0 +1,142 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 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 . + +***/ + +#include "nodeparamviewitem.h" + +#include +#include + +#include "ui/icons/icons.h" + +NodeParamViewItem::NodeParamViewItem(QWidget *parent) : + QWidget(parent) +{ + QVBoxLayout* main_layout = new QVBoxLayout(this); + main_layout->setSpacing(0); + main_layout->setMargin(0); + + // Create title bar widget + title_bar_ = new NodeParamViewItemTitleBar(this); + title_bar_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + + QHBoxLayout* title_bar_layout = new QHBoxLayout(title_bar_); + + title_bar_collapse_btn_ = new QPushButton(); + title_bar_collapse_btn_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + title_bar_collapse_btn_->setStyleSheet("border: none; background: none;"); + title_bar_collapse_btn_->setCheckable(true); + title_bar_collapse_btn_->setChecked(true); + connect(title_bar_collapse_btn_, SIGNAL(clicked(bool)), this, SLOT(SetExpanded(bool))); + title_bar_layout->addWidget(title_bar_collapse_btn_); + + title_bar_lbl_ = new QLabel(title_bar_); + title_bar_layout->addWidget(title_bar_lbl_); + + // Add title bar to widget + main_layout->addWidget(title_bar_); + + // Create and add contents widget + contents_ = new QWidget(this); + content_layout_ = new QGridLayout(contents_); + main_layout->addWidget(contents_); + + // Set correct widget state + SetExpanded(title_bar_collapse_btn_->isChecked()); +} + +void NodeParamViewItem::AttachNode(Node *n) +{ + // Make sure we can attach this node (CanAddNode() should be run by the caller to make sure this node is valid) + Q_ASSERT(CanAddNode(n)); + + // Add node to the list + nodes_.append(n); + + // If the added node was the first node, set up the UI + if (nodes_.size() == 1) { + SetupUI(); + } +} + +bool NodeParamViewItem::CanAddNode(Node* n) +{ + // Ensures that all Nodes have the same ID + return (nodes_.isEmpty() || nodes_.first()->id() == n->id()); +} + +void NodeParamViewItem::changeEvent(QEvent *e) +{ + // FIXME: Retranslate all UI elements + + QWidget::changeEvent(e); +} + +void NodeParamViewItem::SetupUI() +{ + Q_ASSERT(!nodes_.isEmpty()); + + Node* first_node = nodes_.first(); + + title_bar_lbl_->setText(first_node->Name()); + + int row_count = 0; + + for (int i=0;iParameterCount();i++) { + NodeParam* param = first_node->ParamAt(i); + + // This widget only needs to show input parameters + if (param->type() == NodeParam::kInput) { + QLabel* param_label = new QLabel(tr("%1:").arg(param->name())); + + content_layout_->addWidget(param_label, row_count, 0); + + row_count++; + } + } +} + +void NodeParamViewItem::SetExpanded(bool e) +{ + expanded_ = e; + + contents_->setVisible(e); + + if (expanded_) { + title_bar_collapse_btn_->setIcon(olive::icon::TriDown); + } else { + title_bar_collapse_btn_->setIcon(olive::icon::TriRight); + } +} + +NodeParamViewItemTitleBar::NodeParamViewItemTitleBar(QWidget *parent) : + QWidget(parent) +{ +} + +void NodeParamViewItemTitleBar::paintEvent(QPaintEvent *event) +{ + QWidget::paintEvent(event); + + QPainter p(this); + + // Draw bottom border using text color + p.setPen(palette().text().color()); + p.drawLine(0, height() - 1, width(), height() - 1); +} diff --git a/app/widget/nodeparamview/nodeparamviewitem.h b/app/widget/nodeparamview/nodeparamviewitem.h new file mode 100644 index 000000000..dbddf7ddf --- /dev/null +++ b/app/widget/nodeparamview/nodeparamviewitem.h @@ -0,0 +1,74 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 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 . + +***/ + +#ifndef NODEPARAMVIEWITEM_H +#define NODEPARAMVIEWITEM_H + +#include +#include +#include +#include +#include + +#include "node/node.h" + +class NodeParamViewItemTitleBar : public QWidget { +public: + NodeParamViewItemTitleBar(QWidget* parent = nullptr); + +protected: + virtual void paintEvent(QPaintEvent *event) override; +}; + +class NodeParamViewItem : public QWidget +{ + Q_OBJECT +public: + NodeParamViewItem(QWidget* parent); + + void AttachNode(Node* n); + + bool CanAddNode(Node *n); + +protected: + void changeEvent(QEvent *e) override; + +private: + void SetupUI(); + + bool expanded_; + + NodeParamViewItemTitleBar* title_bar_; + + QLabel* title_bar_lbl_; + + QPushButton* title_bar_collapse_btn_; + + QWidget* contents_; + + QGridLayout* content_layout_; + + QList nodes_; + +private slots: + void SetExpanded(bool e); +}; + +#endif // NODEPARAMVIEWITEM_H diff --git a/app/widget/nodeview/nodeview.cpp b/app/widget/nodeview/nodeview.cpp index e67e8f6a6..2828ac8e1 100644 --- a/app/widget/nodeview/nodeview.cpp +++ b/app/widget/nodeview/nodeview.cpp @@ -29,6 +29,7 @@ NodeView::NodeView(QWidget *parent) : setDragMode(RubberBandDrag); connect(&scene_, SIGNAL(changed(const QList&)), this, SLOT(ItemsChanged())); + connect(&scene_, SIGNAL(selectionChanged()), this, SLOT(SceneSelectionChangedSlot())); } void NodeView::SetGraph(NodeGraph *graph) @@ -149,3 +150,22 @@ void NodeView::ItemsChanged() } } } + +void NodeView::SceneSelectionChangedSlot() +{ + // Get the scene's selected items and convert it into a list of selected nodes + QList selected_items = scene_.selectedItems(); + + QList selected_nodes; + + for (int i=0;i(selected_items.at(i)); + + if (item != nullptr) { + selected_nodes.append(item->node()); + } + } + + emit SelectionChanged(selected_nodes); +} diff --git a/app/widget/nodeview/nodeview.h b/app/widget/nodeview/nodeview.h index f5a6b28b8..8cb50fd71 100644 --- a/app/widget/nodeview/nodeview.h +++ b/app/widget/nodeview/nodeview.h @@ -74,6 +74,12 @@ public: */ NodeViewEdge* EdgeToUIObject(NodeEdgePtr n); +signals: + /** + * @brief Signal emitted when the selected nodes have changed + */ + void SelectionChanged(QList selected_nodes); + private: NodeGraph* graph_; @@ -103,6 +109,11 @@ private slots: */ void ItemsChanged(); + /** + * @brief Receiver for when the scene's selected items change + */ + void SceneSelectionChangedSlot(); + }; #endif // NODEVIEW_H diff --git a/app/window/mainwindow/mainwindow.cpp b/app/window/mainwindow/mainwindow.cpp index c8f80e78c..32ccbbf0a 100644 --- a/app/window/mainwindow/mainwindow.cpp +++ b/app/window/mainwindow/mainwindow.cpp @@ -23,8 +23,9 @@ #include // Panel objects -#include "panel/project/project.h" #include "panel/node/node.h" +#include "panel/param/param.h" +#include "panel/project/project.h" #include "panel/timeline/timeline.h" #include "panel/tool/tool.h" #include "panel/viewer/viewer.h" @@ -74,12 +75,17 @@ void olive::MainWindow::ProjectOpen(Project* p) ToolPanel* tool_panel = new ToolPanel(this); addDockWidget(Qt::BottomDockWidgetArea, tool_panel); - NodePanel* task_panel = new NodePanel(this); - addDockWidget(Qt::BottomDockWidgetArea, task_panel); + NodePanel* node_panel = new NodePanel(this); + addDockWidget(Qt::BottomDockWidgetArea, node_panel); + + ParamPanel* param_panel = new ParamPanel(this); + addDockWidget(Qt::BottomDockWidgetArea, param_panel); TimelinePanel* timeline_panel = new TimelinePanel(this); addDockWidget(Qt::BottomDockWidgetArea, timeline_panel); + connect(node_panel, SIGNAL(SelectionChanged(QList)), param_panel, SLOT(SetNodes(QList))); + // FIXME: Test code NodeGraph* graph = new NodeGraph(); graph->setParent(this); @@ -92,6 +98,6 @@ void olive::MainWindow::ProjectOpen(Project* p) graph->AddNode(sg); ImageInput* ii = new ImageInput(); graph->AddNode(ii); - task_panel->SetGraph(graph); + node_panel->SetGraph(graph); // End test code }