void Subtitle::setSecondaryData(const Subtitle &from, bool usePrimaryData) { beginCompositeAction(i18n("Set Secondary Data")); SubtitleIterator fromIt(from, Range::full()); SubtitleIterator thisIt(*this, Range::full()); // the errors that we are going to take from 'from': const int fromErrors = usePrimaryData ? SubtitleLine::PrimaryOnlyErrors : SubtitleLine::SecondaryOnlyErrors; // the errors that we are going to keep: const int thisErrors = SubtitleLine::PrimaryOnlyErrors | SubtitleLine::SharedErrors; for(SubtitleLine *fromLine = fromIt.current(), *thisLine = thisIt.current(); fromLine && thisLine; ++fromIt, ++thisIt, fromLine = fromIt.current(), thisLine = thisIt.current()) { thisLine->setSecondaryText(usePrimaryData ? fromLine->primaryText() : fromLine->secondaryText()); thisLine->setErrorFlags((thisLine->errorFlags() & thisErrors) | (fromLine->errorFlags() & fromErrors)); } if(fromIt.current()) { // from subtitle had more lines than *this QList<SubtitleLine *> lines; for(; fromIt.current(); ++fromIt) { SubtitleLine *thisLine = new SubtitleLine(*fromIt.current()); if(usePrimaryData) thisLine->setSecondaryText(thisLine->primaryText()); thisLine->setPrimaryText(SString()); thisLine->setErrorFlags(SubtitleLine::PrimaryOnlyErrors, false); lines.append(thisLine); } processAction(new InsertLinesAction(*this, lines)); } else if(thisIt.current()) { // *this had more lines than from subtitle for(SubtitleLine *thisLine = thisIt.current(); thisLine; ++thisIt, thisLine = thisIt.current()) { thisLine->setSecondaryText(SString()); thisLine->setErrorFlags(SubtitleLine::SecondaryOnlyErrors, false); } } endCompositeAction(); }
void Subtitle::splitLines(const RangeList &ranges) { beginCompositeAction(i18n("Split Lines")); for(SubtitleIterator it(*this, ranges, true); it.current(); --it) { SubtitleLine *line = it.current(); if(line->primaryLines() > 1) { line->simplifyTextWhiteSpace(SubtitleLine::Primary); long autoDurationsSum = 0; QList<int> autoDurations; SStringList primaryLines = line->primaryText().split('\n'); for(SStringList::ConstIterator ptIt = primaryLines.begin(), ptEnd = primaryLines.end(); ptIt != ptEnd; ++ptIt) { const Time &autoDuration = SubtitleLine::autoDuration((*ptIt).string(), 60, 50, 50); autoDurations.append(autoDuration.toMillis()); autoDurationsSum += autoDuration.toMillis(); } double factor = line->durationTime().toMillis() / autoDurationsSum; SStringList secondaryLines = line->secondaryText().split('\n'); while(secondaryLines.count() < primaryLines.count()) secondaryLines.append(SString()); while(secondaryLines.count() > primaryLines.count()) { SString lastLine = secondaryLines.last(); secondaryLines.pop_back(); secondaryLines.last() += '\n'; secondaryLines.last() += lastLine; } int subLineIndex = it.index(), splitLineIndex = 0; for(SStringList::ConstIterator ptIt = primaryLines.begin(), ptEnd = secondaryLines.end(), stIt = secondaryLines.begin(), stEnd = secondaryLines.end(); ptIt != ptEnd && stIt != stEnd; ++ptIt, ++stIt, ++subLineIndex, ++splitLineIndex) { if(splitLineIndex) { SubtitleLine *newLine = new SubtitleLine(); newLine->setShowTime(line->hideTime() + 1); insertLine(newLine, subLineIndex); line = newLine; } line->setTexts(*ptIt, *stIt); line->setDurationTime(Time((factor * autoDurations[splitLineIndex]) - 1.0)); } } } endCompositeAction(); }
void Subtitle::setPrimaryData(const Subtitle &from, bool usePrimaryData) { beginCompositeAction(i18n("Set Primary Data")); setFormatData(from.m_formatData); setFramesPerSecond(from.framesPerSecond()); SubtitleIterator fromIt(from, Range::full()); SubtitleIterator thisIt(*this, Range::full()); // the errors that we are going to take from 'from': const int fromErrors = (usePrimaryData ? SubtitleLine::PrimaryOnlyErrors : SubtitleLine::SecondaryOnlyErrors) | SubtitleLine::SharedErrors; // the errors that we are going to keep: const int thisErrors = SubtitleLine::SecondaryOnlyErrors; for(SubtitleLine *fromLine = fromIt.current(), *thisLine = thisIt.current(); fromLine && thisLine; ++fromIt, ++thisIt, fromLine = fromIt.current(), thisLine = thisIt.current()) { thisLine->setPrimaryText(usePrimaryData ? fromLine->primaryText() : fromLine->secondaryText()); thisLine->setTimes(fromLine->showTime(), fromLine->hideTime()); thisLine->setErrorFlags((fromLine->errorFlags() & fromErrors) | (thisLine->errorFlags() & thisErrors)); thisLine->setFormatData(fromLine->formatData()); } if(fromIt.current()) { // 'from' had more lines than '*this' QList<SubtitleLine *> lines; for(; fromIt.current(); ++fromIt) { SubtitleLine *thisLine = new SubtitleLine(*fromIt.current()); if(!usePrimaryData) thisLine->setPrimaryText(thisLine->secondaryText()); thisLine->setSecondaryText(SString()); thisLine->setErrorFlags(SubtitleLine::SecondaryOnlyErrors, false); thisLine->setFormatData(fromIt.current()->formatData()); lines.append(thisLine); } InsertLinesAction a(*this, lines); processAction(&a); } else if(thisIt.current()) { // '*this' had more lines than 'from' for(SubtitleLine *thisLine = thisIt.current(); thisLine; ++thisIt, thisLine = thisIt.current()) { thisLine->setPrimaryText(SString()); thisLine->setErrorFlags(SubtitleLine::PrimaryOnlyErrors, false); thisLine->setFormatData(0); } } endCompositeAction(); }
void Subtitle::joinLines(const RangeList &ranges) { beginCompositeAction(i18n("Join Lines")); RangeList obsoletedRanges; for(RangeList::ConstIterator rangesIt = ranges.begin(), end = ranges.end(); rangesIt != end; ++rangesIt) { int rangeStart = (*rangesIt).start(); int rangeEnd = normalizeRangeIndex((*rangesIt).end()); if(rangeStart >= rangeEnd) continue; SubtitleLine *firstLine = m_lines.at(rangeStart); SubtitleLine *lastLine = m_lines.at(rangeEnd); SString primaryText, secondaryText; for(SubtitleIterator it(*this, Range(rangeStart, rangeEnd - 1)); it.current(); ++it) { if(!it.current()->primaryText().isEmpty()) { primaryText.append(it.current()->primaryText()); primaryText.append("\n"); } if(!it.current()->secondaryText().isEmpty()) { secondaryText.append(it.current()->secondaryText()); secondaryText.append("\n"); } } primaryText.append(lastLine->primaryText()); secondaryText.append(lastLine->secondaryText()); firstLine->setTexts(primaryText, secondaryText); firstLine->setHideTime(lastLine->hideTime()); obsoletedRanges << Range(rangeStart + 1, rangeEnd); } removeLines(obsoletedRanges, Both); endCompositeAction(); }
void Replacer::advance() { SubtitleCompositeActionExecutor executor(*m_subtitle, i18n("Replace")); KFind::Result res = KFind::NoMatch; bool selection = m_replace->options() & KFind::SelectedText; bool backwards = m_replace->options() & KFind::FindBackwards; QDialog *replaceNextDialog = this->replaceNextDialog(); // creates the dialog if it didn't existed before do { if(m_replace->needData()) { SubtitleLine *dataLine = m_iterator->current(); if(dataLine) { if(!m_translationMode || m_targetRadioButtons[SubtitleLine::Primary]->isChecked()) { m_feedingPrimary = true; m_replace->setData(dataLine->primaryText().string()); } else if(m_targetRadioButtons[SubtitleLine::Secondary]->isChecked()) { m_feedingPrimary = false; m_replace->setData(dataLine->secondaryText().string()); } else { // m_translationMode && m_targetRadioButtons[SubtitleLine::Both]->isChecked() m_feedingPrimary = !m_feedingPrimary; // we alternate the source of data m_replace->setData((m_feedingPrimary ? dataLine->primaryText() : dataLine->secondaryText()).string()); } } } res = m_replace->replace(); if(res == KFind::NoMatch && (!m_translationMode || !m_targetRadioButtons[SubtitleLine::Both]->isChecked() || !m_feedingPrimary)) { if(backwards) --(*m_iterator); else ++(*m_iterator); if(m_firstIndex == m_iterator->index() || (backwards ? (m_firstIndex == m_iterator->lastIndex() && m_iterator->index() == SubtitleIterator::BehindFirst) : (m_firstIndex == m_iterator->firstIndex() && m_iterator->index() == SubtitleIterator::AfterLast))) { if(replaceNextDialog) replaceNextDialog->hide(); if(m_instancesFound && m_replace->numReplacements()) KMessageBox::information(parentWidget(), i18np("1 replacement done.", "%1 replacements done.", m_replace->numReplacements()), i18n("Replace") ); else // special case KMessageBox::sorry(parentWidget(), i18n("No instances of '%1' found!", m_replace->pattern()), i18n("Replace") ); m_replace->resetCounts(); break; } if(m_iterator->index() < 0) { if(backwards) m_iterator->toLast(); else m_iterator->toFirst(); int numReplacements = m_replace->numReplacements(); m_replace->resetCounts(); if(KMessageBox::warningContinueCancel(parentWidget(), i18np("1 replacement done.", "%1 replacements done.", numReplacements) + "\n\n" + (backwards ? (selection ? i18n("Beginning of selection reached.\nContinue from the end?") : i18n("Beginning of subtitle reached.\nContinue from the end?")) : (selection ? i18n("End of selection reached.\nContinue from the beginning?") : i18n("End of subtitle reached.\nContinue from the beginning?"))), i18n("Replace") ) != KMessageBox::Continue) { if(replaceNextDialog) replaceNextDialog->hide(); break; } } } } while(res != KFind::Match); }
void Subtitle::splitLines(const RangeList &ranges) { beginCompositeAction(i18n("Split Lines")); for(SubtitleIterator it(*this, ranges, true); it.current(); --it) { SubtitleLine *line = it.current(); line->simplifyTextWhiteSpace(SubtitleLine::Primary); SString primaryText = line->primaryText(); if(primaryText.isEmpty()) continue; if(line->primaryLines() < 2) { if(primaryText.count(QChar::Space) == 0) continue; int len = primaryText.length(); int i = len / 2; int j = i + len % 2; for(; ; i--, j++) { if(primaryText[i] == QChar::Space) { primaryText[i] = QChar::LineFeed; break; } Q_ASSERT(j <= len); if(primaryText[j] == QChar::Space) { primaryText[j] = QChar::LineFeed; break; } if(i == 0) { primaryText.append(QChar::LineFeed); break; } } } double autoDurationsSum = 0; QList<double> autoDurations; SStringList primaryLines = primaryText.split('\n'); for(SStringList::ConstIterator ptIt = primaryLines.begin(), ptEnd = primaryLines.end(); ptIt != ptEnd; ++ptIt) { const Time &autoDuration = SubtitleLine::autoDuration(ptIt->string(), 60, 50, 50); autoDurations.append(autoDuration.toMillis()); autoDurationsSum += autoDuration.toMillis(); } double factor = (line->durationTime().toMillis() + 1.) / autoDurationsSum; SStringList secondaryLines = line->secondaryText().split('\n'); while(secondaryLines.count() < primaryLines.count()) secondaryLines.append(SString()); while(secondaryLines.count() > primaryLines.count()) { SString lastLine = secondaryLines.last(); secondaryLines.pop_back(); secondaryLines.last() += '\n'; secondaryLines.last() += lastLine; } int subLineIndex = it.index(), splitLineIndex = 0; for(SStringList::ConstIterator ptIt = primaryLines.begin(), ptEnd = secondaryLines.end(), stIt = secondaryLines.begin(), stEnd = secondaryLines.end(); ptIt != ptEnd && stIt != stEnd; ++ptIt, ++stIt, ++subLineIndex, ++splitLineIndex) { if(splitLineIndex) { SubtitleLine *newLine = new SubtitleLine(); newLine->setShowTime(line->hideTime() + 1); insertLine(newLine, subLineIndex); line = newLine; } line->setTexts(*ptIt, *stIt); line->setDurationTime(Time((factor * autoDurations[splitLineIndex]) - 1.0)); } } endCompositeAction(); }