clean up and remove nodegroupdialog

This commit is contained in:
itsmattkc
2021-12-27 20:56:04 -08:00
parent f8ac3f4e40
commit 65a1c75933
15 changed files with 58 additions and 479 deletions
+11 -3
View File
@@ -1358,10 +1358,10 @@ void Core::SetPreferenceForRenderMode(RenderMode::Mode mode, const QString &pref
Config::Current()[GetRenderModePreferencePrefix(mode, preference)] = value;
}
void Core::LabelNodes(const QVector<Node *> &nodes)
bool Core::LabelNodes(const QVector<Node *> &nodes, MultiUndoCommand *parent)
{
if (nodes.isEmpty()) {
return;
return false;
}
bool ok;
@@ -1390,8 +1390,16 @@ void Core::LabelNodes(const QVector<Node *> &nodes)
rename_command->AddNode(n, s);
}
undo_stack_.push(rename_command);
if (parent) {
parent->add_child(rename_command);
} else {
undo_stack_.push(rename_command);
}
return true;
}
return false;
}
Sequence *Core::CreateNewSequenceForProject(Project* project) const
+1 -1
View File
@@ -253,7 +253,7 @@ public:
/**
* @brief Show a dialog to the user to rename a set of nodes
*/
void LabelNodes(const QVector<Node *> &nodes);
bool LabelNodes(const QVector<Node *> &nodes, MultiUndoCommand *parent = nullptr);
/**
* @brief Create a new sequence named appropriately for the active project
-1
View File
@@ -24,7 +24,6 @@ add_subdirectory(export)
add_subdirectory(footageproperties)
add_subdirectory(footagerelink)
add_subdirectory(keyframeproperties)
add_subdirectory(nodegroup)
add_subdirectory(preferences)
add_subdirectory(progress)
add_subdirectory(rendercancel)
-22
View File
@@ -1,22 +0,0 @@
# 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/>.
set(OLIVE_SOURCES
${OLIVE_SOURCES}
dialog/nodegroup/nodegroupdialog.cpp
dialog/nodegroup/nodegroupdialog.h
PARENT_SCOPE
)
-319
View File
@@ -1,319 +0,0 @@
/***
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 "nodegroupdialog.h"
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QLabel>
#include <QMessageBox>
#include <QSplitter>
#include "panel/node/node.h"
#include "panel/panelmanager.h"
#include "panel/param/param.h"
namespace olive {
#define super QDialog
NodeGroupDialog::NodeGroupDialog(NodeGroup *group, QWidget *parent) :
super(parent),
group_(group),
prepend_undo_(nullptr)
{
QGridLayout *layout = new QGridLayout(this);
int row = 0;
layout->addWidget(new QLabel(tr("Name:")), row, 0);
name_edit_ = new QLineEdit();
name_edit_->setText(group->GetLabel());
layout->addWidget(name_edit_, row, 1);
row++;
QMainWindow *splitter = new QMainWindow();
QWidget *cw = new QWidget();
cw->setFixedSize(0, 0);
splitter->setCentralWidget(cw);
layout->addWidget(splitter, row, 0, 1, 2);
ParamPanel *param_view = PanelManager::instance()->CreatePanel<ParamPanel>(splitter);
param_view->GetParamView()->SetIgnoreNodeFlags(true);
param_view->GetParamView()->SetCreateCheckBoxes(kCheckBoxesOnNonConnected);
splitter->addDockWidget(Qt::LeftDockWidgetArea, param_view);
NodePanel *node_view = PanelManager::instance()->CreatePanel<NodePanel>(splitter);
node_view->GetNodeWidget()->view()->OverrideUndoStack(&undo_stack_);
QMetaObject::invokeMethod(node_view->GetNodeWidget()->view(), &NodeView::CenterOnItemsBoundingRect, Qt::QueuedConnection);
splitter->addDockWidget(Qt::RightDockWidgetArea, node_view);
row++;
QDialogButtonBox *btns = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
btns->setCenterButtons(true);
connect(btns, &QDialogButtonBox::accepted, this, &NodeGroupDialog::accept);
connect(btns, &QDialogButtonBox::rejected, this, &NodeGroupDialog::reject);
layout->addWidget(btns, row, 0, 1, 2);
setWindowTitle(tr("Group Editor - %1").arg(group->GetLabelOrName()));
// Create a project
copied_project_ = new Project();
copied_project_->setParent(this);
// Copy project nodes
// NOTE: I hate this. What might be better is to fold the "ColorManager" and "ProjectSettings"
// nodes into "Project" inputs and make "Project" a node too.
for (int i=0; i<copied_project_->nodes().size(); i++) {
Node *ours = copied_project_->nodes().at(i);
Node *theirs = group_->project()->nodes().at(i);
copy_subnodes_.insert(theirs, ours);
Node::CopyInputs(ours, theirs, false);
}
// Copy group and nodes
copy_group_ = static_cast<NodeGroup*>(group_->copy());
copy_group_->setParent(copied_project_);
// Copy subnodes with positions
const Node::PositionMap &map = group_->GetContextPositions();
for (auto it=map.cbegin(); it!=map.cend(); it++) {
Node *copy = it.key()->copy();
copy->SetUUID(it.key()->GetUUID());
copy->setParent(copied_project_);
copy_group_->SetNodePositionInContext(copy, it.value());
copy_subnodes_.insert(it.key(), copy);
}
for (auto it=map.cbegin(); it!=map.cend(); it++) {
Node::CopyInputs(it.key(), copy_subnodes_.value(it.key()), false);
}
// Copy edges
for (auto it=copy_subnodes_.cbegin(); it!=copy_subnodes_.cend(); it++) {
Node *src = it.key();
Node *cpy = it.value();
for (auto jt=src->input_connections().cbegin(); jt!=src->input_connections().cend(); jt++) {
if (Node *cpy_output = copy_subnodes_.value(jt->second)) {
Node::ConnectEdge(cpy_output, NodeInput(cpy, jt->first.input(), jt->first.element()));
copied_edges_.append({cpy_output, NodeInput(cpy, jt->first.input(), jt->first.element())});
}
}
}
node_view->SetContexts({copy_group_});
for (auto it=group_->GetInputPassthroughs().cbegin(); it!=group_->GetInputPassthroughs().cend(); it++) {
const NodeInput &src_input = it.value();
NodeInput copy_input(copy_subnodes_.value(src_input.node()), src_input.input(), src_input.element());
param_view->GetParamView()->SetInputChecked(copy_input, true);
}
param_view->SetContexts({copy_group_});
}
void NodeGroupDialog::accept()
{
// First, validate if a connection, deleted node, or disabled passthrough is going to disconnect
// something elsewhere in the group. Ask the user to confirm if so.
// Detect removed nodes
QVector<Node*> nodes_to_delete = GetNodesToDelete();
// Detect new connections
QVector<Node::OutputConnection> edges_to_connect = GetNewConnections();
// Warn user if operation will disconnect a node outside the group
if (OperationWillAffectOutsideGroup(nodes_to_delete, edges_to_connect)) {
if (QMessageBox::question(this, QString(), tr("This operation will disconnect nodes outside of this group. Do you wish to continue?"), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) {
return;
}
}
NodeViewDeleteCommand *delete_command = new NodeViewDeleteCommand();
// Remove deleted nodes
foreach (Node *n, nodes_to_delete) {
delete_command->AddNode(n, group_);
}
// Disconnect old edges
foreach (const Node::OutputConnection &edge, copied_edges_) {
bool found = false;
const NodeInput &copy_input = edge.second;
for (auto it=edge.first->output_connections().cbegin(); it!=edge.first->output_connections().cend(); it++) {
if (it->second == copy_input) {
found = true;
break;
}
}
if (!found) {
// Edge has been disconnected
delete_command->AddEdge(copy_subnodes_.key(edge.first), NodeInput(copy_subnodes_.key(copy_input.node()), copy_input.input(), copy_input.element()));
}
}
delete_command->redo_now();
// Add new nodes
MultiUndoCommand *add_command = new MultiUndoCommand();
for (auto it=copy_group_->GetContextPositions().cbegin(); it!=copy_group_->GetContextPositions().cend(); it++) {
Node *n = it.key();
Node *original = copy_subnodes_.key(n);
if (!original) {
// If it's a new node that isn't even in the project yet, add it
original = n->copy();
Node::CopyInputs(n, original, false);
add_command->add_child(new NodeAddCommand(group_->parent(), original));
copy_subnodes_.insert(original, n);
}
// Update position in context
add_command->add_child(new NodeSetPositionCommand(original, group_, it.value()));
}
add_command->redo_now();
// Connect new edges
MultiUndoCommand *connect_command = new MultiUndoCommand();
edges_to_connect = GetNewConnections(); // Update list with new nodes made above if necessary
foreach (const Node::OutputConnection &edge, edges_to_connect) {
connect_command->add_child(new NodeEdgeAddCommand(edge.first, edge.second));
}
connect_command->redo_now();
MultiUndoCommand *command = new MultiUndoCommand();
if (prepend_undo_) {
command->add_child(prepend_undo_);
}
command->add_child(delete_command);
command->add_child(add_command);
command->add_child(connect_command);
// Update group name
if (name_edit_->text() != group_->GetCustomName()) {
command->add_child(new NodeGroupSetCustomNameCommand(group_, name_edit_->text()));
}
Core::instance()->undo_stack()->push(command);
super::accept();
}
void NodeGroupDialog::reject()
{
if (prepend_undo_) {
prepend_undo_->undo_now();
delete prepend_undo_;
}
super::reject();
}
QVector<Node *> NodeGroupDialog::GetNodesToDelete()
{
QVector<Node*> nodes_to_delete;
for (auto it=group_->GetContextPositions().cbegin(); it!=group_->GetContextPositions().cend(); it++) {
Node *original = it.key();
Node *copy = copy_subnodes_.value(original);
if (!copy_group_->ContextContainsNode(copy)) {
nodes_to_delete.append(original);
}
}
return nodes_to_delete;
}
QVector<Node::OutputConnection> NodeGroupDialog::GetNewConnections()
{
QVector<Node::OutputConnection> edges_to_connect;
for (auto it=copy_group_->GetContextPositions().cbegin(); it!=copy_group_->GetContextPositions().cend(); it++) {
const Node::InputConnections &ic = it.key()->input_connections();
for (auto jt=ic.cbegin(); jt!=ic.cend(); jt++) {
// All connections inside this dialog will be valid and inside the group
const NodeInput &copied_input = jt->first;
Node *copied_output = jt->second;
NodeInput original_input(copy_subnodes_.key(copied_input.node()), copied_input.input(), copied_input.element());
Node *original_output = copy_subnodes_.key(copied_output);
bool found = false;
if (original_output) {
for (auto kt=original_output->output_connections().cbegin(); kt!=original_output->output_connections().cend(); kt++) {
if (kt->second == original_input) {
found = true;
break;
}
}
}
if (!found) {
edges_to_connect.append({original_output, original_input});
}
}
}
return edges_to_connect;
}
bool NodeGroupDialog::OperationWillAffectOutsideGroup(const QVector<Node*> &deleted, const QVector<Node::OutputConnection> &connections)
{
// Check if a node to be deleted inputs from a node outside the group
foreach (Node *n, deleted) {
for (auto jt=n->input_connections().cbegin(); jt!=n->input_connections().cend(); jt++) {
if (!group_->ContextContainsNode(jt->second)) {
return true;
}
}
for (auto jt=n->output_connections().cbegin(); jt!=n->output_connections().cend(); jt++) {
if (!group_->ContextContainsNode(jt->second.node())) {
return true;
}
}
}
// Check if a new connection will overwrite a connection from outside the group
foreach (const Node::OutputConnection &edge, connections) {
if (Node *current_conn = edge.second.GetConnectedOutput()) {
if (!group_->ContextContainsNode(current_conn)) {
return true;
}
}
}
return false;
}
}
-75
View File
@@ -1,75 +0,0 @@
/***
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 NODEGROUPDIALOG_H
#define NODEGROUPDIALOG_H
#include <QDialog>
#include <QLineEdit>
#include <QMainWindow>
#include "node/group/group.h"
#include "undo/undostack.h"
namespace olive {
class NodeGroupDialog : public QDialog
{
Q_OBJECT
public:
explicit NodeGroupDialog(NodeGroup *group, QWidget *parent = nullptr);
void PrependUndoCommand(MultiUndoCommand *c)
{
prepend_undo_ = c;
}
public slots:
virtual void accept() override;
virtual void reject() override;
signals:
private:
QVector<Node*> GetNodesToDelete();
QVector<Node::OutputConnection> GetNewConnections();
bool OperationWillAffectOutsideGroup(const QVector<Node *> &deleted, const QVector<Node::OutputConnection> &connections);
NodeGroup *group_;
QLineEdit *name_edit_;
MultiUndoCommand *prepend_undo_;
Project *copied_project_;
NodeGroup *copy_group_;
QMap<Node*, Node*> copy_subnodes_;
QVector<Node::OutputConnection> copied_edges_;
UndoStack undo_stack_;
};
}
#endif // NODEGROUPDIALOG_H
+1 -1
View File
@@ -25,7 +25,7 @@
namespace olive {
PixelSamplerPanel::PixelSamplerPanel(QWidget *parent) :
PanelWidget(QStringLiteral("ProjectPanel"), parent)
PanelWidget(QStringLiteral("PixelSamplerPanel"), parent)
{
sampler_widget_ = new ManagedPixelSamplerWidget();
SetWidgetWithPadding(sampler_widget_);
+7 -18
View File
@@ -24,24 +24,6 @@ namespace olive {
ViewerPanel::ViewerPanel(const QString &object_name, QWidget *parent) :
ViewerPanelBase(object_name, parent)
{
Init();
}
ViewerPanel::ViewerPanel(QWidget *parent) :
ViewerPanelBase(QStringLiteral("ViewerPanel"), parent)
{
Init();
}
void ViewerPanel::Retranslate()
{
ViewerPanelBase::Retranslate();
SetTitle(tr("Viewer"));
}
void ViewerPanel::Init()
{
// Set ViewerWidget as the central widget
ViewerWidget* vw = new ViewerWidget();
@@ -52,4 +34,11 @@ void ViewerPanel::Init()
Retranslate();
}
void ViewerPanel::Retranslate()
{
ViewerPanelBase::Retranslate();
SetTitle(tr("Viewer"));
}
}
+4 -4
View File
@@ -34,14 +34,14 @@ class ViewerPanel : public ViewerPanelBase {
Q_OBJECT
public:
ViewerPanel(const QString& object_name, QWidget* parent);
ViewerPanel(QWidget* parent);
ViewerPanel(QWidget *parent) :
ViewerPanel(QStringLiteral("ViewerPanel"), parent)
{
}
protected:
virtual void Retranslate() override;
private:
void Init();
};
}
+9 -14
View File
@@ -26,7 +26,6 @@
#include <QScrollBar>
#include <QToolTip>
#include "dialog/nodegroup/nodegroupdialog.h"
#include "nodeviewundo.h"
#include "node/audio/volume/volume.h"
#include "node/distort/transform/transformdistortnode.h"
@@ -49,7 +48,6 @@ NodeView::NodeView(QWidget *parent) :
create_edge_output_item_(nullptr),
create_edge_input_item_(nullptr),
paste_command_(nullptr),
undo_stack_(Core::instance()->undo_stack()),
scale_(1.0)
{
setScene(&scene_);
@@ -133,7 +131,7 @@ void NodeView::DeleteSelected()
ctx->DeleteSelected(command);
}
undo_stack_->push(command);
Core::instance()->undo_stack()->push(command);
}
void NodeView::SelectAll()
@@ -227,7 +225,7 @@ void NodeView::SetColorLabel(int index)
command->add_child(new NodeOverrideColorCommand(node, index));
}
undo_stack_->push(command);
Core::instance()->undo_stack()->push(command);
}
void NodeView::ZoomIn()
@@ -282,7 +280,7 @@ void NodeView::keyPressEvent(QKeyEvent *event)
}
}
}
undo_stack_->pushIfHasChildren(pos_command);
Core::instance()->undo_stack()->pushIfHasChildren(pos_command);
break;
}
case Qt::Key_Escape:
@@ -561,7 +559,7 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
}
create_edge_expanded_items_.clear();
undo_stack_->pushIfHasChildren(command);
Core::instance()->undo_stack()->pushIfHasChildren(command);
}
MultiUndoCommand* command = new MultiUndoCommand();
@@ -645,7 +643,7 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
}
dragging_items_.clear();
undo_stack_->pushIfHasChildren(command);
Core::instance()->undo_stack()->pushIfHasChildren(command);
super::mouseReleaseEvent(event);
}
@@ -1234,11 +1232,9 @@ void NodeView::GroupNodes()
command->add_child(new NodeSetPositionCommand(group, context, avg_pos));
// Do command
command->redo_now();
Core::instance()->LabelNodes({group}, command);
NodeGroupDialog ngd(group, this);
ngd.PrependUndoCommand(command);
ngd.exec();
Core::instance()->undo_stack()->push(command);
}
void NodeView::UngroupNodes()
@@ -1273,7 +1269,7 @@ void NodeView::UngroupNodes()
command->add_child(new NodeSetPositionCommand(it.key(), context, group->GetNodePositionDataInContext(it.key())));
}
undo_stack_->push(command);
Core::instance()->undo_stack()->push(command);
}
void NodeView::ShowNodeProperties()
@@ -1281,8 +1277,7 @@ void NodeView::ShowNodeProperties()
Node *first_node = selected_nodes_.first();
if (NodeGroup *group = dynamic_cast<NodeGroup*>(first_node)) {
NodeGroupDialog ngd(group, this);
ngd.exec();
qDebug() << "STUB!";
} else {
LabelSelectedNodes();
}
-7
View File
@@ -77,11 +77,6 @@ public:
void ZoomOut();
void OverrideUndoStack(UndoStack *stack)
{
undo_stack_ = stack;
}
const QVector<Node*> &GetCurrentContexts() const
{
return contexts_;
@@ -195,8 +190,6 @@ private:
QMap<NodeViewItem*, QPointF> dragging_items_;
UndoStack *undo_stack_;
double scale_;
static const double kMinimumScale;
+9
View File
@@ -28,6 +28,8 @@
#include <QStyleOption>
#include <QVariant>
#include "panel/panelmanager.h"
namespace olive {
PanelWidget::PanelWidget(const QString &object_name, QWidget *parent) :
@@ -39,6 +41,13 @@ PanelWidget::PanelWidget(const QString &object_name, QWidget *parent) :
setFocusPolicy(Qt::ClickFocus);
connect(this, &PanelWidget::visibilityChanged, this, &PanelWidget::PanelVisibilityChanged);
PanelManager::instance()->RegisterPanel(this);
}
PanelWidget::~PanelWidget()
{
PanelManager::instance()->UnregisterPanel(this);
}
void PanelWidget::SetMovementLocked(bool locked)
+2
View File
@@ -45,6 +45,8 @@ public:
*/
PanelWidget(const QString& object_name, QWidget* parent);
virtual ~PanelWidget() override;
/**
* @brief Set whether panel movement is locked or not
*/
+1 -1
View File
@@ -273,7 +273,7 @@ void ViewerDisplayWidget::mouseReleaseEvent(QMouseEvent *event)
// Handle gizmo
MultiUndoCommand *command = new MultiUndoCommand();
gizmos_->GizmoRelease(command);
undo_stack()->pushIfHasChildren(command);
Core::instance()->undo_stack()->pushIfHasChildren(command);
gizmo_click_ = false;
} else {
+13 -13
View File
@@ -78,17 +78,17 @@ MainWindow::MainWindow(QWidget *parent) :
setStatusBar(status_bar);
// Create standard panels
node_panel_ = new NodePanel(undo_stack_, this);
footage_viewer_panel_ = new FootageViewerPanel(undo_stack_, this);
param_panel_ = new ParamPanel(undo_stack_, this);
curve_panel_ = new CurvePanel(undo_stack_, this);
sequence_viewer_panel_ = new SequenceViewerPanel(undo_stack_, this);
pixel_sampler_panel_ = new PixelSamplerPanel(undo_stack_, this);
node_panel_ = new NodePanel(this);
footage_viewer_panel_ = new FootageViewerPanel(this);
param_panel_ = new ParamPanel(this);
curve_panel_ = new CurvePanel(this);
sequence_viewer_panel_ = new SequenceViewerPanel(this);
pixel_sampler_panel_ = new PixelSamplerPanel(this);
AppendProjectPanel();
tool_panel_ = new ToolPanel(undo_stack_, this);
task_man_panel_ = new TaskManagerPanel(undo_stack_, this);
tool_panel_ = new ToolPanel(this);
task_man_panel_ = new TaskManagerPanel(this);
AppendTimelinePanel();
audio_monitor_panel_ = new AudioMonitorPanel(undo_stack_, this);
audio_monitor_panel_ = new AudioMonitorPanel(this);
// Make node-related connections
connect(node_panel_, &NodePanel::NodesSelected, param_panel_, &ParamPanel::SelectNodes);
@@ -218,7 +218,7 @@ bool MainWindow::IsSequenceOpen(Sequence *sequence) const
void MainWindow::FolderOpen(Project* p, Folder *i, bool floating)
{
ProjectPanel* panel = new ProjectPanel(undo_stack_, this);
ProjectPanel* panel = new ProjectPanel(this);
panel->set_project(p);
panel->set_root(i);
@@ -256,7 +256,7 @@ void MainWindow::OpenNodeInViewer(ViewerOutput *node)
viewer_panels_.value(node)->raise();
} else {
// Create a viewer for this node
ViewerPanel* viewer = new ViewerPanel(undo_stack_, this);
ViewerPanel* viewer = new ViewerPanel(this);
viewer->SetSignalInsteadOfClose(true);
viewer->setFloating(true);
@@ -816,7 +816,7 @@ void MainWindow::showEvent(QShowEvent *e)
template<typename T>
T *MainWindow::AppendPanelInternal(QList<T*>& list)
{
T* panel = new T(undo_stack_, this);
T* panel = new T(this);
if (!list.isEmpty()) {
tabifyDockWidget(list.last(), panel);
@@ -837,7 +837,7 @@ T *MainWindow::AppendPanelInternal(QList<T*>& list)
template<typename T>
T *MainWindow::AppendFloatingPanelInternal(QList<T *> &list)
{
T* panel = new T(undo_stack_, this);
T* panel = new T(this);
panel->setFloating(true);
panel->show();