From 610b2a94949ed301371f241146073420c754b017 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Sat, 13 Oct 2012 21:21:43 -0700 Subject: [PATCH] Make pasting lines not horribly slow and bad. Closes #1534. --- aegisub/src/command/edit.cpp | 94 +++++++++++++++++++++++++++++++- aegisub/src/subs_grid.cpp | 101 ----------------------------------- aegisub/src/subs_grid.h | 1 - 3 files changed, 92 insertions(+), 104 deletions(-) diff --git a/aegisub/src/command/edit.cpp b/aegisub/src/command/edit.cpp index 2a82aba8f..bbac439a4 100644 --- a/aegisub/src/command/edit.cpp +++ b/aegisub/src/command/edit.cpp @@ -52,7 +52,9 @@ #include "../ass_override.h" #include "../ass_style.h" #include "../dialog_colorpicker.h" +#include "../dialog_paste_over.h" #include "../dialog_search_replace.h" +#include "../main.h" #include "../include/aegisub/context.h" #include "../subs_edit_ctrl.h" #include "../subs_grid.h" @@ -78,6 +80,94 @@ struct validate_sel_multiple : public Command { } }; +void paste_lines(agi::Context *c, bool paste_over) { + wxString data; + if (wxTheClipboard->Open()) { + if (wxTheClipboard->IsSupported(wxDF_TEXT)) { + wxTextDataObject rawdata; + wxTheClipboard->GetData(rawdata); + data = rawdata.GetText(); + } + wxTheClipboard->Close(); + } + if (!data) return; + + AssDialogue *rel_line = c->selectionController->GetActiveLine(); + entryIter pos = find(c->ass->Line.begin(), c->ass->Line.end(), rel_line); + + AssDialogue *first = 0; + SubtitleSelection newsel; + + std::vector pasteOverOptions; + wxStringTokenizer token (data,"\r\n",wxTOKEN_STRTOK); + while (token.HasMoreTokens()) { + // Convert data into an AssDialogue + wxString curdata = token.GetNextToken(); + curdata.Trim(true); + curdata.Trim(false); + AssDialogue *curdiag; + try { + // Try to interpret the line as an ASS line + curdiag = new AssDialogue(curdata); + } + catch (...) { + // Line didn't parse correctly, assume it's plain text that + // should be pasted in the Text field only + curdiag = new AssDialogue(); + curdiag->Text = curdata; + // Make sure pasted plain-text lines always are blank-timed + curdiag->Start = 0; + curdiag->End = 0; + } + + if (!first) + first = curdiag; + + if (!paste_over) { + newsel.insert(curdiag); + c->ass->Line.insert(pos, curdiag); + } + else { + // Get list of options to paste over, if not asked yet + if (pasteOverOptions.empty()) { + DialogPasteOver diag(c->parent); + if (diag.ShowModal()) { + delete curdiag; + return; + } + pasteOverOptions = OPT_GET("Tool/Paste Lines Over/Fields")->GetListBool(); + } + + AssDialogue *line = static_cast(*pos); + if (pasteOverOptions[0]) line->Layer = curdiag->Layer; + if (pasteOverOptions[1]) line->Start = curdiag->Start; + if (pasteOverOptions[2]) line->End = curdiag->End; + if (pasteOverOptions[3]) line->Style = curdiag->Style; + if (pasteOverOptions[4]) line->Actor = curdiag->Actor; + if (pasteOverOptions[5]) line->Margin[0] = curdiag->Margin[0]; + if (pasteOverOptions[6]) line->Margin[1] = curdiag->Margin[1]; + if (pasteOverOptions[7]) line->Margin[2] = curdiag->Margin[2]; + if (pasteOverOptions[8]) line->Effect = curdiag->Effect; + if (pasteOverOptions[9]) line->Text = curdiag->Text; + + delete curdiag; + + do { + ++pos; + } while (pos != c->ass->Line.end() && !dynamic_cast(*pos)); + if (pos == c->ass->Line.end()) + break; + } + } + + if (first) { + c->ass->Commit(_("paste"), paste_over ? AssFile::COMMIT_DIAG_FULL : AssFile::COMMIT_DIAG_ADDREM); + + if (!paste_over) + c->selectionController->SetSelectionAndActive(newsel, first); + } +} + template T get_value(AssDialogue const& line, int blockn, T initial, wxString const& tag, wxString alt = wxString()) { for (int i = blockn; i >= 0; i--) { @@ -629,7 +719,7 @@ struct edit_line_paste : public Command { if (wxTextEntryBase *ctrl = dynamic_cast(c->parent->FindFocus())) ctrl->Paste(); else - c->subsGrid->PasteLines(c->subsGrid->GetFirstSelRow()); + paste_lines(c, false); } }; @@ -652,7 +742,7 @@ struct edit_line_paste_over : public Command { } void operator()(agi::Context *c) { - c->subsGrid->PasteLines(c->subsGrid->GetFirstSelRow(),true); + paste_lines(c, true); } }; diff --git a/aegisub/src/subs_grid.cpp b/aegisub/src/subs_grid.cpp index b8bbdaca4..08d865ee8 100644 --- a/aegisub/src/subs_grid.cpp +++ b/aegisub/src/subs_grid.cpp @@ -52,7 +52,6 @@ #include "ass_dialogue.h" #include "ass_file.h" -#include "dialog_paste_over.h" #include "main.h" #include "utils.h" #include "video_context.h" @@ -210,106 +209,6 @@ void SubtitlesGrid::CutLines(wxArrayInt target) { EndBatch(); } -/// @brief Paste lines from clipboard -/// @param n -/// @param pasteOver -void SubtitlesGrid::PasteLines(int n,bool pasteOver) { - BeginBatch(); - - // Prepare text - wxString data; - - // Read from clipboard - if (wxTheClipboard->Open()) { - if (wxTheClipboard->IsSupported(wxDF_TEXT)) { - wxTextDataObject rawdata; - wxTheClipboard->GetData(rawdata); - data = rawdata.GetText(); - } - wxTheClipboard->Close(); - } - - // Check if it actually got anything - if (!data.empty()) { - // Insert data - int inserted = 0; - std::vector pasteOverOptions; - wxStringTokenizer token (data,"\r\n",wxTOKEN_STRTOK); - while (token.HasMoreTokens()) { - // Convert data into an AssDialogue - wxString curdata = token.GetNextToken(); - curdata.Trim(true); - curdata.Trim(false); - AssDialogue *curdiag; - try { - // Try to interpret the line as an ASS line - curdiag = new AssDialogue(curdata); - } - catch (...) { - // Line didn't parse correctly, assume it's plain text that - // should be pasted in the Text field only - curdiag = new AssDialogue(); - curdiag->Text = curdata; - // Make sure pasted plain-text lines always are blank-timed - curdiag->Start = 0; - curdiag->End = 0; - } - - // Paste over - if (pasteOver) { - if (n+inserted < GetRows()) { - // Get list of options to paste over, if not asked yet - if (pasteOverOptions.empty()) { - DialogPasteOver diag(context->parent); - if (diag.ShowModal()) { - delete curdiag; - EndBatch(); - return; - } - pasteOverOptions = OPT_GET("Tool/Paste Lines Over/Fields")->GetListBool(); - } - - // Paste over - AssDialogue *target = GetDialogue(n+inserted); - if (pasteOverOptions[0]) target->Layer = curdiag->Layer; - if (pasteOverOptions[1]) target->Start = curdiag->Start; - if (pasteOverOptions[2]) target->End = curdiag->End; - if (pasteOverOptions[3]) target->Style = curdiag->Style; - if (pasteOverOptions[4]) target->Actor = curdiag->Actor; - if (pasteOverOptions[5]) target->Margin[0] = curdiag->Margin[0]; - if (pasteOverOptions[6]) target->Margin[1] = curdiag->Margin[1]; - if (pasteOverOptions[7]) target->Margin[2] = curdiag->Margin[2]; - if (pasteOverOptions[8]) target->Effect = curdiag->Effect; - if (pasteOverOptions[9]) target->Text = curdiag->Text; - } - delete curdiag; - } - - // Paste normally - else InsertLine(curdiag,n+inserted,false,false); - - // Increment insertion - inserted++; - } - - // Update data post-insertion - if (inserted > 0) { - context->ass->Commit(_("paste"), pasteOver ? AssFile::COMMIT_DIAG_FULL : AssFile::COMMIT_DIAG_ADDREM); - - // Set selection - if (!pasteOver) { - Selection newsel; - for (int i=n;iass->Line.begin(), context->ass->Line.end(), cast()); --before_first; diff --git a/aegisub/src/subs_grid.h b/aegisub/src/subs_grid.h index 558871daa..9ac9538d1 100644 --- a/aegisub/src/subs_grid.h +++ b/aegisub/src/subs_grid.h @@ -70,7 +70,6 @@ public: /// @brief Cut to clipboard /// @param target Lines to cut void CutLines(wxArrayInt lines); - void PasteLines(int pos,bool over=false); void RecombineLines();