std::vector<AssDialogue*> DialogTimingProcessor::SortDialogues() { std::set<std::string> styles; for (size_t i = 0; i < StyleList->GetCount(); ++i) { if (StyleList->IsChecked(i)) styles.insert(from_wx(StyleList->GetString(i))); } std::vector<AssDialogue*> sorted; if (onlySelection->IsChecked()) { SubtitleSelection sel = c->selectionController->GetSelectedSet(); copy_if(sel.begin(), sel.end(), back_inserter(sorted), [&](AssDialogue *d) { return !d->Comment && styles.count(d->Style); }); } else { transform(c->ass->Line.begin(), c->ass->Line.end(), back_inserter(sorted), cast<AssDialogue*>()); sorted.erase(boost::remove_if(sorted, bind(bad_line, &styles, _1)), sorted.end()); } // Check if rows are valid for (auto diag : sorted) { if (diag->Start > diag->End) { int line = count_if(c->ass->Line.begin(), c->ass->Line.iterator_to(*diag), cast<const AssDialogue*>()); wxMessageBox( wxString::Format(_("One of the lines in the file (%i) has negative duration. Aborting."), line), _("Invalid script"), wxOK | wxICON_ERROR | wxCENTER); sorted.clear(); break; } } boost::sort(sorted, AssFile::CompStart); return sorted; }
void VisualTool<FeatureType>::SetSelection(FeatureType *feat, bool clear) { if (clear) sel_features.clear(); if (sel_features.insert(feat).second && feat->line) { SubtitleSelection sel; if (!clear) sel = c->selectionController->GetSelectedSet(); if (sel.insert(feat->line).second) c->selectionController->SetSelectedSet(sel); } }
bool DialogSpellChecker::CheckLine(AssDialogue *active_line, int start_pos, int *commit_id) { if (active_line->Comment && skip_comments->GetValue()) return false; std::string text = from_wx(active_line->Text); auto tokens = agi::ass::TokenizeDialogueBody(text); agi::ass::SplitWords(text, tokens); word_start = 0; for (auto const& tok : tokens) { if (tok.type != agi::ass::DialogueTokenType::WORD || word_start < start_pos) { word_start += tok.length; continue; } word_len = tok.length; std::string word = text.substr(word_start, word_len); if (auto_ignore.count(word) || spellchecker->CheckWord(word)) { word_start += tok.length; continue; } auto auto_rep = auto_replace.find(word); if (auto_rep == auto_replace.end()) { #ifdef __WXGTK__ // http://trac.wxwidgets.org/ticket/14369 orig_word->Remove(0, -1); replace_word->Remove(0, -1); #endif SubtitleSelection sel; sel.insert(active_line); context->selectionController->SetSelectionAndActive(sel, active_line); SetWord(word); return true; } text.replace(word_start, word_len, auto_rep->second); active_line->Text = from_wx(text); *commit_id = context->ass->Commit(_("spell check replace"), AssFile::COMMIT_DIAG_TEXT, *commit_id); word_start += auto_rep->second.size(); } return false; }
void VisualTool<FeatureType>::RemoveSelection(FeatureType *feat) { if (!sel_features.erase(feat) || !feat->line) return; for (auto sel : sel_features) if (sel->line == feat->line) return; SubtitleSelection sel = c->selectionController->GetSelectedSet(); // Don't deselect the only selected line if (sel.size() <= 1) return; sel.erase(feat->line); // Set the active line to an arbitrary selected line if we just // deselected the active line AssDialogue *new_active = c->selectionController->GetActiveLine(); if (feat->line == new_active) new_active = *sel.begin(); c->selectionController->SetSelectionAndActive(sel, new_active); }
void VisualToolDrag::OnSelectedSetChanged(const SubtitleSelection &added, const SubtitleSelection &removed) { c->selectionController->GetSelectedSet(selection); bool any_changed = false; for (feature_iterator it = features.begin(); it != features.end(); ) { if (removed.count(it->line)) { sel_features.erase(it++); any_changed = true; } else { if (added.count(it->line) && it->type == DRAG_START && line_not_present(sel_features, it)) { sel_features.insert(it); any_changed = true; } ++it; } } if (any_changed) parent->Render(); }
void AssKaraoke::SplitLines(std::set<AssDialogue*> const& lines, agi::Context *c) { if (lines.empty()) return; AssKaraoke kara; SubtitleSelection sel = c->selectionController->GetSelectedSet(); bool did_split = false; for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it); if (!diag || !lines.count(diag)) continue; kara.SetLine(diag); // If there aren't at least two tags there's nothing to split if (kara.size() < 2) continue; bool in_sel = sel.count(diag) > 0; for (auto const& syl : kara) { AssDialogue *new_line = new AssDialogue(*diag); new_line->Start = syl.start_time; new_line->End = syl.start_time + syl.duration; new_line->Text = syl.GetText(false); c->ass->Line.insert(it, *new_line); if (in_sel) sel.insert(new_line); } --it; // Move `it` to the last of the new lines sel.erase(diag); delete diag; did_split = true; } if (!did_split) return; c->ass->Commit(_("splitting"), AssFile::COMMIT_DIAG_ADDREM | AssFile::COMMIT_DIAG_FULL); AssDialogue *new_active = c->selectionController->GetActiveLine(); if (!sel.count(c->selectionController->GetActiveLine())) new_active = *sel.begin(); c->selectionController->SetSelectionAndActive(sel, new_active); }
void DialogShiftTimes::Process(wxCommandEvent &) { int mode = selection_mode->GetSelection(); int type = time_fields->GetSelection(); bool reverse = shift_backward->GetValue(); bool by_time = shift_by_time->GetValue(); bool start = type != 2; bool end = type != 1; SubtitleSelection sel = context->selectionController->GetSelectedSet(); long shift; if (by_time) { shift = shift_time->GetTime(); if (shift == 0) { Close(); return; } } else shift_frames->GetValue().ToLong(&shift); if (reverse) shift = -shift; // Track which rows were shifted for the log int row_number = 0; int block_start = 0; json::Array shifted_blocks; for (auto line : context->ass->Line | agi::of_type<AssDialogue>()) { ++row_number; if (!sel.count(line)) { if (block_start) { json::Object block; block["start"] = block_start; block["end"] = row_number - 1; shifted_blocks.push_back(block); block_start = 0; } if (mode == 1) continue; if (mode == 2 && shifted_blocks.empty()) continue; } else if (!block_start) block_start = row_number; if (start) line->Start = Shift(line->Start, shift, by_time, agi::vfr::START); if (end) line->End = Shift(line->End, shift, by_time, agi::vfr::END); } context->ass->Commit(_("shifting"), AssFile::COMMIT_DIAG_TIME); if (block_start) { json::Object block; block["start"] = block_start; block["end"] = row_number - 1; shifted_blocks.push_back(block); } SaveHistory(shifted_blocks); Close(); }