diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 03aee3b52..6541844ae 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -311,6 +311,7 @@ Undo.MoveToTop="Move '%1' to top in '%2'" Undo.MoveToBottom="Move '%1' to bottom in '%2'" Undo.PasteSource="Paste Source(s) in '%1'" Undo.PasteSourceRef="Paste Source Reference(s) in '%1'" +Undo.GroupItems="Group Items into '%1'" # transition name dialog TransitionNameDlg.Text="Please enter the name of the transition" diff --git a/UI/source-tree.cpp b/UI/source-tree.cpp index d83ef25f8..9aba2d619 100644 --- a/UI/source-tree.cpp +++ b/UI/source-tree.cpp @@ -377,13 +377,32 @@ void SourceTreeItem::EnterEditMode() void SourceTreeItem::ExitEditMode(bool save) { - if (!editor) + ExitEditModeInternal(save); + + if (tree->undoSceneData) { + OBSBasic *main = OBSBasic::Get(); + main->undo_s.pop_disabled(); + + OBSData redoSceneData = main->BackupScene(GetCurrentScene()); + + QString text = QTStr("Undo.GroupItems").arg(newName.c_str()); + main->CreateSceneUndoRedoAction(text, tree->undoSceneData, + redoSceneData); + + tree->undoSceneData = nullptr; + } +} + +void SourceTreeItem::ExitEditModeInternal(bool save) +{ + if (!editor) { return; + } OBSBasic *main = reinterpret_cast(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); - std::string newName = QT_TO_UTF8(editor->text()); + newName = QT_TO_UTF8(editor->text()); setFocusProxy(nullptr); int index = boxLayout->indexOf(editor); @@ -444,9 +463,11 @@ void SourceTreeItem::ExitEditMode(bool save) obs_source_release(scene_source); }; - auto redo = [scene_name, main, newName](const std::string &data) { + std::string editedName = newName; + + auto redo = [scene_name, main, editedName](const std::string &data) { obs_source_t *source = obs_get_source_by_name(data.c_str()); - obs_source_set_name(source, newName.c_str()); + obs_source_set_name(source, editedName.c_str()); obs_source_release(source); obs_source_t *scene_source = @@ -913,6 +934,7 @@ void SourceTreeModel::GroupSelectedItems(QModelIndexList &indices) if (indices.count() == 0) return; + OBSBasic *main = OBSBasic::Get(); OBSScene scene = GetCurrentScene(); QString name = GetNewGroupName(); @@ -923,12 +945,17 @@ void SourceTreeModel::GroupSelectedItems(QModelIndexList &indices) item_order << item; } + st->undoSceneData = main->BackupScene(scene); + obs_sceneitem_t *item = obs_scene_insert_group( scene, QT_TO_UTF8(name), item_order.data(), item_order.size()); if (!item) { + st->undoSceneData = nullptr; return; } + main->undo_s.push_disabled(); + for (obs_sceneitem_t *item : item_order) obs_sceneitem_select(item, false); @@ -954,21 +981,29 @@ void SourceTreeModel::GroupSelectedItems(QModelIndexList &indices) obs_sceneitem_select(item, true); - QMetaObject::invokeMethod(st, "Edit", Qt::QueuedConnection, + QMetaObject::invokeMethod(st, "NewGroupEdit", Qt::QueuedConnection, Q_ARG(int, newIdx)); } void SourceTreeModel::UngroupSelectedGroups(QModelIndexList &indices) { + OBSBasic *main = OBSBasic::Get(); if (indices.count() == 0) return; + OBSScene scene = main->GetCurrentScene(); + OBSData undoData = main->BackupScene(scene); + for (int i = indices.count() - 1; i >= 0; i--) { obs_sceneitem_t *item = items[indices[i].row()]; obs_sceneitem_group_ungroup(item); } SceneChanged(); + + OBSData redoData = main->BackupScene(scene); + main->CreateSceneUndoRedoAction(QTStr("Basic.Main.Ungroup"), undoData, + redoData); } void SourceTreeModel::ExpandGroup(obs_sceneitem_t *item) @@ -1495,20 +1530,55 @@ void SourceTree::selectionChanged(const QItemSelection &selected, QListView::selectionChanged(selected, deselected); } -void SourceTree::Edit(int row) +void SourceTree::NewGroupEdit(int row) +{ + if (!Edit(row)) { + OBSBasic *main = OBSBasic::Get(); + main->undo_s.pop_disabled(); + + blog(LOG_WARNING, "Uh, somehow the edit didn't process, this " + "code should never be reached.\nAnd by " + "\"never be reached\", I mean that " + "theoretically, it should be\nimpossible " + "for this code to be reached. But if this " + "code is reached,\nfeel free to laugh at " + "Jim, because apparently it is, in fact, " + "actually\npossible for this code to be " + "reached. But I mean, again, theoretically\n" + "it should be impossible. So if you see " + "this in your log, just know that\nit's " + "really dumb, and depressing. But at least " + "the undo/redo action is\nstill covered, so " + "in theory things *should* be fine. But " + "it's entirely\npossible that they might " + "not be exactly. But again, yea. This " + "really\nshould not be possible."); + + OBSData redoSceneData = main->BackupScene(GetCurrentScene()); + + QString text = QTStr("Undo.GroupItems").arg("Unknown"); + main->CreateSceneUndoRedoAction(text, undoSceneData, + redoSceneData); + + undoSceneData = nullptr; + } +} + +bool SourceTree::Edit(int row) { SourceTreeModel *stm = GetStm(); if (row < 0 || row >= stm->items.count()) - return; + return false; QModelIndex index = stm->createIndex(row, 0); QWidget *widget = indexWidget(index); SourceTreeItem *itemWidget = reinterpret_cast(widget); if (itemWidget->IsEditing()) - return; + return false; itemWidget->EnterEditMode(); edit(index); + return true; } bool SourceTree::MultipleBaseSelected() const diff --git a/UI/source-tree.hpp b/UI/source-tree.hpp index c0fdcbfd8..c26a584ff 100644 --- a/UI/source-tree.hpp +++ b/UI/source-tree.hpp @@ -69,6 +69,8 @@ private: QLineEdit *editor = nullptr; + std::string newName; + SourceTree *tree; OBSSceneItem sceneitem; OBSSignal sceneRemoveSignal; @@ -83,6 +85,8 @@ private: virtual void paintEvent(QPaintEvent *event) override; + void ExitEditModeInternal(bool save); + private slots: void Clear(); @@ -152,6 +156,8 @@ class SourceTree : public QListView { QStaticText textNoSources; QSvgRenderer iconNoSources; + OBSData undoSceneData; + bool iconsVisible = true; void UpdateNoSourcesMessage(); @@ -197,7 +203,8 @@ public slots: void GroupSelectedItems(); void UngroupSelectedGroups(); void AddGroup(); - void Edit(int idx); + bool Edit(int idx); + void NewGroupEdit(int idx); protected: virtual void mouseDoubleClickEvent(QMouseEvent *event) override;