GUI: chapters: implement name template variable for chapter's start timestamp

The variable takes the form <START> or <START:format> with »format«
defaulting to »%H:%M:%S«.

Implements #1445.
This commit is contained in:
Moritz Bunkus 2015-10-04 11:53:41 +02:00
parent 20a448d2af
commit 299d5337fc
8 changed files with 62 additions and 26 deletions

View File

@ -1,3 +1,12 @@
2015-10-04 Moritz Bunkus <moritz@bunkus.org>
* MKVToolNix GUI: chapter editor enhancement: Added another
variable to the chapter name templates called <START> which is
replaced by the chapter's start timestamp. An optional format can
be specified, e.g. <START:%H:%M:%S.%3n> resulting in something
like 01:35:27.734. This can be used in the 'generate sub-chapters'
or the 'renumber sub-chapters' functionality. Implements #1445.
2015-10-03 Moritz Bunkus <moritz@bunkus.org>
* MKVToolNix GUI: merge tool bug fix: If there's currently no

View File

@ -10,6 +10,7 @@
#include "common/strings/formatting.h"
#include "common/strings/parsing.h"
#include "mkvtoolnix-gui/chapter_editor/generate_sub_chapters_parameters_dialog.h"
#include "mkvtoolnix-gui/chapter_editor/tool.h"
#include "mkvtoolnix-gui/forms/chapter_editor/generate_sub_chapters_parameters_dialog.h"
#include "mkvtoolnix-gui/main_window/main_window.h"
#include "mkvtoolnix-gui/util/settings.h"
@ -59,12 +60,7 @@ GenerateSubChaptersParametersDialog::setupUi(int firstChapterNumber,
void
GenerateSubChaptersParametersDialog::retranslateUi() {
Util::setToolTip(m_ui->leStartTimecode, QY("The format is either the form 'HH:MM:SS.nnnnnnnnn' or a number followed by one of the units 's', 'ms' or 'us'."));
Util::setToolTip(m_ui->leNameTemplate,
Q("<p>%1 %2</p><p>%3 %4</p>")
.arg(QY("This template will be used for new chapter entries."))
.arg(QY("The string '<NUM>' will be replaced by the chapter number.").toHtmlEscaped())
.arg(QY("You can specify a minimum number of places for the chapter number with '<NUM:places>', e.g. '<NUM:3>'.").toHtmlEscaped())
.arg(QY("The resulting number will be padded with leading zeroes if the number of places is less than specified.")));
Util::setToolTip(m_ui->leNameTemplate, Tool::chapterNameTemplateToolTip());
}
int

View File

@ -10,6 +10,7 @@
#include "common/strings/formatting.h"
#include "common/strings/parsing.h"
#include "mkvtoolnix-gui/chapter_editor/renumber_sub_chapters_parameters_dialog.h"
#include "mkvtoolnix-gui/chapter_editor/tool.h"
#include "mkvtoolnix-gui/forms/chapter_editor/renumber_sub_chapters_parameters_dialog.h"
#include "mkvtoolnix-gui/main_window/main_window.h"
#include "mkvtoolnix-gui/util/settings.h"
@ -50,12 +51,7 @@ RenumberSubChaptersParametersDialog::setupUi(int firstChapterNumber,
m_ui->cbLanguageOfNamesToReplace->setCurrentIndex(0);
Util::setToolTip(m_ui->leNameTemplate,
Q("<p>%1 %2</p><p>%3 %4</p>")
.arg(QY("This template will be used for new chapter entries."))
.arg(QY("The string '<NUM>' will be replaced by the chapter number.").toHtmlEscaped())
.arg(QY("You can specify a minimum number of places for the chapter number with '<NUM:places>', e.g. '<NUM:3>'.").toHtmlEscaped())
.arg(QY("The resulting number will be padded with leading zeroes if the number of places is less than specified.")));
Util::setToolTip(m_ui->leNameTemplate, Tool::chapterNameTemplateToolTip());
m_ui->cbFirstEntryToRenumber->setFocus();

View File

@ -349,7 +349,7 @@ Tab::timecodesToChapters(std::vector<timecode_c> const &timecodes)
for (auto const &timecode : timecodes) {
auto nameTemplate = QString{ cfg.m_chapterNameTemplate };
auto name = formatChapterName(nameTemplate, ++idx);
auto name = formatChapterName(nameTemplate, ++idx, timecode);
auto atom = mtx::construct::cons<KaxChapterAtom>(new KaxChapterTimeStart, timecode.to_ns(),
mtx::construct::cons<KaxChapterDisplay>(new KaxChapterString, name,
new KaxChapterLanguage, to_utf8(cfg.m_defaultChapterLanguage)));
@ -962,7 +962,7 @@ Tab::createEmptyChapter(int64_t startTime,
auto &cfg = Util::Settings::get();
auto chapter = std::make_shared<KaxChapterAtom>();
auto &display = GetChild<KaxChapterDisplay>(*chapter);
auto name = formatChapterName(nameTemplate ? *nameTemplate : cfg.m_chapterNameTemplate, chapterNumber);
auto name = formatChapterName(nameTemplate ? *nameTemplate : cfg.m_chapterNameTemplate, chapterNumber, timecode_c::ns(startTime));
GetChild<KaxChapterUID>(*chapter).SetValue(0);
GetChild<KaxChapterTimeStart>(*chapter).SetValue(startTime);
@ -1212,13 +1212,15 @@ Tab::duplicateElement() {
QString
Tab::formatChapterName(QString const &nameTemplate,
int chapterNumber)
int chapterNumber,
timecode_c const &startTimecode)
const {
auto name = QString{ nameTemplate };
auto re = QRegularExpression{Q("<NUM(?::(\\d+))?>")};
auto name = QString{ nameTemplate };
auto numberRe = QRegularExpression{Q("<NUM(?::(\\d+))?>")};
auto timecodeRe = QRegularExpression{Q("<START(?::([^>]+))?>")};
while (true) {
auto matches = re.match(name);
auto matches = numberRe.match(name);
if (!matches.hasMatch())
break;
@ -1228,6 +1230,15 @@ Tab::formatChapterName(QString const &nameTemplate,
name.replace(matches.capturedStart(), matches.capturedLength(), strNumber);
}
while (true) {
auto matches = timecodeRe.match(name);
if (!matches.hasMatch())
break;
auto format = matches.capturedLength(1) ? matches.captured(1) : Q("%H:%M:%S");
name.replace(matches.capturedStart(), matches.capturedLength(), Q(format_timecode(startTimecode, to_utf8(format))));
}
return name;
}
@ -1300,7 +1311,8 @@ Tab::changeChapterName(QModelIndex const &parentIdx,
return false;
}
auto name = to_wide(formatChapterName(nameTemplate, chapterNumber));
auto startTimecode = FindChildValue<KaxChapterTimeStart>(*chapter);
auto name = to_wide(formatChapterName(nameTemplate, chapterNumber, timecode_c::ns(startTimecode)));
if (RenumberSubChaptersParametersDialog::NameMatch::First == nameMatchingMode) {
GetChild<KaxChapterString>(GetChild<KaxChapterDisplay>(*chapter)).SetValue(name);

View File

@ -165,7 +165,7 @@ protected:
QString currentState() const;
ChaptersPtr timecodesToChapters(std::vector<timecode_c> const &timecodes) const;
QString formatChapterName(QString const &nameTemplate, int chapterNumber) const;
QString formatChapterName(QString const &nameTemplate, int chapterNumber, timecode_c const &startTimecode) const;
bool changeChapterName(QModelIndex const &parentIdx, int row, int chapterNumber, QString const &nameTemplate, RenumberSubChaptersParametersDialog::NameMatch nameMatchingMode, QString const &languageOfNamesToReplace,
bool skipHidden);

View File

@ -293,4 +293,28 @@ Tool::setupTabPositions() {
ui->editors->setTabPosition(Util::Settings::get().m_tabPosition);
}
QString
Tool::chapterNameTemplateToolTip() {
return Q("<p>%1 %2 %3</p><p>%4 %5</p><p>%6 %7 %8</p><ul><li>%9</li><li>%10</li><li>%11</li><li>%12</li><li>%13</li><li>%14</li><li>%15</li><li>%16</li></ul>")
.arg(QY("This template will be used for new chapter entries."))
.arg(QY("The string '<NUM>' will be replaced by the chapter number.").toHtmlEscaped())
.arg(QY("The string '<START>' will be replaced by the chapter's start timestamp.").toHtmlEscaped())
.arg(QY("You can specify a minimum number of places for the chapter number with '<NUM:places>', e.g. '<NUM:3>'.").toHtmlEscaped())
.arg(QY("The resulting number will be padded with leading zeroes if the number of places is less than specified."))
.arg(QY("You can control the format used by the start timestamp with <START:format>.").toHtmlEscaped())
.arg(QY("The format defaults to %H:%M:%S if none is given."))
.arg(QY("Valid format codes are:"))
.arg(QY("%h hours"))
.arg(QY("%H hours zero-padded to two places"))
.arg(QY("%m minutes"))
.arg(QY("%M minutes zero-padded to two places"))
.arg(QY("%s seconds"))
.arg(QY("%S seconds zero-padded to two places"))
.arg(QY("%n nanoseconds with nine places"))
.arg(QY("%<1-9>n nanoseconds with up to nine places (e.g. three places with %3n)").toHtmlEscaped());
}
}}}

View File

@ -62,6 +62,9 @@ protected:
virtual void dragEnterEvent(QDragEnterEvent *event) override;
virtual void dropEvent(QDropEvent *event) override;
public:
static QString chapterNameTemplateToolTip();
};
}}}

View File

@ -7,6 +7,7 @@
#include "common/qt.h"
#include "common/translation.h"
#include "mkvtoolnix-gui/app.h"
#include "mkvtoolnix-gui/chapter_editor/tool.h"
#include "mkvtoolnix-gui/forms/main_window/preferences_dialog.h"
#include "mkvtoolnix-gui/main_window/preferences_dialog.h"
#include "mkvtoolnix-gui/merge/additional_command_line_options_dialog.h"
@ -125,12 +126,7 @@ PreferencesDialog::setupToolTips() {
.arg(QY("Normally completed jobs stay in the queue even over restarts until the user clears them out manually."))
.arg(QY("You can opt for having them removed automatically under certain conditions.")));
Util::setToolTip(ui->leCENameTemplate,
Q("<p>%1 %2</p><p>%3 %4</p>")
.arg(QY("This template will be used for new chapter entries."))
.arg(QY("The string '<NUM>' will be replaced by the chapter number.").toHtmlEscaped())
.arg(QY("You can specify a minimum number of places for the chapter number with '<NUM:places>', e.g. '<NUM:3>'.").toHtmlEscaped())
.arg(QY("The resulting number will be padded with leading zeroes if the number of places is less than specified.")));
Util::setToolTip(ui->leCENameTemplate, ChapterEditor::Tool::chapterNameTemplateToolTip());
Util::setToolTip(ui->cbCEDefaultLanguage, QY("This is the language that newly added chapter names get assigned automatically."));
Util::setToolTip(ui->cbCEDefaultCountry, QY("This is the country that newly added chapter names get assigned automatically."));
Util::setToolTip(ui->cbCEDropLastFromBlurayPlaylist,