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;
}
示例#2
0
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);
	}
}
示例#3
0
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;
}
示例#4
0
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);
}
示例#5
0
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();
}
示例#6
0
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();
}