From 6ff9ab9f54034a14f8c7ae2103805cbd4fc2d019 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 23 May 2021 10:16:39 +1000 Subject: [PATCH 1/2] menu: added hidden secondary delete option to pick up backspace shortcut --- app/widget/menu/menushared.h | 10 ++++++++-- app/window/mainwindow/mainmenu.cpp | 22 ++++++++++++++++++++++ app/window/mainwindow/mainmenu.h | 7 +++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/app/widget/menu/menushared.h b/app/widget/menu/menushared.h index 36628385a..34d2cecb4 100644 --- a/app/widget/menu/menushared.h +++ b/app/widget/menu/menushared.h @@ -52,6 +52,14 @@ public: static MenuShared* instance(); + QAction* edit_delete_item() + { + return edit_delete_item_; + } + +public slots: + void DeleteSelectedTriggered(); + private: // "New" menu shared items QAction* new_project_item_; @@ -97,8 +105,6 @@ private: private slots: void SplitAtPlayheadTriggered(); - void DeleteSelectedTriggered(); - void RippleDeleteTriggered(); void SetInTriggered(); diff --git a/app/window/mainwindow/mainmenu.cpp b/app/window/mainwindow/mainmenu.cpp index 2e273dcff..ede11462d 100644 --- a/app/window/mainwindow/mainmenu.cpp +++ b/app/window/mainwindow/mainmenu.cpp @@ -73,6 +73,9 @@ MainMenu::MainMenu(MainWindow *parent) : // edit_menu_ = new Menu(this); + connect(edit_menu_, &Menu::aboutToShow, this, &MainMenu::EditMenuAboutToShow); + connect(edit_menu_, &Menu::aboutToHide, this, &MainMenu::EditMenuAboutToHide); + edit_undo_item_ = Core::instance()->undo_stack()->GetUndoAction(); Menu::ConformItem(edit_undo_item_, "undo", "Ctrl+Z"); edit_menu_->addAction(edit_undo_item_); @@ -82,6 +85,14 @@ MainMenu::MainMenu(MainWindow *parent) : edit_menu_->addSeparator(); MenuShared::instance()->AddItemsForEditMenu(edit_menu_, true); + { + // Create "alternate delete" action so we can pick up backspace as well as delete while still + // keeping them configurable + edit_delete2_item_ = new QAction(); + Menu::ConformItem(edit_delete2_item_, "delete2", MenuShared::instance(), &MenuShared::DeleteSelectedTriggered, "Backspace"); + auto actions = edit_menu_->actions(); + edit_menu_->insertAction(actions.at(actions.indexOf(MenuShared::instance()->edit_delete_item()) + 1), edit_delete2_item_); + } edit_menu_->addSeparator(); edit_select_all_item_ = edit_menu_->AddItem("selectall", this, &MainMenu::SelectAllTriggered, "Ctrl+A"); edit_deselect_all_item_ = edit_menu_->AddItem("deselectall", this, &MainMenu::DeselectAllTriggered, "Ctrl+Shift+A"); @@ -298,6 +309,16 @@ void MainMenu::FileMenuAboutToShow() } } +void MainMenu::EditMenuAboutToShow() +{ + edit_delete2_item_->setVisible(false); +} + +void MainMenu::EditMenuAboutToHide() +{ + edit_delete2_item_->setVisible(true); +} + void MainMenu::ViewMenuAboutToShow() { // Parent is QMainWindow @@ -620,6 +641,7 @@ void MainMenu::Retranslate() edit_menu_->setTitle(tr("&Edit")); //edit_undo_item_->setText(tr("&Undo")); FIXME: Does Qt translate these automatically? //edit_redo_item_->setText(tr("Redo")); + edit_delete2_item_->setText(tr("Delete (alt)")); edit_insert_item_->setText(tr("Insert")); edit_overwrite_item_->setText(tr("Overwrite")); edit_select_all_item_->setText(tr("Select &All")); diff --git a/app/window/mainwindow/mainmenu.h b/app/window/mainwindow/mainmenu.h index d0444bbaf..82277344b 100644 --- a/app/window/mainwindow/mainmenu.h +++ b/app/window/mainwindow/mainmenu.h @@ -66,6 +66,12 @@ private slots: */ void FileMenuAboutToShow(); + /** + * @brief Slot triggered just before the Edit menu shows + */ + void EditMenuAboutToShow(); + void EditMenuAboutToHide(); + /** * @brief Slot triggered just before the View menu shows */ @@ -202,6 +208,7 @@ private: Menu* edit_menu_; QAction* edit_undo_item_; QAction* edit_redo_item_; + QAction* edit_delete2_item_; QAction* edit_select_all_item_; QAction* edit_deselect_all_item_; QAction* edit_insert_item_; From 09dc79f9f6cb8ee6d04c4a59a52a31163e608291 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 23 May 2021 10:38:30 +1000 Subject: [PATCH 2/2] project: remove array element when deleting a folder's subitem Fixes #1639 --- app/node/node.h | 110 +++++++++--------- app/node/project/folder/folder.cpp | 18 +++ app/node/project/folder/folder.h | 40 +++++++ .../projectexplorer/projectexplorer.cpp | 4 + 4 files changed, 117 insertions(+), 55 deletions(-) diff --git a/app/node/node.h b/app/node/node.h index 71e6e78cd..d4ad010fc 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -768,6 +768,61 @@ public: static const QString kDefaultOutput; + class ArrayRemoveCommand : public UndoCommand + { + public: + ArrayRemoveCommand(Node* node, const QString& input, int index) : + node_(node), + input_(input), + index_(index) + { + } + + virtual Project* GetRelevantProject() const override; + + protected: + virtual void redo() override + { + // Save immediate data + if (node_->IsInputKeyframable(input_)) { + is_keyframing_ = node_->IsInputKeyframing(input_, index_); + } + standard_value_ = node_->GetSplitStandardValue(input_, index_); + keyframes_ = node_->GetKeyframeTracks(input_, index_); + node_->GetImmediate(input_, index_)->delete_all_keyframes(&memory_manager_); + + node_->InputArrayRemove(input_, index_, false); + } + + virtual void undo() override + { + node_->InputArrayInsert(input_, index_, false); + + // Restore keyframes + foreach (const NodeKeyframeTrack& track, keyframes_) { + foreach (NodeKeyframe* key, track) { + key->setParent(node_); + } + } + node_->SetSplitStandardValue(input_, standard_value_, index_); + + if (node_->IsInputKeyframable(input_)) { + node_->SetInputIsKeyframing(input_, is_keyframing_, index_); + } + } + + private: + Node* node_; + QString input_; + int index_; + + SplitValue standard_value_; + bool is_keyframing_; + QVector keyframes_; + QObject memory_manager_; + + }; + protected: enum InputFlag { /// By default, inputs are keyframable, connectable, and NOT arrays @@ -976,61 +1031,6 @@ private: }; - class ArrayRemoveCommand : public UndoCommand - { - public: - ArrayRemoveCommand(Node* node, const QString& input, int index) : - node_(node), - input_(input), - index_(index) - { - } - - virtual Project* GetRelevantProject() const override; - - protected: - virtual void redo() override - { - // Save immediate data - if (node_->IsInputKeyframable(input_)) { - is_keyframing_ = node_->IsInputKeyframing(input_, index_); - } - standard_value_ = node_->GetSplitStandardValue(input_, index_); - keyframes_ = node_->GetKeyframeTracks(input_, index_); - node_->GetImmediate(input_, index_)->delete_all_keyframes(&memory_manager_); - - node_->InputArrayRemove(input_, index_, false); - } - - virtual void undo() override - { - node_->InputArrayInsert(input_, index_, false); - - // Restore keyframes - foreach (const NodeKeyframeTrack& track, keyframes_) { - foreach (NodeKeyframe* key, track) { - key->setParent(node_); - } - } - node_->SetSplitStandardValue(input_, standard_value_, index_); - - if (node_->IsInputKeyframable(input_)) { - node_->SetInputIsKeyframing(input_, is_keyframing_, index_); - } - } - - private: - Node* node_; - QString input_; - int index_; - - SplitValue standard_value_; - bool is_keyframing_; - QVector keyframes_; - QObject memory_manager_; - - }; - class ArrayResizeCommand : public UndoCommand { public: diff --git a/app/node/project/folder/folder.cpp b/app/node/project/folder/folder.cpp index dc07f574e..9508425f2 100644 --- a/app/node/project/folder/folder.cpp +++ b/app/node/project/folder/folder.cpp @@ -24,6 +24,7 @@ #include "node/project/footage/footage.h" #include "node/project/sequence/sequence.h" #include "ui/icons/icons.h" +#include "widget/nodeview/nodeviewundo.h" namespace olive { @@ -155,4 +156,21 @@ void FolderAddChild::undo() folder_->InputArrayRemoveLast(Folder::kChildInput); } +void Folder::RemoveElementCommand::redo() +{ + if (!subcommand_) { + remove_index_ = folder_->index_of_child_in_array(child_); + if (remove_index_ != -1) { + NodeInput connected_input(folder_, Folder::kChildInput, remove_index_); + subcommand_ = new MultiUndoCommand(); + subcommand_->add_child(new NodeEdgeRemoveCommand(folder_->GetConnectedOutput(connected_input), connected_input)); + subcommand_->add_child(new Node::ArrayRemoveCommand(folder_, Folder::kChildInput, remove_index_)); + } + } + + if (subcommand_) { + subcommand_->redo(); + } +} + } diff --git a/app/node/project/folder/folder.h b/app/node/project/folder/folder.h index 3e96cb293..6d0521433 100644 --- a/app/node/project/folder/folder.h +++ b/app/node/project/folder/folder.h @@ -115,6 +115,46 @@ public: static const QString kChildInput; + class RemoveElementCommand : public UndoCommand + { + public: + RemoveElementCommand(Folder *folder, Node *child) : + folder_(folder), + child_(child), + subcommand_(nullptr) + { + } + + virtual ~RemoveElementCommand() override + { + delete subcommand_; + } + + virtual Project *GetRelevantProject() const override + { + return folder_->project(); + } + + virtual void redo() override; + + virtual void undo() override + { + if (subcommand_) { + subcommand_->undo(); + } + } + + private: + Folder *folder_; + + Node *child_; + + int remove_index_; + + MultiUndoCommand *subcommand_; + + }; + signals: void BeginInsertItem(Node* n, int index); diff --git a/app/widget/projectexplorer/projectexplorer.cpp b/app/widget/projectexplorer/projectexplorer.cpp index c05a69d11..49720bb0a 100644 --- a/app/widget/projectexplorer/projectexplorer.cpp +++ b/app/widget/projectexplorer/projectexplorer.cpp @@ -223,6 +223,10 @@ bool ProjectExplorer::DeleteItemsInternal(const QVector& selected, bool& command->add_child(new CloseSequenceCommand(sequence)); } + if (node->folder()) { + command->add_child(new Folder::RemoveElementCommand(node->folder(), node)); + } + command->add_child(new NodeRemoveWithExclusiveDependenciesAndDisconnect(node)); } }